Merge branch 'development' of
[Mograsim.git] / 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.HashMap;
4 import java.util.HashSet;
5 import java.util.Map;
6 import java.util.Optional;
7 import java.util.Set;
8
9 import com.google.gson.JsonElement;
10 import com.google.gson.JsonObject;
11
12 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
13 import net.mograsim.logic.model.editor.handles.ComponentHandle;
14 import net.mograsim.logic.model.editor.handles.Handle;
15 import net.mograsim.logic.model.editor.handles.HandleManager;
16 import net.mograsim.logic.model.editor.handles.PinHandle;
17 import net.mograsim.logic.model.editor.states.StateManager;
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.serializing.DeserializedSubmodelComponent;
22 import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator;
23
24 public final class Editor
25 {
26         final Selection selection = new Selection();
27         final Set<ComponentInfo> copyBuffer = new HashSet<>();
28         public final DeserializedSubmodelComponent toBeEdited;
29         public final HandleManager handleManager;
30         final static Map<GUIComponent, String> identifierPerComponent = new HashMap<>();
31         public final EditorGUI gui;
32         public final StateManager stateManager;
33         private final SaveLoadManager saveManager;
34         Snapping snapping = Snapping.ABSOLUTE;
35         private double snapX = 5, snapY = 5;
36         public final DialogManager dialogManager;
37
38         public Editor(DeserializedSubmodelComponent toBeEdited)
39         {
40                 this.toBeEdited = toBeEdited;
41                 handleManager = new HandleManager(this);
42                 gui = new EditorGUI(this);
43                 stateManager = new StateManager(this);
44                 handleManager.init();
45                 saveManager = new SaveLoadManager(this);
46                 dialogManager = new DialogManager(gui.shell);
47
48                 toBeEdited.submodel.addComponentRemovedListener(c -> identifierPerComponent.remove(c));
49                 
50                 gui.open();
51         }
52         
53         public ViewModelModifiable getSubmodel()
54         {
55                 return toBeEdited.getSubmodelModifiable();
56         }
57
58         public Selection getSelection()
59         {
60                 return selection;
61         }
62
63         //TODO: Remove this error prone method: Relative offset may change between multiple moves,
64         //because Handles have different ways of responding to reqMove(...), causing strange behaviour
65         @Deprecated
66         public void moveSelection(double x, double y)
67         {
68                 Point ref = selection.getTopLeft();
69                 Point snapped = new Point(x, y);
70                 applySnapping(snapped);
71
72                 for (Handle c : selection)
73                 {
74                         double newX, newY;
75                         newX = snapped.x + c.getPosX() - ref.x;
76                         newY = snapped.y + c.getPosY() - ref.y;
77                         c.reqMove(newX, newY);
78                 }
79         }
80         
81         public void moveHandles(double x, double y, Map<Handle, Point> handleOffsetMap)
82         {
83                 Point snapped = new Point(x, y);
84                 applySnapping(snapped);
85
86                 for (Handle c : handleOffsetMap.keySet())
87                 {
88                         Point offset = handleOffsetMap.get(c);
89                         double newX, newY;
90                         newX = snapped.x + offset.x;
91                         newY = snapped.y + offset.y;
92                         c.reqMove(newX, newY);
93                 }
94         }
95
96         public void deleteSelection()
97         {
98                 selection.forEach(h -> h.reqDelete());
99                 selection.clear();
100         }
101
102         public void copy()
103         {
104                 copyBuffer.clear();
105                 Point refPoint = selection.getTopLeft();
106                 for (Handle h : selection)
107                 {
108                         Optional<ComponentInfo> cInfo = h.reqCopy(refPoint);
109                         if(cInfo.isPresent())
110                                 copyBuffer.add(cInfo.get());
111                 }
112         }
113
114         public void paste(double x, double y)
115         {
116                 selection.clear();
117                 for (ComponentInfo info : copyBuffer)
118                 {
119                         GUIComponent comp = addComponent(info.identifier, info.params);
120                         ComponentHandle h = handleManager.getHandle(comp);
121                         h.reqMove(info.relX, info.relY);
122                         selection.add(h);
123                 }
124                 moveSelection(x, y);
125         }
126         
127         public void save()
128         {
129                 saveManager.save();
130         }
131
132         public void addComponent(double x, double y)
133         {
134                 GUIComponent c = addComponent(gui.getAddListSelected(), new JsonObject());
135                 selection.clear();
136                 selection.add(handleManager.getHandle(c));
137                 moveSelection(x, y);
138         }
139         
140         private GUIComponent addComponent(String identifier, JsonElement params)
141         {
142                 GUIComponent comp = IndirectGUIComponentCreator.createComponent(toBeEdited.getSubmodelModifiable(), identifier,
143                                 params);
144                 identifierPerComponent.put(comp, identifier);
145                 return comp;
146         }
147         
148         public static String getIdentifier(GUIComponent c)
149         {
150                 return identifierPerComponent.get(c);
151         }
152
153         public void duplicate()
154         {
155                 copy();
156                 Point origin = selection.getTopLeft();
157                 paste(origin.x + 20, origin.y + 20);
158         }
159
160         private void applySnapping(Point newP)
161         {
162                 switch (snapping)
163                 {
164                 case OFF:
165                         break;
166                 case ABSOLUTE:
167                         newP.x -= newP.x % snapX;
168                         newP.y -= newP.y % snapY;
169                         break;
170                 }
171         }
172
173         public static class ComponentInfo
174         {
175                 public final double relX, relY;
176                 public final String identifier;
177                 public final JsonElement params;
178                 
179                 public ComponentInfo(double relX, double relY, String identifier, JsonElement params)
180                 {
181                         this.relX = relX;
182                         this.relY = relY;
183                         this.identifier = identifier;
184                         this.params = params;
185                 }
186         }
187
188         public Point getCanvasMousePosition()
189         {
190                 //TODO
191                 org.eclipse.swt.graphics.Point canvasLoc = gui.logicCanvas.getLocation(),
192                                 mouseLoc = gui.display.getCursorLocation(), shellLoc = gui.shell.getLocation();
193                 return new Point(mouseLoc.x - shellLoc.x - canvasLoc.x, mouseLoc.y - shellLoc.y - canvasLoc.y);
194         }
195
196         public Point getWorldMousePosition()
197         {
198                 return gui.logicCanvas.canvasToWorldCoords(getCanvasMousePosition());
199         }
200
201         public void addWire(PinHandle a, PinHandle b)
202         {
203                 new GUIWire(toBeEdited.getSubmodelModifiable(), a.getPin(), b.getPin(), new Point[0]);
204         }
205
206         public static enum Snapping
207         {
208                 OFF, ABSOLUTE;
209         }
210         
211         public static void main(String[] args)
212         {
213                 SaveLoadManager.openLoadDialog();
214         }
215 }