View Javadoc

1   /**********************************************
2    * Copyright (C) 2010 Lukas Laag
3    * This file is part of svgreal.
4    * 
5    * svgreal is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    * 
10   * svgreal is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License
16   * along with svgreal.  If not, see http://www.gnu.org/licenses/
17   **********************************************/
18  package org.vectomatic.svg.edit.client;
19  
20  import java.util.HashMap;
21  import java.util.Map;
22  
23  import org.vectomatic.dom.svg.OMSVGSVGElement;
24  import org.vectomatic.dom.svg.ui.SVGImage;
25  import org.vectomatic.dom.svg.utils.SVGConstants;
26  import org.vectomatic.svg.edit.client.command.EditTitleCommandFactory;
27  import org.vectomatic.svg.edit.client.engine.SVGModel;
28  import org.vectomatic.svg.edit.client.event.RotationEvent;
29  import org.vectomatic.svg.edit.client.event.RotationHandler;
30  import org.vectomatic.svg.edit.client.gxt.layout.AbsoluteLayerLayout;
31  import org.vectomatic.svg.edit.client.gxt.layout.AbsoluteLayerLayoutData;
32  import org.vectomatic.svg.edit.client.gxt.widget.Compass;
33  import org.vectomatic.svg.edit.client.gxt.widget.KeyNavExt;
34  import org.vectomatic.svg.edit.client.gxt.widget.SVGTreePanelDragSource;
35  import org.vectomatic.svg.edit.client.gxt.widget.SVGTreePanelDropTarget;
36  import org.vectomatic.svg.edit.client.gxt.widget.TreePanelExt;
37  import org.vectomatic.svg.edit.client.model.ModelConstants;
38  import org.vectomatic.svg.edit.client.model.ValidationError.Severity;
39  import org.vectomatic.svg.edit.client.model.svg.SVGElementModel;
40  import org.vectomatic.svg.edit.client.utils.DecoratedImageCache.HAlign;
41  import org.vectomatic.svg.edit.client.utils.DecoratedImageCache.VAlign;
42  
43  import com.extjs.gxt.ui.client.Style;
44  import com.extjs.gxt.ui.client.Style.LayoutRegion;
45  import com.extjs.gxt.ui.client.data.ChangeEvent;
46  import com.extjs.gxt.ui.client.data.ChangeListener;
47  import com.extjs.gxt.ui.client.data.ModelData;
48  import com.extjs.gxt.ui.client.data.ModelIconProvider;
49  import com.extjs.gxt.ui.client.dnd.DND.Feedback;
50  import com.extjs.gxt.ui.client.event.BaseEvent;
51  import com.extjs.gxt.ui.client.event.ComponentEvent;
52  import com.extjs.gxt.ui.client.event.DragEvent;
53  import com.extjs.gxt.ui.client.event.Events;
54  import com.extjs.gxt.ui.client.event.Listener;
55  import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
56  import com.extjs.gxt.ui.client.event.SelectionProvider;
57  import com.extjs.gxt.ui.client.event.SelectionService;
58  import com.extjs.gxt.ui.client.event.SliderEvent;
59  import com.extjs.gxt.ui.client.event.TreePanelEvent;
60  import com.extjs.gxt.ui.client.store.Record;
61  import com.extjs.gxt.ui.client.store.TreeStore;
62  import com.extjs.gxt.ui.client.util.Margins;
63  import com.extjs.gxt.ui.client.util.Rectangle;
64  import com.extjs.gxt.ui.client.util.Size;
65  import com.extjs.gxt.ui.client.widget.Component;
66  import com.extjs.gxt.ui.client.widget.Editor;
67  import com.extjs.gxt.ui.client.widget.LayoutContainer;
68  import com.extjs.gxt.ui.client.widget.Slider;
69  import com.extjs.gxt.ui.client.widget.Window;
70  import com.extjs.gxt.ui.client.widget.form.TextField;
71  import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
72  import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
73  import com.extjs.gxt.ui.client.widget.layout.FitData;
74  import com.extjs.gxt.ui.client.widget.layout.FitLayout;
75  import com.extjs.gxt.ui.client.widget.menu.Menu;
76  import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.TreeNode;
77  import com.extjs.gxt.ui.client.widget.treepanel.TreePanelSelectionModel;
78  import com.extjs.gxt.ui.client.widget.treepanel.TreePanelView;
79  import com.google.gwt.core.client.GWT;
80  import com.google.gwt.dom.client.Style.Unit;
81  import com.google.gwt.event.dom.client.MouseMoveEvent;
82  import com.google.gwt.event.dom.client.MouseOutEvent;
83  import com.google.gwt.event.dom.client.MouseOutHandler;
84  import com.google.gwt.event.dom.client.MouseOverEvent;
85  import com.google.gwt.event.dom.client.MouseOverHandler;
86  import com.google.gwt.resources.client.ImageResource;
87  import com.google.gwt.user.client.ui.AbstractImagePrototype;
88  
89  /**
90   * GXT window class dedicated to displaying and editing
91   * a single SVG image. The window has several layers: the
92   * bottom layer contains the SVG image itself and the top
93   * layer contains widgets to manipulate it (rotation compass
94   * and scale slider).
95   * @author laaglu
96   */
97  public class SVGWindow extends Window {
98  	public static final String WINDOW_ACTIVE_STYLE = "x-window-active";
99  	/**
100 	 * The SVG model backing this window
101 	 */
102 	private SVGModel svgModel;
103 	/**
104 	 * The SVG rotation compass
105 	 */
106 	protected Compass compass;
107 	/**
108 	 * The SVG scale slider
109 	 */
110 	protected Slider scaleSlider;
111 	/**
112 	 * The navigation tree
113 	 */
114 	protected TreePanelExt<SVGElementModel> tree;
115 	/**
116 	 * The contextual menu
117 	 */
118 	protected Menu contextMenu;
119 	/**
120 	 * True when the context menu is displayed
121 	 */
122 	protected boolean displaysContextMenu;
123 	/**
124 	 * To control keyboard input
125 	 */
126 	protected KeyNavExt<ComponentEvent> keyNav;
127 	/**
128 	 * The drag'n'drop source
129 	 */
130 	protected SVGTreePanelDragSource dndSource;
131 	/**
132 	 * The drag'n'drop source
133 	 */
134 	protected SVGTreePanelDropTarget dndTarget;
135 	/**
136 	 * Constructor
137 	 * @param svgModel
138 	 * The SVG model to display
139 	 */
140 	public SVGWindow(final SVGModel svgModel) {
141 		super();
142 		keyNav = new KeyNavExt<ComponentEvent>(this) {
143 			@Override
144 			public void onKeyPress(ComponentEvent ce) {
145 				svgModel.onKeyPress(ce);
146 			}
147 			@Override
148 			public void onKeyUp(ComponentEvent ce) {
149 				svgModel.onKeyUp(ce);
150 			}
151 		};
152 		this.svgModel = svgModel;
153 		setPlain(true);
154 		setMaximizable(true);
155 		setMinWidth(200);
156 		setMinHeight(170);
157 		
158 		// Listen to model name changes
159 		svgModel.getRoot().addChangeListener(new ChangeListener() {
160 			@Override
161 			public void modelChanged(ChangeEvent event) {
162 				String title = event.getSource().get(SVGConstants.SVG_TITLE_ATTRIBUTE);
163 				String heading = getHeading();
164 				if (!heading.equals(title)) {
165 					setHeading(title);
166 				}
167 			}			
168 		});
169 		
170 	    /////////////////////////////////////////////////
171 		// A CSS multi-layer container
172 	    // The container hierarchy is as follows:
173 	    // splitterPanel (LayoutContainer + BorderLayout)
174 	    //   tree (TreePanel)
175 	    //   layersContainer (LayoutContainer + AbsoluteLayerLayout)
176 	    //     svgContainer (LayoutContainer)
177 	    //       image (SVGImage)
178 	    //     compass (SVGImage)
179 	    //     scaleSlider (Slider)
180 	    /////////////////////////////////////////////////
181 	    LayoutContainer splitterPanel = new LayoutContainer();
182 	    splitterPanel.setLayout(new BorderLayout());
183 
184 	    LayoutContainer layersContainer = new LayoutContainer();
185 		GWT.log("borders: " + getBorders());
186 	    layersContainer.setLayout(new AbsoluteLayerLayout());
187 
188 	    // Create the contextual menu
189 		contextMenu = new Menu();
190 
191 	    // Create the SVG view
192 		LayoutContainer svgContainer = new LayoutContainer() {
193 			@Override
194 			protected void onShowContextMenu(int x, int y) {
195 				GWT.log("SVGWindow.onShowContextMenu");
196 				displaysContextMenu = true;
197 				svgModel.updateContextMenu(contextMenu);
198 				super.onShowContextMenu(x, y);
199 			}
200 			@Override
201 			protected void onHideContextMenu() {
202 				GWT.log("SVGWindow.onHideContextMenu");
203 				displaysContextMenu = false;
204 			}
205 		};
206 		svgContainer.setLayout(new FitLayout() {
207 			@Override
208 			protected void setItemSize(Component item, Size size) {
209 				GWT.log("setItemSize(" + size + ")");
210 //				super.setItemSize(item, size);
211 				svgModel.setWindowRect(size.width, size.height);
212 			}
213 		});
214 		svgContainer.setContextMenu(contextMenu);
215 	    svgContainer.setScrollMode(Style.Scroll.AUTO);
216 	    svgContainer.setStyleAttribute("background-color", SVGConstants.CSS_WHITE_VALUE);
217 	    OMSVGSVGElement svg = svgModel.getSvgElement();
218 	    SVGImage image = new SVGImage(svg) {
219 	    	protected void onAttach() {
220 	    		GWT.log("onAttach");
221 	    		svgModel.onAttach();
222 	    	}
223 	    };
224 	    svgContainer.add(image);
225 	    layersContainer.add(svgContainer, new AbsoluteLayerLayoutData(
226 	    		AbsoluteLayerLayoutData.HORIZONTAL_ATTACH_LEFT | AbsoluteLayerLayoutData.VERTICAL_ATTACH_TOP,
227 	    		0,
228 	    		0,
229 	    		0,
230 	    		0,
231 	    		10));
232 	    // Trap mouse events to update grid rulers
233 	    svgContainer.addDomHandler(svgModel.getGrid().getMouseMoveHandler(), MouseMoveEvent.getType());
234 	    
235 	    // Create the tree view
236 	    TreeStore<SVGElementModel> treeStore = svgModel.getStore();
237 		tree = new TreePanelExt<SVGElementModel>(treeStore) {
238 			@Override
239 			protected void onShowContextMenu(int x, int y) {
240 				displaysContextMenu = true;
241 				svgModel.updateContextMenu(contextMenu);
242 				super.onShowContextMenu(x, y);
243 			}
244 			@Override
245 			protected void onHideContextMenu() {
246 				displaysContextMenu = false;
247 			}
248             @Override
249             protected void onDoubleClick(TreePanelEvent tpe) {
250                 TreeNode treeNode = tree.findNode(tpe.getTarget());
251                 SVGElementModel model = treeNode.getModel();
252                 renameModel(model);
253            }
254         };
255 		tree.setView(new TreePanelView<SVGElementModel>() {
256 			@Override
257 			public void onSelectChange(SVGElementModel model, boolean select) {
258 				super.onSelectChange(model, select);
259 				if (svgModel.isHighlightingMode()) {
260 					svgModel.displayTwin(model, select);
261 				}
262 			}			
263 		}); 
264 		tree.setSelectionModel(svgModel.getSelectionModel());
265 		tree.setContextMenu(contextMenu);
266 
267 	    tree.setIconProvider(new ModelIconProvider<SVGElementModel>() {
268 	    	Map<Severity, ImageResource> severityToResource = new HashMap<Severity, ImageResource>();
269 	    	{
270 	    		severityToResource.put(Severity.WARNING, AppBundle.INSTANCE.warning());
271 	    		severityToResource.put(Severity.ERROR, AppBundle.INSTANCE.error());
272 	    		severityToResource.put(null, null);
273 	    	}
274 			@Override
275 			public AbstractImagePrototype getIcon(SVGElementModel model) {
276 				Severity severity = model.getSeverity();
277 				return SvgrealApp.getApp().getImageCache().getImageWithDecoration(model.getMetaModel().getIcon(), severityToResource.get(severity), HAlign.LEFT, VAlign.BOTTOM);
278 			}
279 	    	
280 	    });
281 //	    tree.setCheckable(true);
282 	    tree.setWidth(150);  
283 	    tree.setDisplayProperty(SVGConstants.SVG_TITLE_TAG);
284 	    tree.setTrackMouseOver(true);
285 	    tree.setStyleAttribute("background-color", SVGConstants.CSS_WHITE_VALUE);
286 	    tree.setAutoExpand(true);
287 //	    ToolTipConfig tooltipConfig = new ToolTipConfig();
288 //	    tooltipConfig.setTrackMouse(true);
289 //	    tooltipConfig.setDismissDelay(0);
290 //	    tree.setToolTip(tooltipConfig);
291 	    
292 	    ///////////// Configure highlighting
293 	    svg.addMouseOverHandler(new MouseOverHandler() {
294 			@Override
295 			public void onMouseOver(MouseOverEvent event) {
296 	        	if (!displaysContextMenu) {
297 	        		svgModel.setHighlightingMode(true);
298 	        	}
299 			}
300 		});
301 	    svg.addMouseOutHandler(new MouseOutHandler() {
302 			
303 			@Override
304 			public void onMouseOut(MouseOutEvent event) {
305 	        	if (!displaysContextMenu) {
306 	        		svgModel.setHighlightingMode(false);
307 	        	}
308 			}
309 		});
310 	    tree.addListener(Events.OnMouseOver, new Listener<TreePanelEvent<SVGElementModel>>() {
311 	        public void handleEvent(TreePanelEvent<SVGElementModel> be) {
312 //	        	ToolTipConfig tooltipConfig = tree.getToolTip().getToolTipConfig();
313 //	        	String desc = null;
314 	        	if (!displaysContextMenu) {
315 					svgModel.setHighlightingMode(true);
316 		        	SVGElementModel model = be.getItem();
317 		        	if (model != null) {
318 		        		svgModel.highlightModel(model);
319 //		        		if (model instanceof SVGNamedElementModel) {
320 //		        			desc = model.get(SVGConstants.SVG_DESC_TAG);
321 //		        		}
322 		        	}
323 		        }
324 //	        	if (desc != null) {
325 //	        		if (!desc.equals(tooltipConfig.getTitle())) {
326 //	        			tooltipConfig.setTitle(desc);
327 //	        			tree.getToolTip().show();
328 //	        		}
329 //	        	} else {
330 //		        	tree.getToolTip().hide();
331 //	        	}
332 	        }
333 	    });
334 	    tree.addListener(Events.OnMouseOut, new Listener<TreePanelEvent<SVGElementModel>>() {
335 	        public void handleEvent(TreePanelEvent<SVGElementModel> be) {
336 	        	if (!displaysContextMenu) {
337 	        		svgModel.setHighlightingMode(false);
338 //        			tree.setToolTip((String)null);
339 	        	}
340 	        }
341 	    });
342 
343 	    ///////////// Configure drag'n'drop
344 	    dndSource = new SVGTreePanelDragSource(this);
345 	    dndTarget = new SVGTreePanelDropTarget(this);
346 	    dndTarget.setAllowSelfAsSource(true);  
347 	    dndTarget.setFeedback(Feedback.BOTH);  
348 
349 	    ///////////// Top-level layout
350 	    BorderLayoutData layoutData = new BorderLayoutData(LayoutRegion.WEST, 150, 100, 250);  
351 	    layoutData.setMargins(new Margins(0, 5, 0, 0));  
352 	    layoutData.setSplit(true);  
353 	    layoutData.setCollapsible(true);  
354 	    splitterPanel.add(tree, layoutData);
355 	    splitterPanel.add(layersContainer, new BorderLayoutData(LayoutRegion.CENTER));
356 
357 	    /////////////////////////////////////////////////
358 	    // Populate the higher layer
359 	    /////////////////////////////////////////////////
360 		
361 		// Create the compass
362 	    compass = GWT.create(Compass.class);
363 	    final OMSVGSVGElement compassSvg = compass.getSvgElement();
364 	    compassSvg.getStyle().setWidth(100, Unit.PX);
365 	    compassSvg.getStyle().setHeight(100, Unit.PX);
366 	    compass.addRotationHandler(new RotationHandler() {
367 	    	@Override
368 	    	public void onRotate(RotationEvent event) {
369 	    		svgModel.setRotation(event.getAngle());
370 	    	}	
371 	    });
372 		LayoutContainer compassContainer = new LayoutContainer();
373 		AppCss css = AppBundle.INSTANCE.css();
374 		compassContainer.addStyleName(css.compassContainer());
375 		SVGImage compassImage = new SVGImage(compassSvg);
376 		compassImage.addClassNameBaseVal(css.compass());
377 		compassContainer.add(compassImage);
378 	    layersContainer.add(compassContainer, new AbsoluteLayerLayoutData(
379 	    		AbsoluteLayerLayoutData.HORIZONTAL_ATTACH_RIGHT | AbsoluteLayerLayoutData.VERTICAL_ATTACH_TOP,
380 	    		0,
381 	    		0,
382 	    		0,
383 	    		0,
384 	    		20));
385 	    
386 		// Create the scale slider
387 		LayoutContainer sliderContainer = new LayoutContainer();
388 		sliderContainer.addStyleName(css.scaleSliderContainer());
389 		scaleSlider = new Slider() {
390 			@Override
391 	    	protected String onFormatValue(int value) {
392 				return Integer.toString((int)(svgModel.getScale() * 100)) + "%";
393 	    	}
394 
395 		};
396 		scaleSlider.addStyleName(css.scaleSlider());
397 		sliderContainer.add(scaleSlider);
398 		scaleSlider.setHeight(100);
399 		scaleSlider.setMinValue(0);
400 		scaleSlider.setMaxValue(100);
401 		scaleSlider.setIncrement(1);
402 		scaleSlider.setValue(50);
403 		scaleSlider.setVertical(true);
404 		layersContainer.add(sliderContainer, new AbsoluteLayerLayoutData(
405 	    		AbsoluteLayerLayoutData.HORIZONTAL_ATTACH_RIGHT | AbsoluteLayerLayoutData.VERTICAL_ATTACH_TOP,
406 	    		0,
407 	    		0,
408 	    		0,
409 	    		0,
410 	    		20));
411 		scaleSlider.addListener(Events.Change, new Listener<SliderEvent>() {
412 			@Override
413 			public void handleEvent(SliderEvent be) {
414 				// Convert from slider unit to transform unit
415 				int value = be.getNewValue();
416 				float scale;
417 				if (value >= 50) {
418 					scale = 1f + (value - 50f) / 10f * 4 / 5;
419 				} else {
420 					scale = 1f / (1f + (49 - value) / 10f * 4 / 5);
421 				}
422 				svgModel.setScale(scale);
423 			}	    	
424 	    });
425 	    
426 //	    ToolBar toolBar = new ToolBar();
427 //	    ToggleButton selectButton = new ToggleButton();
428 //	    selectButton.setIcon(AbstractImagePrototype.create(AppBundle.INSTANCE.cursor()));
429 //	    selectButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
430 //			@Override
431 //			public void componentSelected(ButtonEvent ce) {
432 //				model.setSelectionMode(((ToggleButton)ce.getButton()).isPressed());
433 //			}
434 //	    });
435 //	    toolBar.add(selectButton);
436 //	    setTopComponent(toolBar);
437 	    
438 		setLayout(new FitLayout());
439 		add(splitterPanel, new FitData(4));
440 		
441 		/*addListener(Events.Activate, new Listener<WindowEvent>() {
442 			@Override
443 			public void handleEvent(WindowEvent we) {
444 				activate();
445 			}
446 		});*/
447 	}
448 	
449 	@Override
450 	protected void moveDrag(DragEvent de) {
451 		int windowBarHeight = SvgrealApp.getWindowBarHeight();
452 		if (de.getY() < windowBarHeight) {
453 			de.setY(windowBarHeight);
454 		}
455 	}
456 	
457 	public SVGModel getSvgModel() {
458 		return svgModel;
459 	}
460 	
461 	public TreePanelExt<SVGElementModel> getTree() {
462 		return tree;
463 	}
464 
465 	/**
466 	 * Sets the scaling of the main image through the scale slider.
467 	 * @param scale
468 	 * The scale (50 means scale 1:1)
469 	 */
470 	public void setScaleSlider(int value) {
471 		scaleSlider.setValue(value);
472 	}
473 
474 	/**
475 	 * Sets the rotation of the main image through the
476 	 * compass widget.
477 	 * @param angleDeg
478 	 * The angle (in degrees)
479 	 */
480 	public void setRotationCompass(int angleDeg) {
481 		compass.setRotation(angleDeg);
482 	}	
483 	/* GWT bug ?
484 	 * line 234: The method endDrag(DragEvent) in the type Window is not applicable for the arguments (DragEvent, boolean)*/
485 //	protected void endDrag(DragEvent de, boolean canceled) {
486 //		GWT.log("endDrag" + de.getX() + " " + de.getY());
487 //		int windowBarHeight = VectomaticApp2.getWindowBarHeight();
488 //		if (de.getY() < windowBarHeight) {
489 //			de.setY(windowBarHeight);
490 //		}
491 //		super.endDrag(de, canceled);
492 //	}
493 	/*@Override
494 	protected void onHide() {
495 		GWT.log("SVGWindow(" + getHeading() + ").onHide");
496 		TreePanelSelectionModel<SVGElementModel> selection = tree.getSelectionModel();
497 		selection.deselectAll();
498 		super.onHide();
499 	}*/
500 	
501 	public void activate() {
502 		GWT.log("SVGWindow(" + getHeading() + ").activate");
503 		el().addStyleName(WINDOW_ACTIVE_STYLE);
504 		TreePanelSelectionModel<SVGElementModel> selection = tree.getSelectionModel();
505 		SelectionService.get().register(selection);
506 		updateSelectionListeners();
507 	}
508 	
509 	public void updateSelectionListeners() {
510 		TreePanelSelectionModel<SVGElementModel> selection = tree.getSelectionModel();
511 		selection.fireEvent(Events.SelectionChange, new SelectionChangedEvent<SVGElementModel>(selection, selection.getSelectedItems()));
512 	}
513 	
514 	public void updateIcon(SVGElementModel model) {
515 		tree.getView().onIconStyleChange(tree.findTreeNode(model), tree.getIconProvider().getIcon(model));
516 	}
517 	
518 	public void deactivate() {
519 		GWT.log("SVGWindow(" + getHeading() + ").deactivate");
520 		Object selection = tree.getSelectionModel();
521 		SelectionService.get().unregister((SelectionProvider<ModelData>)selection);
522 		el().removeStyleName(WINDOW_ACTIVE_STYLE);
523 	}
524 	
525 	@Override
526     protected void fitContainer() {
527 		Rectangle rect = SvgrealApp.getApp().getRectangle();
528 		setPosition(rect.x, rect.y);
529 		setSize(rect.width, rect.height);
530     }
531 	
532 	public void renameModel(final SVGElementModel model) {
533         final EditTitleCommandFactory commandFactory = (EditTitleCommandFactory) EditTitleCommandFactory.INSTANTIATOR.create();
534         commandFactory.start(this);
535         commandFactory.updateStatus(ModelConstants.INSTANCE.renameElementCmdFactory2());
536 
537         final TextField<String> nameField = new TextField<String>();
538         Editor nameEditor = new Editor(nameField);
539         nameEditor.setAutoHeight(true);
540         nameEditor.setAutoWidth(true);
541         nameEditor.setCompleteOnEnter(true);
542         Listener<BaseEvent> editorListener = new Listener<BaseEvent>() {
543             @Override
544             public void handleEvent(BaseEvent be) {
545             	GWT.log("Editor: " + be.getType());
546             	if (be.getType() == Events.Complete) {
547                 	Record record = svgModel.getStore().getRecord(model);
548                 	record.set(SVGConstants.SVG_TITLE_TAG, nameField.getValue());
549                 	record.commit(false);
550                     commandFactory.stop();                    		
551             	}
552             	if (be.getType() == Events.CancelEdit) {
553                     commandFactory.stop();                    		
554             	}
555            }
556         };
557         nameEditor.addListener(Events.Complete, editorListener);
558         nameEditor.addListener(Events.CancelEdit, editorListener);
559         TreeNode treeNode = tree.findTreeNode(model);
560         nameEditor.startEdit(treeNode.getElement(), model.get(SVGConstants.SVG_TITLE_TAG));
561 	}
562 
563 	
564 }
565