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