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 = newLength - oldLength.getAndSet(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 if (pointHandlesPerWire.containsKey(owner))
222 List<WirePointHandle> handles = pointHandlesPerWire.get(owner);
223 int pointIndex = handles.indexOf(h);
224 handles.remove(pointIndex);
226 owner.removePathPoint(pointIndex);
230 private void removeWirePointHandles(GUIWire owner)
232 if (!pointHandlesPerWire.containsKey(owner))
234 pointHandlesPerWire.get(owner).forEach(h ->
236 wirePointHandles.remove(h);
239 pointHandlesPerWire.remove(owner);
242 private void addWireHandle(GUIWire w)
244 WireHandle h = new WireHandle(w);
245 handlePerWire.put(w, h);
249 private void removeWireHandle(GUIWire w)
251 WireHandle h = handlePerWire.get(w);
252 handlePerWire.remove(w);
256 private void addHandle(Handle h)
259 callHandleAddedListeners(h);
262 private void removeHandle(Handle h)
265 callHandleRemovedListeners(h);
269 public StaticPinHandle getHandle(Pin parent)
271 return handlePerPin.get(parent);
274 public ComponentHandle getHandle(GUIComponent parent)
276 return handlePerComp.get(parent);
279 public WireHandle getHandle(GUIWire parent)
281 return handlePerWire.get(parent);
284 public Handle getInterfacePinHandle(Pin p)
286 return handlePerInterfacePin.get(p);
290 * @return A Collection of the registered {@link WirePointHandle}s of the specified wire
292 public Collection<WirePointHandle> getWirePointHandles(GUIWire parent)
294 return pointHandlesPerWire.get(parent).stream().collect(Collectors.toSet());
298 * @return An unmodifiable view of all registered {@link Handle}s
300 public Collection<Handle> getHandles()
302 return Collections.unmodifiableCollection(handles);
306 * @return An unmodifiable view of all registered {@link StaticPinHandle}s
308 public Collection<StaticPinHandle> getPinHandles()
310 return Collections.unmodifiableCollection(handlePerPin.values());
314 * @return An unmodifiable view of all registered {@link InterfacePinHandle}s
316 public Collection<InterfacePinHandle> getInterfacePinHandles()
318 return Collections.unmodifiableCollection(handlePerInterfacePin.values());
322 * @return An unmodifiable view of all registered {@link ComponentHandle}s
324 public Collection<ComponentHandle> getComponentHandles()
326 return Collections.unmodifiableCollection(handlePerComp.values());
330 * @return An unmodifiable view of all registered {@link WireHandle}s
332 public Collection<WireHandle> getWireHandles()
334 return Collections.unmodifiableCollection(handlePerWire.values());
338 * @return An unmodifiable view of all registered {@link WirePointHandle}s
340 public Collection<WirePointHandle> getWirePointHandles()
342 return Collections.unmodifiableSet(wirePointHandles);
345 public void click(Point clicked, int stateMask)
347 EditorState entryState = editor.stateManager.getState();
349 // TODO: As soon as wires connected to a component being removed also are removed, change priority
350 if (!cornerHandle.click(clicked.x, clicked.y, stateMask, entryState))
351 if (!click(handlePerPin.values(), clicked, entryState, stateMask))
352 if (!click(handlePerInterfacePin.values(), clicked, entryState, stateMask))
353 if (!click(getWirePointHandles(), clicked, entryState, stateMask))
354 if (!click(getWireHandles(), clicked, entryState, stateMask))
355 if (!click(handlePerComp.values(), clicked, entryState, stateMask))
356 entryState.clickedEmpty(clicked, stateMask);
357 entryState.clicked(clicked, stateMask);
360 private static boolean click(Collection<? extends Handle> handles, Point clicked, EditorState state, int stateMask)
362 for (Handle h : handles)
363 if (h.click(clicked.x, clicked.y, stateMask, state))
368 public void addHandleAddedListener(Consumer<Handle> c)
370 handleAddedListeners.add(c);
373 private void callHandleAddedListeners(Handle added)
375 handleAddedListeners.forEach(l -> l.accept(added));
378 public void removeHandleAddedListener(Consumer<Handle> c)
380 handleAddedListeners.remove(c);
383 public void addHandleRemovedListener(Consumer<Handle> c)
385 handleRemovedListeners.add(c);
388 private void callHandleRemovedListeners(Handle removed)
390 handleRemovedListeners.forEach(l -> l.accept(removed));
393 public void removeHandleRemovedListener(Consumer<Handle> c)
395 handleRemovedListeners.remove(c);