1 package net.mograsim.logic.model.editor;
3 import java.io.IOException;
4 import java.util.HashMap;
5 import java.util.HashSet;
7 import java.util.Optional;
10 import com.google.gson.JsonElement;
11 import com.google.gson.JsonNull;
12 import com.google.gson.JsonParser;
13 import com.google.gson.JsonSyntaxException;
15 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
16 import net.mograsim.logic.model.am2900.Am2900Loader;
17 import net.mograsim.logic.model.editor.handles.ComponentHandle;
18 import net.mograsim.logic.model.editor.handles.Handle;
19 import net.mograsim.logic.model.editor.handles.HandleManager;
20 import net.mograsim.logic.model.editor.handles.PinHandle;
21 import net.mograsim.logic.model.editor.states.StateManager;
22 import net.mograsim.logic.model.editor.ui.DialogManager;
23 import net.mograsim.logic.model.editor.ui.EditorGUI;
24 import net.mograsim.logic.model.model.ViewModelModifiable;
25 import net.mograsim.logic.model.model.components.GUIComponent;
26 import net.mograsim.logic.model.model.wires.GUIWire;
27 import net.mograsim.logic.model.serializing.DeserializedSubmodelComponent;
28 import net.mograsim.logic.model.serializing.IdentifyParams;
29 import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator;
31 public final class Editor
33 final Selection selection = new Selection();
34 final Set<ComponentInfo> copyBuffer = new HashSet<>();
35 public final DeserializedSubmodelComponent toBeEdited;
36 public final HandleManager handleManager;
37 final static Map<GUIComponent, String> identifierPerComponent = new HashMap<>();
38 public final EditorGUI gui;
39 public final StateManager stateManager;
40 private final SaveLoadManager saveManager;
41 private Snapping snapping = Snapping.ABSOLUTE;
42 private double snapX = 5, snapY = 5;
43 public final DialogManager dialogManager;
44 public final EditorUserInput userInput;
46 public Editor(DeserializedSubmodelComponent toBeEdited)
48 this.toBeEdited = toBeEdited;
49 handleManager = new HandleManager(this);
50 gui = new EditorGUI(this);
51 userInput = new EditorUserInput(this);
52 stateManager = new StateManager(this);
54 saveManager = new SaveLoadManager(this);
55 dialogManager = new DialogManager(gui.shell);
57 toBeEdited.submodel.addComponentRemovedListener(c -> identifierPerComponent.remove(c));
62 public ViewModelModifiable getSubmodel()
64 return toBeEdited.getSubmodelModifiable();
67 public Selection getSelection()
72 // TODO: Remove this error prone method: Relative offset may change between multiple moves,
73 // because Handles have different ways of responding to reqMove(...), causing strange behaviour
75 public void moveSelection(double x, double y)
77 Point ref = selection.getTopLeft();
78 Point snapped = new Point(x, y);
79 applySnapping(snapped);
81 for (Handle c : selection)
84 newX = snapped.x + c.getPosX() - ref.x;
85 newY = snapped.y + c.getPosY() - ref.y;
86 c.reqMove(newX, newY);
90 public void moveHandles(double x, double y, Map<Handle, Point> handleOffsetMap)
92 Point snapped = new Point(x, y);
93 applySnapping(snapped);
95 for (Handle c : handleOffsetMap.keySet())
97 Point offset = handleOffsetMap.get(c);
99 newX = snapped.x + offset.x;
100 newY = snapped.y + offset.y;
101 c.reqMove(newX, newY);
105 public void deleteSelection()
107 selection.forEach(h -> h.reqDelete());
114 Point refPoint = selection.getTopLeft();
115 for (Handle h : selection)
117 Optional<ComponentInfo> cInfo = h.reqCopy(refPoint);
118 if (cInfo.isPresent())
119 copyBuffer.add(cInfo.get());
123 public void paste(double x, double y)
126 for (ComponentInfo info : copyBuffer)
128 GUIComponent comp = addComponent(info.identifier, info.params);
129 ComponentHandle h = handleManager.getHandle(comp);
130 h.reqMove(info.relX, info.relY);
143 saveManager.openSaveAsDialog();
146 public void addComponent(double x, double y)
148 boolean successful = false;
149 JsonElement params = JsonNull.INSTANCE;
150 outer: while (!successful)
152 String selected = gui.getAddListSelected();
155 GUIComponent c = addComponent(selected, params);
157 selection.add(handleManager.getHandle(c));
161 catch (@SuppressWarnings("unused") UnsupportedOperationException | JsonSyntaxException | NumberFormatException e)
163 String result = DialogManager.openMultiLineTextDialog("Add component", "Create", "Cancel", "Parameters:");
166 params = new JsonParser().parse(result);
171 private GUIComponent addComponent(String identifier, JsonElement params)
173 GUIComponent comp = IndirectGUIComponentCreator.createComponent(toBeEdited.getSubmodelModifiable(), identifier, params);
174 identifierPerComponent.put(comp, identifier);
178 public static String getIdentifier(GUIComponent c)
180 if (identifierPerComponent.containsKey(c))
181 return identifierPerComponent.get(c);
182 return c.getIDForSerializing(new IdentifyParams());
185 public void duplicate()
188 Point origin = selection.getTopLeft();
189 paste(origin.x + 20, origin.y + 20);
192 private void applySnapping(Point newP)
199 newP.x = (int) (newP.x / snapX + .5) * snapX;
200 newP.y = (int) (newP.y / snapY + .5) * snapY;
207 public static class ComponentInfo
209 public final double relX, relY;
210 public final String identifier;
211 public final JsonElement params;
213 public ComponentInfo(double relX, double relY, String identifier, JsonElement params)
217 this.identifier = identifier;
218 this.params = params;
222 @SuppressWarnings("unused")
223 public void addWire(PinHandle a, PinHandle b)
225 new GUIWire(toBeEdited.getSubmodelModifiable(), a.getPin(), b.getPin(), new Point[0]);
228 public static enum Snapping
233 public String toString()
235 return super.toString().toLowerCase();
239 public static void main(String[] args) throws IOException
241 Am2900Loader.setup();
242 SaveLoadManager.openLoadDialog();
245 public Snapping getSnapping()
250 public void setSnapping(Snapping snapping)
252 this.snapping = snapping;