LogicUICanvas now uses the new listener system; changes in clicked()
authorDaniel Kirschten <daniel.kirschten@gmx.de>
Tue, 28 May 2019 09:44:30 +0000 (11:44 +0200)
committerDaniel Kirschten <daniel.kirschten@gmx.de>
Tue, 28 May 2019 09:48:09 +0000 (11:48 +0200)
LogicUI/src/era/mi/gui/LogicUICanvas.java
LogicUI/src/era/mi/gui/LogicUIStandalone.java
LogicUI/src/era/mi/gui/examples/Playground.java
LogicUI/src/era/mi/gui/model/ViewModel.java
LogicUI/src/era/mi/gui/model/components/GUIComponent.java
LogicUI/src/era/mi/gui/model/wires/GUIWire.java

index a752711..d6b32d7 100644 (file)
@@ -1,14 +1,11 @@
 package era.mi.gui;\r
 \r
-import java.util.HashSet;\r
-import java.util.Set;\r
-\r
 import org.eclipse.swt.SWT;\r
 import org.eclipse.swt.widgets.Composite;\r
 import org.eclipse.swt.widgets.Event;\r
 \r
+import era.mi.gui.model.ViewModel;\r
 import era.mi.gui.model.components.GUIComponent;\r
-import era.mi.gui.model.wires.GUIWire;\r
 import era.mi.gui.model.wires.Pin;\r
 import net.haspamelodica.swt.helper.gcs.GeneralGC;\r
 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;\r
@@ -22,49 +19,26 @@ import net.haspamelodica.swt.helper.zoomablecanvas.ZoomableCanvas;
  */\r
 public class LogicUICanvas extends ZoomableCanvas\r
 {\r
-       private final Set<GUIComponent> components;\r
-       private final Set<GUIWire> wires;\r
+       private final ViewModel model;\r
 \r
-       public LogicUICanvas(Composite parent, int style)\r
+       public LogicUICanvas(Composite parent, int style, ViewModel model)\r
        {\r
                super(parent, style);\r
 \r
-               components = new HashSet<>();\r
-               wires = new HashSet<>();\r
+               this.model = model;\r
+\r
+               model.addComponentAddedListener(c -> redrawThreadsafe());\r
+               model.addWireAddedListener(c -> redrawThreadsafe());\r
 \r
                addZoomedRenderer(gc ->\r
                {\r
                        Rectangle visibleRegion = new Rectangle(offX, offY, gW / zoom, gH / zoom);\r
-                       components.forEach(c -> drawComponent(gc, c, visibleRegion));\r
+                       model.getComponents().forEach(c -> drawComponent(gc, c, visibleRegion));\r
                });\r
-               addZoomedRenderer(gc -> wires.forEach(w -> w.render(gc)));\r
+               addZoomedRenderer(gc -> model.getWires().forEach(w -> w.render(gc)));\r
                addListener(SWT.MouseDown, this::mouseDown);\r
        }\r
 \r
-       /**\r
-        * Add a component to be drawn. Returns the given component for convenience.\r
-        * \r
-        * @author Daniel Kirschten\r
-        */\r
-       // TODO replace with model change listener\r
-       public <C extends GUIComponent> C addComponent(C component)\r
-       {\r
-               components.add(component);\r
-               return component;\r
-       }\r
-\r
-       /**\r
-        * Add a graphical wire between the given connection points of the given components. The given components have to be added and the given\r
-        * connection points have to be connected logically first.\r
-        * \r
-        * @author Daniel Kirschten\r
-        */\r
-       // TODO replace with model change listener\r
-       public void addWire(Pin pin1, Pin pin2, Point... path)\r
-       {\r
-               wires.add(new GUIWire(this::redrawThreadsafe, pin1, pin2, path));\r
-       }\r
-\r
        private void drawComponent(GeneralGC gc, GUIComponent component, Rectangle visibleRegion)\r
        {\r
                component.render(gc, visibleRegion);\r
@@ -81,11 +55,10 @@ public class LogicUICanvas extends ZoomableCanvas
                if (e.button == 1)\r
                {\r
                        Point click = displayToWorldCoords(e.x, e.y);\r
-                       for (GUIComponent component : components)\r
-                               if (component.getBounds().contains(click))\r
+                       for (GUIComponent component : model.getComponents())\r
+                               if (component.getBounds().contains(click) && component.clicked(click.x, click.y))\r
                                {\r
-                                       if (component.clicked(click.x, click.y))\r
-                                               redraw();\r
+                                       redraw();\r
                                        break;\r
                                }\r
                }\r
index 638ecf4..3e29a6e 100644 (file)
@@ -30,7 +30,7 @@ public class LogicUIStandalone
                display = new Display();\r
                shell = new Shell(display);\r
                shell.setLayout(new FillLayout());\r
-               ui = new LogicUICanvas(shell, SWT.NONE);\r
+               ui = new LogicUICanvas(shell, SWT.NONE, model);\r
 \r
                ZoomableCanvasUserInput userInput = new ZoomableCanvasUserInput(ui);\r
                userInput.buttonDrag = 3;\r
index eafa1a5..74da19c 100644 (file)
@@ -5,6 +5,7 @@ import era.mi.gui.LogicUIStandalone;
 import era.mi.gui.model.ViewModel;
 import era.mi.gui.model.components.GUIAndGate;
 import era.mi.gui.model.components.GUINotGate;
+import era.mi.gui.model.wires.GUIWire;
 
 public class Playground
 {
@@ -22,11 +23,11 @@ public class Playground
 
        public static void addComponentsAndWires(LogicUICanvas ui, ViewModel model)
        {
-               GUIAndGate andGate = ui.addComponent(new GUIAndGate(model));
+               GUIAndGate andGate = new GUIAndGate(model);
                andGate.moveTo(10, 10);
-               GUINotGate notGate = ui.addComponent(new GUINotGate(model));
+               GUINotGate notGate = new GUINotGate(model);
                notGate.moveTo(10, 40);
 
-               ui.addWire(andGate.getPins().get(0), notGate.getPins().get(1));
+               new GUIWire(model, andGate.getPins().get(0), notGate.getPins().get(1));
        }
 }
\ No newline at end of file
index 5a41d0e..4eb81e8 100644 (file)
@@ -1,6 +1,7 @@
 package era.mi.gui.model;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.function.Consumer;
 
@@ -10,7 +11,9 @@ import era.mi.gui.model.wires.GUIWire;
 public class ViewModel
 {
        private final List<GUIComponent> components;
+       private final List<GUIComponent> componentsUnmodifiable;
        private final List<GUIWire> wires;
+       private final List<GUIWire> wiresUnmodifiable;
 
        private final List<Consumer<GUIComponent>> componentAddedListeners;
        private final List<Consumer<GUIComponent>> componentRemovedListeners;
@@ -20,7 +23,9 @@ public class ViewModel
        public ViewModel()
        {
                components = new ArrayList<>();
+               componentsUnmodifiable = Collections.unmodifiableList(components);
                wires = new ArrayList<>();
+               wiresUnmodifiable = Collections.unmodifiableList(wires);
 
                componentAddedListeners = new ArrayList<>();
                componentRemovedListeners = new ArrayList<>();
@@ -32,7 +37,7 @@ public class ViewModel
         * Adds the given component to the list of components and calls all componentAddedListeners. Don't call this method from application
         * code as it is automatically called in GUIComponent::new.
         */
-       public void addComponent(GUIComponent component)
+       public void componentCreated(GUIComponent component)
        {
                if (components.contains(component))
                        throw new IllegalStateException("Don't add the same component twice!");
@@ -44,7 +49,7 @@ public class ViewModel
         * Removes the given component from the list of components and calls all componentRemovedListeners. Don't call this method from
         * application code as it is automatically called in GUIComponent::destroy.
         */
-       public void removeComponent(GUIComponent component)
+       public void componentDestroyed(GUIComponent component)
        {
                if (!components.contains(component))
                        throw new IllegalStateException("Don't remove the same component twice!");
@@ -52,6 +57,40 @@ public class ViewModel
                callComponentRemovedListeners(component);
        }
 
+       /**
+        * Adds the given component to the list of components and calls all componentAddedListeners. Don't call this method from application
+        * code as it is automatically called in GUIComponent::new.
+        */
+       public void wireCreated(GUIWire wire)
+       {
+               if (wires.contains(wire))
+                       throw new IllegalStateException("Don't add the same wire twice!");
+               wires.add(wire);
+               callWireAddedListeners(wire);
+       }
+
+       /**
+        * Removes the given component from the list of components and calls all componentRemovedListeners. Don't call this method from
+        * application code as it is automatically called in GUIComponent::destroy.
+        */
+       public void wireDestroyed(GUIWire wire)
+       {
+               if (!wires.contains(wire))
+                       throw new IllegalStateException("Don't remove the same wire twice!");
+               wires.remove(wire);
+               callWireRemovedListeners(wire);
+       }
+
+       public List<GUIComponent> getComponents()
+       {
+               return componentsUnmodifiable;
+       }
+
+       public List<GUIWire> getWires()
+       {
+               return wiresUnmodifiable;
+       }
+
        // @formatter:off
        public void addComponentAddedListener     (Consumer<GUIComponent> listener){componentAddedListeners  .add   (listener);}
        public void addComponentRemovedListener   (Consumer<GUIComponent> listener){componentRemovedListeners.add   (listener);}
index 7f4107d..cf9b23a 100644 (file)
@@ -33,6 +33,8 @@ public abstract class GUIComponent
                this.componentMovedListeners = new ArrayList<>();
                this.pinAddedListeners = new ArrayList<>();
                this.pinRemovedListeners = new ArrayList<>();
+
+               model.componentCreated(this);
        }
 
        public void moveTo(double x, double y)
@@ -50,9 +52,9 @@ public abstract class GUIComponent
                return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
        }
 
-       // TODO
        /**
-        * Called when this component is clicked. Relative coordinates of the click are given. Returns true if this component has to be redrawn.
+        * Called when this component is clicked. Absolute coordinates of the click are given. Returns true if this component consumed this
+        * click.
         */
        public boolean clicked(double x, double y)
        {
index d0bd990..649ddb6 100644 (file)
@@ -3,6 +3,7 @@ package era.mi.gui.model.wires;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Color;
 
+import era.mi.gui.model.ViewModel;
 import era.mi.logic.types.Bit;
 import era.mi.logic.wires.Wire;
 import net.haspamelodica.swt.helper.gcs.GeneralGC;
@@ -16,7 +17,7 @@ public class GUIWire
 
        private Wire wire;
 
-       public GUIWire(Runnable redraw, Pin pin1, Pin pin2, Point... path)
+       public GUIWire(ViewModel model, Pin pin1, Pin pin2, Point... path)
        {
                this.path = new double[path.length * 2 + 4];
                for (int srcI = 0, dstI = 2; srcI < path.length; srcI++, dstI += 2)
@@ -32,6 +33,8 @@ public class GUIWire
                pos = pin2.getPos();
                this.path[this.path.length - 2] = pos.x;
                this.path[this.path.length - 1] = pos.y;
+
+               model.wireCreated(this);
        }
 
        public void render(GeneralGC gc)