Merge branch 'development' of
[Mograsim.git] / LogicUI / src / era / mi / gui / model / wires / GUIWire.java
1 package era.mi.gui.model.wires;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.function.Consumer;
6
7 import era.mi.gui.ColorHelper;
8 import era.mi.gui.model.ViewModel;
9 import era.mi.logic.types.BitVectorFormatter;
10 import era.mi.logic.wires.Wire.ReadEnd;
11 import net.haspamelodica.swt.helper.gcs.GeneralGC;
12 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
13
14 public class GUIWire
15 {
16         private final ViewModel model;
17         public final int logicWidth;
18         private Pin pin1;
19         private Pin pin2;
20         private double[] path;
21
22         private final List<Consumer<? super GUIWire>> wireLookChangedListeners;
23
24         private ReadEnd end;
25
26         public GUIWire(ViewModel model, Pin pin1, Pin pin2, Point... path)
27         {
28                 this.model = model;
29                 this.logicWidth = pin1.logicWidth;
30                 if (pin2.logicWidth != pin1.logicWidth)
31                         throw new IllegalArgumentException("Can't connect pins of different logic width");
32                 this.path = new double[path.length * 2 + 4];
33                 for (int srcI = 0, dstI = 2; srcI < path.length; srcI++, dstI += 2)
34                 {
35                         this.path[dstI + 0] = path[srcI].x;
36                         this.path[dstI + 1] = path[srcI].y;
37                 }
38
39                 this.pin1 = pin1;
40                 this.pin2 = pin2;
41
42                 wireLookChangedListeners = new ArrayList<>();
43
44                 pin1.addPinMovedListener(p -> pin1Moved());
45                 pin2.addPinMovedListener(p -> pin2Moved());
46                 pin1Moved();
47                 pin2Moved();
48
49                 model.wireCreated(this);
50         }
51
52         private void pin1Moved()
53         {
54                 Point pos = pin1.getPos();
55                 this.path[0] = pos.x;
56                 this.path[1] = pos.y;
57         }
58
59         private void pin2Moved()
60         {
61                 Point pos = pin2.getPos();
62                 this.path[this.path.length - 2] = pos.x;
63                 this.path[this.path.length - 1] = pos.y;
64         }
65
66         public void destroy()
67         {
68                 model.wireDestroyed(this);
69         }
70
71         public void render(GeneralGC gc)
72         {
73                 ColorHelper.executeWithDifferentForeground(gc, BitVectorFormatter.formatAsColor(end), () -> gc.drawPolyline(path));
74         }
75
76         public void setLogicModelBinding(ReadEnd end)
77         {
78                 this.end = end;
79                 end.addObserver((i, o) -> callWireLookChangedListeners());
80         }
81
82         public Pin getPin1()
83         {
84                 return pin1;
85         }
86
87         public Pin getPin2()
88         {
89                 return pin2;
90         }
91
92         // @formatter:off
93         public void addWireLookChangedListener   (Consumer<? super GUIWire> listener) {wireLookChangedListeners.add   (listener);}
94
95         public void removeWireLookChangedListener(Consumer<? super GUIWire> listener) {wireLookChangedListeners.remove(listener);}
96
97         private void callWireLookChangedListeners() {wireLookChangedListeners.forEach(l -> l.accept(this));}
98         // @formatter:on
99
100 }