From 76aab0b31c1dcaad26592e876f94da067767989c Mon Sep 17 00:00:00 2001 From: hneemann Date: Wed, 6 Apr 2016 18:57:33 +0200 Subject: [PATCH] improved measurement ordering --- src/main/dig/Ampel_Einfach.dig | 42 +- src/main/dig/MS-JK.dig | 374 +++++++++--------- .../java/de/neemann/digital/core/Model.java | 15 + .../digital/draw/elements/Circuit.java | 19 + .../java/de/neemann/digital/gui/Main.java | 38 +- .../gui/components/CircuitComponent.java | 59 +-- .../gui/components/ElementOrderer.java | 31 +- .../digital/gui/components/OrderMerger.java | 39 ++ .../digital/gui/components/ProbeDialog.java | 12 +- .../gui/components/data/DataSetDialog.java | 20 +- .../components/data/MeasurementFilter.java | 15 - .../gui/components/OrderMergerTest.java | 31 ++ 12 files changed, 410 insertions(+), 285 deletions(-) create mode 100644 src/main/java/de/neemann/digital/gui/components/OrderMerger.java delete mode 100644 src/main/java/de/neemann/digital/gui/components/data/MeasurementFilter.java create mode 100644 src/test/java/de/neemann/digital/gui/components/OrderMergerTest.java diff --git a/src/main/dig/Ampel_Einfach.dig b/src/main/dig/Ampel_Einfach.dig index 287e379a4..2de9f4cd7 100644 --- a/src/main/dig/Ampel_Einfach.dig +++ b/src/main/dig/Ampel_Einfach.dig @@ -5,6 +5,10 @@ JK_FF + + valueIsProbe + true + Label z_0 @@ -16,6 +20,10 @@ JK_FF + + valueIsProbe + true + Label z_1 @@ -36,6 +44,21 @@ 0 + + Clock + + + Label + Takt + + + Frequency + 10 + + + + 0 + LED @@ -87,17 +110,6 @@ 0 - - Clock - - - Label - Takt - - - - 0 - @@ -201,4 +213,12 @@ + + Takt + z_0 + z_1 + Rot + Gelb + GrĂ¼n + \ No newline at end of file diff --git a/src/main/dig/MS-JK.dig b/src/main/dig/MS-JK.dig index cca6d0baa..6d09b1c86 100644 --- a/src/main/dig/MS-JK.dig +++ b/src/main/dig/MS-JK.dig @@ -1,5 +1,6 @@ + 1 And @@ -9,7 +10,7 @@ 3 - + 0 @@ -20,13 +21,13 @@ 3 - + 0 Not - + 0 @@ -41,7 +42,7 @@ 1 - + 0 @@ -52,43 +53,43 @@ C - + 0 NOr - + 0 NOr - + 0 And - + 0 And - + 0 NOr - + 0 NOr - + 0 @@ -99,7 +100,7 @@ Q - + 0 @@ -110,7 +111,7 @@ ~Q - + 0 @@ -125,214 +126,221 @@ 1 - + 0 - - + + - - + + - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + C + J + K + Q + ~Q + \ No newline at end of file diff --git a/src/main/java/de/neemann/digital/core/Model.java b/src/main/java/de/neemann/digital/core/Model.java index f99a47bbc..fc4f924c6 100644 --- a/src/main/java/de/neemann/digital/core/Model.java +++ b/src/main/java/de/neemann/digital/core/Model.java @@ -361,6 +361,16 @@ public class Model { return signals; } + /** + * @return a copy of all registered Signals + */ + public ArrayList getSignalsCopy() { + ArrayList n = new ArrayList<>(signals.size()); + n.addAll(signals); + return n; + } + + /** * registers a ROM to the model * @param rom the ROM @@ -419,6 +429,11 @@ public class Model { public int compareTo(Signal o) { return name.compareTo(o.name); } + + @Override + public String toString() { + return name; + } } } diff --git a/src/main/java/de/neemann/digital/draw/elements/Circuit.java b/src/main/java/de/neemann/digital/draw/elements/Circuit.java index db6fa67df..76013e2c4 100644 --- a/src/main/java/de/neemann/digital/draw/elements/Circuit.java +++ b/src/main/java/de/neemann/digital/draw/elements/Circuit.java @@ -23,6 +23,7 @@ import de.neemann.digital.lang.Lang; import java.awt.*; import java.io.*; import java.util.*; +import java.util.List; /** * @author hneemann @@ -39,6 +40,7 @@ public class Circuit { private ElementAttributes attributes; private final ArrayList visualElements; private ArrayList wires; + private List measurementOrdering; private transient boolean dotsPresent = false; private transient boolean modified = false; @@ -430,4 +432,21 @@ public class Circuit { return pinList.toArray(new ObservableValue[pinList.size()]); } + /** + * Gets the ordering of values used to show measurements + * + * @return list of names + */ + public List getMeasurementOrdering() { + return measurementOrdering; + } + + /** + * Sets the ordering of values used to show measurements + * + * @param measurementOrdering + */ + public void setMeasurementOrdering(List measurementOrdering) { + this.measurementOrdering = measurementOrdering; + } } diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index 9a72d2d90..ee8d5da6c 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -13,9 +13,9 @@ import de.neemann.digital.draw.model.RealTimeClock; import de.neemann.digital.draw.shapes.ShapeFactory; import de.neemann.digital.gui.components.CircuitComponent; import de.neemann.digital.gui.components.ElementOrderer; +import de.neemann.digital.gui.components.OrderMerger; import de.neemann.digital.gui.components.ProbeDialog; import de.neemann.digital.gui.components.data.DataSetDialog; -import de.neemann.digital.gui.components.data.MeasurementFilter; import de.neemann.digital.gui.components.listing.ROMListingDialog; import de.neemann.digital.gui.state.State; import de.neemann.digital.gui.state.StateManager; @@ -31,6 +31,8 @@ import java.awt.event.WindowEvent; import java.io.Closeable; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.prefs.Preferences; @@ -45,7 +47,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { private static final Icon ICON_STEP = IconCreator.create("step.gif"); private static final Icon ICON_ELEMENT = IconCreator.create("element.gif"); private static final Icon ICON_SELECT = IconCreator.create("Select24.gif"); - // private static final Icon ICON_WIRE = IconCreator.create("wire.gif"); private static final Icon ICON_NEW = IconCreator.create("New24.gif"); private static final Icon ICON_OPEN = IconCreator.create("Open24.gif"); private static final Icon ICON_OPEN_WIN = IconCreator.create("OpenNew24.gif"); @@ -73,7 +74,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { private ScheduledThreadPoolExecutor timerExecuter = new ScheduledThreadPoolExecutor(1); private State elementState; - //private State wireState; private State selectState; private State runModelState; private State runModelMicroState; @@ -203,7 +203,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { JMenu edit = new JMenu(Lang.get("menu_edit")); bar.add(edit); - //ToolTipAction wireStateAction = wireState.createToolTipAction(Lang.get("menu_wire"), ICON_WIRE).setToolTip(Lang.get("menu_wire_tt")); ToolTipAction elementStateAction = elementState.createToolTipAction(Lang.get("menu_element"), ICON_ELEMENT).setToolTip(Lang.get("menu_element_tt")); ToolTipAction selectStateAction = selectState.createToolTipAction(Lang.get("menu_select"), ICON_SELECT).setToolTip(Lang.get("menu_select_tt")); @@ -226,8 +225,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { ToolTipAction orderMeasurements = new ToolTipAction(Lang.get("menu_orderMeasurements")) { @Override public void actionPerformed(ActionEvent e) { - ElementOrder o = new ElementOrder(circuitComponent.getCircuit(), new MeasurementFilter()); - new ElementOrderer<>(Main.this, Lang.get("menu_orderMeasurements"), o).setVisible(true); + orderMeasurements(); } }.setToolTip(Lang.get("menu_orderMeasurements_tt")); @@ -241,7 +239,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { edit.add(elementStateAction.createJMenuItem()); - //edit.add(wireStateAction.createJMenuItem()); edit.add(selectStateAction.createJMenuItem()); edit.add(orderInputs.createJMenuItem()); edit.add(orderOutputs.createJMenuItem()); @@ -316,7 +313,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { run.add(runModelMicroAction.createJMenuItem()); run.add(doStep.createJMenuItem()); run.add(runToBreak.createJMenuItem()); - //run.add(speedTest.createJMenuItem()); run.add(showProbes); run.add(showGraph); run.add(showListing); @@ -329,7 +325,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { toolBar.add(save.createJButtonNoText()); toolBar.addSeparator(); toolBar.add(elementState.setIndicator(elementStateAction.createJButtonNoText())); - //toolBar.add(wireState.setIndicator(wireStateAction.createJButtonNoText())); toolBar.add(selectState.setIndicator(selectStateAction.createJButtonNoText())); toolBar.add(circuitComponent.getDeleteAction().createJButtonNoText()); toolBar.addSeparator(); @@ -353,9 +348,24 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { setLocationRelativeTo(parent); } + private void orderMeasurements() { + try { + Model m = new ModelDescription(circuitComponent.getCircuit(), library).createModel(); + circuitComponent.getCircuit().clearState(); + ArrayList names = new ArrayList<>(); + for (Model.Signal s : m.getSignals()) + names.add(s.getName()); + new OrderMerger(circuitComponent.getCircuit().getMeasurementOrdering()).order(names); + ElementOrderer.ListOrder o = new ElementOrderer.ListOrder<>(names); + new ElementOrderer<>(Main.this, Lang.get("menu_orderMeasurements"), o).setVisible(true); + circuitComponent.getCircuit().setMeasurementOrdering(names); + } catch (Exception e1) { + showSwingError(Lang.get("msg_errorCreatingModel"), e1); + } + } + private void setupStates() { elementState = stateManager.register(new ModeState(CircuitComponent.Mode.part)); - //wireState = stateManager.register(new ModeState(CircuitComponent.Mode.wire)); selectState = stateManager.register(new ModeState(CircuitComponent.Mode.select)); runModelState = stateManager.register(new State() { @Override @@ -425,11 +435,13 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave { runToBreak.setEnabled(!runClock && model.isFastRunModel()); - if (showProbes.isSelected()) - new ProbeDialog(this, model, updateEvent).setVisible(true); + List ordering = circuitComponent.getCircuit().getMeasurementOrdering(); + if (showProbes.isSelected()) { + new ProbeDialog(this, model, updateEvent, ordering).setVisible(true); + } if (showGraph.isSelected()) - new DataSetDialog(this, model, updateEvent).setVisible(true); + new DataSetDialog(this, model, updateEvent, ordering).setVisible(true); if (showListing.isSelected()) for (ROM rom : model.getRoms()) diff --git a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java index 9b021f6ba..f81e7769a 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -39,9 +39,9 @@ import java.util.HashSet; * @author hneemann */ public class CircuitComponent extends JComponent { - private static final Icon iconDelete = IconCreator.create("Delete24.gif"); + private static final Icon ICON_DELETE = IconCreator.create("Delete24.gif"); + private static final String DEL_ACTION = "myDelAction"; - private static final String delAction = "myDelAction"; private final ElementLibrary library; private final ShapeFactory shapeFactory; private final HashSet highLighted; @@ -59,8 +59,8 @@ public class CircuitComponent extends JComponent { setCircuit(aCircuit); KeyStroke delKey = KeyStroke.getKeyStroke("DELETE"); - getInputMap().put(delKey, delAction); - getActionMap().put(delAction, deleteAction); + getInputMap().put(delKey, DEL_ACTION); + getActionMap().put(DEL_ACTION, deleteAction); setFocusable(true); @@ -92,10 +92,6 @@ public class CircuitComponent extends JComponent { listener = new PartMouseListener(); setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); break; - case wire: - listener = new WireMouseListener(); - setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); - break; case select: listener = new SelectMouseListener(); setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); @@ -202,7 +198,7 @@ public class CircuitComponent extends JComponent { setModeAndReset(Mode.part); } - public enum Mode {part, wire, running, select} + public enum Mode {part, running, select} private abstract class Mouse extends MouseAdapter implements MouseMotionListener { private Vector pos; @@ -225,49 +221,6 @@ public class CircuitComponent extends JComponent { } } - private class WireMouseListener extends Mouse { - - private Wire wire; - - @Override - public void mouseClicked(MouseEvent e) { - if (e.getButton() == MouseEvent.BUTTON1) { - if (wire != null) { - circuit.add(wire); - Vector startPos = raster(getPosVector(e)); - if (circuit.isPinPos(startPos)) - wire = null; - else - wire = new Wire(startPos, startPos); - } else { - Vector startPos = raster(getPosVector(e)); - wire = new Wire(startPos, startPos); - } - repaint(); - } else { - if (wire != null) { - wire = null; - repaint(); - } else - editAttributes(e); - } - } - - @Override - public void mouseMoved(MouseEvent e) { - if (wire != null) { - wire.setP2(raster(getPosVector(e))); - repaint(); - } - } - - @Override - public void drawTo(Graphic gr) { - if (wire != null) - wire.drawTo(gr, false); - } - } - private class PartMouseListener extends Mouse { private VisualElement partToInsert; @@ -522,7 +475,7 @@ public class CircuitComponent extends JComponent { private class DelAction extends ToolTipAction { DelAction() { - super(Lang.get("menu_delete"), iconDelete); + super(Lang.get("menu_delete"), ICON_DELETE); setToolTip(Lang.get("menu_delete_tt")); } diff --git a/src/main/java/de/neemann/digital/gui/components/ElementOrderer.java b/src/main/java/de/neemann/digital/gui/components/ElementOrderer.java index 15887ea7f..155c7a7ab 100644 --- a/src/main/java/de/neemann/digital/gui/components/ElementOrderer.java +++ b/src/main/java/de/neemann/digital/gui/components/ElementOrderer.java @@ -62,10 +62,35 @@ public class ElementOrderer extends JDialog { } - private static class ArrayOrderInterface implements OrderInterface { + public static class ListOrder implements OrderInterface { + private java.util.List list; + + public ListOrder(java.util.List list) { + this.list = list; + } + + @Override + public int size() { + return list.size(); + } + + @Override + public T get(int index) { + return list.get(index); + } + + @Override + public void swap(int i, int j) { + T z = list.get(i); + list.set(i, list.get(j)); + list.set(j, z); + } + } + + private static class ArrayOrder implements OrderInterface { private final T[] data; - public ArrayOrderInterface(T[] data) { + public ArrayOrder(T[] data) { this.data = data; } @@ -129,6 +154,6 @@ public class ElementOrderer extends JDialog { } public static void main(String[] args) { - new ElementOrderer<>(null, "Test", new ArrayOrderInterface<>(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9})).setVisible(true); + new ElementOrderer<>(null, "Test", new ArrayOrder<>(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9})).setVisible(true); } } diff --git a/src/main/java/de/neemann/digital/gui/components/OrderMerger.java b/src/main/java/de/neemann/digital/gui/components/OrderMerger.java new file mode 100644 index 000000000..d8e97196b --- /dev/null +++ b/src/main/java/de/neemann/digital/gui/components/OrderMerger.java @@ -0,0 +1,39 @@ +package de.neemann.digital.gui.components; + +import java.util.List; + +/** + * @author hneemann + */ +public class OrderMerger { + private final List oldOrdering; + + public OrderMerger(List oldOrdering) { + this.oldOrdering = oldOrdering; + } + + public > void order(L list) { + if (oldOrdering == null || oldOrdering.size() == 0) + return; + + int n = 0; + for (O o : oldOrdering) { + int found = -1; + for (int i = n; i < list.size(); i++) { + if (equals(list.get(i), o)) { + found = i; + break; + } + } + if (found >= 0) { + N r = list.remove(found); + list.add(n, r); + n++; + } + } + } + + public boolean equals(N a, O b) { + return a.equals(b); + } +} diff --git a/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java b/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java index 8443c7f28..b55b0eecc 100644 --- a/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/ProbeDialog.java @@ -13,6 +13,7 @@ import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; +import java.util.List; /** * @author hneemann @@ -22,12 +23,19 @@ public class ProbeDialog extends JDialog implements ModelStateObserver { private final ModelEvent.Event type; private final SignalTableModel tableModel; - public ProbeDialog(Frame owner, Model model, ModelEvent.Event type) { + public ProbeDialog(Frame owner, Model model, ModelEvent.Event type, List ordering) { super(owner, Lang.get("win_measures"), false); setDefaultCloseOperation(DISPOSE_ON_CLOSE); this.type = type; - ArrayList signals = model.getSignals(); + ArrayList signals = model.getSignalsCopy(); + new OrderMerger(ordering) { + @Override + public boolean equals(Model.Signal a, String b) { + return a.getName().equals(b); + } + }.order(signals); + tableModel = new SignalTableModel(signals); JTable list = new JTable(tableModel); getContentPane().add(new JScrollPane(list), BorderLayout.CENTER); diff --git a/src/main/java/de/neemann/digital/gui/components/data/DataSetDialog.java b/src/main/java/de/neemann/digital/gui/components/data/DataSetDialog.java index b685cfaef..7a13e1760 100644 --- a/src/main/java/de/neemann/digital/gui/components/data/DataSetDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/data/DataSetDialog.java @@ -3,6 +3,7 @@ package de.neemann.digital.gui.components.data; import de.neemann.digital.core.Model; import de.neemann.digital.core.ModelEvent; import de.neemann.digital.core.ModelStateObserver; +import de.neemann.digital.gui.components.OrderMerger; import de.neemann.digital.lang.Lang; import javax.swing.*; @@ -10,6 +11,7 @@ import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; +import java.util.List; /** * The Dialog which shows the data to plot. @@ -27,17 +29,25 @@ public class DataSetDialog extends JDialog implements ModelStateObserver { /** * Creates a new instance * - * @param owner the parent frame - * @param model the model used to collect the data - * @param type the event type which triggers a new DataSample + * @param owner the parent frame + * @param model the model used to collect the data + * @param type the event type which triggers a new DataSample + * @param ordering */ - public DataSetDialog(Frame owner, Model model, ModelEvent.Event type) { + public DataSetDialog(Frame owner, Model model, ModelEvent.Event type, List ordering) { super(owner, Lang.get("win_measures"), false); setDefaultCloseOperation(DISPOSE_ON_CLOSE); setAlwaysOnTop(true); this.type = type; - signals = model.getSignals(); + signals = model.getSignalsCopy(); + new OrderMerger(ordering) { + @Override + public boolean equals(Model.Signal a, String b) { + return a.getName().equals(b); + } + }.order(signals); + dataSet = new DataSet(signals); dsc = new DataSetComponent(dataSet); diff --git a/src/main/java/de/neemann/digital/gui/components/data/MeasurementFilter.java b/src/main/java/de/neemann/digital/gui/components/data/MeasurementFilter.java deleted file mode 100644 index 0b2ca8d68..000000000 --- a/src/main/java/de/neemann/digital/gui/components/data/MeasurementFilter.java +++ /dev/null @@ -1,15 +0,0 @@ -package de.neemann.digital.gui.components.data; - -import de.neemann.digital.draw.elements.ElementOrder; -import de.neemann.digital.draw.elements.VisualElement; - -/** - * @author hneemann - */ -public class MeasurementFilter implements ElementOrder.ElementMatcher { - @Override - public boolean matches(VisualElement element) { - String name = element.getElementName(); - return name.equals("In") || name.equals("Out") || name.equals("LED") || name.equals("Clock") || name.equals("Probe"); - } -} diff --git a/src/test/java/de/neemann/digital/gui/components/OrderMergerTest.java b/src/test/java/de/neemann/digital/gui/components/OrderMergerTest.java new file mode 100644 index 000000000..df967db91 --- /dev/null +++ b/src/test/java/de/neemann/digital/gui/components/OrderMergerTest.java @@ -0,0 +1,31 @@ +package de.neemann.digital.gui.components; + +import junit.framework.TestCase; + +import java.util.ArrayList; + +/** + * @author hneemann + */ +public class OrderMergerTest extends TestCase { + public void testOrder() throws Exception { + ArrayList oldList = new ArrayList<>(); + oldList.add("b"); + oldList.add("d"); + + ArrayList newList = new ArrayList<>(); + newList.add("a"); + newList.add("b"); + newList.add("c"); + newList.add("d"); + + new OrderMerger(oldList).order(newList); + + assertEquals(4, newList.size()); + assertEquals("b", newList.get(0)); + assertEquals("d", newList.get(1)); + assertEquals("a", newList.get(2)); + assertEquals("c", newList.get(3)); + } + +} \ No newline at end of file