1 package com.mxgraph.examples.swing;
2 
3 import java.awt.Color;
4 import java.awt.Image;
5 import java.awt.Point;
6 import java.awt.Toolkit;
7 import java.awt.image.ImageObserver;
8 import java.net.URL;
9 import java.text.NumberFormat;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.ServiceLoader;
13 
14 import javax.swing.ImageIcon;
15 import javax.swing.JOptionPane;
16 import javax.swing.UIManager;
17 import javax.xml.parsers.DocumentBuilderFactory;
18 
19 import org.apache.commons.codec.binary.Hex;
20 import org.w3c.dom.Document;
21 import org.w3c.dom.Element;
22 import org.w3c.dom.Node;
23 import org.w3c.dom.NodeList;
24 
25 import com.mxgraph.examples.swing.editor.BasicGraphEditor;
26 import com.mxgraph.examples.swing.editor.EditorMenuBar;
27 import com.mxgraph.examples.swing.editor.EditorPalette;
28 import com.mxgraph.examples.swing.editor.EditorPaletteFactory;
29 import com.mxgraph.io.mxCodec;
30 import com.mxgraph.model.mxCell;
31 import com.mxgraph.model.mxGeometry;
32 import com.mxgraph.model.mxICell;
33 import com.mxgraph.model.mxIGraphModel;
34 import com.mxgraph.swing.mxGraphComponent;
35 import com.mxgraph.swing.util.mxGraphTransferable;
36 import com.mxgraph.swing.util.mxSwingConstants;
37 import com.mxgraph.util.mxConstants;
38 import com.mxgraph.util.mxEvent;
39 import com.mxgraph.util.mxEventObject;
40 import com.mxgraph.util.mxEventSource.mxIEventListener;
41 import com.mxgraph.util.mxPoint;
42 import com.mxgraph.util.mxResources;
43 import com.mxgraph.util.mxUtils;
44 import com.mxgraph.view.mxCellState;
45 import com.mxgraph.view.mxGraph;
46 
47 public class GraphEditor extends BasicGraphEditor
48 {
49 
50 	private static final String ATTRIBUTE_REF = "ref";
51 
52 	private static final String ELEMENT_PALETTE = "palette";
53 
54 	private static final String ATTRIBUTE_HEIGHT = "height";
55 
56 	private static final String ATTRIBUTE_WIDTH = "width";
57 
58 	/**
59 	 *
60 	 */
61 	private static final long serialVersionUID = -4601740824088314699L;
62 
63 	/**
64 	 * Holds the shared number formatter.
65 	 *
66 	 * @see NumberFormat#getInstance()
67 	 */
68 	public static final NumberFormat numberFormat = NumberFormat.getInstance();
69 
70 	/**
71 	 * Holds the URL for the icon to be used as a handle for creating new
72 	 * connections. This is currently unused.
73 	 */
74 	public static URL url = null;
75 
76 	//GraphEditor.class.getResource("/com/mxgraph/examples/swing/images/connector.gif");
77 
GraphEditor(Config config)78 	public GraphEditor(Config config)
79 	{
80 		this("mxGraph Editor", new CustomGraphComponent(new CustomGraph()), config);
81 	}
82 
83 	/**
84 	 * @param palettes External palete definitions url's.
85 	 */
GraphEditor(String appTitle, mxGraphComponent component, Config config)86 	public GraphEditor(String appTitle, mxGraphComponent component, Config config) {
87 		super(appTitle, component, config);
88 		final mxGraph graph = graphComponent.getGraph();
89 
90 		// Creates the shapes palette
91 		EditorPalette shapesPalette = insertPalette(mxResources.get("shapes"));
92 		EditorPalette imagesPalette = insertPalette(mxResources.get("images"));
93 		EditorPalette symbolsPalette = insertPalette(mxResources.get("symbols"));
94 
95 		loadPalettes();
96 
97 		ServiceLoader<EditorPaletteFactory> sl = ServiceLoader.load(EditorPaletteFactory.class, this.getClass().getClassLoader());
98 		Iterator<EditorPaletteFactory> epfit = sl.iterator();
99 		while (epfit.hasNext()) {
100 			EditorPaletteFactory epf = epfit.next();
101 			EditorPalette customPalette = insertPalette(epf.getTitle());
102 			epf.populate(customPalette);
103 		}
104 
105 		// Sets the edge template to be used for creating new edges if an edge
106 		// is clicked in the shape palette
107 		shapesPalette.addListener(mxEvent.SELECT, new mxIEventListener()
108 		{
109 			public void invoke(Object sender, mxEventObject evt)
110 			{
111 				Object tmp = evt.getProperty("transferable");
112 
113 				if (tmp instanceof mxGraphTransferable)
114 				{
115 					mxGraphTransferable t = (mxGraphTransferable) tmp;
116 					Object cell = t.getCells()[0];
117 
118 					if (graph.getModel().isEdge(cell))
119 					{
120 						((CustomGraph) graph).setEdgeTemplate(cell);
121 					}
122 				}
123 			}
124 
125 		});
126 
127 		// Adds some template cells for dropping into the graph
128 		shapesPalette
129 				.addTemplate(
130 						"Container",
131 						new ImageIcon(
132 								GraphEditor.class
133 										.getResource("/com/mxgraph/examples/swing/images/swimlane.png")),
134 						"swimlane", 280, 280, "Container");
135 		shapesPalette
136 				.addTemplate(
137 						"Icon",
138 						new ImageIcon(
139 								GraphEditor.class
140 										.getResource("/com/mxgraph/examples/swing/images/rounded.png")),
141 						"icon;image=/com/mxgraph/examples/swing/images/wrench.png",
142 						70, 70, "Icon");
143 		shapesPalette
144 				.addTemplate(
145 						"Label",
146 						new ImageIcon(
147 								GraphEditor.class
148 										.getResource("/com/mxgraph/examples/swing/images/rounded.png")),
149 						"label;image=/com/mxgraph/examples/swing/images/gear.png",
150 						130, 50, "Label");
151 		shapesPalette
152 				.addTemplate(
153 						"Rectangle",
154 						new ImageIcon(
155 								GraphEditor.class
156 										.getResource("/com/mxgraph/examples/swing/images/rectangle.png")),
157 						null, 160, 120, "");
158 		shapesPalette
159 				.addTemplate(
160 						"Rounded Rectangle",
161 						new ImageIcon(
162 								GraphEditor.class
163 										.getResource("/com/mxgraph/examples/swing/images/rounded.png")),
164 						"rounded=1", 160, 120, "");
165 		shapesPalette
166 				.addTemplate(
167 						"Ellipse",
168 						new ImageIcon(
169 								GraphEditor.class
170 										.getResource("/com/mxgraph/examples/swing/images/ellipse.png")),
171 						"ellipse", 160, 160, "");
172 		shapesPalette
173 				.addTemplate(
174 						"Double Ellipse",
175 						new ImageIcon(
176 								GraphEditor.class
177 										.getResource("/com/mxgraph/examples/swing/images/doubleellipse.png")),
178 						"ellipse;shape=doubleEllipse", 160, 160, "");
179 		shapesPalette
180 				.addTemplate(
181 						"Triangle",
182 						new ImageIcon(
183 								GraphEditor.class
184 										.getResource("/com/mxgraph/examples/swing/images/triangle.png")),
185 						"triangle", 120, 160, "");
186 		shapesPalette
187 				.addTemplate(
188 						"Rhombus",
189 						new ImageIcon(
190 								GraphEditor.class
191 										.getResource("/com/mxgraph/examples/swing/images/rhombus.png")),
192 						"rhombus", 160, 160, "");
193 		shapesPalette
194 				.addTemplate(
195 						"Horizontal Line",
196 						new ImageIcon(
197 								GraphEditor.class
198 										.getResource("/com/mxgraph/examples/swing/images/hline.png")),
199 						"line", 160, 10, "");
200 		shapesPalette
201 				.addTemplate(
202 						"Hexagon",
203 						new ImageIcon(
204 								GraphEditor.class
205 										.getResource("/com/mxgraph/examples/swing/images/hexagon.png")),
206 						"shape=hexagon", 160, 120, "");
207 		shapesPalette
208 				.addTemplate(
209 						"Cylinder",
210 						new ImageIcon(
211 								GraphEditor.class
212 										.getResource("/com/mxgraph/examples/swing/images/cylinder.png")),
213 						"shape=cylinder", 120, 160, "");
214 		shapesPalette.addTemplate("Actor", new ImageIcon(GraphEditor.class
215 				.getResource("/com/mxgraph/examples/swing/images/actor.png")),
216 				"shape=actor", 120, 160, "");
217 		shapesPalette.addTemplate("Cloud", new ImageIcon(GraphEditor.class
218 				.getResource("/com/mxgraph/examples/swing/images/cloud.png")),
219 				"ellipse;shape=cloud", 160, 120, "");
220 
221 		shapesPalette
222 				.addEdgeTemplate(
223 						"Straight",
224 						new ImageIcon(
225 								GraphEditor.class
226 										.getResource("/com/mxgraph/examples/swing/images/straight.png")),
227 						"straight", 120, 120, "");
228 		shapesPalette
229 				.addEdgeTemplate(
230 						"Horizontal Connector",
231 						new ImageIcon(
232 								GraphEditor.class
233 										.getResource("/com/mxgraph/examples/swing/images/connect.png")),
234 						null, 100, 100, "");
235 		shapesPalette
236 				.addEdgeTemplate(
237 						"Vertical Connector",
238 						new ImageIcon(
239 								GraphEditor.class
240 										.getResource("/com/mxgraph/examples/swing/images/vertical.png")),
241 						"vertical", 100, 100, "");
242 		shapesPalette
243 				.addEdgeTemplate(
244 						"Entity Relation",
245 						new ImageIcon(
246 								GraphEditor.class
247 										.getResource("/com/mxgraph/examples/swing/images/entity.png")),
248 						"entity", 100, 100, "");
249 		shapesPalette.addEdgeTemplate("Arrow", new ImageIcon(GraphEditor.class
250 				.getResource("/com/mxgraph/examples/swing/images/arrow.png")),
251 				"arrow", 120, 120, "");
252 
253 		imagesPalette.addTemplate("Bell", new ImageIcon(GraphEditor.class
254 				.getResource("/com/mxgraph/examples/swing/images/bell.png")),
255 				"image;image=/com/mxgraph/examples/swing/images/bell.png", 50,
256 				50, "Bell");
257 		imagesPalette.addTemplate("Box", new ImageIcon(GraphEditor.class
258 				.getResource("/com/mxgraph/examples/swing/images/box.png")),
259 				"image;image=/com/mxgraph/examples/swing/images/box.png", 50,
260 				50, "Box");
261 		imagesPalette
262 				.addTemplate(
263 						"Cube",
264 						new ImageIcon(
265 								GraphEditor.class
266 										.getResource("/com/mxgraph/examples/swing/images/cube_green.png")),
267 						"image;image=/com/mxgraph/examples/swing/images/cube_green.png",
268 						50, 50, "Cube");
269 		imagesPalette
270 				.addTemplate(
271 						"User",
272 						new ImageIcon(
273 								GraphEditor.class
274 										.getResource("/com/mxgraph/examples/swing/images/dude3.png")),
275 						"roundImage;image=/com/mxgraph/examples/swing/images/dude3.png",
276 						50, 50, "User");
277 		imagesPalette
278 				.addTemplate(
279 						"Earth",
280 						new ImageIcon(
281 								GraphEditor.class
282 										.getResource("/com/mxgraph/examples/swing/images/earth.png")),
283 						"roundImage;image=/com/mxgraph/examples/swing/images/earth.png",
284 						50, 50, "Earth");
285 		imagesPalette.addTemplate("Gear", new ImageIcon(GraphEditor.class
286 				.getResource("/com/mxgraph/examples/swing/images/gear.png")),
287 				"roundImage;image=/com/mxgraph/examples/swing/images/gear.png",
288 				50, 50, "Gear");
289 		imagesPalette.addTemplate("Home", new ImageIcon(GraphEditor.class
290 				.getResource("/com/mxgraph/examples/swing/images/house.png")),
291 				"image;image=/com/mxgraph/examples/swing/images/house.png", 50,
292 				50, "Home");
293 		imagesPalette
294 				.addTemplate(
295 						"Package",
296 						new ImageIcon(
297 								GraphEditor.class
298 										.getResource("/com/mxgraph/examples/swing/images/package.png")),
299 						"image;image=/com/mxgraph/examples/swing/images/package.png",
300 						50, 50, "Package");
301 		imagesPalette
302 				.addTemplate(
303 						"Printer",
304 						new ImageIcon(
305 								GraphEditor.class
306 										.getResource("/com/mxgraph/examples/swing/images/printer.png")),
307 						"image;image=/com/mxgraph/examples/swing/images/printer.png",
308 						50, 50, "Printer");
309 		imagesPalette.addTemplate("Server", new ImageIcon(GraphEditor.class
310 				.getResource("/com/mxgraph/examples/swing/images/server.png")),
311 				"image;image=/com/mxgraph/examples/swing/images/server.png",
312 				50, 50, "Server");
313 		imagesPalette
314 				.addTemplate(
315 						"Workplace",
316 						new ImageIcon(
317 								GraphEditor.class
318 										.getResource("/com/mxgraph/examples/swing/images/workplace.png")),
319 						"image;image=/com/mxgraph/examples/swing/images/workplace.png",
320 						50, 50, "Workplace");
321 		imagesPalette
322 				.addTemplate(
323 						"Wrench",
324 						new ImageIcon(
325 								GraphEditor.class
326 										.getResource("/com/mxgraph/examples/swing/images/wrench.png")),
327 						"roundImage;image=/com/mxgraph/examples/swing/images/wrench.png",
328 						50, 50, "Wrench");
329 
330 		symbolsPalette
331 				.addTemplate(
332 						"Cancel",
333 						new ImageIcon(
334 								GraphEditor.class
335 										.getResource("/com/mxgraph/examples/swing/images/cancel_end.png")),
336 						"roundImage;image=/com/mxgraph/examples/swing/images/cancel_end.png",
337 						80, 80, "Cancel");
338 		symbolsPalette
339 				.addTemplate(
340 						"Error",
341 						new ImageIcon(
342 								GraphEditor.class
343 										.getResource("/com/mxgraph/examples/swing/images/error.png")),
344 						"roundImage;image=/com/mxgraph/examples/swing/images/error.png",
345 						80, 80, "Error");
346 		symbolsPalette
347 				.addTemplate(
348 						"Event",
349 						new ImageIcon(
350 								GraphEditor.class
351 										.getResource("/com/mxgraph/examples/swing/images/event.png")),
352 						"roundImage;image=/com/mxgraph/examples/swing/images/event.png",
353 						80, 80, "Event");
354 		symbolsPalette
355 				.addTemplate(
356 						"Fork",
357 						new ImageIcon(
358 								GraphEditor.class
359 										.getResource("/com/mxgraph/examples/swing/images/fork.png")),
360 						"rhombusImage;image=/com/mxgraph/examples/swing/images/fork.png",
361 						80, 80, "Fork");
362 		symbolsPalette
363 				.addTemplate(
364 						"Inclusive",
365 						new ImageIcon(
366 								GraphEditor.class
367 										.getResource("/com/mxgraph/examples/swing/images/inclusive.png")),
368 						"rhombusImage;image=/com/mxgraph/examples/swing/images/inclusive.png",
369 						80, 80, "Inclusive");
370 		symbolsPalette.addTemplate("Link", new ImageIcon(GraphEditor.class
371 				.getResource("/com/mxgraph/examples/swing/images/link.png")),
372 				"roundImage;image=/com/mxgraph/examples/swing/images/link.png",
373 				80, 80, "Link");
374 		symbolsPalette
375 				.addTemplate(
376 						"Merge",
377 						new ImageIcon(
378 								GraphEditor.class
379 										.getResource("/com/mxgraph/examples/swing/images/merge.png")),
380 						"rhombusImage;image=/com/mxgraph/examples/swing/images/merge.png",
381 						80, 80, "Merge");
382 		symbolsPalette
383 				.addTemplate(
384 						"Message",
385 						new ImageIcon(
386 								GraphEditor.class
387 										.getResource("/com/mxgraph/examples/swing/images/message.png")),
388 						"roundImage;image=/com/mxgraph/examples/swing/images/message.png",
389 						80, 80, "Message");
390 		symbolsPalette
391 				.addTemplate(
392 						"Multiple",
393 						new ImageIcon(
394 								GraphEditor.class
395 										.getResource("/com/mxgraph/examples/swing/images/multiple.png")),
396 						"roundImage;image=/com/mxgraph/examples/swing/images/multiple.png",
397 						80, 80, "Multiple");
398 		symbolsPalette.addTemplate("Rule", new ImageIcon(GraphEditor.class
399 				.getResource("/com/mxgraph/examples/swing/images/rule.png")),
400 				"roundImage;image=/com/mxgraph/examples/swing/images/rule.png",
401 				80, 80, "Rule");
402 		symbolsPalette
403 				.addTemplate(
404 						"Terminate",
405 						new ImageIcon(
406 								GraphEditor.class
407 										.getResource("/com/mxgraph/examples/swing/images/terminate.png")),
408 						"roundImage;image=/com/mxgraph/examples/swing/images/terminate.png",
409 						80, 80, "Terminate");
410 		symbolsPalette
411 				.addTemplate(
412 						"Timer",
413 						new ImageIcon(
414 								GraphEditor.class
415 										.getResource("/com/mxgraph/examples/swing/images/timer.png")),
416 						"roundImage;image=/com/mxgraph/examples/swing/images/timer.png",
417 						80, 80, "Timer");
418 	}
419 
loadPalettes()420 	private void loadPalettes() {
421 		try {
422 			String palettesEncoded = getConfig().getPalettes(); /* new String(Hex.encodeHex("file:/C:/_temp/palettes.xml".getBytes())); /*/
423 			if (palettesEncoded==null) {
424 				return;
425 			}
426 			String urlsStr = new String(Hex.decodeHex(palettesEncoded.toCharArray()));
427 			if (urlsStr==null || urlsStr.trim().length()==0) {
428 				return;
429 			}
430 
431 			String[] usa = urlsStr.split(";");
432 			StringBuilder sourceUrl = getConfig()==null ? null : new StringBuilder(getConfig().getDokuHost()+new String(Hex.decodeHex(getConfig().getDokuBase().toCharArray())));
433 			URL dokuBaseURL = sourceUrl==null ? null : new URL(sourceUrl.toString());
434 			for (int i=0; i<usa.length; ++i) {
435 				String trimmed = usa[i].trim();
436 				if (trimmed.length()>0) {
437 					loadPalette(new URL(dokuBaseURL, trimmed));
438 				}
439 			}
440 		} catch (Exception e) {
441 			e.printStackTrace();
442 			JOptionPane.showMessageDialog(
443 	    			graphComponent,
444 					"Cannot load palettes: "+e,
445 					"Error loading external palettes",
446 					JOptionPane.ERROR_MESSAGE);
447 
448 		}
449 	}
450 
url2element(URL url)451 	private static Element url2element(URL url) throws Exception {
452 		return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(url.openStream()).getDocumentElement();
453 	}
454 
loadPalette(Element pElement, URL base)455 	private void loadPalette(Element pElement, URL base) throws Exception {
456 		if (pElement.hasAttribute(ATTRIBUTE_REF)) {
457 			loadPalette(new URL(base, pElement.getAttribute(ATTRIBUTE_REF)));
458 		} else {
459 			EditorPalette palette = insertPalette(pElement.getAttribute("name"));
460 			NodeList tplnl = pElement.getChildNodes();
461 			for (int j=0, m=tplnl.getLength(); j<m; ++j) {
462 				Node tc = tplnl.item(j);
463 				if (tc instanceof Element && "template".equals(tc.getNodeName())) {
464 					Element tce = (Element) tc;
465 					URL tURL = new URL(base, tce.getAttribute("src"));
466 					Image image = Toolkit.getDefaultToolkit().getImage(tURL);
467 					ImageIcon imageIcon = new ImageIcon(image);
468 					ImageObserver imageObserver = null;
469 					int iWidth = tce.hasAttribute(ATTRIBUTE_WIDTH)? Integer.parseInt(tce.getAttribute(ATTRIBUTE_WIDTH)) : image.getWidth(imageObserver);
470 					if (iWidth==-1) {
471 						iWidth = 100;
472 					}
473 					int iHeight = tce.hasAttribute(ATTRIBUTE_HEIGHT)? Integer.parseInt(tce.getAttribute(ATTRIBUTE_HEIGHT)) : image.getHeight(imageObserver);
474 					if (iHeight==-1) {
475 						iHeight = 100;
476 					}
477 					palette.addTemplate(
478 							tce.getAttribute("name"),
479 							imageIcon,
480 							"image;image="+tURL,
481 							iWidth,
482 							iHeight,
483 							tce.getAttribute("name"));
484 
485 				}
486 			}
487 		}
488 	}
489 
loadPalette(URL pURL)490 	private void loadPalette(URL pURL) {
491 		try {
492 			Element root = url2element(pURL);
493 			if (ELEMENT_PALETTE.equals(root.getNodeName())) {
494 				loadPalette(root, pURL);
495 			} else {
496 				NodeList pdcnl = root.getChildNodes();
497 				for (int i=0, l=pdcnl.getLength(); i<l; ++i) {
498 					Node child = pdcnl.item(i);
499 					if (child instanceof Element && ELEMENT_PALETTE.equals(child.getNodeName())) {
500 						loadPalette((Element) child, pURL);
501 					}
502 				}
503 			}
504 		} catch (Exception e) {
505 			e.printStackTrace();
506 			JOptionPane.showMessageDialog(
507 	    			graphComponent,
508 					"Cannot load palette from "+pURL+": "+e,
509 					"Error loading external palette",
510 					JOptionPane.ERROR_MESSAGE);
511 		}
512 	}
513 
514 	/**
515 	 *
516 	 */
517 	public static class CustomGraphComponent extends mxGraphComponent
518 	{
519 
520 		/**
521 		 *
522 		 */
523 		private static final long serialVersionUID = -6833603133512882012L;
524 
525 		/**
526 		 *
527 		 * @param graph
528 		 */
CustomGraphComponent(mxGraph graph)529 		public CustomGraphComponent(mxGraph graph)
530 		{
531 			super(graph);
532 
533 			// Sets switches typically used in an editor
534 			setPageVisible(true);
535 			setGridVisible(true);
536 			setToolTips(true);
537 			getConnectionHandler().setCreateTarget(true);
538 
539 			// Loads the defalt stylesheet from an external file
540 			mxCodec codec = new mxCodec();
541 			Document doc = mxUtils.loadDocument(GraphEditor.class.getResource(
542 					"/com/mxgraph/examples/swing/resources/default-style.xml")
543 					.toString());
544 			codec.decode(doc.getDocumentElement(), graph.getStylesheet());
545 
546 			// Sets the background to white
547 			getViewport().setOpaque(false);
548 			setBackground(Color.WHITE);
549 		}
550 
551 		/**
552 		 * Overrides drop behaviour to set the cell style if the target
553 		 * is not a valid drop target and the cells are of the same
554 		 * type (eg. both vertices or both edges).
555 		 */
importCells(Object[] cells, double dx, double dy, Object target, Point location)556 		public Object[] importCells(Object[] cells, double dx, double dy,
557 				Object target, Point location)
558 		{
559 			if (target == null && cells.length == 1 && location != null)
560 			{
561 				target = getCellAt(location.x, location.y);
562 
563 				if (target instanceof mxICell && cells[0] instanceof mxICell)
564 				{
565 					mxICell targetCell = (mxICell) target;
566 					mxICell dropCell = (mxICell) cells[0];
567 
568 					if (targetCell.isVertex() == dropCell.isVertex()
569 							|| targetCell.isEdge() == dropCell.isEdge())
570 					{
571 						mxIGraphModel model = graph.getModel();
572 						model.setStyle(target, model.getStyle(cells[0]));
573 						graph.setSelectionCell(target);
574 
575 						return null;
576 					}
577 				}
578 			}
579 
580 			return super.importCells(cells, dx, dy, target, location);
581 		}
582 
583 	}
584 
585 	/**
586 	 * A graph that creates new edges from a given template edge.
587 	 */
588 	public static class CustomGraph extends mxGraph
589 	{
590 		/**
591 		 * Holds the edge to be used as a template for inserting new edges.
592 		 */
593 		protected Object edgeTemplate;
594 
595 		/**
596 		 * Custom graph that defines the alternate edge style to be used when
597 		 * the middle control point of edges is double clicked (flipped).
598 		 */
CustomGraph()599 		public CustomGraph()
600 		{
601 			setAlternateEdgeStyle("edgeStyle=mxEdgeStyle.ElbowConnector;elbow=vertical");
602 		}
603 
604 		/**
605 		 * Sets the edge template to be used to inserting edges.
606 		 */
setEdgeTemplate(Object template)607 		public void setEdgeTemplate(Object template)
608 		{
609 			edgeTemplate = template;
610 		}
611 
612 		/**
613 		 * Prints out some useful information about the cell in the tooltip.
614 		 */
getToolTipForCell(Object cell)615 		public String getToolTipForCell(Object cell)
616 		{
617 			String tip = "<html>";
618 			mxGeometry geo = getModel().getGeometry(cell);
619 			mxCellState state = getView().getState(cell);
620 
621 			if (getModel().isEdge(cell))
622 			{
623 				tip += "points={";
624 
625 				if (geo != null)
626 				{
627 					List<mxPoint> points = geo.getPoints();
628 
629 					if (points != null)
630 					{
631 						Iterator<mxPoint> it = points.iterator();
632 
633 						while (it.hasNext())
634 						{
635 							mxPoint point = it.next();
636 							tip += "[x=" + numberFormat.format(point.getX())
637 									+ ",y=" + numberFormat.format(point.getY())
638 									+ "],";
639 						}
640 
641 						tip = tip.substring(0, tip.length() - 1);
642 					}
643 				}
644 
645 				tip += "}<br>";
646 				tip += "absPoints={";
647 
648 				if (state != null)
649 				{
650 
651 					for (int i = 0; i < state.getAbsolutePointCount(); i++)
652 					{
653 						mxPoint point = state.getAbsolutePoint(i);
654 						tip += "[x=" + numberFormat.format(point.getX())
655 								+ ",y=" + numberFormat.format(point.getY())
656 								+ "],";
657 					}
658 
659 					tip = tip.substring(0, tip.length() - 1);
660 				}
661 
662 				tip += "}";
663 			}
664 			else
665 			{
666 				tip += "geo=[";
667 
668 				if (geo != null)
669 				{
670 					tip += "x=" + numberFormat.format(geo.getX()) + ",y="
671 							+ numberFormat.format(geo.getY()) + ",width="
672 							+ numberFormat.format(geo.getWidth()) + ",height="
673 							+ numberFormat.format(geo.getHeight());
674 				}
675 
676 				tip += "]<br>";
677 				tip += "state=[";
678 
679 				if (state != null)
680 				{
681 					tip += "x=" + numberFormat.format(state.getX()) + ",y="
682 							+ numberFormat.format(state.getY()) + ",width="
683 							+ numberFormat.format(state.getWidth())
684 							+ ",height="
685 							+ numberFormat.format(state.getHeight());
686 				}
687 
688 				tip += "]";
689 			}
690 
691 			mxPoint trans = getView().getTranslate();
692 
693 			tip += "<br>scale=" + numberFormat.format(getView().getScale())
694 					+ ", translate=[x=" + numberFormat.format(trans.getX())
695 					+ ",y=" + numberFormat.format(trans.getY()) + "]";
696 			tip += "</html>";
697 
698 			return tip;
699 		}
700 
701 		/**
702 		 * Overrides the method to use the currently selected edge template for
703 		 * new edges.
704 		 *
705 		 * @param graph
706 		 * @param parent
707 		 * @param id
708 		 * @param value
709 		 * @param source
710 		 * @param target
711 		 * @param style
712 		 * @return
713 		 */
createEdge(Object parent, String id, Object value, Object source, Object target, String style)714 		public Object createEdge(Object parent, String id, Object value,
715 				Object source, Object target, String style)
716 		{
717 			if (edgeTemplate != null)
718 			{
719 				mxCell edge = (mxCell) cloneCells(new Object[] { edgeTemplate })[0];
720 				edge.setId(id);
721 
722 				return edge;
723 			}
724 
725 			return super.createEdge(parent, id, value, source, target, style);
726 		}
727 
728 	}
729 
730 	/**
731 	 *
732 	 * @param args
733 	 */
main(String[] args)734 	public static void main(String[] args)
735 	{
736 		try
737 		{
738 			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
739 		}
740 		catch (Exception e1)
741 		{
742 			e1.printStackTrace();
743 		}
744 
745 		mxSwingConstants.SHADOW_COLOR = Color.LIGHT_GRAY;
746 		mxConstants.W3C_SHADOWCOLOR = "#D3D3D3";
747 		GraphEditor editor = new GraphEditor(null);
748 		editor.createFrame(new EditorMenuBar(editor)).setVisible(true);
749 	}
750 }
751