Mercurial > hg > ccmieditor
comparison java/src/uk/ac/qmul/eecs/ccmi/gui/GraphPanel.java @ 3:9e67171477bc
PHANTOM Omni Heptic device release
author | Fiore Martin <fiore@eecs.qmul.ac.uk> |
---|---|
date | Wed, 25 Apr 2012 17:09:09 +0100 |
parents | 9418ab7b7f3f |
children | d66dd5880081 |
comparison
equal
deleted
inserted
replaced
2:4b2f975e35fa | 3:9e67171477bc |
---|---|
22 | 22 |
23 import java.awt.Color; | 23 import java.awt.Color; |
24 import java.awt.Dimension; | 24 import java.awt.Dimension; |
25 import java.awt.Graphics; | 25 import java.awt.Graphics; |
26 import java.awt.Graphics2D; | 26 import java.awt.Graphics2D; |
27 import java.awt.event.ActionEvent; | |
28 import java.awt.event.InputEvent; | 27 import java.awt.event.InputEvent; |
29 import java.awt.event.KeyEvent; | |
30 import java.awt.event.MouseAdapter; | 28 import java.awt.event.MouseAdapter; |
31 import java.awt.event.MouseEvent; | 29 import java.awt.event.MouseEvent; |
32 import java.awt.event.MouseMotionAdapter; | 30 import java.awt.event.MouseMotionAdapter; |
33 import java.awt.geom.Point2D; | 31 import java.awt.geom.Point2D; |
34 import java.awt.geom.Rectangle2D; | 32 import java.awt.geom.Rectangle2D; |
38 import java.util.LinkedList; | 36 import java.util.LinkedList; |
39 import java.util.List; | 37 import java.util.List; |
40 import java.util.ResourceBundle; | 38 import java.util.ResourceBundle; |
41 import java.util.Set; | 39 import java.util.Set; |
42 | 40 |
43 import javax.swing.AbstractAction; | |
44 import javax.swing.JOptionPane; | 41 import javax.swing.JOptionPane; |
45 import javax.swing.JPanel; | 42 import javax.swing.JPanel; |
46 import javax.swing.KeyStroke; | |
47 | 43 |
48 import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionEvent; | 44 import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionEvent; |
49 import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionListener; | 45 import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionListener; |
50 import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionModel; | 46 import uk.ac.qmul.eecs.ccmi.diagrammodel.CollectionModel; |
51 import uk.ac.qmul.eecs.ccmi.diagrammodel.ConnectNodesException; | 47 import uk.ac.qmul.eecs.ccmi.diagrammodel.ConnectNodesException; |
52 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramElement; | 48 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramElement; |
53 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramModelTreeNode; | |
54 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramNode; | 49 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramNode; |
50 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramTreeNode; | |
55 import uk.ac.qmul.eecs.ccmi.diagrammodel.ElementChangedEvent; | 51 import uk.ac.qmul.eecs.ccmi.diagrammodel.ElementChangedEvent; |
52 import uk.ac.qmul.eecs.ccmi.network.Command; | |
53 import uk.ac.qmul.eecs.ccmi.network.DiagramEventActionSource; | |
56 import uk.ac.qmul.eecs.ccmi.utils.InteractionLog; | 54 import uk.ac.qmul.eecs.ccmi.utils.InteractionLog; |
57 | 55 |
58 /** | 56 /** |
59 * A panel to draw a graph | 57 * A panel to draw a graph |
60 */ | 58 */ |
86 | 84 |
87 selectedElements = new HashSet<DiagramElement>(); | 85 selectedElements = new HashSet<DiagramElement>(); |
88 moveLockedElements = new HashSet<Object>(); | 86 moveLockedElements = new HashSet<Object>(); |
89 | 87 |
90 toolbar.addEdgeCreatedListener(new innerEdgeListener()); | 88 toolbar.addEdgeCreatedListener(new innerEdgeListener()); |
91 | |
92 getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,0),"delete"); | |
93 getActionMap().put("delete", new AbstractAction(){ | |
94 @Override | |
95 public void actionPerformed(ActionEvent evt) { | |
96 /* nothing selected DELETE key has no effect */ | |
97 if(selectedElements.isEmpty()) | |
98 return; | |
99 /* create a new Set to maintain iterator consistency as elementTakenOut will change selectedItems */ | |
100 HashSet<DiagramElement> iterationSet = new HashSet<DiagramElement>(selectedElements); | |
101 HashSet<DiagramElement>alreadyLockedElements = new HashSet<DiagramElement>(); | |
102 /* check which, of the selected elements, can be deleted and which ones are currently held by * | |
103 * other clients. If an element is locked it's removed from the list and put into a separated set */ | |
104 for(Iterator<DiagramElement> itr=iterationSet.iterator(); itr.hasNext();){ | |
105 DiagramElement selected = itr.next(); | |
106 if(!modelUpdater.getLock(selected, Lock.DELETE)){ | |
107 itr.remove(); | |
108 alreadyLockedElements.add(selected); | |
109 } | |
110 } | |
111 ResourceBundle resources = ResourceBundle.getBundle(EditorFrame.class.getName()); | |
112 /* all the elements are locked by other clients */ | |
113 if(iterationSet.isEmpty()){ | |
114 iLog("Could not get lock on any selected element for deletion",""); | |
115 JOptionPane.showMessageDialog( | |
116 JOptionPane.getFrameForComponent(GraphPanel.this), | |
117 alreadyLockedElements.size() == 1 ? // singular vs plural | |
118 resources.getString("dialog.lock_failure.delete") : | |
119 resources.getString("dialog.lock_failure.deletes")); | |
120 return; | |
121 } | |
122 | |
123 String warning = ""; | |
124 if(!alreadyLockedElements.isEmpty()){ | |
125 StringBuilder builder = new StringBuilder(resources.getString("dialog.lock_failure.deletes_warning")); | |
126 for(DiagramElement alreadyLocked : alreadyLockedElements) | |
127 builder.append(alreadyLocked.getName()).append(' '); | |
128 warning = builder.append('\n').toString(); | |
129 iLog("Could not get lock on some selected element for deletion",warning); | |
130 } | |
131 | |
132 iLog("open delete dialog",warning); | |
133 int answer = JOptionPane.showConfirmDialog( | |
134 JOptionPane.getFrameForComponent(GraphPanel.this), | |
135 warning+resources.getString("dialog.confirm.deletions"), | |
136 resources.getString("dialog.confirm.title"), | |
137 SpeechOptionPane.YES_NO_OPTION); | |
138 if(answer == JOptionPane.YES_OPTION){ | |
139 /* the user chose to delete the elements, proceed (locks * | |
140 * will be automatically removed upon deletion by the server ) */ | |
141 for(DiagramElement selected : iterationSet) | |
142 modelUpdater.takeOutFromCollection(selected); | |
143 }else{ | |
144 /* the user chose not to delete the elements, release the acquired locks */ | |
145 for(DiagramElement selected : iterationSet){ | |
146 /* if it's a node all its attached edges were locked as well */ | |
147 /*if(selected instanceof Node){ DONE IN THE SERVER | |
148 Node n = (Node)selected; | |
149 for(int i=0; i<n.getEdgesNum();i++){ | |
150 modelUpdater.yieldLock(n.getEdgeAt(i), Lock.DELETE); | |
151 } | |
152 }*/ | |
153 modelUpdater.yieldLock(selected, Lock.DELETE); | |
154 } | |
155 iLog("cancel delete node dialog",""); | |
156 } | |
157 }}); | |
158 | 89 |
159 /* ---- COLLECTION LISTENER ---- | 90 /* ---- COLLECTION LISTENER ---- |
160 * Adding a collection listener. This listener reacts at changes in the model | 91 * Adding a collection listener. This listener reacts at changes in the model |
161 * by any source, and thus the graph itself. Basically it refreshes the graph | 92 * by any source, and thus the graph itself. Basically it refreshes the graph |
162 * and paints again all the nodes and edges. | 93 * and paints again all the nodes and edges. |
168 if(element instanceof Node) | 99 if(element instanceof Node) |
169 nodes.add((Node)element); | 100 nodes.add((Node)element); |
170 else | 101 else |
171 edges.add((Edge)element); | 102 edges.add((Edge)element); |
172 checkBounds(element,false); | 103 checkBounds(element,false); |
173 if(e.getDiagramElement() instanceof Node && e.getSource().equals(model) ){ //FIXME change model into this model source changes | 104 if(e.getDiagramElement() instanceof Node && e.getSource().equals(DiagramEventSource.GRPH)){ |
174 setElementSelected(e.getDiagramElement()); | 105 setElementSelected(e.getDiagramElement()); |
175 dragMode = DRAG_NODE; | 106 dragMode = DRAG_NODE; |
176 } | 107 } |
177 revalidate(); | 108 revalidate(); |
178 repaint(); | 109 repaint(); |
179 } | 110 } |
180 @Override | 111 @Override |
181 public void elementTakenOut(final CollectionEvent e) { | 112 public void elementTakenOut(final CollectionEvent e) { |
182 DiagramElement element = e.getDiagramElement(); | 113 DiagramElement element = e.getDiagramElement(); |
183 if(element instanceof Node){ | 114 if(element instanceof Node){ |
184 if(nodePopup != null && nodePopup.nodeRef.equals(element)) | 115 if(nodePopup != null && nodePopup.getElement().equals(element)) |
185 nodePopup.setVisible(false); | 116 nodePopup.setVisible(false); |
186 nodes.remove(element); | 117 nodes.remove(element); |
187 } | 118 } |
188 else{ | 119 else{ |
189 if(edgePopup != null && edgePopup.edgeRef.equals(element)) | 120 if(edgePopup != null && edgePopup.getElement().equals(element)) |
190 edgePopup.setVisible(false); | 121 edgePopup.setVisible(false); |
191 edges.remove(element); | 122 edges.remove(element); |
192 } | 123 } |
193 checkBounds(e.getDiagramElement(),true); | 124 checkBounds(e.getDiagramElement(),true); |
194 removeElementFromSelection(e.getDiagramElement()); | 125 removeElementFromSelection(e.getDiagramElement()); |
227 if((event.getModifiers() & InputEvent.BUTTON1_MASK) == 0) { | 158 if((event.getModifiers() & InputEvent.BUTTON1_MASK) == 0) { |
228 if(e != null){ | 159 if(e != null){ |
229 if( e.contains(mousePoint)){ | 160 if( e.contains(mousePoint)){ |
230 Node extremityNode = e.getClosestNode(mousePoint,EDGE_END_MIN_CLICK_DIST); | 161 Node extremityNode = e.getClosestNode(mousePoint,EDGE_END_MIN_CLICK_DIST); |
231 if(extremityNode == null){ // click far from the attached nodes, only prompt with set name item | 162 if(extremityNode == null){ // click far from the attached nodes, only prompt with set name item |
232 EdgePopupMenu pop = new EdgePopupMenu(e,GraphPanel.this,modelUpdater); | 163 CCmIPopupMenu.EdgePopupMenu pop = new CCmIPopupMenu.EdgePopupMenu(e,GraphPanel.this,modelUpdater,selectedElements); |
233 edgePopup = pop; | 164 edgePopup = pop; |
234 pop.show(GraphPanel.this, event.getX(), event.getY()); | 165 pop.show(GraphPanel.this, event.getX(), event.getY()); |
235 }else{ // click near an attached nodes, prompt for name change, set end label and select arrow head | 166 }else{ // click near an attached nodes, prompt for name change, set end label and select arrow head |
236 EdgePopupMenu pop = new EdgePopupMenu(e,extremityNode,GraphPanel.this,modelUpdater); | 167 CCmIPopupMenu.EdgePopupMenu pop = new CCmIPopupMenu.EdgePopupMenu(e,extremityNode,GraphPanel.this,modelUpdater,selectedElements); |
237 edgePopup = pop; | 168 edgePopup = pop; |
238 pop.show(GraphPanel.this, event.getX(), event.getY()); | 169 pop.show(GraphPanel.this, event.getX(), event.getY()); |
239 } | 170 } |
240 } | 171 } |
241 }else if(n != null){ | 172 }else if(n != null){ |
242 NodePopupMenu pop = new NodePopupMenu(n,GraphPanel.this,modelUpdater); | 173 CCmIPopupMenu.NodePopupMenu pop = new CCmIPopupMenu.NodePopupMenu(n,GraphPanel.this,modelUpdater,selectedElements); |
243 nodePopup = pop; | 174 nodePopup = pop; |
244 pop.show(GraphPanel.this, event.getX(), event.getY()); | 175 pop.show(GraphPanel.this, event.getX(), event.getY()); |
245 }else | 176 }else |
246 return; | 177 return; |
247 } | 178 } |
248 | 179 |
249 /* - one click && palette == select - */ | 180 /* - one click && palette == select - */ |
250 else if (tool == null){ | 181 else if (tool == null){ |
251 if(n != null){ // node selected | 182 if(n != null){ // node selected |
252 if (isCtrl) | 183 if (isCtrl){ |
253 addElementToSelection(n,false); | 184 addElementToSelection(n,false); |
254 else | 185 }else{ |
255 setElementSelected(n); | 186 setElementSelected(n); |
187 } | |
256 dragMode = DRAG_NODE; | 188 dragMode = DRAG_NODE; |
257 }else if (e != null){ // edge selected | 189 }else if (e != null){ // edge selected |
258 if (isCtrl){ | 190 if (isCtrl){ |
259 addElementToSelection(e,false); | 191 addElementToSelection(e,false); |
260 dragMode = DRAG_NODE; | 192 dragMode = DRAG_NODE; |
261 }else{ | 193 }else{ |
262 setElementSelected(e); | 194 setElementSelected(e); |
263 modelUpdater.startMove(e, mousePoint); | 195 modelUpdater.startMove(e, mousePoint,DiagramEventSource.GRPH); |
264 dragMode = DRAG_EDGE; | 196 dragMode = DRAG_EDGE; |
265 } | 197 } |
266 }else{ // nothing selected : make selection lasso | 198 }else{ // nothing selected : make selection lasso |
267 if (!isCtrl) | 199 if (!isCtrl) |
268 clearSelection(); | 200 clearSelection(); |
282 Node prototype = (Node) tool; | 214 Node prototype = (Node) tool; |
283 Node newNode = (Node) prototype.clone(); | 215 Node newNode = (Node) prototype.clone(); |
284 Rectangle2D bounds = newNode.getBounds(); | 216 Rectangle2D bounds = newNode.getBounds(); |
285 /* perform the translation from the origin */ | 217 /* perform the translation from the origin */ |
286 newNode.translate(new Point2D.Double(), mousePoint.getX() - bounds.getX(), | 218 newNode.translate(new Point2D.Double(), mousePoint.getX() - bounds.getX(), |
287 mousePoint.getY() - bounds.getY()); | 219 mousePoint.getY() - bounds.getY(),DiagramEventSource.NONE); |
288 /* log stuff */ | 220 /* log stuff */ |
289 iLog("insert node",""+((newNode.getId() == DiagramElement.NO_ID) ? "(no id)" : newNode.getId())); | 221 iLog("insert node",""+((newNode.getId() == DiagramElement.NO_ID) ? "(no id)" : newNode.getId())); |
290 /* insert the node into the model (no lock needed) */ | 222 /* insert the node into the model (no lock needed) */ |
291 modelUpdater.insertInCollection(newNode); | 223 modelUpdater.insertInCollection(newNode,DiagramEventSource.GRPH); |
292 } | 224 } |
293 } | 225 } |
294 | 226 |
295 lastMousePoint = mousePoint; | 227 lastMousePoint = mousePoint; |
296 mouseDownPoint = mousePoint; | 228 mouseDownPoint = mousePoint; |
302 final Point2D mousePoint = new Point2D.Double( | 234 final Point2D mousePoint = new Point2D.Double( |
303 (event.getX()+minX)/zoom, | 235 (event.getX()+minX)/zoom, |
304 (event.getY()+minY)/zoom | 236 (event.getY()+minY)/zoom |
305 ); | 237 ); |
306 if(lastSelected != null){ | 238 if(lastSelected != null){ |
307 if(lastSelected instanceof Node){ | 239 if(lastSelected instanceof Node || selectedElements.size() > 1){ // differentiate between translate and edge bending |
308 if(wasMoving){ | 240 if(wasMoving){ |
309 iLog("move selected stop",mousePoint.getX()+" "+ mousePoint.getY()); | 241 iLog("move selected stop",mousePoint.getX()+" "+ mousePoint.getY()); |
310 for(Object element : moveLockedElements){ | 242 for(Object element : moveLockedElements){ |
311 modelUpdater.stopMove((GraphElement)element); | 243 modelUpdater.stopMove((GraphElement)element,DiagramEventSource.GRPH); |
312 modelUpdater.yieldLock((DiagramModelTreeNode)element, Lock.MOVE); | 244 boolean isNode = element instanceof Node; |
245 modelUpdater.yieldLock((DiagramTreeNode)element, | |
246 Lock.MOVE, | |
247 new DiagramEventActionSource( | |
248 DiagramEventSource.GRPH, | |
249 isNode ? Command.Name.STOP_NODE_MOVE : Command.Name.STOP_EDGE_MOVE, | |
250 ((DiagramElement)element).getId(),((DiagramElement)element).getName())); | |
313 } | 251 } |
314 moveLockedElements.clear(); | 252 moveLockedElements.clear(); |
315 } | 253 } |
316 }else{ // instanceof Edge | 254 }else{ // instanceof Edge && selectedelements.size() = 1. Bending |
317 if(wasMoving){ | 255 if(wasMoving){ |
318 iLog("bend edge stop",mousePoint.getX()+" "+ mousePoint.getY()); | 256 iLog("bend edge stop",mousePoint.getX()+" "+ mousePoint.getY()); |
319 if(moveLockedEdge != null){ | 257 if(moveLockedEdge != null){ |
320 modelUpdater.stopMove(moveLockedEdge); | 258 modelUpdater.stopMove(moveLockedEdge,DiagramEventSource.GRPH); |
321 modelUpdater.yieldLock(moveLockedEdge, Lock.MOVE); | 259 modelUpdater.yieldLock(moveLockedEdge, Lock.MOVE, new DiagramEventActionSource( |
260 DiagramEventSource.GRPH, | |
261 Command.Name.BEND, | |
262 moveLockedEdge.getId(), | |
263 moveLockedEdge.getName())); | |
322 moveLockedEdge = null; | 264 moveLockedEdge = null; |
323 } | 265 } |
324 } | 266 } |
325 } | 267 } |
326 } | 268 } |
346 wasMoving = true; | 288 wasMoving = true; |
347 /* when the motion starts, we need to get the move-lock from the server */ | 289 /* when the motion starts, we need to get the move-lock from the server */ |
348 Iterator<DiagramElement> iterator = selectedElements.iterator(); | 290 Iterator<DiagramElement> iterator = selectedElements.iterator(); |
349 while(iterator.hasNext()){ | 291 while(iterator.hasNext()){ |
350 DiagramElement element = iterator.next(); | 292 DiagramElement element = iterator.next(); |
351 if(modelUpdater.getLock(element, Lock.MOVE)){ | 293 boolean isNode = element instanceof Node; |
294 if(modelUpdater.getLock(element, | |
295 Lock.MOVE, | |
296 new DiagramEventActionSource( | |
297 DiagramEventSource.GRPH, | |
298 isNode ? Command.Name.TRANSLATE_NODE : Command.Name.TRANSLATE_EDGE, | |
299 element.getId(), | |
300 element.getName()))){ | |
352 moveLockedElements.add(element); | 301 moveLockedElements.add(element); |
353 }else{ | 302 }else{ |
354 iLog("Could not get move lock for element",DiagramElement.toLogString(element)); | 303 iLog("Could not get move lock for element",DiagramElement.toLogString(element)); |
355 iterator.remove(); | 304 iterator.remove(); |
356 } | 305 } |
358 iLog("move selected start",mousePoint.getX()+" "+ mousePoint.getY()); | 307 iLog("move selected start",mousePoint.getX()+" "+ mousePoint.getY()); |
359 } | 308 } |
360 | 309 |
361 for (DiagramElement selected : selectedElements){ | 310 for (DiagramElement selected : selectedElements){ |
362 if(selected instanceof Node) | 311 if(selected instanceof Node) |
363 modelUpdater.translate((Node)selected, lastMousePoint, dx, dy); | 312 modelUpdater.translate((Node)selected, lastMousePoint, dx, dy,DiagramEventSource.GRPH); |
364 else | 313 else |
365 modelUpdater.translate((Edge)selected, lastMousePoint, dx, dy); | 314 modelUpdater.translate((Edge)selected, lastMousePoint, dx, dy,DiagramEventSource.GRPH); |
366 } | 315 } |
367 } else if(dragMode == DRAG_EDGE){ | 316 } else if(dragMode == DRAG_EDGE){ |
368 if(!wasMoving){ | 317 if(!wasMoving){ |
369 wasMoving = true; | 318 wasMoving = true; |
370 if(modelUpdater.getLock(lastSelected, Lock.MOVE)) | 319 if(modelUpdater.getLock(lastSelected, |
320 Lock.MOVE, | |
321 new DiagramEventActionSource( | |
322 DiagramEventSource.GRPH, | |
323 Command.Name.BEND, | |
324 lastSelected.getId(), | |
325 lastSelected.getName())) | |
326 ){ | |
371 moveLockedEdge = (Edge)lastSelected; | 327 moveLockedEdge = (Edge)lastSelected; |
372 else | 328 }else{ |
373 iLog("Could not get move lock for element",DiagramElement.toLogString(lastSelected)); | 329 iLog("Could not get move lock for element",DiagramElement.toLogString(lastSelected)); |
330 } | |
374 iLog("bend edge start",mousePoint.getX()+" "+ mousePoint.getY()); | 331 iLog("bend edge start",mousePoint.getX()+" "+ mousePoint.getY()); |
375 } | 332 } |
376 if(moveLockedEdge != null) | 333 if(moveLockedEdge != null) |
377 modelUpdater.bend(moveLockedEdge, new Point2D.Double(mousePoint.getX(), mousePoint.getY())); | 334 modelUpdater.bend(moveLockedEdge, new Point2D.Double(mousePoint.getX(), mousePoint.getY()),DiagramEventSource.GRPH); |
378 } else if (dragMode == DRAG_LASSO){ | 335 } else if (dragMode == DRAG_LASSO){ |
379 double x1 = mouseDownPoint.getX(); | 336 double x1 = mouseDownPoint.getX(); |
380 double y1 = mouseDownPoint.getY(); | 337 double y1 = mouseDownPoint.getY(); |
381 double x2 = mousePoint.getX(); | 338 double x2 = mousePoint.getX(); |
382 double y2 = mousePoint.getY(); | 339 double y2 = mousePoint.getY(); |
696 if(element instanceof Node) | 653 if(element instanceof Node) |
697 nodesToConnect.add((Node)element); | 654 nodesToConnect.add((Node)element); |
698 } | 655 } |
699 try { | 656 try { |
700 e.connect(nodesToConnect); | 657 e.connect(nodesToConnect); |
701 modelUpdater.insertInCollection(e); | 658 /* perform the command, no lock is needed for inserting */ |
659 modelUpdater.insertInCollection(e,DiagramEventSource.GRPH); | |
702 } catch (ConnectNodesException cnEx) { | 660 } catch (ConnectNodesException cnEx) { |
703 JOptionPane.showMessageDialog(GraphPanel.this, | 661 JOptionPane.showMessageDialog(GraphPanel.this, |
704 cnEx.getLocalizedMessage(), | 662 cnEx.getLocalizedMessage(), |
705 ResourceBundle.getBundle(EditorFrame.class.getName()).getString("dialog.error.title"), | 663 ResourceBundle.getBundle(EditorFrame.class.getName()).getString("dialog.error.title"), |
706 JOptionPane.ERROR_MESSAGE); | 664 JOptionPane.ERROR_MESSAGE); |
714 private DiagramModelUpdater modelUpdater; | 672 private DiagramModelUpdater modelUpdater; |
715 private CollectionModel<Node,Edge> model; | 673 private CollectionModel<Node,Edge> model; |
716 | 674 |
717 private Grid grid; | 675 private Grid grid; |
718 private GraphToolbar toolbar; | 676 private GraphToolbar toolbar; |
719 private NodePopupMenu nodePopup; | 677 private CCmIPopupMenu.NodePopupMenu nodePopup; |
720 private EdgePopupMenu edgePopup; | 678 private CCmIPopupMenu.EdgePopupMenu edgePopup; |
721 | 679 |
722 private double zoom; | 680 private double zoom; |
723 private double gridSize; | 681 private double gridSize; |
724 private boolean hideGrid; | 682 private boolean hideGrid; |
725 private boolean wasMoving; | 683 private boolean wasMoving; |