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