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