Splitted LogicUI into LogicUICanvas and LogicUIStandalone
[Mograsim.git] / LogicUI / src / era / mi / gui / LogicUICanvas.java
1 package era.mi.gui;\r
2 \r
3 import java.util.HashMap;\r
4 import java.util.HashSet;\r
5 import java.util.Map;\r
6 import java.util.Set;\r
7 \r
8 import org.eclipse.swt.SWT;\r
9 import org.eclipse.swt.widgets.Composite;\r
10 import org.eclipse.swt.widgets.Event;\r
11 \r
12 import era.mi.gui.components.BasicGUIComponent;\r
13 import era.mi.gui.wires.GUIWire;\r
14 import net.haspamelodica.swt.helper.gcs.GeneralGC;\r
15 import net.haspamelodica.swt.helper.gcs.TranslatedGC;\r
16 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;\r
17 import net.haspamelodica.swt.helper.zoomablecanvas.ZoomableCanvas;\r
18 \r
19 /**\r
20  * Simulation visualizer canvas.\r
21  * \r
22  * @author Daniel Kirschten\r
23  */\r
24 public class LogicUICanvas extends ZoomableCanvas\r
25 {\r
26         private final Set<BasicGUIComponent> components;\r
27         private final Map<BasicGUIComponent, Point> componentPositions;\r
28         private final Set<GUIWire> wires;\r
29 \r
30         public LogicUICanvas(Composite parent, int style)\r
31         {\r
32                 super(parent, style);\r
33 \r
34                 components = new HashSet<>();\r
35                 componentPositions = new HashMap<>();\r
36                 wires = new HashSet<>();\r
37 \r
38                 addZoomedRenderer(gc -> components.forEach(c -> drawComponent(gc, c)));\r
39                 addZoomedRenderer(gc -> wires.forEach(w -> w.render(gc)));\r
40                 addListener(SWT.MouseDown, this::mouseDown);\r
41         }\r
42 \r
43         /**\r
44          * Add a component to be drawn. Returns the given component for convenience.\r
45          * \r
46          * @author Daniel Kirschten\r
47          */\r
48         public <C extends BasicGUIComponent> C addComponent(C component, double x, double y)\r
49         {\r
50                 components.add(component);\r
51                 componentPositions.put(component, new Point(x, y));\r
52                 return component;\r
53         }\r
54 \r
55         /**\r
56          * Add a graphical wire between the given connection points of the given components. The given components have to be added and the given\r
57          * connection points have to be connected logically first.\r
58          * \r
59          * @author Daniel Kirschten\r
60          */\r
61         public void addWire(BasicGUIComponent component1, int component1ConnectionIndex, BasicGUIComponent component2,\r
62                         int component2ConnectionIndex, Point... path)\r
63         {\r
64                 wires.add(new GUIWire(this::redrawThreadsafe, component1, component1ConnectionIndex, componentPositions.get(component1), component2,\r
65                                 component2ConnectionIndex, componentPositions.get(component2), path));\r
66         }\r
67 \r
68         private void drawComponent(GeneralGC gc, BasicGUIComponent component)\r
69         {\r
70                 TranslatedGC tgc = new TranslatedGC(gc, componentPositions.get(component));\r
71                 component.render(tgc);\r
72                 tgc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLUE));\r
73         }\r
74 \r
75         private void mouseDown(Event e)\r
76         {\r
77                 if (e.button == 1)\r
78                 {\r
79                         Point click = displayToWorldCoords(e.x, e.y);\r
80                         for (BasicGUIComponent component : components)\r
81                                 if (component.getBounds().translate(componentPositions.get(component)).contains(click))\r
82                                 {\r
83                                         if (component.clicked(click.x, click.y))\r
84                                                 redraw();\r
85                                         break;\r
86                                 }\r
87                 }\r
88         }\r
89 }