1 package net.mograsim.logic.model.editor.handles;
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;
11 import java.util.concurrent.atomic.AtomicInteger;
12 import java.util.function.Consumer;
13 import java.util.stream.Collectors;
15 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
16 import net.mograsim.logic.model.editor.Editor;
17 import net.mograsim.logic.model.editor.states.EditorState;
18 import net.mograsim.logic.model.model.ViewModelModifiable;
19 import net.mograsim.logic.model.model.components.GUIComponent;
20 import net.mograsim.logic.model.model.wires.GUIWire;
21 import net.mograsim.logic.model.model.wires.MovablePin;
22 import net.mograsim.logic.model.model.wires.Pin;
24 public class HandleManager
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;
34 private final Collection<Consumer<Handle>> handleAddedListeners;
35 private final Collection<Consumer<Handle>> handleRemovedListeners;
36 private final Editor editor;
37 private boolean initialized = false;
39 private CornerHandle cornerHandle;
41 public HandleManager(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<>();
52 handleAddedListeners = new ArrayList<>();
53 handleRemovedListeners = new ArrayList<>();
55 ViewModelModifiable model = editor.getSubmodel();
57 model.addComponentAddedListener(c -> registerComponent(c));
59 model.addComponentRemovedListener(c ->
61 removeComponentHandle(c);
64 model.addWireAddedListener(w ->
69 model.addWireRemovedListener(w ->
72 removeWirePointHandles(w);
76 ////////////////////////////////////////
77 // -- Setting up initial handles -- ///
78 //////////////////////////////////////
83 System.err.println("Warning! HandleManager was already initialized.");
86 ViewModelModifiable model = editor.getSubmodel();
87 Map<String, GUIComponent> compsByName = model.getComponentsByName();
88 Set<GUIComponent> comps = new HashSet<>(compsByName.values());
89 GUIComponent interfaceComp = compsByName.get("_submodelinterface");
90 comps.remove(interfaceComp);
91 registerInterfaceComponent(interfaceComp);
92 comps.forEach(c -> registerComponent(c));
94 model.getWiresByName().values().forEach(w -> registerWire(w));
95 addHandle(cornerHandle = new CornerHandle(editor.toBeEdited));
99 private void registerInterfaceComponent(GUIComponent c)
101 c.getPins().values().forEach(p -> addInterfacePinHandle(p));
102 c.addPinAddedListener(p -> addInterfacePinHandle(p));
103 c.addPinRemovedListener(p -> removeInterfacePinHandle(p));
106 private void registerComponent(GUIComponent c)
108 addComponentHandle(c);
110 c.getPins().values().forEach(p -> addPinHandle(p));
112 c.addPinAddedListener(p -> addPinHandle(p));
113 c.addPinRemovedListener(p -> removePinHandle(p));
116 private void registerWire(GUIWire wire)
118 Point[] path = wire.getPath();
119 AtomicInteger oldLength = new AtomicInteger(path == null ? 0 : path.length);
120 wire.addPathChangedListener(w ->
122 Point[] newPath = w.getPath();
123 int newLength = newPath == null ? 0 : newPath.length;
124 int diff = newLength - oldLength.getAndSet(newLength);
129 for (int i = 0; i < diff; i++)
130 addWirePointHandle(w);
133 List<WirePointHandle> wpHandles = pointHandlesPerWire.get(w);
134 int size = wpHandles.size();
135 for (int i = 0; i < size; i++)
137 wpHandles.get(i).setIndex(i);
140 pointHandlesPerWire.get(w).forEach(h -> h.updatePos());
145 for (int i = 0; i < path.length; i++)
147 addWirePointHandle(wire);
151 /////////////////////////////////////
152 // -- Adding/Removing handles -- ///
153 ///////////////////////////////////
155 private void addComponentHandle(GUIComponent c)
157 ComponentHandle h = new ComponentHandle(c);
158 handlePerComp.put(c, h);
162 private void removeComponentHandle(GUIComponent c)
164 ComponentHandle h = handlePerComp.get(c);
165 handlePerComp.remove(c);
169 private void addPinHandle(Pin owner)
171 StaticPinHandle h = new StaticPinHandle(owner);
172 handlePerPin.put(owner, h);
176 private void removePinHandle(Pin owner)
178 StaticPinHandle h = handlePerPin.get(owner);
179 handlePerPin.remove(owner);
183 private void addInterfacePinHandle(Pin p)
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);
193 private void removeInterfacePinHandle(Pin p)
195 InterfacePinHandle h = handlePerInterfacePin.get(p);
196 handlePerInterfacePin.remove(p);
200 private void addWirePointHandle(GUIWire w)
202 List<WirePointHandle> wireHandles = pointHandlesPerWire.get(w);
204 if (wireHandles != null)
205 wireHandles.add(h = new WirePointHandle(this, w, wireHandles.size()));
208 wireHandles = new ArrayList<>();
209 h = new WirePointHandle(this, w, 0);
211 pointHandlesPerWire.put(h.parent, wireHandles);
213 this.wirePointHandles.add(h);
217 void destroyWirePointHandle(GUIWire owner, WirePointHandle h)
219 if (pointHandlesPerWire.containsKey(owner))
221 List<WirePointHandle> handles = pointHandlesPerWire.get(owner);
222 int pointIndex = handles.indexOf(h);
223 handles.remove(pointIndex);
225 owner.removePathPoint(pointIndex);
229 private void removeWirePointHandles(GUIWire owner)
231 if (!pointHandlesPerWire.containsKey(owner))
233 pointHandlesPerWire.get(owner).forEach(h ->
235 wirePointHandles.remove(h);
238 pointHandlesPerWire.remove(owner);
241 private void addWireHandle(GUIWire w)
243 WireHandle h = new WireHandle(w);
244 handlePerWire.put(w, h);
248 private void removeWireHandle(GUIWire w)
250 WireHandle h = handlePerWire.get(w);
251 handlePerWire.remove(w);
255 private void addHandle(Handle h)
258 callHandleAddedListeners(h);
261 private void removeHandle(Handle h)
264 callHandleRemovedListeners(h);
268 public StaticPinHandle getHandle(Pin parent)
270 return handlePerPin.get(parent);
273 public ComponentHandle getHandle(GUIComponent parent)
275 return handlePerComp.get(parent);
278 public WireHandle getHandle(GUIWire parent)
280 return handlePerWire.get(parent);
283 public Handle getInterfacePinHandle(Pin p)
285 return handlePerInterfacePin.get(p);
289 * @return A Collection of the registered {@link WirePointHandle}s of the specified wire
291 public Collection<WirePointHandle> getWirePointHandles(GUIWire parent)
293 return pointHandlesPerWire.get(parent).stream().collect(Collectors.toSet());
297 * @return An unmodifiable view of all registered {@link Handle}s
299 public Collection<Handle> getHandles()
301 return Collections.unmodifiableCollection(handles);
305 * @return An unmodifiable view of all registered {@link StaticPinHandle}s
307 public Collection<StaticPinHandle> getPinHandles()
309 return Collections.unmodifiableCollection(handlePerPin.values());
313 * @return An unmodifiable view of all registered {@link InterfacePinHandle}s
315 public Collection<InterfacePinHandle> getInterfacePinHandles()
317 return Collections.unmodifiableCollection(handlePerInterfacePin.values());
321 * @return An unmodifiable view of all registered {@link ComponentHandle}s
323 public Collection<ComponentHandle> getComponentHandles()
325 return Collections.unmodifiableCollection(handlePerComp.values());
329 * @return An unmodifiable view of all registered {@link WireHandle}s
331 public Collection<WireHandle> getWireHandles()
333 return Collections.unmodifiableCollection(handlePerWire.values());
337 * @return An unmodifiable view of all registered {@link WirePointHandle}s
339 public Collection<WirePointHandle> getWirePointHandles()
341 return Collections.unmodifiableSet(wirePointHandles);
344 public void click(Point clicked, int stateMask)
346 EditorState entryState = editor.stateManager.getState();
348 if (!cornerHandle.click(clicked.x, clicked.y, stateMask, entryState))
349 if (!click(handlePerPin.values(), clicked, entryState, stateMask))
350 if (!click(handlePerInterfacePin.values(), clicked, entryState, stateMask))
351 if (!click(getWirePointHandles(), clicked, entryState, stateMask))
352 if (!click(getWireHandles(), clicked, entryState, stateMask))
353 if (!click(handlePerComp.values(), clicked, entryState, stateMask))
354 entryState.clickedEmpty(clicked, stateMask);
355 entryState.clicked(clicked, stateMask);
358 private static boolean click(Collection<? extends Handle> handles, Point clicked, EditorState state, int stateMask)
360 for (Handle h : handles)
361 if (h.click(clicked.x, clicked.y, stateMask, state))
366 public void addHandleAddedListener(Consumer<Handle> c)
368 handleAddedListeners.add(c);
371 private void callHandleAddedListeners(Handle added)
373 handleAddedListeners.forEach(l -> l.accept(added));
376 public void removeHandleAddedListener(Consumer<Handle> c)
378 handleAddedListeners.remove(c);
381 public void addHandleRemovedListener(Consumer<Handle> c)
383 handleRemovedListeners.add(c);
386 private void callHandleRemovedListeners(Handle removed)
388 handleRemovedListeners.forEach(l -> l.accept(removed));
391 public void removeHandleRemovedListener(Consumer<Handle> c)
393 handleRemovedListeners.remove(c);