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.components.submodels.SubmodelComponent;
21 import net.mograsim.logic.model.model.wires.GUIWire;
22 import net.mograsim.logic.model.model.wires.MovablePin;
23 import net.mograsim.logic.model.model.wires.Pin;
25 public class HandleManager
27 private final Map<Pin, StaticPinHandle> handlePerPin;
28 private final Map<Pin, InterfacePinHandle> handlePerInterfacePin;
29 private final Map<GUIWire, List<WirePointHandle>> pointHandlesPerWire;
30 private final Map<GUIWire, WireHandle> handlePerWire;
31 private final Set<Handle> handles;
32 private final Set<WirePointHandle> wirePointHandles;
33 private final Map<GUIComponent, ComponentHandle> handlePerComp;
35 private final Collection<Consumer<Handle>> handleAddedListeners;
36 private final Collection<Consumer<Handle>> handleRemovedListeners;
37 private final Editor editor;
38 private boolean initialized = false;
40 private CornerHandle cornerHandle;
42 public HandleManager(Editor editor)
45 handlePerPin = new HashMap<>();
46 handlePerInterfacePin = new HashMap<>();
47 pointHandlesPerWire = new HashMap<>();
48 handlePerComp = new HashMap<>();
49 handles = new HashSet<>();
50 wirePointHandles = new HashSet<>();
51 handlePerWire = new HashMap<>();
53 handleAddedListeners = new ArrayList<>();
54 handleRemovedListeners = new ArrayList<>();
56 ViewModelModifiable model = editor.getSubmodel();
58 model.addComponentAddedListener(c -> registerComponent(c));
60 model.addComponentRemovedListener(c ->
62 removeComponentHandle(c);
65 model.addWireAddedListener(w ->
70 model.addWireRemovedListener(w ->
73 removeWirePointHandles(w);
77 ////////////////////////////////////////
78 // -- Setting up initial handles -- ///
79 //////////////////////////////////////
84 System.err.println("Warning! HandleManager was already initialized.");
87 ViewModelModifiable model = editor.getSubmodel();
88 Map<String, GUIComponent> compsByName = model.getComponentsByName();
89 Set<GUIComponent> comps = new HashSet<>(compsByName.values());
90 GUIComponent interfaceComp = compsByName.get(SubmodelComponent.SUBMODEL_INTERFACE_NAME);
91 comps.remove(interfaceComp);
92 registerInterfaceComponent(interfaceComp);
93 comps.forEach(c -> registerComponent(c));
95 model.getWiresByName().values().forEach(w -> registerWire(w));
96 addHandle(cornerHandle = new CornerHandle(editor.toBeEdited));
100 private void registerInterfaceComponent(GUIComponent c)
102 c.getPins().values().forEach(p -> addInterfacePinHandle(p));
103 c.addPinAddedListener(p -> addInterfacePinHandle(p));
104 c.addPinRemovedListener(p -> removeInterfacePinHandle(p));
107 private void registerComponent(GUIComponent c)
109 addComponentHandle(c);
111 c.getPins().values().forEach(p -> addPinHandle(p));
113 c.addPinAddedListener(p -> addPinHandle(p));
114 c.addPinRemovedListener(p -> removePinHandle(p));
117 private void registerWire(GUIWire wire)
119 Point[] path = wire.getPath();
120 AtomicInteger oldLength = new AtomicInteger(path == null ? 0 : path.length);
121 wire.addPathChangedListener(w ->
123 Point[] newPath = w.getPath();
124 int newLength = newPath == null ? 0 : newPath.length;
125 int diff = oldLength.getAndSet(newLength) - newLength;
130 for (int i = 0; i < diff; i++)
131 addWirePointHandle(w);
134 List<WirePointHandle> wpHandles = pointHandlesPerWire.get(w);
135 int size = wpHandles.size();
136 for (int i = 0; i < size; i++)
138 wpHandles.get(i).setIndex(i);
141 pointHandlesPerWire.get(w).forEach(h -> h.updatePos());
146 for (int i = 0; i < path.length; i++)
148 addWirePointHandle(wire);
152 /////////////////////////////////////
153 // -- Adding/Removing handles -- ///
154 ///////////////////////////////////
156 private void addComponentHandle(GUIComponent c)
158 ComponentHandle h = new ComponentHandle(c);
159 handlePerComp.put(c, h);
163 private void removeComponentHandle(GUIComponent c)
165 ComponentHandle h = handlePerComp.get(c);
166 handlePerComp.remove(c);
170 private void addPinHandle(Pin owner)
172 StaticPinHandle h = new StaticPinHandle(owner);
173 handlePerPin.put(owner, h);
177 private void removePinHandle(Pin owner)
179 StaticPinHandle h = handlePerPin.get(owner);
180 handlePerPin.remove(owner);
184 private void addInterfacePinHandle(Pin p)
186 // The following is not an alternative to the cast, because the new pin is not yet in the map, when the listener is called
187 // editor.toBeEdited.getSubmodelMovablePins().get(p.name);
188 MovablePin pM = (MovablePin) p;
189 InterfacePinHandle h = new InterfacePinHandle(pM, editor.toBeEdited);
190 handlePerInterfacePin.put(pM, h);
194 private void removeInterfacePinHandle(Pin p)
196 InterfacePinHandle h = handlePerInterfacePin.get(p);
197 handlePerInterfacePin.remove(p);
201 private void addWirePointHandle(GUIWire w)
203 List<WirePointHandle> wireHandles = pointHandlesPerWire.get(w);
205 if (wireHandles != null)
206 wireHandles.add(h = new WirePointHandle(this, w, wireHandles.size()));
209 wireHandles = new ArrayList<>();
210 h = new WirePointHandle(this, w, 0);
212 pointHandlesPerWire.put(h.parent, wireHandles);
214 this.wirePointHandles.add(h);
218 void destroyWirePointHandle(GUIWire owner, WirePointHandle h)
220 List<WirePointHandle> handles = pointHandlesPerWire.get(owner);
221 int pointIndex = handles.indexOf(h);
222 handles.remove(pointIndex);
224 owner.removePathPoint(pointIndex);
227 private void removeWirePointHandles(GUIWire owner)
229 if (!pointHandlesPerWire.containsKey(owner))
231 pointHandlesPerWire.get(owner).forEach(h ->
233 wirePointHandles.remove(h);
236 pointHandlesPerWire.remove(owner);
239 private void addWireHandle(GUIWire w)
241 WireHandle h = new WireHandle(w);
242 handlePerWire.put(w, h);
246 private void removeWireHandle(GUIWire w)
248 WireHandle h = handlePerWire.get(w);
249 handlePerWire.remove(w);
253 private void addHandle(Handle h)
256 callHandleAddedListeners(h);
259 private void removeHandle(Handle h)
262 callHandleRemovedListeners(h);
266 public StaticPinHandle getHandle(Pin parent)
268 return handlePerPin.get(parent);
271 public ComponentHandle getHandle(GUIComponent parent)
273 return handlePerComp.get(parent);
276 public WireHandle getHandle(GUIWire parent)
278 return handlePerWire.get(parent);
281 public Handle getInterfacePinHandle(Pin p)
283 return handlePerInterfacePin.get(p);
287 * @return A Collection of the registered {@link WirePointHandle}s of the specified wire
289 public Collection<WirePointHandle> getWirePointHandles(GUIWire parent)
291 return pointHandlesPerWire.get(parent).stream().collect(Collectors.toSet());
295 * @return An unmodifiable view of all registered {@link Handle}s
297 public Collection<Handle> getHandles()
299 return Collections.unmodifiableCollection(handles);
303 * @return An unmodifiable view of all registered {@link StaticPinHandle}s
305 public Collection<StaticPinHandle> getPinHandles()
307 return Collections.unmodifiableCollection(handlePerPin.values());
311 * @return An unmodifiable view of all registered {@link InterfacePinHandle}s
313 public Collection<InterfacePinHandle> getInterfacePinHandles()
315 return Collections.unmodifiableCollection(handlePerInterfacePin.values());
319 * @return An unmodifiable view of all registered {@link ComponentHandle}s
321 public Collection<ComponentHandle> getComponentHandles()
323 return Collections.unmodifiableCollection(handlePerComp.values());
327 * @return An unmodifiable view of all registered {@link WireHandle}s
329 public Collection<WireHandle> getWireHandles()
331 return Collections.unmodifiableCollection(handlePerWire.values());
335 * @return An unmodifiable view of all registered {@link WirePointHandle}s
337 public Collection<WirePointHandle> getWirePointHandles()
339 return Collections.unmodifiableSet(wirePointHandles);
342 public void click(Point clicked, int stateMask)
344 EditorState entryState = editor.stateManager.getState();
346 // TODO: As soon as wires connected to a component being removed also are removed, change priority
347 if (!cornerHandle.click(clicked.x, clicked.y, stateMask, entryState))
348 if (!click(handlePerPin.values(), clicked, entryState, stateMask))
349 if (!click(handlePerInterfacePin.values(), clicked, entryState, stateMask))
350 if (!click(getWirePointHandles(), clicked, entryState, stateMask))
351 if (!click(getWireHandles(), clicked, entryState, stateMask))
352 if (!click(handlePerComp.values(), clicked, entryState, stateMask))
353 entryState.clickedEmpty(clicked, stateMask);
354 entryState.clicked(clicked, stateMask);
357 private static boolean click(Collection<? extends Handle> handles, Point clicked, EditorState state, int stateMask)
359 for (Handle h : handles)
360 if (h.click(clicked.x, clicked.y, stateMask, state))
365 public void addHandleAddedListener(Consumer<Handle> c)
367 handleAddedListeners.add(c);
370 private void callHandleAddedListeners(Handle added)
372 handleAddedListeners.forEach(l -> l.accept(added));
375 public void removeHandleAddedListener(Consumer<Handle> c)
377 handleAddedListeners.remove(c);
380 public void addHandleRemovedListener(Consumer<Handle> c)
382 handleRemovedListeners.add(c);
385 private void callHandleRemovedListeners(Handle removed)
387 handleRemovedListeners.forEach(l -> l.accept(removed));
390 public void removeHandleRemovedListener(Consumer<Handle> c)
392 handleRemovedListeners.remove(c);