2dd89a3596d3ce455c17a14eee957cda512ef287
[Mograsim.git] / LogicUI / src / mograsim / logic / ui / LogicUICanvas.java
1 package mograsim.logic.ui;\r
2 \r
3 import java.util.function.Consumer;\r
4 \r
5 import org.eclipse.swt.SWT;\r
6 import org.eclipse.swt.widgets.Composite;\r
7 import org.eclipse.swt.widgets.Event;\r
8 \r
9 import mograsim.logic.ui.model.ViewModel;\r
10 import mograsim.logic.ui.model.components.GUIComponent;\r
11 import mograsim.logic.ui.model.wires.GUIWire;\r
12 import mograsim.logic.ui.model.wires.Pin;\r
13 import net.haspamelodica.swt.helper.gcs.GeneralGC;\r
14 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;\r
15 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;\r
16 import net.haspamelodica.swt.helper.zoomablecanvas.ZoomableCanvas;\r
17 \r
18 /**\r
19  * Simulation visualizer canvas.\r
20  * \r
21  * @author Daniel Kirschten\r
22  */\r
23 public class LogicUICanvas extends ZoomableCanvas\r
24 {\r
25         private static final boolean DRAW_PINS = false;\r
26 \r
27         private final ViewModel model;\r
28 \r
29         public LogicUICanvas(Composite parent, int style, ViewModel model)\r
30         {\r
31                 super(parent, style);\r
32 \r
33                 this.model = model;\r
34 \r
35                 Consumer<Object> redrawConsumer = o -> redrawThreadsafe();\r
36                 Consumer<Pin> pinAddedListener = p ->\r
37                 {\r
38                         p.addPinMovedListener(redrawConsumer);\r
39                         redrawThreadsafe();\r
40                 };\r
41                 Consumer<Pin> pinRemovedListener = p ->\r
42                 {\r
43                         p.removePinMovedListener(redrawConsumer);\r
44                         redrawThreadsafe();\r
45                 };\r
46                 Consumer<? super GUIComponent> componentAddedListener = c ->\r
47                 {\r
48                         c.addComponentLookChangedListener(redrawConsumer);\r
49                         c.addComponentMovedListener(redrawConsumer);\r
50                         c.addPinAddedListener(pinAddedListener);\r
51                         c.addPinRemovedListener(pinRemovedListener);\r
52                         redrawThreadsafe();\r
53                 };\r
54                 model.addComponentAddedListener(componentAddedListener);\r
55                 model.getComponents().forEach(componentAddedListener);\r
56                 model.addComponentRemovedListener(c ->\r
57                 {\r
58                         c.removeComponentLookChangedListener(redrawConsumer);\r
59                         c.removeComponentMovedListener(redrawConsumer);\r
60                         c.removePinAddedListener(pinAddedListener);\r
61                         c.removePinRemovedListener(pinRemovedListener);\r
62                         redrawThreadsafe();\r
63                 });\r
64                 Consumer<? super GUIWire> wireAddedListener = w ->\r
65                 {\r
66                         w.addWireLookChangedListener(redrawConsumer);\r
67                         redrawThreadsafe();\r
68                 };\r
69                 model.addWireAddedListener(wireAddedListener);\r
70                 model.getWires().forEach(wireAddedListener);\r
71                 model.addWireRemovedListener(w ->\r
72                 {\r
73                         w.removeWireLookChangedListener(redrawConsumer);\r
74                         redrawThreadsafe();\r
75                 });\r
76 \r
77                 addZoomedRenderer(gc ->\r
78                 {\r
79                         gc.setLineWidth(.5);\r
80                         model.getWires().forEach(w -> w.render(gc));\r
81                         Rectangle visibleRegion = new Rectangle(offX, offY, gW / zoom, gH / zoom);\r
82                         model.getComponents().forEach(c -> drawComponent(gc, c, visibleRegion));\r
83                 });\r
84                 addListener(SWT.MouseDown, this::mouseDown);\r
85         }\r
86 \r
87         private void drawComponent(GeneralGC gc, GUIComponent component, Rectangle visibleRegion)\r
88         {\r
89                 component.render(gc, visibleRegion);\r
90                 if (DRAW_PINS)\r
91                 {\r
92                         gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_DARK_CYAN));\r
93                         for (Pin p : component.getPins())\r
94                         {\r
95                                 Point pos = p.getPos();\r
96                                 gc.fillOval(pos.x - 1, pos.y - 1, 2, 2);\r
97                         }\r
98                 }\r
99         }\r
100 \r
101         private void mouseDown(Event e)\r
102         {\r
103                 if (e.button == 1)\r
104                 {\r
105                         Point click = displayToWorldCoords(e.x, e.y);\r
106                         for (GUIComponent component : model.getComponents())\r
107                                 if (component.getBounds().contains(click) && component.clicked(click.x, click.y))\r
108                                 {\r
109                                         redraw();\r
110                                         break;\r
111                                 }\r
112                 }\r
113         }\r
114 }