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 = oldLength.getAndSet(newLength) - 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 List<WirePointHandle> handles = pointHandlesPerWire.get(owner);
220 int pointIndex = handles.indexOf(h);
221 handles.remove(pointIndex);
223 owner.removePathPoint(pointIndex);
226 private void removeWirePointHandles(GUIWire owner)
228 if (!pointHandlesPerWire.containsKey(owner))
230 pointHandlesPerWire.get(owner).forEach(h ->
232 wirePointHandles.remove(h);
235 pointHandlesPerWire.remove(owner);
238 private void addWireHandle(GUIWire w)
240 WireHandle h = new WireHandle(w);
241 handlePerWire.put(w, h);
245 private void removeWireHandle(GUIWire w)
247 WireHandle h = handlePerWire.get(w);
248 handlePerWire.remove(w);
252 private void addHandle(Handle h)
255 callHandleAddedListeners(h);
258 private void removeHandle(Handle h)
261 callHandleRemovedListeners(h);
265 public StaticPinHandle getHandle(Pin parent)
267 return handlePerPin.get(parent);
270 public ComponentHandle getHandle(GUIComponent parent)
272 return handlePerComp.get(parent);
275 public WireHandle getHandle(GUIWire parent)
277 return handlePerWire.get(parent);
280 public Handle getInterfacePinHandle(Pin p)
282 return handlePerInterfacePin.get(p);
286 * @return A Collection of the registered {@link WirePointHandle}s of the specified wire
288 public Collection<WirePointHandle> getWirePointHandles(GUIWire parent)
290 return pointHandlesPerWire.get(parent).stream().collect(Collectors.toSet());
294 * @return An unmodifiable view of all registered {@link Handle}s
296 public Collection<Handle> getHandles()
298 return Collections.unmodifiableCollection(handles);
302 * @return An unmodifiable view of all registered {@link StaticPinHandle}s
304 public Collection<StaticPinHandle> getPinHandles()
306 return Collections.unmodifiableCollection(handlePerPin.values());
310 * @return An unmodifiable view of all registered {@link InterfacePinHandle}s
312 public Collection<InterfacePinHandle> getInterfacePinHandles()
314 return Collections.unmodifiableCollection(handlePerInterfacePin.values());
318 * @return An unmodifiable view of all registered {@link ComponentHandle}s
320 public Collection<ComponentHandle> getComponentHandles()
322 return Collections.unmodifiableCollection(handlePerComp.values());
326 * @return An unmodifiable view of all registered {@link WireHandle}s
328 public Collection<WireHandle> getWireHandles()
330 return Collections.unmodifiableCollection(handlePerWire.values());
334 * @return An unmodifiable view of all registered {@link WirePointHandle}s
336 public Collection<WirePointHandle> getWirePointHandles()
338 return Collections.unmodifiableSet(wirePointHandles);
341 public void click(Point clicked, int stateMask)
343 EditorState entryState = editor.stateManager.getState();
345 if (!cornerHandle.click(clicked.x, clicked.y, stateMask, entryState))
346 if (!click(handlePerPin.values(), clicked, entryState, stateMask))
347 if (!click(handlePerInterfacePin.values(), clicked, entryState, stateMask))
348 if (!click(getWirePointHandles(), clicked, entryState, stateMask))
349 if (!click(getWireHandles(), clicked, entryState, stateMask))
350 if (!click(handlePerComp.values(), clicked, entryState, stateMask))
351 entryState.clickedEmpty(clicked, stateMask);
352 entryState.clicked(clicked, stateMask);
355 private static boolean click(Collection<? extends Handle> handles, Point clicked, EditorState state, int stateMask)
357 for (Handle h : handles)
358 if (h.click(clicked.x, clicked.y, stateMask, state))
363 public void addHandleAddedListener(Consumer<Handle> c)
365 handleAddedListeners.add(c);
368 private void callHandleAddedListeners(Handle added)
370 handleAddedListeners.forEach(l -> l.accept(added));
373 public void removeHandleAddedListener(Consumer<Handle> c)
375 handleAddedListeners.remove(c);
378 public void addHandleRemovedListener(Consumer<Handle> c)
380 handleRemovedListeners.add(c);
383 private void callHandleRemovedListeners(Handle removed)
385 handleRemovedListeners.forEach(l -> l.accept(removed));
388 public void removeHandleRemovedListener(Consumer<Handle> c)
390 handleRemovedListeners.remove(c);