fiore@3
|
1 /*
|
fiore@3
|
2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
|
fiore@3
|
3
|
fiore@3
|
4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
|
fiore@3
|
5
|
fiore@3
|
6 This program is free software: you can redistribute it and/or modify
|
fiore@3
|
7 it under the terms of the GNU General Public License as published by
|
fiore@3
|
8 the Free Software Foundation, either version 3 of the License, or
|
fiore@3
|
9 (at your option) any later version.
|
fiore@3
|
10
|
fiore@3
|
11 This program is distributed in the hope that it will be useful,
|
fiore@3
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
fiore@3
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
fiore@3
|
14 GNU General Public License for more details.
|
fiore@3
|
15
|
fiore@3
|
16 You should have received a copy of the GNU General Public License
|
fiore@3
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
fiore@3
|
18 */
|
fiore@3
|
19 package uk.ac.qmul.eecs.ccmi.gui;
|
fiore@3
|
20
|
fiore@3
|
21 import java.awt.Component;
|
fiore@3
|
22 import java.awt.event.ActionEvent;
|
fiore@3
|
23 import java.awt.event.ActionListener;
|
fiore@3
|
24 import java.text.MessageFormat;
|
fiore@3
|
25 import java.util.ArrayList;
|
fiore@3
|
26 import java.util.Collections;
|
fiore@3
|
27 import java.util.Comparator;
|
fiore@3
|
28 import java.util.Iterator;
|
fiore@3
|
29 import java.util.List;
|
fiore@3
|
30 import java.util.ResourceBundle;
|
fiore@3
|
31 import java.util.Set;
|
fiore@3
|
32
|
fiore@3
|
33 import javax.swing.JMenuItem;
|
fiore@3
|
34 import javax.swing.JOptionPane;
|
fiore@3
|
35 import javax.swing.JPopupMenu;
|
fiore@3
|
36
|
fiore@3
|
37 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramElement;
|
fiore@3
|
38 import uk.ac.qmul.eecs.ccmi.diagrammodel.NodeProperties;
|
fiore@3
|
39 import uk.ac.qmul.eecs.ccmi.network.AwarenessMessage;
|
fiore@3
|
40 import uk.ac.qmul.eecs.ccmi.network.Command;
|
fiore@3
|
41 import uk.ac.qmul.eecs.ccmi.network.DiagramEventActionSource;
|
fiore@3
|
42 import uk.ac.qmul.eecs.ccmi.utils.InteractionLog;
|
fiore@3
|
43
|
fiore@3
|
44 /**
|
fiore@3
|
45 * This class provides the two menus to handle nodes and edges on the visual graph. This class
|
fiore@3
|
46 * provides an abstract implementation common to both the node and edge menus. The specific
|
fiore@3
|
47 * implementations are internal static classes, inheriting from this class.
|
fiore@3
|
48 *
|
fiore@3
|
49 */
|
fiore@3
|
50 @SuppressWarnings("serial")
|
fiore@3
|
51 public abstract class CCmIPopupMenu extends JPopupMenu {
|
fiore@3
|
52 /**
|
fiore@3
|
53 * This constructor is called by subclasses constructor.
|
fiore@3
|
54 *
|
fiore@3
|
55 * @param reference the element this menu refers to (it popped up by right-clicking on it)
|
fiore@3
|
56 * @param parentComponent the component where the menu is going to be displayed
|
fiore@3
|
57 * @param modelUpdater the model updater to make changed to {@code reference}
|
fiore@3
|
58 * @param selectedElements other elements eventually selected on the graph, which are going
|
fiore@3
|
59 * to undergo the same changes as {@code reference}, being selected together with it.
|
fiore@3
|
60 */
|
fiore@3
|
61 protected CCmIPopupMenu(DiagramElement reference,
|
fiore@3
|
62 Component parentComponent, DiagramModelUpdater modelUpdater,
|
fiore@3
|
63 Set<DiagramElement> selectedElements) {
|
fiore@3
|
64 super();
|
fiore@3
|
65 this.modelUpdater = modelUpdater;
|
fiore@3
|
66 this.parentComponent = parentComponent;
|
fiore@3
|
67 this.reference = reference;
|
fiore@3
|
68 this.selectedElements = selectedElements;
|
fiore@3
|
69 }
|
fiore@3
|
70
|
fiore@3
|
71 /**
|
fiore@3
|
72 * Returns the the element this menu refers to.
|
fiore@3
|
73 * @return the element this menu refers to.
|
fiore@3
|
74 */
|
fiore@3
|
75 public DiagramElement getElement(){
|
fiore@3
|
76 return reference;
|
fiore@3
|
77 }
|
fiore@3
|
78
|
fiore@3
|
79 /**
|
fiore@3
|
80 * Add the a menu item to this menu. A menu item, once clicked on, will prompt the user for a new name
|
fiore@3
|
81 * for the referee element and will execute the update through the modelUpdater passed as argument
|
fiore@3
|
82 * to the constructor.
|
fiore@3
|
83 */
|
fiore@3
|
84 protected void addNameMenuItem() {
|
fiore@3
|
85 /* add set name menu item */
|
fiore@3
|
86 JMenuItem setNameMenuItem = new JMenuItem(
|
fiore@3
|
87 resources.getString("menu.set_name"));
|
fiore@3
|
88 setNameMenuItem.addActionListener(new ActionListener() {
|
fiore@3
|
89 @Override
|
fiore@3
|
90 public void actionPerformed(ActionEvent e) {
|
fiore@3
|
91 String type = (reference instanceof Node) ? "node" : "edge";
|
fiore@3
|
92 if (!modelUpdater.getLock(reference, Lock.NAME,
|
fiore@3
|
93 new DiagramEventActionSource(DiagramEventSource.GRPH,
|
fiore@3
|
94 Command.Name.SET_NODE_NAME, reference.getId(),reference.getName()))) {
|
fiore@3
|
95 iLog("Could not get the lock on " + type + " for renaming",
|
fiore@3
|
96 DiagramElement.toLogString(reference));
|
fiore@3
|
97 JOptionPane.showMessageDialog(parentComponent,
|
fiore@3
|
98 MessageFormat.format(resources
|
fiore@3
|
99 .getString("dialog.lock_failure.name"),
|
fiore@3
|
100 type));
|
fiore@3
|
101 return;
|
fiore@3
|
102 }
|
fiore@3
|
103 iLog("open rename " + type + " dialog",
|
fiore@3
|
104 DiagramElement.toLogString(reference));
|
fiore@3
|
105 String name = JOptionPane.showInputDialog(parentComponent,
|
fiore@3
|
106 MessageFormat.format(
|
fiore@3
|
107 resources.getString("dialog.input.name"),
|
fiore@3
|
108 reference.getName()), reference.getName());
|
fiore@3
|
109 if (name == null)
|
fiore@3
|
110 iLog("cancel rename " + type + " dialog",
|
fiore@3
|
111 DiagramElement.toLogString(reference));
|
fiore@3
|
112 else
|
fiore@3
|
113 /* node has been locked at selection time */
|
fiore@3
|
114 modelUpdater.setName(reference, name.trim(),
|
fiore@3
|
115 DiagramEventSource.GRPH);
|
fiore@3
|
116 modelUpdater.yieldLock(reference, Lock.NAME,
|
fiore@3
|
117 new DiagramEventActionSource(DiagramEventSource.GRPH,
|
fiore@3
|
118 Command.Name.SET_NODE_NAME, reference.getId(),reference.getName()));
|
fiore@3
|
119 }
|
fiore@3
|
120
|
fiore@3
|
121 });
|
fiore@3
|
122 add(setNameMenuItem);
|
fiore@3
|
123 }
|
fiore@3
|
124
|
fiore@3
|
125 /**
|
fiore@3
|
126 * Add the a delete item to this menu. A menu item, once clicked on, will prompt the user for a confirmation
|
fiore@3
|
127 * for the deletion of referee element and will execute the update through the modelUpdater passed as argument
|
fiore@3
|
128 * to the constructor.
|
fiore@3
|
129 */
|
fiore@3
|
130 protected void addDeleteMenuItem() {
|
fiore@3
|
131 JMenuItem deleteMenuItem = new JMenuItem(resources.getString("menu.delete"));
|
fiore@3
|
132 deleteMenuItem.addActionListener(new ActionListener() {
|
fiore@3
|
133 @Override
|
fiore@3
|
134 public void actionPerformed(ActionEvent evt) {
|
fiore@3
|
135 /* create a new Set to maintain iterator consistency as elementTakenOut will change selectedItems */
|
fiore@3
|
136 List<DiagramElement> workList = new ArrayList<DiagramElement>(selectedElements);
|
fiore@3
|
137 /* right click on an element with no selection involved */
|
fiore@3
|
138 if(workList.isEmpty()){
|
fiore@3
|
139 workList.add(reference);
|
fiore@3
|
140 /* right click on an element with other elements selected, thus we ignore the *
|
fiore@3
|
141 * currently selected elements and try to delete only the right clicked one. */
|
fiore@3
|
142 }else if(!workList.contains(reference)){
|
fiore@3
|
143 workList.clear();
|
fiore@3
|
144 workList.add(reference);
|
fiore@3
|
145 }else{
|
fiore@3
|
146 /* If the right clicked element selected together with other elements, try to *
|
fiore@3
|
147 * delete them all. First delete all edges and then all nodes to keep consistency. *
|
fiore@3
|
148 * We are deleting a bunch of objects and if a node is deleted before an edge *
|
fiore@3
|
149 * attached to it, then an exception will be triggered at the moment of edge *
|
fiore@3
|
150 * deletion because the edge will be already deleted as a result of the node deletion */
|
fiore@3
|
151 Collections.sort(workList, new Comparator<DiagramElement>(){
|
fiore@3
|
152 @Override
|
fiore@3
|
153 public int compare(DiagramElement e1,DiagramElement e2) {
|
fiore@3
|
154 boolean e1isEdge = e1 instanceof Edge;
|
fiore@3
|
155 boolean e2isEdge = e2 instanceof Edge;
|
fiore@3
|
156 if(e1isEdge && !e2isEdge){
|
fiore@3
|
157 return -1;
|
fiore@3
|
158 }
|
fiore@3
|
159 if(!e1isEdge && e2isEdge){
|
fiore@3
|
160 return 1;
|
fiore@3
|
161 }
|
fiore@3
|
162 return 0;
|
fiore@3
|
163 }
|
fiore@3
|
164 });
|
fiore@3
|
165 }
|
fiore@3
|
166
|
fiore@3
|
167 List<DiagramElement>alreadyLockedElements = new ArrayList<DiagramElement>(workList.size());
|
fiore@3
|
168 /* check which, of the selected elements, can be deleted and which ones are currently held by *
|
fiore@3
|
169 * other clients. If an element is locked it's removed from the list and put into a separated set */
|
fiore@3
|
170 for(Iterator<DiagramElement> itr=workList.iterator(); itr.hasNext();){
|
fiore@3
|
171 DiagramElement selected = itr.next();
|
fiore@3
|
172 boolean isNode = selected instanceof Node;
|
fiore@3
|
173 if(!modelUpdater.getLock(selected,
|
fiore@3
|
174 Lock.DELETE,
|
fiore@3
|
175 new DiagramEventActionSource(
|
fiore@3
|
176 DiagramEventSource.GRPH,
|
fiore@3
|
177 isNode ? Command.Name.REMOVE_NODE : Command.Name.REMOVE_EDGE,
|
fiore@3
|
178 selected.getId(),selected.getName()))){
|
fiore@3
|
179 itr.remove();
|
fiore@3
|
180 alreadyLockedElements.add(selected);
|
fiore@3
|
181 }
|
fiore@3
|
182 }
|
fiore@3
|
183
|
fiore@3
|
184 /* all the elements are locked by other clients */
|
fiore@3
|
185 if(workList.isEmpty()){
|
fiore@3
|
186 iLog("Could not get lock on any selected element for deletion","");
|
fiore@3
|
187 JOptionPane.showMessageDialog(
|
fiore@3
|
188 JOptionPane.getFrameForComponent(parentComponent),
|
fiore@3
|
189 alreadyLockedElements.size() == 1 ? // singular vs plural
|
fiore@3
|
190 resources.getString("dialog.lock_failure.delete") :
|
fiore@3
|
191 resources.getString("dialog.lock_failure.deletes"));
|
fiore@3
|
192 return;
|
fiore@3
|
193 }
|
fiore@3
|
194
|
fiore@3
|
195 String warning = "";
|
fiore@3
|
196 if(!alreadyLockedElements.isEmpty()){
|
fiore@3
|
197 StringBuilder builder = new StringBuilder(resources.getString("dialog.lock_failure.deletes_warning"));
|
fiore@3
|
198 for(DiagramElement alreadyLocked : alreadyLockedElements)
|
fiore@3
|
199 builder.append(alreadyLocked.getName()).append(' ');
|
fiore@3
|
200 warning = builder.append('\n').toString();
|
fiore@3
|
201 iLog("Could not get lock on some selected element for deletion",warning);
|
fiore@3
|
202 }
|
fiore@3
|
203
|
fiore@3
|
204 iLog("open delete dialog",warning);
|
fiore@3
|
205 int answer = JOptionPane.showConfirmDialog(
|
fiore@3
|
206 JOptionPane.getFrameForComponent(parentComponent),
|
fiore@3
|
207 warning+resources.getString("dialog.confirm.deletions"),
|
fiore@3
|
208 resources.getString("dialog.confirm.title"),
|
fiore@3
|
209 SpeechOptionPane.YES_NO_OPTION);
|
fiore@3
|
210 if(answer == JOptionPane.YES_OPTION){
|
fiore@3
|
211 /* the user chose to delete the elements, proceed (locks *
|
fiore@3
|
212 * will be automatically removed upon deletion by the server ) */
|
fiore@3
|
213 for(DiagramElement selected : workList){
|
fiore@3
|
214 modelUpdater.takeOutFromCollection(selected,DiagramEventSource.GRPH);
|
fiore@3
|
215 modelUpdater.sendAwarenessMessage(
|
fiore@3
|
216 AwarenessMessage.Name.STOP_A,
|
fiore@3
|
217 new DiagramEventActionSource(DiagramEventSource.TREE,
|
fiore@3
|
218 (selected instanceof Node) ? Command.Name.REMOVE_NODE : Command.Name.REMOVE_EDGE,
|
fiore@3
|
219 selected.getId(),selected.getName())
|
fiore@3
|
220 );
|
fiore@3
|
221 }
|
fiore@3
|
222 }else{
|
fiore@3
|
223 /* the user chose not to delete the elements, release the acquired locks */
|
fiore@3
|
224 for(DiagramElement selected : workList){
|
fiore@3
|
225 /* if it's a node all its attached edges were locked as well */
|
fiore@3
|
226 /*if(selected instanceof Node){ DONE IN THE SERVER
|
fiore@3
|
227 Node n = (Node)selected;
|
fiore@3
|
228 for(int i=0; i<n.getEdgesNum();i++){
|
fiore@3
|
229 modelUpdater.yieldLock(n.getEdgeAt(i), Lock.DELETE);
|
fiore@3
|
230 }}*/
|
fiore@3
|
231 boolean isNode = selected instanceof Node;
|
fiore@3
|
232 modelUpdater.yieldLock(selected,
|
fiore@3
|
233 Lock.DELETE,
|
fiore@3
|
234 new DiagramEventActionSource(
|
fiore@3
|
235 DiagramEventSource.GRPH,
|
fiore@3
|
236 isNode ? Command.Name.REMOVE_NODE : Command.Name.REMOVE_EDGE,
|
fiore@3
|
237 selected.getId(),selected.getName()));
|
fiore@3
|
238 }
|
fiore@3
|
239 iLog("cancel delete node dialog","");
|
fiore@3
|
240 }
|
fiore@3
|
241 }
|
fiore@3
|
242 });
|
fiore@3
|
243 add(deleteMenuItem);
|
fiore@3
|
244 }
|
fiore@3
|
245
|
fiore@3
|
246 /**
|
fiore@3
|
247 * Performs the log in the InteractionLog.
|
fiore@3
|
248 * @param action the action to log.
|
fiore@3
|
249 * @param args additional arguments to add to the log.
|
fiore@3
|
250 *
|
fiore@5
|
251 * @see uk.ac.qmul.eecs.ccmi.utils.InteractionLog
|
fiore@3
|
252 */
|
fiore@3
|
253 protected void iLog(String action, String args) {
|
fiore@3
|
254 InteractionLog.log("GRAPH", action, args);
|
fiore@3
|
255 }
|
fiore@3
|
256
|
fiore@3
|
257 /**
|
fiore@3
|
258 *
|
fiore@3
|
259 * A popup menu to perform changes (e.g. delete, rename etc.) to a node from the visual graph.
|
fiore@3
|
260 *
|
fiore@3
|
261 */
|
fiore@3
|
262 public static class NodePopupMenu extends CCmIPopupMenu {
|
fiore@3
|
263 /**
|
fiore@3
|
264 *
|
fiore@3
|
265 * @param node the node this menu refers to.
|
fiore@3
|
266 * @param parentComponent the component where the menu is going to be displayed.
|
fiore@3
|
267 * @param modelUpdater the model updater used to make changed to {@code node}.
|
fiore@3
|
268 * @param selectedElements other elements eventually selected on the graph, which are going
|
fiore@3
|
269 * to undergo the same changes as {@code node}, being selected together with it.
|
fiore@3
|
270 */
|
fiore@3
|
271 NodePopupMenu(Node node, Component parentComponent,
|
fiore@3
|
272 DiagramModelUpdater modelUpdater,
|
fiore@3
|
273 Set<DiagramElement> selectedElements) {
|
fiore@3
|
274 super(node, parentComponent, modelUpdater, selectedElements);
|
fiore@3
|
275 addNameMenuItem();
|
fiore@3
|
276 addPropertyMenuItem();
|
fiore@3
|
277 addDeleteMenuItem();
|
fiore@3
|
278 }
|
fiore@3
|
279
|
fiore@3
|
280 private void addPropertyMenuItem() {
|
fiore@3
|
281 final Node nodeRef = (Node) reference;
|
fiore@3
|
282 /* if the node has no properties defined, then don't add the menu item */
|
fiore@3
|
283 if(nodeRef.getProperties().isNull())
|
fiore@3
|
284 return;
|
fiore@3
|
285 /* add set property menu item*/
|
fiore@3
|
286 JMenuItem setPropertiesMenuItem = new JMenuItem(resources.getString("menu.set_properties"));
|
fiore@3
|
287 setPropertiesMenuItem.addActionListener(new ActionListener(){
|
fiore@3
|
288 @Override
|
fiore@3
|
289 public void actionPerformed(ActionEvent e) {
|
fiore@3
|
290 if(!modelUpdater.getLock(nodeRef, Lock.PROPERTIES, new DiagramEventActionSource(DiagramEventSource.GRPH,Command.Name.SET_PROPERTIES,nodeRef.getId(),reference.getName()))){
|
fiore@3
|
291 iLog("Could not get the lock on node for properties",DiagramElement.toLogString(nodeRef));
|
fiore@3
|
292 JOptionPane.showMessageDialog(parentComponent, resources.getString("dialog.lock_failure.properties"));
|
fiore@3
|
293 return;
|
fiore@3
|
294 }
|
fiore@3
|
295 iLog("open edit properties dialog",DiagramElement.toLogString(nodeRef));
|
fiore@3
|
296 NodeProperties properties = PropertyEditorDialog.showDialog(JOptionPane.getFrameForComponent(parentComponent),nodeRef.getPropertiesCopy());
|
fiore@3
|
297 if(properties == null){ // user clicked on cancel
|
fiore@3
|
298 iLog("cancel edit properties dialog",DiagramElement.toLogString(nodeRef));
|
fiore@3
|
299 modelUpdater.yieldLock(nodeRef, Lock.PROPERTIES, new DiagramEventActionSource(DiagramEventSource.GRPH,Command.Name.SET_PROPERTIES,nodeRef.getId(),reference.getName()));
|
fiore@3
|
300 return;
|
fiore@3
|
301 }
|
fiore@3
|
302 if(!properties.isNull())
|
fiore@3
|
303 modelUpdater.setProperties(nodeRef,properties,DiagramEventSource.GRPH);
|
fiore@3
|
304 modelUpdater.yieldLock(nodeRef, Lock.PROPERTIES,new DiagramEventActionSource(DiagramEventSource.GRPH,Command.Name.SET_PROPERTIES,nodeRef.getId(),reference.getName()));
|
fiore@3
|
305 }
|
fiore@3
|
306 });
|
fiore@3
|
307 add(setPropertiesMenuItem);
|
fiore@3
|
308 }
|
fiore@3
|
309 }
|
fiore@3
|
310
|
fiore@3
|
311 /**
|
fiore@3
|
312 * A popup menu to perform changes (e.g. delete, rename etc.) to a edge from the visual graph.
|
fiore@3
|
313 */
|
fiore@3
|
314 public static class EdgePopupMenu extends CCmIPopupMenu {
|
fiore@3
|
315 /**
|
fiore@3
|
316 * Constructs an {@code EdgePopupMenu} to perform changes to an edge from the visual diagram.
|
fiore@3
|
317 * This constructor is normally called when the user clicks in the neighbourhood of a node
|
fiore@3
|
318 * connected to this edge. the menu will then include items to change an end label or
|
fiore@3
|
319 * an arrow head.
|
fiore@3
|
320 * @param edge the edge this menu refers to.
|
fiore@3
|
321 * @param node one attached node some menu item will refer to.
|
fiore@3
|
322 * @param parentComponent the component where the menu is going to be displayed.
|
fiore@3
|
323 * @param modelUpdater the model updater used to make changed to {@code edge}.
|
fiore@3
|
324 * @param selectedElements other elements eventually selected on the graph, which are going
|
fiore@3
|
325 * to undergo the same changes as {@code edge}, being selected together with it.
|
fiore@3
|
326 */
|
fiore@3
|
327 public EdgePopupMenu( Edge edge, Node node, Component parentComponent, DiagramModelUpdater modelUpdater,
|
fiore@3
|
328 Set<DiagramElement> selectedElements){
|
fiore@3
|
329 super(edge,parentComponent,modelUpdater,selectedElements);
|
fiore@3
|
330 addNameMenuItem();
|
fiore@3
|
331 if(node != null){
|
fiore@3
|
332 nodeRef = node;
|
fiore@3
|
333 Object[] arrowHeads = new Object[edge.getAvailableEndDescriptions().length + 1];
|
fiore@3
|
334 for(int i=0;i<edge.getAvailableEndDescriptions().length;i++){
|
fiore@3
|
335 arrowHeads[i] = edge.getAvailableEndDescriptions()[i].toString();
|
fiore@3
|
336 }
|
fiore@3
|
337 arrowHeads[arrowHeads.length-1] = Edge.NO_ENDDESCRIPTION_STRING;
|
fiore@3
|
338 addEndMenuItems(arrowHeads);
|
fiore@3
|
339 }
|
fiore@3
|
340 addDeleteMenuItem();
|
fiore@3
|
341 }
|
fiore@3
|
342
|
fiore@3
|
343 /**
|
fiore@3
|
344 * Constructs an {@code EdgePopupMenu} to perform changes to an edge from the visual diagram.
|
fiore@3
|
345 * This constructor is normally called when the user clicks around the midpoint of the edge
|
fiore@3
|
346 * @param edge the edge this menu refers to.
|
fiore@3
|
347 * @param parentComponent the component where the menu is going to be displayed.
|
fiore@3
|
348 * @param modelUpdater the model updater used to make changed to {@code edge}.
|
fiore@3
|
349 * @param selectedElements other elements eventually selected on the graph, which are going
|
fiore@3
|
350 * to undergo the same changes as {@code edge}, being selected together with it.
|
fiore@3
|
351 */
|
fiore@3
|
352 public EdgePopupMenu( Edge edge, Component parentComponent, DiagramModelUpdater modelUpdater,
|
fiore@3
|
353 Set<DiagramElement> selectedElements){
|
fiore@3
|
354 this(edge,null,parentComponent,modelUpdater,selectedElements);
|
fiore@3
|
355 }
|
fiore@3
|
356
|
fiore@3
|
357 private void addEndMenuItems(final Object[] arrowHeads){
|
fiore@3
|
358 final Edge edgeRef = (Edge)reference;
|
fiore@3
|
359 /* Label menu item */
|
fiore@3
|
360 JMenuItem setLabelMenuItem = new JMenuItem(resources.getString("menu.set_label"));
|
fiore@3
|
361 setLabelMenuItem.addActionListener(new ActionListener(){
|
fiore@3
|
362 @Override
|
fiore@3
|
363 public void actionPerformed(ActionEvent evt) {
|
fiore@3
|
364 if(!modelUpdater.getLock(edgeRef, Lock.EDGE_END, new DiagramEventActionSource(DiagramEventSource.GRPH,Command.Name.SET_ENDLABEL,edgeRef.getId(),reference.getName()))){
|
fiore@3
|
365 iLog("Could not get lock on edge for end label",DiagramElement.toLogString(edgeRef)+" end node:"+DiagramElement.toLogString(nodeRef));
|
fiore@3
|
366 JOptionPane.showMessageDialog(parentComponent, resources.getString("dialog.lock_failure.end"));
|
fiore@3
|
367 return;
|
fiore@3
|
368 }
|
fiore@3
|
369 iLog("open edge label dialog",DiagramElement.toLogString(edgeRef)+" end node:"+DiagramElement.toLogString(nodeRef));
|
fiore@3
|
370 String text = JOptionPane.showInputDialog(parentComponent,resources.getString("dialog.input.label"));
|
fiore@3
|
371 if(text != null)
|
fiore@3
|
372 modelUpdater.setEndLabel(edgeRef,nodeRef,text,DiagramEventSource.GRPH);
|
fiore@3
|
373 else
|
fiore@3
|
374 iLog("cancel edge label dialog",DiagramElement.toLogString(edgeRef)+" end node:"+DiagramElement.toLogString(nodeRef));
|
fiore@3
|
375 modelUpdater.yieldLock(edgeRef, Lock.EDGE_END, new DiagramEventActionSource(DiagramEventSource.GRPH,Command.Name.SET_ENDLABEL,edgeRef.getId(),reference.getName()));
|
fiore@3
|
376 }
|
fiore@3
|
377 });
|
fiore@3
|
378 add(setLabelMenuItem);
|
fiore@3
|
379
|
fiore@3
|
380 if(arrowHeads.length > 1){
|
fiore@3
|
381 /* arrow head menu item */
|
fiore@3
|
382 JMenuItem selectArrowHeadMenuItem = new JMenuItem(resources.getString("menu.choose_arrow_head"));
|
fiore@3
|
383 selectArrowHeadMenuItem.addActionListener(new ActionListener(){
|
fiore@3
|
384 @Override
|
fiore@3
|
385 public void actionPerformed(ActionEvent e) {
|
fiore@3
|
386 if(!modelUpdater.getLock(edgeRef, Lock.EDGE_END, new DiagramEventActionSource(DiagramEventSource.GRPH,Command.Name.SET_ENDDESCRIPTION,edgeRef.getId(),reference.getName()))){
|
fiore@3
|
387 iLog("Could not get lock on edge for arrow head",DiagramElement.toLogString(edgeRef)+" end node:"+DiagramElement.toLogString(nodeRef));
|
fiore@3
|
388 JOptionPane.showMessageDialog(parentComponent, resources.getString("dialog.lock_failure.end"));
|
fiore@3
|
389 return;
|
fiore@3
|
390 }
|
fiore@3
|
391 iLog("open select arrow head dialog",DiagramElement.toLogString(edgeRef)+" end node:"+DiagramElement.toLogString(nodeRef));
|
fiore@3
|
392 String arrowHead = (String)JOptionPane.showInputDialog(
|
fiore@3
|
393 parentComponent,
|
fiore@3
|
394 resources.getString("dialog.input.arrow"),
|
fiore@3
|
395 resources.getString("dialog.input.arrow.title"),
|
fiore@3
|
396 JOptionPane.PLAIN_MESSAGE,
|
fiore@3
|
397 null,
|
fiore@3
|
398 arrowHeads,
|
fiore@3
|
399 arrowHeads);
|
fiore@3
|
400 if(arrowHead == null){
|
fiore@3
|
401 iLog("cancel select arrow head dialog",DiagramElement.toLogString(edgeRef)+" end node:"+DiagramElement.toLogString(nodeRef));
|
fiore@3
|
402 modelUpdater.yieldLock(edgeRef, Lock.EDGE_END, new DiagramEventActionSource(DiagramEventSource.GRPH,Command.Name.SET_ENDDESCRIPTION,edgeRef.getId(),reference.getName()));
|
fiore@3
|
403 return;
|
fiore@3
|
404 }
|
fiore@3
|
405 for(int i=0; i<edgeRef.getAvailableEndDescriptions().length;i++){
|
fiore@3
|
406 if(edgeRef.getAvailableEndDescriptions()[i].toString().equals(arrowHead)){
|
fiore@3
|
407 modelUpdater.setEndDescription(edgeRef, nodeRef, i,DiagramEventSource.GRPH);
|
fiore@3
|
408 modelUpdater.yieldLock(edgeRef, Lock.EDGE_END, new DiagramEventActionSource(DiagramEventSource.GRPH,Command.Name.SET_ENDDESCRIPTION,edgeRef.getId(),reference.getName()));
|
fiore@3
|
409 return;
|
fiore@3
|
410 }
|
fiore@3
|
411 }
|
fiore@3
|
412 /* the user selected the none menu item */
|
fiore@3
|
413 modelUpdater.setEndDescription(edgeRef,nodeRef, Edge.NO_END_DESCRIPTION_INDEX,DiagramEventSource.GRPH);
|
fiore@3
|
414 modelUpdater.yieldLock(edgeRef, Lock.EDGE_END, new DiagramEventActionSource(DiagramEventSource.GRPH,Command.Name.SET_ENDDESCRIPTION,edgeRef.getId(),reference.getName()));
|
fiore@3
|
415 }
|
fiore@3
|
416 });
|
fiore@3
|
417 add(selectArrowHeadMenuItem);
|
fiore@3
|
418 }
|
fiore@3
|
419 }
|
fiore@3
|
420
|
fiore@3
|
421 private Node nodeRef;
|
fiore@3
|
422 }
|
fiore@3
|
423
|
fiore@3
|
424 /**
|
fiore@3
|
425 * the model updater used to make changed to {@code reference}.
|
fiore@3
|
426 */
|
fiore@3
|
427 protected DiagramModelUpdater modelUpdater;
|
fiore@3
|
428 /**
|
fiore@3
|
429 * the component where the menu is going to be displayed.
|
fiore@3
|
430 */
|
fiore@3
|
431 protected Component parentComponent;
|
fiore@3
|
432 /**
|
fiore@3
|
433 * the element this menu refers to.
|
fiore@3
|
434 */
|
fiore@3
|
435 protected DiagramElement reference;
|
fiore@3
|
436 /**
|
fiore@3
|
437 * other elements eventually selected on the graph, which are going
|
fiore@3
|
438 * to undergo the same changes as {@code reference}, being selected together with it.
|
fiore@3
|
439 */
|
fiore@3
|
440 protected Set<DiagramElement> selectedElements;
|
fiore@3
|
441 private static ResourceBundle resources = ResourceBundle.getBundle(CCmIPopupMenu.class.getName());
|
fiore@3
|
442 }
|