9.8 KiB
RKM Value Notation for Resistance and Capacitance
Let users read and type resistor and capacitor values in RKM (IEC 60062) notation, where the unit
letter replaces the decimal point (4K7, 0R22, 2n2, 0u22), as well as in today's decimal
form (4.7K, 0.22uF). Typing a value with a unit letter in it, in either notation, also sets the
unit, so 4K7 typed into a field whose unit is Ω becomes 4.7 K.
1. User-facing behaviour
Config menu
One radio submenu in ConfigPlugin covering both resistance and capacitance, built the same way
as Snap To and Ruler Inch Subdivision... (ToggleAction, string config key, title stored as
the value):
Config
...
Value Notation > (after Sticky Points, alphabetical like the rest)
(o) Decimal (4.7K, 0.22uF)
( ) RKM (4K7, 0u22)
...
- Key
IPlugInPort.VALUE_NOTATION_KEY = "valueNotation", valuesVALUE_NOTATION_DECIMAL/VALUE_NOTATION_RKM, default decimal. - Switching notation repaints the canvas immediately, so labels on the board change at once.
What the notation controls (display)
The notation governs Resistance.toString() and Capacitance.toString() and therefore everything
built on them: labels drawn on the canvas, getValueForDisplay() (search, BOM, netlist text,
project explorer, AI assistant context). The edit dialog's value field is the exception: it always
shows the bare decimal number, because the unit box beside it already carries the unit and an RKM
code there would repeat it.
| Value | Decimal (unchanged) | RKM |
|---|---|---|
| 4.7 Ω | 4.7Ω |
4R7 |
| 0.22 Ω | 0.22Ω |
0R22 |
| 100 Ω | 100Ω |
100R |
| 4.7 K | 4.7K |
4K7 |
| 47 K | 47K |
47K |
| 1 M | 1M |
1M |
| 0.22 uF | 0.22uF |
0u22 |
| 2.2 nF | 2.2nF |
2n2 |
| 100 nF | 100nF |
100n |
| 4.7 pF | 4.7pF |
4p7 |
| 1000 uF | 1000uF |
1000u |
Rules: RKM keeps the stored unit (it never renormalises 4700 Ω to 4K7), uses R for ohms, drops
the trailing F on capacitance, puts the unit letter where the decimal point was, and writes it
as a suffix for whole numbers. The digits after the letter are rounded the same way as today's
0.#### decimal format.
What the user can type (input)
The value field accepts, in both notations:
- a bare number (
4.7,0,22) — the unit is unchanged, as today; - a decimal number with a unit (
4.7k,0.22uF,220 nF,4.7ohm,4.7Ω); - an RKM code (
4K7,4k7,0R22,R22,2n2,0u22,4µ7,1M,100R).
When the text carries a unit, the unit combo switches to it and the property gets the new value and unit together. Accepted unit letters, case-insensitive except where noted:
- Resistance:
R,Ω,ohm/ohms→ Ω;K/k→ K;M/m/Meg→ M (there is no milliohm unit, so a lower-casemon a resistor means mega, as it does on many parts lists). - Capacitance:
p→ pF;n→ nF;u/µ→ uF;m→ mF (case-sensitive:Mis not accepted, to avoid reading "mega");Falone → F. A trailingFafter any of these is optional (4u7F,2.2nF).
A unit letter that does not belong to the measure (4u7 on a resistor) shows the existing warning
icon, as any unparseable text does today.
Commit behaviour. The property is updated on every keystroke, as today — the edit dialog's
Enter key commits straight away, so it cannot wait for focus loss. When the field loses focus,
the text is rewritten as the bare decimal number (4K7 typed → 4.7 with the combo showing K),
whichever notation is selected. The text is not reformatted while the user is typing, so the
caret never jumps.
2. Design
Core (diylc-core, org.diylc.core.measures)
ValueNotation— new enumDECIMAL, RKMholding the formatting and parsing logic, so the two measure classes stay thin:String format(double value, Unit unit, String rkmSymbol)— decimal falls through to the existing0.####+unit.toString(); RKM implements the rules in §1.static ParsedMeasure parse(String text, ...)— returns value + unit (unitnullfor a bare number), or throwsIllegalArgumentException. One small recordParsedMeasure<U>at the bottom of the file.
- Current notation. One
private static volatile ValueNotation currentonValueNotationwith staticgetCurrent()/setCurrent(), shared byResistanceandCapacitance.toString()reads the field, neverConfigurationManager: it runs fromdraw()on every repaint. DefaultDECIMAL, so headless rendering, the regression suite and unit tests are unchanged unless they opt in. - Unit display symbol for RKM.
ResistanceUnitandCapacitanceUnitget anrkmSymbolconstructor argument (R/K/M,p/n/u/m/F). Enum constant names andtoString()are untouched — XStream stores the constant name, so files are unaffected. - Parsing.
Resistance.parseResistance/Capacitance.parseCapacitancedelegate toValueNotation.parse, so RKM is accepted everywhere a string is turned into a value: the editor,V1FileParser,TangoNetlistParser,CapacitorDatasheetServiceand — important oncetoString()can emit4K7— the AI assistant, which receives values as text and writes them back through these parsers. Existing accepted inputs must keep parsing identically. InductanceandPowerare out of scope; their names are left as they are.
Wiring the setting
org.diylc.presenter.ValueNotationBinder.bind(configManager, refresh) reads the key once,
pushes it into ValueNotation.setCurrent(), and on change updates the static, calls
DrawingCache.Instance.clear() (cached component images contain the old labels) and refreshes
the canvas. It is called from ConfigPlugin.connect(), not from the Presenter constructor:
the notation is global, and the many secondary presenters (project preview, cloud thumbnails,
batch converter, regression runner) are built on in-memory configurations and would reset it to
decimal.
Swing (diylc-swing)
-
MeasureTextField— new field inorg.diylc.swing.gui.editor, besideMeasureEditor. Same look asDoubleTextField(warning icon on the right) but it parses throughValueNotation.parsefor the measure type and fires aMEASURE_PROPERTYchange carrying value + optional unit; onfocusLostit reformats its text. It is generic over the unit enum so it can serveInductancelater without changes.Recommendation: keep it in DIYLC rather than extending
DoubleTextFieldinbancika-gui-framework. The framework is consumed as the vendoredlib/swing-framework-1.1.jar, so a change there means rebuilding and re-vendoring the jar for a widget whose parsing rules are DIYLC domain knowledge.DoubleTextFieldkeeps servingPercentageEditor,LoadlineEditorFrameand every other plain-number measure.One
DoubleTextFieldbug is worth fixing in the framework separately, and the new field must not copy it:DecimalFormat.parseObject(String)accepts a valid prefix, so4R7silently parses as4today, with no warning. -
MeasureEditor— usesMeasureTextFieldwhen the property type isResistanceorCapacitance,DoubleTextFieldotherwise. On a value + unit event it sets the combo's selected unit behind a guard flag, so the combo's ownActionListenerdoes not fire a secondsetValue. Read-only properties keep today's behaviour (disabled field, combo converts). -
MeasureArrayEditor(MultiSectionCapacitor) — each section value is parsed with the same rules. Units travel per section in the text (47u / 22u / 10u) and a section without a unit takes the combo's unit, as today. The combo shows the first section's unit; in decimal notation a section in a different unit is written with its unit (47 / 100nF). Changing the combo applies its unit to every section, as before. -
ConfigPlugin— theValue Notationsubmenu (IconLoader.Decimal), and the call toValueNotationBinder.bind.
Localization
New keys in English.txt and every other file in lang/: Value Notation,
Decimal (4.7K, 0.22uF), RKM (4K7, 0u22).
Because ToggleAction stores its title as the config value, the stored values are the English
titles and MainFrame translates only what is shown.
3. Compatibility
.diyfiles storevalueand the unit enum name; neither changes. No serialization impact.- With the default (decimal) every string the app produces is byte-identical to today, so
regression references do not move. A regression run is still worth doing after implementation,
since
parseResistance/parseCapacitancechange. - A user who switches to RKM gets RKM in BOM and netlist exports as well. That is the intended "everywhere" behaviour; anything that re-imports those files goes through the RKM-aware parsers.
4. Tests (diylc-core, JUnit 4)
ValueNotationTest:
- formatting: every row of the §1 table, both notations; zero, null, values ≥ 1000 in their unit, rounding at the fourth decimal;
- parsing: every input form in §1, per measure; case rules (
mvsMfor capacitance); comma as decimal separator; rejects4u7on a resistor,4K7K,K, empty text; - round trip:
parse(format(x))returnsxfor both notations; - regression guard: every string currently accepted by
parseResistance/parseCapacitance(the inputs inV1FileParser,TangoNetlistParserandCapacitorDatasheetServicetests andAiEditScriptEditorTest) still parses to the same value.
5. Status and next steps
Implemented as described; mvn -q test passes, including ValueNotationTest.
- Try it in the running app: the edit dialog (single value and
MultiSectionCapacitor), canvas labels after switching notation, BOM export. - Run the regression suite to confirm decimal output is unchanged.
- Optional, in
bancika-gui-framework: stopDoubleTextField/DoubleArrayTextFieldaccepting a valid prefix (4R7read as4).