Wrote TODO
[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         // TODO introduce input/output/tristate hints
21         /**
22          * The {@link GUIComponent} this pin belongs to
23          */
24         public final GUIComponent component;
25         /**
26          * The name identifying this pin. Is unique for a {@link GUIComponent}.
27          */
28         public final String name;
29         /**
30          * The logical width of this pin. Denotes how many bits this pin consists of.
31          */
32         public final int logicWidth;
33
34         /**
35          * The X position of this pin, relative to its component's location.
36          */
37         protected double relX;
38         /**
39          * The Y position of this pin, relative to its component's location.
40          */
41         protected double relY;
42
43         private final List<Consumer<? super Pin>> pinMovedListeners;
44         private final List<Runnable> redrawListeners;
45
46         // creation and destruction
47
48         /**
49          * Creates a new pin. Usually it is not needed to call this constructor manually, as {@link GUIComponent}s create their pins themselves.
50          * 
51          * @author Daniel Kirschten
52          */
53         public Pin(GUIComponent component, String name, int logicWidth, double relX, double relY)
54         {
55                 this.component = component;
56                 this.name = name;
57                 this.logicWidth = logicWidth;
58                 this.relX = relX;
59                 this.relY = relY;
60
61                 this.pinMovedListeners = new ArrayList<>();
62                 this.redrawListeners = new ArrayList<>();
63
64                 component.addComponentMovedListener(c -> callPinMovedListeners());
65         }
66
67         // "graphical" operations
68
69         /**
70          * Returns the X position of this pin relative to the position of its component.
71          * 
72          * @author Daniel Kirschten
73          */
74         public double getRelX()
75         {
76                 return relX;
77         }
78
79         /**
80          * Returns the Y position of this pin relative to the position of its component.
81          * 
82          * @author Daniel Kirschten
83          */
84         public double getRelY()
85         {
86                 return relY;
87         }
88
89         /**
90          * Returns the position of this pin relative to the position of its component.
91          * 
92          * @author Daniel Kirschten
93          */
94         public Point getRelPos()
95         {
96                 return new Point(relX, relY);
97         }
98
99         /**
100          * Returns the absolute position of this pin.
101          * 
102          * @author Daniel Kirschten
103          */
104         public Point getPos()
105         {
106                 return new Point(relX + component.getPosX(), relY + component.getPosY());
107         }
108
109         /**
110          * Sets the position of this pin relative to the position of its component.
111          * 
112          * @author Daniel Kirschten
113          */
114         protected void setRelPos(double relX, double relY)
115         {
116                 this.relX = relX;
117                 this.relY = relY;
118                 callPinMovedListeners();
119                 callRedrawListeners();
120         }
121
122         // listeners
123
124         // @formatter:off
125         public void addPinMovedListener   (Consumer<? super Pin> listener){pinMovedListeners.add   (listener);}
126         public void addRedrawListener     (Runnable              listener){redrawListeners  .add   (listener);}
127
128         public void removePinMovedListener(Consumer<? super Pin> listener){pinMovedListeners.remove(listener);}
129         public void removeRedrawListener  (Runnable              listener){redrawListeners  .remove(listener);}
130
131         private void callPinMovedListeners() {pinMovedListeners.forEach(l -> l.accept(this));}
132         private void callRedrawListeners  () {redrawListeners  .forEach(l -> l.run   (    ));}
133         // @formatter:on
134
135         @Override
136         public String toString()
137         {
138                 return "Pin [" + name + ", point=" + getPos() + "]";
139         }
140 }