Merge branch 'development' of
[Mograsim.git] / net.mograsim.logic.model / src / net / mograsim / logic / model / model / wires / Pin.java
1 package net.mograsim.logic.model.model.wires;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.function.Consumer;
6
7 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
8 import net.mograsim.logic.model.model.components.GUIComponent;
9
10 /**
11  * A connection interface between a GUIComponent and the rest of a ViewModel. Pins usually are created by {@link GUIComponent}s themselves.
12  * <br>
13  * A pin has a name identifying it. Pin names are unique for a {@link GUIComponent}: Every pin of a {@link GUIComponent} has a different
14  * name, but different {@link GUIComponent}s can have pins with the same name.
15  * 
16  * @author Daniel Kirschten
17  */
18 public class Pin
19 {
20         /**
21          * The {@link GUIComponent} this pin belongs to
22          */
23         public final GUIComponent component;
24         /**
25          * The name identifying this pin. Is unique for a {@link GUIComponent}.
26          */
27         public final String name;
28         /**
29          * The logical width of this pin. Denotes how many bits this pin consists of.
30          */
31         public final int logicWidth;
32
33         /**
34          * The X position of this pin, relative to its component's location.
35          */
36         protected double relX;
37         /**
38          * The Y position of this pin, relative to its component's location.
39          */
40         protected double relY;
41
42         private final List<Consumer<? super Pin>> pinMovedListeners;
43         private final List<Runnable> redrawListeners;
44
45         // creation and destruction
46
47         /**
48          * Creates a new pin. Usually it is not needed to call this constructor manually, as {@link GUIComponent}s create their pins themselves.
49          * 
50          * @author Daniel Kirschten
51          */
52         public Pin(GUIComponent component, String name, int logicWidth, double relX, double relY)
53         {
54                 this.component = component;
55                 this.name = name;
56                 this.logicWidth = logicWidth;
57                 this.relX = relX;
58                 this.relY = relY;
59
60                 this.pinMovedListeners = new ArrayList<>();
61                 this.redrawListeners = new ArrayList<>();
62
63                 component.addComponentMovedListener(c -> callPinMovedListeners());
64         }
65
66         // "graphical" operations
67
68         /**
69          * Returns the X position of this pin relative to the position of its component.
70          * 
71          * @author Daniel Kirschten
72          */
73         public double getRelX()
74         {
75                 return relX;
76         }
77
78         /**
79          * Returns the Y position of this pin relative to the position of its component.
80          * 
81          * @author Daniel Kirschten
82          */
83         public double getRelY()
84         {
85                 return relY;
86         }
87
88         /**
89          * Returns the position of this pin relative to the position of its component.
90          * 
91          * @author Daniel Kirschten
92          */
93         public Point getRelPos()
94         {
95                 return new Point(relX, relY);
96         }
97
98         /**
99          * Returns the absolute position of this pin.
100          * 
101          * @author Daniel Kirschten
102          */
103         public Point getPos()
104         {
105                 return new Point(relX + component.getPosX(), relY + component.getPosY());
106         }
107
108         /**
109          * Sets the position of this pin relative to the position of its component.
110          * 
111          * @author Daniel Kirschten
112          */
113         protected void setRelPos(double relX, double relY)
114         {
115                 this.relX = relX;
116                 this.relY = relY;
117                 callPinMovedListeners();
118                 callRedrawListeners();
119         }
120
121         // listeners
122
123         // @formatter:off
124         public void addPinMovedListener   (Consumer<? super Pin> listener){pinMovedListeners.add   (listener);}
125         public void addRedrawListener     (Runnable              listener){redrawListeners  .add   (listener);}
126
127         public void removePinMovedListener(Consumer<? super Pin> listener){pinMovedListeners.remove(listener);}
128         public void removeRedrawListener  (Runnable              listener){redrawListeners  .remove(listener);}
129
130         private void callPinMovedListeners() {pinMovedListeners.forEach(l -> l.accept(this));}
131         private void callRedrawListeners  () {redrawListeners  .forEach(l -> l.run   (    ));}
132         // @formatter:on
133
134         @Override
135         public String toString()
136         {
137                 return "Pin [" + name + ", point=" + getPos() + "]";
138         }
139 }