WireCrossPoint now renders at the correct location
[Mograsim.git] / LogicUI / src / era / mi / gui / LogicUICanvas.java
1 package era.mi.gui;\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 era.mi.gui.model.ViewModel;\r
10 import era.mi.gui.model.components.GUIComponent;\r
11 import era.mi.gui.model.wires.GUIWire;\r
12 import era.mi.gui.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 final ViewModel model;\r
26 \r
27         public LogicUICanvas(Composite parent, int style, ViewModel model)\r
28         {\r
29                 super(parent, style);\r
30 \r
31                 this.model = model;\r
32 \r
33                 Consumer<Object> redrawConsumer = o -> redrawThreadsafe();\r
34                 Consumer<Pin> pinAddedListener = p ->\r
35                 {\r
36                         p.addPinMovedListener(redrawConsumer);\r
37                         redrawThreadsafe();\r
38                 };\r
39                 Consumer<Pin> pinRemovedListener = p ->\r
40                 {\r
41                         p.removePinMovedListener(redrawConsumer);\r
42                         redrawThreadsafe();\r
43                 };\r
44                 Consumer<? super GUIComponent> componentAddedListener = c ->\r
45                 {\r
46                         c.addComponentLookChangedListener(redrawConsumer);\r
47                         c.addComponentMovedListener(redrawConsumer);\r
48                         c.addPinAddedListener(pinAddedListener);\r
49                         c.addPinRemovedListener(pinRemovedListener);\r
50                         redrawThreadsafe();\r
51                 };\r
52                 model.addComponentAddedListener(componentAddedListener);\r
53                 model.getComponents().forEach(componentAddedListener);\r
54                 model.addComponentRemovedListener(c ->\r
55                 {\r
56                         c.removeComponentLookChangedListener(redrawConsumer);\r
57                         c.removeComponentMovedListener(redrawConsumer);\r
58                         c.removePinAddedListener(pinAddedListener);\r
59                         c.removePinRemovedListener(pinRemovedListener);\r
60                         redrawThreadsafe();\r
61                 });\r
62                 Consumer<? super GUIWire> wireAddedListener = w ->\r
63                 {\r
64                         w.addWireLookChangedListener(redrawConsumer);\r
65                         redrawThreadsafe();\r
66                 };\r
67                 model.addWireAddedListener(wireAddedListener);\r
68                 model.getWires().forEach(wireAddedListener);\r
69                 model.addWireRemovedListener(w ->\r
70                 {\r
71                         w.removeWireLookChangedListener(redrawConsumer);\r
72                         redrawThreadsafe();\r
73                 });\r
74 \r
75                 addZoomedRenderer(gc ->\r
76                 {\r
77                         Rectangle visibleRegion = new Rectangle(offX, offY, gW / zoom, gH / zoom);\r
78                         model.getComponents().forEach(c -> drawComponent(gc, c, visibleRegion));\r
79                 });\r
80                 addZoomedRenderer(gc -> model.getWires().forEach(w -> w.render(gc)));\r
81                 addListener(SWT.MouseDown, this::mouseDown);\r
82         }\r
83 \r
84         private void drawComponent(GeneralGC gc, GUIComponent component, Rectangle visibleRegion)\r
85         {\r
86                 component.render(gc, visibleRegion);\r
87                 gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_DARK_CYAN));\r
88                 for (Pin p : component.getPins())\r
89                 {\r
90                         Point pos = p.getPos();\r
91                         gc.fillOval(pos.x - 1, pos.y - 1, 2, 2);\r
92                 }\r
93         }\r
94 \r
95         private void mouseDown(Event e)\r
96         {\r
97                 if (e.button == 1)\r
98                 {\r
99                         Point click = displayToWorldCoords(e.x, e.y);\r
100                         for (GUIComponent component : model.getComponents())\r
101                                 if (component.getBounds().contains(click) && component.clicked(click.x, click.y))\r
102                                 {\r
103                                         redraw();\r
104                                         break;\r
105                                 }\r
106                 }\r
107         }\r
108 }