]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/elements/EditorStateManager.java
Fixed event mask of org.simantics.diagram.elements.TextGridNode
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / elements / EditorStateManager.java
1 package org.simantics.diagram.elements;
2
3 import java.awt.geom.Point2D;
4 import java.awt.geom.Rectangle2D;
5 import java.util.LinkedList;
6 import java.util.List;
7
8 import org.simantics.db.common.utils.Logger;
9 import org.simantics.diagram.elements.EditorState.ModificationClass;
10 import org.simantics.g2d.canvas.ICanvasContext;
11 import org.simantics.g2d.element.IElement;
12 import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent;
13 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;
14 import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
15 import org.simantics.scl.runtime.function.Function1;
16 import org.simantics.scl.runtime.function.Function2;
17
18 import com.kitfox.svg.SVGDiagram;
19 import com.kitfox.svg.SVGElement;
20 import com.kitfox.svg.SVGException;
21 import com.kitfox.svg.Text;
22 import com.kitfox.svg.Tspan;
23 import com.kitfox.svg.animation.AnimationElement;
24
25 /**
26  * @author Antti Villberg
27  * @since 1.31.0
28  */
29 class EditorStateManager {
30
31         static String TERM_STRING = "-----";
32         static String EDITOR_CLASS = "edit";
33         static String EDITOR_ID = "edit";
34         private SVGNode node;
35
36         private LinkedList<EditorState> editorState = null;
37         private int editorStateIndex = 0;
38
39         EditorStateManager(SVGNode node) {
40                 this.node = node;
41         }
42
43         public boolean isEditMode() {
44                 return editorState != null;
45         }
46
47         public EditorState currentState() {
48                 return editorState.get(editorStateIndex);
49         }
50
51         public int currentHash() {
52                 if(!isEditMode()) return 0;
53                 return currentState().hashCode();
54         }
55
56         public void activateEditMode(SVGDiagram diagram, Text text) {
57
58                 if(isEditMode()) return;
59
60                 if(text.getId().length() == 0) return;
61
62                 EditorState es = new EditorState();
63                 es.base = new EditorStateStatic();
64                 es.base.textElementId = text.getId();
65
66                 Tspan span = (Tspan)text.getContent().get(0);
67                 String currentText = span.getText();
68
69                 SingleElementNode sne = node.getSingleElementNode();
70                 if (sne == null)
71                         return;
72
73                 Function1<String,String> fullTextFunction = sne.getParameter("textEditorFullText"); 
74                 if(fullTextFunction != null)
75                         es.currentText = fullTextFunction.apply(es.base.textElementId);
76                 if(es.currentText == null) {
77                         es.currentText = currentText;
78                 }
79
80                 es.caretPosition = es.currentText.length();
81                 es.selectionOtherPosition = 0;
82
83                 // Measure the Y-dimensions of the font
84                 try {
85                         span.setText("Ig");
86                         text.rebuild();
87                         diagram.updateTime(0);
88                         es.base.verticalDimensions = text.getBoundingBox(); 
89                         span.setText(TERM_STRING);
90                         text.rebuild();
91                         diagram.updateTime(0);
92                         es.base.termStringWidth = text.getBoundingBox().getWidth(); 
93                         span.setText(currentText);
94                         text.rebuild();
95                         diagram.updateTime(0);
96                 } catch (SVGException e) {
97                         e.printStackTrace();
98                 }
99
100                 ICanvasContext ctx = DiagramNodeUtil.getCanvasContext(node);
101                 IElement ie = DiagramNodeUtil.getElement(ctx, sne);
102
103                 EditDataNode data = EditDataNode.getNode(node);
104                 deactivateEdit(data, null);
105                 TextEditActivation result = new TextEditActivation(0, ie, ctx);
106                 data.setTextEditActivation(result);
107
108                 editorState = new LinkedList<>();
109                 editorState.push(es);
110                 editorStateIndex = 0;
111
112                 paint();
113
114         }
115
116         private TextEditActivation editActivation;
117
118         void applyEdit() {
119                 SingleElementNode sne = node.getSingleElementNode();
120                 if (sne != null) {
121                         EditorState es = currentState();
122                         Function2<String,String,Object> editor = sne.getParameter("textEditor");
123                         if(editor != null) {
124                                 editor.apply(es.base.textElementId, es.currentText);
125                         }
126                 }
127         }
128
129         protected boolean deactivateEdit() {
130                 boolean result = deactivateEdit( editActivation );
131                 result |= editActivation != null;
132                 editActivation = null;
133                 editorState = null;
134                 paint();
135                 return result;
136         }
137
138         protected boolean deactivateEdit(TextEditActivation activation) {
139                 return deactivateEdit( EditDataNode.getNode(node), activation );
140         }
141
142         protected boolean deactivateEdit(EditDataNode data, TextEditActivation activation) {
143                 TextEditActivation previous = data.getTextEditActivation();
144                 if (previous != null && (previous == activation || activation == null)) {
145                         previous.release();
146                         data.setTextEditActivation(null);
147                         return true;
148                 }
149                 return false;
150         }
151
152         protected boolean keyPressed(KeyPressedEvent e) {
153                 if(isEditMode()) {
154                         EditorState es = currentState();
155                         EditorState nes = es.copy();
156                         if(nes.keyPressed(this, e)) {
157                                 if(!isEditMode()) {
158                                         // This key actually terminated editing
159                                         return true;
160                                 }
161                                 if(nes.shouldReplace(es)) {
162                                         es.replace(nes);
163                                 } else {
164                                         while(editorState.size() > (editorStateIndex + 1))
165                                                 editorState.removeLast();
166                                         editorState.add(nes);
167                                         editorStateIndex = editorState.size() - 1;
168                                 }
169                                 return true; 
170                         }
171                 }
172                 return false;
173         }
174
175
176         public boolean tryToStartEditMode(SVGDiagram diagram) {
177                 SVGElement element = diagram.getElement(EDITOR_ID);
178                 if(element != null && element instanceof Text) {
179                         activateEditMode(diagram, (Text)element);
180                         return true;
181                 }
182                 return false;
183         }
184
185         public boolean tryToStartEditMode(SVGDiagram diagram, MouseClickEvent e) {
186
187                 if(diagram != null) {
188
189                         Point2D local = node.controlToLocal( e.controlPosition );
190                         // FIXME: once the event coordinate systems are cleared up, remove this workaround
191                         local = node.parentToLocal(local);
192
193                         double tolerance = 2.0;
194                         Rectangle2D pickRect = new Rectangle2D.Double(local.getX()-tolerance, local.getY()-tolerance, 2*tolerance, 2*tolerance); 
195
196                         try {
197                                 List<?> retVec = diagram.pick(pickRect, null);
198                                 for(int i=0;i<retVec.size();i++) {
199                                         List<?> l = (List<?>)retVec.get(i);
200                                         for(int j=0;j<l.size();j++) {
201                                                 SVGElement element = (SVGElement)l.get(j);      
202                                                 if(element instanceof Tspan) {
203                                                         return true;
204                                                 }
205                                                 if(element instanceof Text) {
206                                                         Text text = (Text)element;
207                                                         if(text.hasAttribute("class", AnimationElement.AT_XML)) {
208                                                                 String clazz = text.getPresAbsolute("class").getStringValue();
209                                                                 if(clazz.contains(EDITOR_CLASS)) {
210                                                                         activateEditMode(diagram, text);
211                                                                         return true;
212                                                                 }
213                                                         }
214                                                 }
215                                         }
216                                 }
217
218                         } catch (SVGException e1) {
219                                 Logger.defaultLogError(e1);
220                         }
221                 }
222
223                 return false;
224
225         }
226
227         boolean applyEditMode(SVGDiagram diagram) throws SVGException {
228
229                 if(isEditMode()) {
230                         EditorState es = currentState();
231                         es.applyEditMode(diagram);
232                         return true;
233                 }
234
235                 return false;
236
237         }
238
239         void paint() {
240                 node.cleanDiagramCache();
241                 node.repaint();
242         }
243
244         void undo() {
245                 while(editorStateIndex > 0 && currentState().modificationClass.equals(ModificationClass.NO_EDIT)) {
246                         editorStateIndex--;
247                 }
248                 if(editorStateIndex > 0)
249                         editorStateIndex--;
250                 paint();
251         }
252
253         void redo() {
254                 while(editorStateIndex < editorState.size() - 1 && currentState().modificationClass.equals(ModificationClass.NO_EDIT)) {
255                         editorStateIndex++;
256                 }
257                 if(editorStateIndex < editorState.size() - 1) {
258                         editorStateIndex++;
259                 }
260                 paint();
261         }
262
263 }