Corrected incorrect correction of bit order
[Mograsim.git] / net.mograsim.logic.ui / src / net / mograsim / logic / ui / LogicUICanvas.java
index 3a08097..8e01a16 100644 (file)
@@ -1,19 +1,32 @@
 package net.mograsim.logic.ui;
 
-import java.util.function.Consumer;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
 
-import net.haspamelodica.swt.helper.gcs.GeneralGC;
 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
 import net.haspamelodica.swt.helper.zoomablecanvas.ZoomableCanvas;
+import net.mograsim.logic.core.types.Bit;
+import net.mograsim.logic.core.types.BitVector;
 import net.mograsim.logic.ui.model.ViewModel;
 import net.mograsim.logic.ui.model.components.GUIComponent;
-import net.mograsim.logic.ui.model.wires.GUIWire;
-import net.mograsim.logic.ui.model.wires.Pin;
+import net.mograsim.logic.ui.model.components.SubmodelComponent;
+import net.mograsim.logic.ui.model.components.SubmodelInterface;
+import net.mograsim.logic.ui.model.wires.WireCrossPoint;
+import net.mograsim.preferences.Preferences;
 
 /**
  * Simulation visualizer canvas.
@@ -22,7 +35,7 @@ import net.mograsim.logic.ui.model.wires.Pin;
  */
 public class LogicUICanvas extends ZoomableCanvas
 {
-       private static final boolean DRAW_PINS = false;
+       private static final boolean OPEN_DEBUG_SETHIGHLEVELSTATE_SHELL = false;
 
        private final ViewModel model;
 
@@ -32,70 +45,20 @@ public class LogicUICanvas extends ZoomableCanvas
 
                this.model = model;
 
-               Consumer<Object> redrawConsumer = o -> redrawThreadsafe();
-               Consumer<Pin> pinAddedListener = p ->
-               {
-                       p.addPinMovedListener(redrawConsumer);
-                       redrawThreadsafe();
-               };
-               Consumer<Pin> pinRemovedListener = p ->
-               {
-                       p.removePinMovedListener(redrawConsumer);
-                       redrawThreadsafe();
-               };
-               Consumer<? super GUIComponent> componentAddedListener = c ->
-               {
-                       c.addComponentLookChangedListener(redrawConsumer);
-                       c.addComponentMovedListener(redrawConsumer);
-                       c.addPinAddedListener(pinAddedListener);
-                       c.addPinRemovedListener(pinRemovedListener);
-                       redrawThreadsafe();
-               };
-               model.addComponentAddedListener(componentAddedListener);
-               model.getComponents().forEach(componentAddedListener);
-               model.addComponentRemovedListener(c ->
-               {
-                       c.removeComponentLookChangedListener(redrawConsumer);
-                       c.removeComponentMovedListener(redrawConsumer);
-                       c.removePinAddedListener(pinAddedListener);
-                       c.removePinRemovedListener(pinRemovedListener);
-                       redrawThreadsafe();
-               });
-               Consumer<? super GUIWire> wireAddedListener = w ->
-               {
-                       w.addWireLookChangedListener(redrawConsumer);
-                       redrawThreadsafe();
-               };
-               model.addWireAddedListener(wireAddedListener);
-               model.getWires().forEach(wireAddedListener);
-               model.addWireRemovedListener(w ->
-               {
-                       w.removeWireLookChangedListener(redrawConsumer);
-                       redrawThreadsafe();
-               });
-
+               LogicUIRenderer renderer = new LogicUIRenderer(model);
                addZoomedRenderer(gc ->
                {
-                       gc.setLineWidth(.5);
-                       model.getWires().forEach(w -> w.render(gc));
-                       Rectangle visibleRegion = new Rectangle(offX, offY, gW / zoom, gH / zoom);
-                       model.getComponents().forEach(c -> drawComponent(gc, c, visibleRegion));
+                       Color background = Preferences.current().getColor("net.mograsim.logic.ui.color.background");
+                       if (background != null)
+                               setBackground(background);// this.setBackground, not gc.setBackground to have the background fill the canvas
+                       renderer.render(gc, new Rectangle(-offX / zoom, -offY / zoom, gW / zoom, gH / zoom));
                });
+               model.addRedrawListener(this::redrawThreadsafe);
+
                addListener(SWT.MouseDown, this::mouseDown);
-       }
 
-       private void drawComponent(GeneralGC gc, GUIComponent component, Rectangle visibleRegion)
-       {
-               component.render(gc, visibleRegion);
-               if (DRAW_PINS)
-               {
-                       gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_DARK_CYAN));
-                       for (Pin p : component.getPins())
-                       {
-                               Point pos = p.getPos();
-                               gc.fillOval(pos.x - 1, pos.y - 1, 2, 2);
-                       }
-               }
+               if (OPEN_DEBUG_SETHIGHLEVELSTATE_SHELL)
+                       openDebugSetHighLevelStateShell(model);
        }
 
        private void mouseDown(Event e)
@@ -111,4 +74,103 @@ public class LogicUICanvas extends ZoomableCanvas
                                }
                }
        }
+
+       private void openDebugSetHighLevelStateShell(ViewModel model)
+       {
+               Shell debugShell = new Shell();
+               debugShell.setLayout(new GridLayout(2, false));
+               new Label(debugShell, SWT.NONE).setText("Target component: ");
+               Combo componentSelector = new Combo(debugShell, SWT.DROP_DOWN | SWT.READ_ONLY);
+               componentSelector.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               List<GUIComponent> componentsByItemIndex = new ArrayList<>();
+               model.addComponentAddedListener(c -> recalculateComponentSelector(componentsByItemIndex, componentSelector, model));
+               model.addComponentRemovedListener(c -> recalculateComponentSelector(componentsByItemIndex, componentSelector, model));
+               recalculateComponentSelector(componentsByItemIndex, componentSelector, model);
+               new Label(debugShell, SWT.NONE).setText("Target state ID: ");
+               Text stateIDText = new Text(debugShell, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
+               stateIDText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               new Label(debugShell, SWT.NONE).setText("Value type: ");
+               Composite radioGroup = new Composite(debugShell, SWT.NONE);
+               radioGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               GridLayout radioGroupLayout = new GridLayout(2, false);
+               radioGroupLayout.marginHeight = 0;
+               radioGroupLayout.marginWidth = 0;
+               radioGroup.setLayout(radioGroupLayout);
+               Button radioBit = new Button(radioGroup, SWT.RADIO);
+               radioBit.setText("Single bit");
+               Button radioBitVector = new Button(radioGroup, SWT.RADIO);
+               radioBitVector.setText("Bitvector");
+               new Label(debugShell, SWT.NONE).setText("Value string representation: \n(Bit vectors: MSBit...LSBit)");
+               Text valueText = new Text(debugShell, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
+               valueText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               Button send = new Button(debugShell, SWT.PUSH);
+               send.setText("Send!");
+               Button get = new Button(debugShell, SWT.PUSH);
+               get.setText("Get!");
+               Text output = new Text(debugShell, SWT.READ_ONLY);
+               output.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
+               Listener sendAction = e ->
+               {
+                       try
+                       {
+                               if (componentSelector.getSelectionIndex() >= componentsByItemIndex.size())
+                                       throw new RuntimeException("No valid component selected");
+                               GUIComponent target = componentsByItemIndex.get(componentSelector.getSelectionIndex());
+                               String valueString = valueText.getText();
+                               Object value;
+                               if (radioBit.getSelection())
+                                       value = Bit.parse(valueString);
+                               else if (radioBitVector.getSelection())
+                                       value = BitVector.parse(new StringBuilder(valueString).reverse().toString());
+                               else
+                                       throw new RuntimeException("No value type selected");
+                               target.setHighLevelState(stateIDText.getText(), value);
+                               output.setText("Success!");
+                       }
+                       catch (Exception x)
+                       {
+                               output.setText(x.getClass().getSimpleName() + (x.getMessage() == null ? "" : ": " + x.getMessage()));
+                       }
+               };
+               Listener getAction = e ->
+               {
+                       try
+                       {
+                               if (componentSelector.getSelectionIndex() >= componentsByItemIndex.size())
+                                       throw new RuntimeException("No valid component selected");
+                               output.setText("Success! Value: \r\n"
+                                               + componentsByItemIndex.get(componentSelector.getSelectionIndex()).getHighLevelState(stateIDText.getText()));
+                       }
+                       catch (Exception x)
+                       {
+                               output.setText(x.getClass().getSimpleName() + (x.getMessage() == null ? "" : ": " + x.getMessage()));
+                       }
+               };
+               send.addListener(SWT.Selection, sendAction);
+               valueText.addListener(SWT.DefaultSelection, sendAction);
+               get.addListener(SWT.Selection, getAction);
+               stateIDText.addListener(SWT.DefaultSelection, getAction);
+               debugShell.open();
+       }
+
+       private void recalculateComponentSelector(List<GUIComponent> componentsByItemIndex, Combo componentSelector, ViewModel model)
+       {
+               componentsByItemIndex.clear();
+               componentSelector.setItems();
+               addComponentSelectorItems(componentsByItemIndex, "", componentSelector, model);
+       }
+
+       private void addComponentSelectorItems(List<GUIComponent> componentsByItemIndex, String base, Combo componentSelector, ViewModel model)
+       {
+               for (GUIComponent c : model.getComponents())
+                       if (!(c instanceof WireCrossPoint || c instanceof SubmodelInterface))
+                       {
+                               String item = base + c.getIdentifier();
+                               componentsByItemIndex.add(c);
+                               componentSelector.add(item);
+                               if (c instanceof SubmodelComponent)
+                                       addComponentSelectorItems(componentsByItemIndex, item + " -> ", componentSelector, ((SubmodelComponent) c).submodel);
+                       }
+       }
+
 }
\ No newline at end of file