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