The final restructured version for automatic build using maven tycho
[Mograsim.git] / plugins / net.mograsim.logic.model.editor / src / net / mograsim / logic / model / editor / Editor.java
1 package net.mograsim.logic.model.editor;
2
3 import java.util.HashSet;
4 import java.util.Map;
5 import java.util.Optional;
6 import java.util.Set;
7
8 import com.google.gson.JsonElement;
9 import com.google.gson.JsonNull;
10 import com.google.gson.JsonParser;
11 import com.google.gson.JsonSyntaxException;
12
13 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
14 import net.mograsim.logic.model.am2900.Am2900Loader;
15 import net.mograsim.logic.model.editor.handles.ComponentHandle;
16 import net.mograsim.logic.model.editor.handles.Handle;
17 import net.mograsim.logic.model.editor.handles.HandleManager;
18 import net.mograsim.logic.model.editor.handles.PinHandle;
19 import net.mograsim.logic.model.editor.states.StateManager;
20 import net.mograsim.logic.model.editor.ui.DialogManager;
21 import net.mograsim.logic.model.editor.ui.EditorGUI;
22 import net.mograsim.logic.model.model.LogicModelModifiable;
23 import net.mograsim.logic.model.model.components.ModelComponent;
24 import net.mograsim.logic.model.model.wires.ModelWire;
25 import net.mograsim.logic.model.serializing.DeserializedSubmodelComponent;
26 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
27 import net.mograsim.logic.model.snippets.highlevelstatehandlers.DefaultHighLevelStateHandler;
28 import net.mograsim.logic.model.snippets.outlinerenderers.DefaultOutlineRenderer;
29 import net.mograsim.logic.model.snippets.symbolrenderers.DefaultSymbolRenderer;
30
31 public final class Editor
32 {
33         final Selection selection = new Selection();
34         final Set<ComponentInfo> copyBuffer = new HashSet<>();
35         public final DeserializedSubmodelComponent toBeEdited;
36         public final HandleManager handleManager;
37         public final EditorGUI gui;
38         public final StateManager stateManager;
39         private final SaveLoadManager saveManager;
40         private Snapping snapping = Snapping.ABSOLUTE;
41         private double snapX = 5, snapY = 5;
42         public final DialogManager dialogManager;
43         public final EditorUserInput userInput;
44
45         public Editor(DeserializedSubmodelComponent toBeEdited)
46         {
47                 this.toBeEdited = toBeEdited;
48                 handleManager = new HandleManager(this);
49                 gui = new EditorGUI(this);
50                 userInput = new EditorUserInput(this);
51                 stateManager = new StateManager(this);
52                 handleManager.init();
53                 saveManager = new SaveLoadManager(this);
54                 dialogManager = new DialogManager(gui.shell);
55
56                 gui.open();
57         }
58
59         public LogicModelModifiable getSubmodel()
60         {
61                 return toBeEdited.getSubmodelModifiable();
62         }
63
64         public Selection getSelection()
65         {
66                 return selection;
67         }
68
69         // TODO: Remove this error prone method: Relative offset may change between multiple moves,
70         // because Handles have different ways of responding to reqMove(...), causing strange behaviour
71         @Deprecated
72         public void moveSelection(double x, double y)
73         {
74                 Point ref = selection.getTopLeft();
75                 Point snapped = new Point(x, y);
76                 applySnapping(snapped);
77
78                 for (Handle c : selection)
79                 {
80                         double newX, newY;
81                         newX = snapped.x + c.getPosX() - ref.x;
82                         newY = snapped.y + c.getPosY() - ref.y;
83                         c.reqMove(newX, newY);
84                 }
85         }
86
87         public void moveHandles(double x, double y, Map<Handle, Point> handleOffsetMap)
88         {
89                 Point snapped = new Point(x, y);
90                 applySnapping(snapped);
91
92                 for (Handle c : handleOffsetMap.keySet())
93                 {
94                         Point offset = handleOffsetMap.get(c);
95                         double newX, newY;
96                         newX = snapped.x + offset.x;
97                         newY = snapped.y + offset.y;
98                         c.reqMove(newX, newY);
99                 }
100         }
101
102         public void deleteSelection()
103         {
104                 selection.forEach(h -> h.reqDelete());
105                 selection.clear();
106         }
107
108         public void copy()
109         {
110                 copyBuffer.clear();
111                 Point refPoint = selection.getTopLeft();
112                 for (Handle h : selection)
113                 {
114                         Optional<ComponentInfo> cInfo = h.reqCopy(refPoint);
115                         if (cInfo.isPresent())
116                                 copyBuffer.add(cInfo.get());
117                 }
118         }
119
120         public void paste(double x, double y)
121         {
122                 selection.clear();
123                 for (ComponentInfo info : copyBuffer)
124                 {
125                         ModelComponent comp = addComponent(info.identifier, info.params);
126                         ComponentHandle h = handleManager.getHandle(comp);
127                         h.reqMove(info.relX, info.relY);
128                         selection.add(h);
129                 }
130                 moveSelection(x, y);
131         }
132
133         public void save()
134         {
135                 saveManager.save();
136         }
137
138         public void saveAs()
139         {
140                 saveManager.openSaveAsDialog();
141         }
142
143         public void addComponent(double x, double y)
144         {
145                 boolean successful = false;
146                 JsonElement params = JsonNull.INSTANCE;
147                 outer: while (!successful)
148                 {
149                         String selected = gui.getAddListSelected();
150                         try
151                         {
152                                 ModelComponent c = addComponent(selected, params);
153                                 selection.clear();
154                                 selection.add(handleManager.getHandle(c));
155                                 moveSelection(x, y);
156                                 successful = true;
157                         }
158                         catch (@SuppressWarnings("unused") UnsupportedOperationException | JsonSyntaxException | NumberFormatException
159                                         | NullPointerException e)
160                         {
161                                 String result = DialogManager.openMultiLineTextDialog("Add component", "Create", "Cancel", "Parameters:");
162                                 if (result == null)
163                                         break outer;
164                                 params = new JsonParser().parse(result);
165                         }
166                 }
167         }
168
169         private ModelComponent addComponent(String identifier, JsonElement params)
170         {
171                 return IndirectModelComponentCreator.createComponent(toBeEdited.getSubmodelModifiable(), identifier, params);
172         }
173
174         public void duplicate()
175         {
176                 copy();
177                 Point origin = selection.getTopLeft();
178                 paste(origin.x + 20, origin.y + 20);
179         }
180
181         private void applySnapping(Point newP)
182         {
183                 switch (snapping)
184                 {
185                 case OFF:
186                         break;
187                 case ABSOLUTE:
188                         newP.x = (int) (newP.x / snapX + .5) * snapX;
189                         newP.y = (int) (newP.y / snapY + .5) * snapY;
190                         break;
191                 default:
192                         break;
193                 }
194         }
195
196         public static class ComponentInfo
197         {
198                 public final double relX, relY;
199                 public final String identifier;
200                 public final JsonElement params;
201
202                 public ComponentInfo(double relX, double relY, String identifier, JsonElement params)
203                 {
204                         this.relX = relX;
205                         this.relY = relY;
206                         this.identifier = identifier;
207                         this.params = params;
208                 }
209         }
210
211         @SuppressWarnings("unused")
212         public void addWire(PinHandle a, PinHandle b)
213         {
214                 new ModelWire(toBeEdited.getSubmodelModifiable(), a.getPin(), b.getPin(), new Point[0]);
215         }
216
217         public static enum Snapping
218         {
219                 OFF, ABSOLUTE;
220
221                 @Override
222                 public String toString()
223                 {
224                         return super.toString().toLowerCase();
225                 }
226         }
227
228         public static void main(String[] args)
229         {
230                 Am2900Loader.setup();
231                 openNewEditor();
232 //              SaveLoadManager.openLoadDialog();
233         }
234
235         public static void openNewEditor()
236         {
237                 DeserializedSubmodelComponent toBeEdited = new DeserializedSubmodelComponent(new LogicModelModifiable(), null, null, null);
238                 toBeEdited.setOutlineRenderer(new DefaultOutlineRenderer(toBeEdited));
239                 toBeEdited.setSymbolRenderer(new DefaultSymbolRenderer(toBeEdited));
240                 toBeEdited.setHighLevelStateHandler(new DefaultHighLevelStateHandler());
241                 new Editor(toBeEdited);
242         }
243
244         public Snapping getSnapping()
245         {
246                 return snapping;
247         }
248
249         public void setSnapping(Snapping snapping)
250         {
251                 this.snapping = snapping;
252         }
253 }