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