1 package net.mograsim.logic.model.editor;
3 import java.util.HashMap;
4 import java.util.HashSet;
6 import java.util.Optional;
9 import com.google.gson.JsonElement;
10 import com.google.gson.JsonNull;
11 import com.google.gson.JsonParser;
12 import com.google.gson.JsonSyntaxException;
14 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
15 import net.mograsim.logic.model.am2900.Am2900Loader;
16 import net.mograsim.logic.model.editor.handles.ComponentHandle;
17 import net.mograsim.logic.model.editor.handles.Handle;
18 import net.mograsim.logic.model.editor.handles.HandleManager;
19 import net.mograsim.logic.model.editor.handles.PinHandle;
20 import net.mograsim.logic.model.editor.states.StateManager;
21 import net.mograsim.logic.model.editor.ui.DialogManager;
22 import net.mograsim.logic.model.editor.ui.EditorGUI;
23 import net.mograsim.logic.model.model.ViewModelModifiable;
24 import net.mograsim.logic.model.model.components.GUIComponent;
25 import net.mograsim.logic.model.model.wires.GUIWire;
26 import net.mograsim.logic.model.serializing.DeserializedSubmodelComponent;
27 import net.mograsim.logic.model.serializing.IdentifyParams;
28 import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator;
29 import net.mograsim.logic.model.snippets.highlevelstatehandlers.DefaultHighLevelStateHandler;
30 import net.mograsim.logic.model.snippets.outlinerenderers.DefaultOutlineRenderer;
31 import net.mograsim.logic.model.snippets.symbolrenderers.DefaultSymbolRenderer;
33 public final class Editor
35 final Selection selection = new Selection();
36 final Set<ComponentInfo> copyBuffer = new HashSet<>();
37 public final DeserializedSubmodelComponent toBeEdited;
38 public final HandleManager handleManager;
39 final static Map<GUIComponent, String> identifierPerComponent = new HashMap<>();
40 public final EditorGUI gui;
41 public final StateManager stateManager;
42 private final SaveLoadManager saveManager;
43 private Snapping snapping = Snapping.ABSOLUTE;
44 private double snapX = 5, snapY = 5;
45 public final DialogManager dialogManager;
46 public final EditorUserInput userInput;
48 public Editor(DeserializedSubmodelComponent toBeEdited)
50 this.toBeEdited = toBeEdited;
51 handleManager = new HandleManager(this);
52 gui = new EditorGUI(this);
53 userInput = new EditorUserInput(this);
54 stateManager = new StateManager(this);
56 saveManager = new SaveLoadManager(this);
57 dialogManager = new DialogManager(gui.shell);
59 toBeEdited.submodel.addComponentRemovedListener(c -> identifierPerComponent.remove(c));
64 public ViewModelModifiable getSubmodel()
66 return toBeEdited.getSubmodelModifiable();
69 public Selection getSelection()
74 // TODO: Remove this error prone method: Relative offset may change between multiple moves,
75 // because Handles have different ways of responding to reqMove(...), causing strange behaviour
77 public void moveSelection(double x, double y)
79 Point ref = selection.getTopLeft();
80 Point snapped = new Point(x, y);
81 applySnapping(snapped);
83 for (Handle c : selection)
86 newX = snapped.x + c.getPosX() - ref.x;
87 newY = snapped.y + c.getPosY() - ref.y;
88 c.reqMove(newX, newY);
92 public void moveHandles(double x, double y, Map<Handle, Point> handleOffsetMap)
94 Point snapped = new Point(x, y);
95 applySnapping(snapped);
97 for (Handle c : handleOffsetMap.keySet())
99 Point offset = handleOffsetMap.get(c);
101 newX = snapped.x + offset.x;
102 newY = snapped.y + offset.y;
103 c.reqMove(newX, newY);
107 public void deleteSelection()
109 selection.forEach(h -> h.reqDelete());
116 Point refPoint = selection.getTopLeft();
117 for (Handle h : selection)
119 Optional<ComponentInfo> cInfo = h.reqCopy(refPoint);
120 if (cInfo.isPresent())
121 copyBuffer.add(cInfo.get());
125 public void paste(double x, double y)
128 for (ComponentInfo info : copyBuffer)
130 GUIComponent comp = addComponent(info.identifier, info.params);
131 ComponentHandle h = handleManager.getHandle(comp);
132 h.reqMove(info.relX, info.relY);
145 saveManager.openSaveAsDialog();
148 public void addComponent(double x, double y)
150 boolean successful = false;
151 JsonElement params = JsonNull.INSTANCE;
152 outer: while (!successful)
154 String selected = gui.getAddListSelected();
157 GUIComponent c = addComponent(selected, params);
159 selection.add(handleManager.getHandle(c));
163 catch (@SuppressWarnings("unused") UnsupportedOperationException | JsonSyntaxException | NumberFormatException
164 | NullPointerException e)
166 String result = DialogManager.openMultiLineTextDialog("Add component", "Create", "Cancel", "Parameters:");
169 params = new JsonParser().parse(result);
174 private GUIComponent addComponent(String identifier, JsonElement params)
176 GUIComponent comp = IndirectGUIComponentCreator.createComponent(toBeEdited.getSubmodelModifiable(), identifier, params);
177 identifierPerComponent.put(comp, identifier);
181 public static String getIdentifier(GUIComponent c)
183 if (identifierPerComponent.containsKey(c))
184 return identifierPerComponent.get(c);
185 return c.getIDForSerializing(new IdentifyParams());
188 public void duplicate()
191 Point origin = selection.getTopLeft();
192 paste(origin.x + 20, origin.y + 20);
195 private void applySnapping(Point newP)
202 newP.x = (int) (newP.x / snapX + .5) * snapX;
203 newP.y = (int) (newP.y / snapY + .5) * snapY;
210 public static class ComponentInfo
212 public final double relX, relY;
213 public final String identifier;
214 public final JsonElement params;
216 public ComponentInfo(double relX, double relY, String identifier, JsonElement params)
220 this.identifier = identifier;
221 this.params = params;
225 @SuppressWarnings("unused")
226 public void addWire(PinHandle a, PinHandle b)
228 new GUIWire(toBeEdited.getSubmodelModifiable(), a.getPin(), b.getPin(), new Point[0]);
231 public static enum Snapping
236 public String toString()
238 return super.toString().toLowerCase();
242 public static void main(String[] args)
244 Am2900Loader.setup();
246 // SaveLoadManager.openLoadDialog();
249 public static void openNewEditor()
251 DeserializedSubmodelComponent toBeEdited = new DeserializedSubmodelComponent(new ViewModelModifiable(), null, null, null);
252 toBeEdited.setOutlineRenderer(new DefaultOutlineRenderer(toBeEdited));
253 toBeEdited.setSymbolRenderer(new DefaultSymbolRenderer(toBeEdited));
254 toBeEdited.setHighLevelStateHandler(new DefaultHighLevelStateHandler());
255 new Editor(toBeEdited);
258 public Snapping getSnapping()
263 public void setSnapping(Snapping snapping)
265 this.snapping = snapping;