From 048f1bae52c2db431800d744a74903f7d3e6b01f Mon Sep 17 00:00:00 2001 From: Bob Jacobsen Date: Wed, 26 Aug 2026 09:38:40 +0100 Subject: [PATCH 1/5] Add checkbox to CDI --- src/org/openlcb/cdi/CdiRep.java | 2 + src/org/openlcb/cdi/jdom/JdomCdiRep.java | 9 ++++ src/org/openlcb/cdi/swing/CdiPanel.java | 64 ++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/src/org/openlcb/cdi/CdiRep.java b/src/org/openlcb/cdi/CdiRep.java index fcc9deff..f7e487ca 100644 --- a/src/org/openlcb/cdi/CdiRep.java +++ b/src/org/openlcb/cdi/CdiRep.java @@ -119,6 +119,8 @@ public static interface IntegerRep extends Item { public boolean isSliderShowValue(); // Did the CDI content hint that this value should be presented as a radio button? public boolean isRadioButtonHint(); + // Did the CDI content hint that this value should be presented as a checkbox? + public boolean isCheckboxHint(); } public static interface FloatRep extends Item { diff --git a/src/org/openlcb/cdi/jdom/JdomCdiRep.java b/src/org/openlcb/cdi/jdom/JdomCdiRep.java index 86f8569f..0cc8c560 100644 --- a/src/org/openlcb/cdi/jdom/JdomCdiRep.java +++ b/src/org/openlcb/cdi/jdom/JdomCdiRep.java @@ -596,6 +596,15 @@ public boolean isRadioButtonHint() { return true; } + @Override + public boolean isCheckboxHint() { + Element hints = e.getChild("hints"); + if (hints == null) return false; + Element checkbox = hints.getChild("checkbox"); + if (checkbox == null) return false; + return true; + } + } diff --git a/src/org/openlcb/cdi/swing/CdiPanel.java b/src/org/openlcb/cdi/swing/CdiPanel.java index 54202327..d4ce55c2 100644 --- a/src/org/openlcb/cdi/swing/CdiPanel.java +++ b/src/org/openlcb/cdi/swing/CdiPanel.java @@ -74,6 +74,7 @@ import javax.swing.ComboBoxModel; import javax.swing.InputVerifier; import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFileChooser; @@ -2644,11 +2645,59 @@ String getDisplayText() { } + // represents a checkbox + private class CheckboxPane extends JPanel { + + final int SELECTED_CHOICE = 1; + final int UNSELECTED_CHOICE = 0; + + CdiRep.Map map; + JCheckBox checkbox; + + CheckboxPane(CdiRep.Map map, ActionListener action) { + this.map = map; + + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + // create the pane and fill with labelled checkbox + String label = map.getValues().get(SELECTED_CHOICE); + checkbox = new JCheckBox(label); + add(checkbox); + checkbox.addActionListener(action); + } + + long getCurrentValue() { + return Long.parseLong(getCurrentValueString()); + } + + // value is a numeric string + void setCurrentValue(String value) { + if (value.equals(map.getValues().get(SELECTED_CHOICE))) { + checkbox.setSelected(true); + } else { + checkbox.setSelected(false); + } + } + + String getCurrentValueString() { + if (checkbox.isSelected()) { + return map.getKeys().get(SELECTED_CHOICE); + } else { + return map.getKeys().get(UNSELECTED_CHOICE); + } + } + + String getDisplayText() { + return getCurrentValueString(); + } + + } + private class IntPane extends EntryPane { JTextField textField = null; JComboBox box = null; SliderWithView sliderView = null; RadioButtonPane radiobuttons = null; + CheckboxPane checkbox = null; CdiRep.Map map = null; private final ConfigRepresentation.IntegerEntry entry; boolean suppressExternal = false; // used to suppress slider output when changed from read @@ -2673,6 +2722,15 @@ public void actionPerformed(ActionEvent actionEvent) { }; radiobuttons = new RadioButtonPane(map, action); textComponent = radiobuttons; + } else if (entry.rep.isCheckboxHint()) { + ActionListener action = new ActionListener() { + @Override + public void actionPerformed(ActionEvent actionEvent) { + updateColor(); + } + }; + checkbox = new CheckboxPane(map, action); + textComponent = checkbox; } else { box = new JComboBox(map.getValues().toArray(new String[]{""})) { public java.awt.Dimension getMaximumSize() { @@ -2776,6 +2834,8 @@ protected void writeDisplayTextToNode() { value = sliderView.slider.getValue(); } else if (radiobuttons != null) { value = radiobuttons.getCurrentValue(); + } else if (checkbox != null) { + value = checkbox.getCurrentValue(); } else { // have to get key from stored map value String entry = (String) box.getSelectedItem(); @@ -2834,6 +2894,8 @@ protected String getDisplayText() { return ""+sliderView.slider.getValue(); } else if (radiobuttons != null) { return radiobuttons.getDisplayText(); + } else if (checkbox != null) { + return checkbox.getDisplayText(); } String s = (box == null) ? (String) textField.getText() : (String) box.getSelectedItem(); @@ -2853,6 +2915,8 @@ protected String getCurrentValue() { return ""+sliderView.slider.getValue(); } else if (radiobuttons != null) { return radiobuttons.getCurrentValueString(); + } else if (checkbox != null) { + return checkbox.getCurrentValueString(); } String s; From a6fa883a704bab7ed21eb508d80c249c73347815 Mon Sep 17 00:00:00 2001 From: Bob Jacobsen Date: Mon, 31 Aug 2026 09:36:31 -0400 Subject: [PATCH 2/5] make test more reliable --- test/org/openlcb/cdi/swing/CdiPanelDemo.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/org/openlcb/cdi/swing/CdiPanelDemo.java b/test/org/openlcb/cdi/swing/CdiPanelDemo.java index 4310e09e..e34c6954 100644 --- a/test/org/openlcb/cdi/swing/CdiPanelDemo.java +++ b/test/org/openlcb/cdi/swing/CdiPanelDemo.java @@ -34,8 +34,10 @@ public void displayFile(String fileName) { // find file & load file fci.setDialogTitle("Find desired CDI file"); fci.rescanCurrentDirectory(); - - int retVal = fci.showOpenDialog(null); + + f.pack(); + f.setVisible(true); + int retVal = fci.showOpenDialog(f); // handle selection or cancel if (retVal != JFileChooser.APPROVE_OPTION) { // Run the script from it's filename From aa40ab5dc325a21c5633c63e3e11521b3c97779c Mon Sep 17 00:00:00 2001 From: Bob Jacobsen Date: Mon, 31 Aug 2026 09:36:45 -0400 Subject: [PATCH 3/5] more work on chekbox --- src/org/openlcb/cdi/swing/CdiPanel.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/org/openlcb/cdi/swing/CdiPanel.java b/src/org/openlcb/cdi/swing/CdiPanel.java index d4ce55c2..ffde25e1 100644 --- a/src/org/openlcb/cdi/swing/CdiPanel.java +++ b/src/org/openlcb/cdi/swing/CdiPanel.java @@ -2651,7 +2651,7 @@ private class CheckboxPane extends JPanel { final int SELECTED_CHOICE = 1; final int UNSELECTED_CHOICE = 0; - CdiRep.Map map; + CdiRep.Map map; // keys are numeric contents, values are string names JCheckBox checkbox; CheckboxPane(CdiRep.Map map, ActionListener action) { @@ -2669,7 +2669,7 @@ long getCurrentValue() { return Long.parseLong(getCurrentValueString()); } - // value is a numeric string + // value is a name string void setCurrentValue(String value) { if (value.equals(map.getValues().get(SELECTED_CHOICE))) { checkbox.setSelected(true); @@ -2678,7 +2678,7 @@ void setCurrentValue(String value) { } } - String getCurrentValueString() { + String getCurrentValueString() { // returns the numeric value of current selection as a string if (checkbox.isSelected()) { return map.getKeys().get(SELECTED_CHOICE); } else { @@ -2687,7 +2687,11 @@ String getCurrentValueString() { } String getDisplayText() { - return getCurrentValueString(); + if (checkbox.isSelected()) { + return map.getValues().get(SELECTED_CHOICE); + } else { + return map.getValues().get(UNSELECTED_CHOICE); + } } } From f3c18e157e8ab307134aa5d32620389e8127dc03 Mon Sep 17 00:00:00 2001 From: Bob Jacobsen Date: Tue, 1 Sep 2026 07:11:54 -0400 Subject: [PATCH 4/5] better demo read/write of memory --- .../openlcb/cdi/impl/DemoReadWriteAccess.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/org/openlcb/cdi/impl/DemoReadWriteAccess.java b/src/org/openlcb/cdi/impl/DemoReadWriteAccess.java index 7239baf3..507d36b9 100644 --- a/src/org/openlcb/cdi/impl/DemoReadWriteAccess.java +++ b/src/org/openlcb/cdi/impl/DemoReadWriteAccess.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; import org.jdom2.Document; @@ -20,20 +21,32 @@ public class DemoReadWriteAccess extends ReadWriteAccess { private final static Logger logger = Logger.getLogger(DemoReadWriteAccess.class.getName()); + // store written values for later reading + private long getAddressHash(long address, int space, int length) { + return address+1000000*space+1000000000*length; + } + + private final static HashMap contents = new HashMap<>(); + @Override public void doWrite(long address, int space, byte[] data, MemoryConfigurationService.McsWriteHandler handler) { - logger.log(Level.INFO, "Wrote {0} bytes", data.length); - logger.log(Level.INFO, "write {0} {1}: {2}", new Object[]{address, space, org.openlcb.Utilities.toHexDotsString(data)}); + logger.log(Level.INFO, "write {0} {1} with {2} bytes: {3}", new Object[]{address, space, data.length, org.openlcb.Utilities.toHexDotsString(data)}); + + contents.put(getAddressHash(address, space, data.length), data); } @Override public void doRead(long address, int space, int length, MemoryConfigurationService.McsReadHandler handler) { - byte[] resp = new byte[length]; - for (int i = 0; i < resp.length; ++i) { - resp[i] = (byte)(((address + i) % 91) + 32); + byte[] resp = contents.get(getAddressHash(address, space, length)); + if (resp == null) { + // no prior write, load with ascii letters + resp = new byte[length]; + for (int i = 0; i < resp.length; ++i) { + resp[i] = (byte)(((address + i) % 91) + 32); + } } handler.handleReadData(null, space, address, resp); - logger.log(Level.INFO, "read {0} {1}", new Object[]{address, space}); + logger.log(Level.INFO, "read {0} {1} with {2} bytes: {3}", new Object[]{address, space, resp.length, org.openlcb.Utilities.toHexDotsString(resp)}); } static public ConfigRepresentation demoRepFromSample(Element root) { From aedeef0d8e71430f48c2fad36a4829bd75f48827 Mon Sep 17 00:00:00 2001 From: Bob Jacobsen Date: Tue, 1 Sep 2026 07:12:35 -0400 Subject: [PATCH 5/5] fix checkbox readback oversight --- src/org/openlcb/cdi/swing/CdiPanel.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/org/openlcb/cdi/swing/CdiPanel.java b/src/org/openlcb/cdi/swing/CdiPanel.java index ffde25e1..48593582 100644 --- a/src/org/openlcb/cdi/swing/CdiPanel.java +++ b/src/org/openlcb/cdi/swing/CdiPanel.java @@ -2861,6 +2861,8 @@ protected void updateDisplayText(@NonNull String value) { sliderView.slider.setValue(Integer.parseInt(value)); } else if (radiobuttons != null) { radiobuttons.setCurrentValue(value); + } else if (checkbox != null) { + checkbox.setCurrentValue(value); } if (box != null) { // check to see if item exists