Added DeserializedSubmodelComponent Editor project
[Mograsim.git] / net.mograsim.logic.ui.editor / src / net / mograsim / logic / ui / editor / handles / HandleManager.java
1 package net.mograsim.logic.ui.editor.handles;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Iterator;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12 import java.util.function.Consumer;
13 import java.util.stream.Collectors;
14
15 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
16 import net.mograsim.logic.ui.editor.Editor;
17 import net.mograsim.logic.ui.editor.states.EditorState;
18 import net.mograsim.logic.ui.model.ViewModelModifiable;
19 import net.mograsim.logic.ui.model.components.GUIComponent;
20 import net.mograsim.logic.ui.model.wires.GUIWire;
21 import net.mograsim.logic.ui.model.wires.MovablePin;
22 import net.mograsim.logic.ui.model.wires.Pin;
23
24 public class HandleManager
25 {
26         private final Map<Pin, StaticPinHandle> handlePerPin;
27         private final Map<Pin, InterfacePinHandle> handlePerInterfacePin;
28         private final Map<GUIWire, List<WirePointHandle>> pointHandlesPerWire;
29         private final Map<GUIWire, WireHandle> handlePerWire;
30         private final Set<Handle> handles;
31         private final Set<WirePointHandle> wirePointHandles;
32         private final Map<GUIComponent, ComponentHandle> handlePerComp;
33
34         private final Collection<Consumer<Handle>> handleAddedListeners;
35         private final Collection<Consumer<Handle>> handleRemovedListeners;
36         private final Editor editor;
37         private boolean initialized = false;
38
39         private CornerHandle cornerHandle;
40
41         public HandleManager(Editor editor)
42         {
43                 this.editor = editor;
44                 handlePerPin = new HashMap<>();
45                 handlePerInterfacePin = new HashMap<>();
46                 pointHandlesPerWire = new HashMap<>();
47                 handlePerComp = new HashMap<>();
48                 handles = new HashSet<>();
49                 wirePointHandles = new HashSet<>();
50                 handlePerWire = new HashMap<>();
51
52                 handleAddedListeners = new ArrayList<>();
53                 handleRemovedListeners = new ArrayList<>();
54
55                 ViewModelModifiable model = editor.getSubmodel();
56
57                 model.addComponentAddedListener(c -> registerComponent(c));
58
59                 model.addComponentRemovedListener(c ->
60                 {
61                         removeComponentHandle(c);
62                 });
63
64                 model.addWireAddedListener(w ->
65                 {
66                         registerWire(w);
67                 });
68
69                 model.addWireRemovedListener(w ->
70                 {
71                         removeWireHandle(w);
72                         removeWirePointHandles(w);
73                 });
74         }
75
76         ////////////////////////////////////////
77         // -- Setting up initial handles -- ///
78         //////////////////////////////////////
79
80         public void init()
81         {
82                 if (initialized)
83                         System.err.println("Warning! HandleManager was already initialized.");
84                 else
85                 {
86                         ViewModelModifiable model = editor.getSubmodel();
87
88                         Iterator<GUIComponent> cIt = model.getComponents().iterator();
89                         // First GUIComponent is the Submodel Interface
90                         registerInterfaceComponent(cIt.next());
91                         cIt.forEachRemaining(c -> registerComponent(c));
92                         model.getWires().forEach(w -> registerWire(w));
93                         addHandle(cornerHandle = new CornerHandle(editor.toBeEdited));
94                 }
95         }
96
97         private void registerInterfaceComponent(GUIComponent c)
98         {
99                 c.getPins().values().forEach(p -> addInterfacePinHandle(p));
100                 c.addPinAddedListener(p -> addInterfacePinHandle(p));
101                 c.addPinRemovedListener(p -> removeInterfacePinHandle(p));
102         }
103
104         private void registerComponent(GUIComponent c)
105         {
106                 addComponentHandle(c);
107
108                 c.getPins().values().forEach(p -> addPinHandle(p));
109
110                 c.addPinAddedListener(p -> addPinHandle(p));
111                 c.addPinRemovedListener(p -> removePinHandle(p));
112         }
113
114         private void registerWire(GUIWire wire)
115         {
116                 wire.addPathChangedListener((w, diff) ->
117                 {
118                         if(diff != 0)
119                         {
120                                 if(diff > 0)
121                                 {
122                                         for(int i = 0; i < diff; i++)
123                                                 addWirePointHandle(w);
124                                 }
125                                 else
126                                 {
127                                         for(int i = 0; i > diff; i--)
128                                         {
129                                                 removeLastWirePointHandle(wire);
130                                         }
131                                 }
132                                 
133                                 List<WirePointHandle> wpHandles = pointHandlesPerWire.get(w);
134                                 int size = wpHandles.size();
135                                 for(int i = 0; i < size; i++)
136                                 {
137                                         wpHandles.get(i).setIndex(i);
138                                 }
139                         }
140                         pointHandlesPerWire.get(w).forEach(h -> h.updatePos());
141                 });
142                 addWireHandle(wire);
143                 if (wire.getPath() == null)
144                         return;
145                 for (int i = 0; i < wire.getPath().length; i++)
146                 {
147                         addWirePointHandle(wire);
148                 }
149         }
150
151         /////////////////////////////////////
152         // -- Adding/Removing handles -- ///
153         ///////////////////////////////////
154
155         private void addComponentHandle(GUIComponent c)
156         {
157                 ComponentHandle h = new ComponentHandle(c);
158                 handlePerComp.put(c, h);
159                 addHandle(h);
160         }
161
162         private void removeComponentHandle(GUIComponent c)
163         {
164                 ComponentHandle h = handlePerComp.get(c);
165                 handlePerComp.remove(c);
166                 removeHandle(h);
167         }
168
169         private void addPinHandle(Pin owner)
170         {
171                 StaticPinHandle h = new StaticPinHandle(owner);
172                 handlePerPin.put(owner, h);
173                 addHandle(h);
174         }
175
176         private void removePinHandle(Pin owner)
177         {
178                 StaticPinHandle h = handlePerPin.get(owner);
179                 handlePerPin.remove(owner);
180                 removeHandle(h);
181         }
182
183         private void addInterfacePinHandle(Pin p)
184         {
185                 //The following is not an alternative to the cast, because the new pin is not yet in the map, when the listener is called
186                 //editor.toBeEdited.getSubmodelMovablePins().get(p.name);
187                 MovablePin pM = (MovablePin) p;
188                 InterfacePinHandle h = new InterfacePinHandle(pM, editor.toBeEdited);
189                 handlePerInterfacePin.put(pM, h);
190                 addHandle(h);
191         }
192
193         private void removeInterfacePinHandle(Pin p)
194         {
195                 InterfacePinHandle h = handlePerInterfacePin.get(p);
196                 handlePerInterfacePin.remove(p);
197                 removeHandle(h);
198         }
199
200         private void addWirePointHandle(GUIWire w)
201         {
202                 List<WirePointHandle> wireHandles = pointHandlesPerWire.get(w);
203                 WirePointHandle h;
204                 if (wireHandles != null)
205                         wireHandles.add(h = new WirePointHandle(w, wireHandles.size()));
206                 else
207                 {
208                         wireHandles = new ArrayList<>();
209                         h = new WirePointHandle(w, 0);
210                         wireHandles.add(h);
211                         pointHandlesPerWire.put(h.parent, wireHandles);
212                 }
213                 this.wirePointHandles.add(h);
214                 addHandle(h);
215         }
216
217         private void removeLastWirePointHandle(GUIWire owner)
218         {
219                 Handle h = pointHandlesPerWire.get(owner).remove(0);
220                 wirePointHandles.remove(h);
221                 removeHandle(h);
222         }
223
224         private void removeWirePointHandles(GUIWire owner)
225         {
226                 if(!pointHandlesPerWire.containsKey(owner))
227                         return;
228                 pointHandlesPerWire.get(owner).forEach(h ->
229                 {
230                         wirePointHandles.remove(h);
231                         removeHandle(h);
232                 });
233                 pointHandlesPerWire.remove(owner);
234         }
235
236         private void addWireHandle(GUIWire w)
237         {
238                 WireHandle h = new WireHandle(w);
239                 handlePerWire.put(w, h);
240                 addHandle(h);
241         }
242
243         private void removeWireHandle(GUIWire w)
244         {
245                 WireHandle h = handlePerWire.get(w);
246                 handlePerWire.remove(w);
247                 removeHandle(h);
248         }
249
250         private void addHandle(Handle h)
251         {
252                 handles.add(h);
253                 callHandleAddedListeners(h);
254         }
255
256         private void removeHandle(Handle h)
257         {
258                 handles.remove(h);
259                 callHandleRemovedListeners(h);
260                 h.destroy();
261         }
262
263         public StaticPinHandle getHandle(Pin parent)
264         {
265                 return handlePerPin.get(parent);
266         }
267
268         public ComponentHandle getHandle(GUIComponent parent)
269         {
270                 return handlePerComp.get(parent);
271         }
272
273         public WireHandle getHandle(GUIWire parent)
274         {
275                 return handlePerWire.get(parent);
276         }
277         
278         public Handle getInterfacePinHandle(Pin p)
279         {
280                 return handlePerInterfacePin.get(p);
281         }
282
283         /**
284          * @return A Collection of the registered {@link WirePointHandle}s of the specified wire
285          */
286         public Collection<WirePointHandle> getWirePointHandles(GUIWire parent)
287         {
288                 return pointHandlesPerWire.get(parent).stream().collect(Collectors.toSet());
289         }
290
291         /**
292          * @return An unmodifiable view of all registered {@link Handle}s
293          */
294         public Collection<Handle> getHandles()
295         {
296                 return Collections.unmodifiableCollection(handles);
297         }
298
299         /**
300          * @return An unmodifiable view of all registered {@link StaticPinHandle}s
301          */
302         public Collection<StaticPinHandle> getPinHandles()
303         {
304                 return Collections.unmodifiableCollection(handlePerPin.values());
305         }
306         
307         /**
308          * @return An unmodifiable view of all registered {@link InterfacePinHandle}s
309          */
310         public Collection<InterfacePinHandle> getInterfacePinHandles()
311         {
312                 return Collections.unmodifiableCollection(handlePerInterfacePin.values());
313         }
314
315         /**
316          * @return An unmodifiable view of all registered {@link ComponentHandle}s
317          */
318         public Collection<ComponentHandle> getComponentHandles()
319         {
320                 return Collections.unmodifiableCollection(handlePerComp.values());
321         }
322
323         /**
324          * @return An unmodifiable view of all registered {@link WireHandle}s
325          */
326         public Collection<WireHandle> getWireHandles()
327         {
328                 return Collections.unmodifiableCollection(handlePerWire.values());
329         }
330
331         /**
332          * @return An unmodifiable view of all registered {@link WirePointHandle}s
333          */
334         public Collection<WirePointHandle> getWirePointHandles()
335         {
336                 return Collections.unmodifiableSet(wirePointHandles);
337         }
338
339         public void click(Point clicked, int stateMask)
340         {
341                 EditorState entryState = editor.stateManager.getState();
342
343                 if (!cornerHandle.click(clicked.x, clicked.y, stateMask, entryState))
344                         if (!click(handlePerPin.values(), clicked, entryState, stateMask))
345                                 if (!click(handlePerInterfacePin.values(), clicked, entryState, stateMask))
346                                         if (!click(getWirePointHandles(), clicked, entryState, stateMask))
347                                                 if (!click(handlePerComp.values(), clicked, entryState, stateMask))
348                                                         if (!click(getWireHandles(), clicked, entryState, stateMask))
349                                                                 entryState.clickedEmpty(clicked, stateMask);
350                 entryState.clicked(clicked, stateMask);
351         }
352
353         private boolean click(Collection<? extends Handle> handles, Point clicked, EditorState state, int stateMask)
354         {
355                 for (Handle h : handles)
356                         if (h.click(clicked.x, clicked.y, stateMask, state))
357                                 return true;
358                 return false;
359         }
360
361         public void addHandleAddedListener(Consumer<Handle> c)
362         {
363                 handleAddedListeners.add(c);
364         }
365
366         private void callHandleAddedListeners(Handle added)
367         {
368                 handleAddedListeners.forEach(l -> l.accept(added));
369         }
370
371         public void removeHandleAddedListener(Consumer<Handle> c)
372         {
373                 handleAddedListeners.remove(c);
374         }
375
376         public void addHandleRemovedListener(Consumer<Handle> c)
377         {
378                 handleRemovedListeners.add(c);
379         }
380
381         private void callHandleRemovedListeners(Handle removed)
382         {
383                 handleRemovedListeners.forEach(l -> l.accept(removed));
384         }
385
386         public void removeHandleRemovedListener(Consumer<Handle> c)
387         {
388                 handleRemovedListeners.remove(c);
389         }
390 }