1 /*
2  * $Id: EditorActions.java,v 1.6 2009/12/08 19:52:50 gaudenz Exp $
3  * Copyright (c) 2001-2009, JGraph Ltd
4  *
5  * All rights reserved.
6  *
7  * See LICENSE file for license details. If you are unable to locate
8  * this file please contact info (at) jgraph (dot) com.
9  */
10 package com.mxgraph.examples.swing.editor;
11 
12 import java.awt.Color;
13 import java.awt.Component;
14 import java.awt.event.ActionEvent;
15 import java.awt.event.ActionListener;
16 import java.awt.image.BufferedImage;
17 import java.awt.print.PageFormat;
18 import java.awt.print.Paper;
19 import java.awt.print.PrinterException;
20 import java.awt.print.PrinterJob;
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.FilterInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.OutputStreamWriter;
29 import java.lang.reflect.Method;
30 import java.net.ProxySelector;
31 import java.net.URL;
32 import java.net.URLConnection;
33 
34 import javax.imageio.ImageIO;
35 import javax.swing.AbstractAction;
36 import javax.swing.ImageIcon;
37 import javax.swing.JCheckBoxMenuItem;
38 import javax.swing.JColorChooser;
39 import javax.swing.JEditorPane;
40 import javax.swing.JOptionPane;
41 import javax.swing.JSplitPane;
42 import javax.swing.SwingUtilities;
43 import javax.swing.SwingWorker;
44 import javax.swing.text.html.HTML;
45 import javax.swing.text.html.HTMLDocument;
46 import javax.swing.text.html.HTMLEditorKit;
47 import javax.xml.parsers.DocumentBuilder;
48 import javax.xml.parsers.DocumentBuilderFactory;
49 
50 import org.apache.commons.codec.binary.Hex;
51 import org.apache.http.HttpResponse;
52 import org.apache.http.HttpStatus;
53 import org.apache.http.client.methods.HttpPost;
54 import org.apache.http.entity.mime.MultipartEntity;
55 import org.apache.http.entity.mime.content.InputStreamBody;
56 import org.apache.http.entity.mime.content.StringBody;
57 import org.apache.http.impl.client.DefaultHttpClient;
58 import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
59 import org.w3c.dom.Document;
60 
61 import com.mxgraph.analysis.mxDistanceCostFunction;
62 import com.mxgraph.analysis.mxGraphAnalysis;
63 import com.mxgraph.io.mxCodec;
64 import com.mxgraph.model.mxCell;
65 import com.mxgraph.model.mxIGraphModel;
66 import com.mxgraph.swing.mxGraphComponent;
67 import com.mxgraph.swing.mxGraphOutline;
68 import com.mxgraph.swing.handler.mxConnectionHandler;
69 import com.mxgraph.swing.util.mxGraphActions;
70 import com.mxgraph.swing.view.mxCellEditor;
71 import com.mxgraph.util.mxCellRenderer;
72 import com.mxgraph.util.mxConstants;
73 import com.mxgraph.util.mxResources;
74 import com.mxgraph.util.mxUtils;
75 import com.mxgraph.view.mxGraph;
76 
77 /**
78  * @author Administrator
79  *
80  */
81 public class EditorActions {
82 
83 	/**
84 	 *
85 	 * @param e
86 	 * @return Returns the graph for the given action event.
87 	 */
getEditor(ActionEvent e)88 	public static final BasicGraphEditor getEditor(ActionEvent e) {
89 		if (e.getSource() instanceof Component) {
90 			Component component = (Component) e.getSource();
91 
92 			while (component != null && !(component instanceof BasicGraphEditor)) {
93 				component = component.getParent();
94 			}
95 
96 			return (BasicGraphEditor) component;
97 		}
98 
99 		return null;
100 	}
101 
102 	/**
103 	 *
104 	 */
105 	@SuppressWarnings("serial")
106 	public static class ToggleRulersItem extends JCheckBoxMenuItem {
107 		/**
108 		 *
109 		 */
ToggleRulersItem(final BasicGraphEditor editor, String name)110 		public ToggleRulersItem(final BasicGraphEditor editor, String name) {
111 			super(name);
112 			setSelected(editor.getGraphComponent().getColumnHeader() != null);
113 
114 			addActionListener(new ActionListener() {
115 				/**
116 				 *
117 				 */
118 				public void actionPerformed(ActionEvent e) {
119 					mxGraphComponent graphComponent = editor
120 							.getGraphComponent();
121 
122 					if (graphComponent.getColumnHeader() != null) {
123 						graphComponent.setColumnHeader(null);
124 						graphComponent.setRowHeader(null);
125 					} else {
126 						graphComponent.setColumnHeaderView(new EditorRuler(
127 								graphComponent,
128 								EditorRuler.ORIENTATION_HORIZONTAL));
129 						graphComponent.setRowHeaderView(new EditorRuler(
130 								graphComponent,
131 								EditorRuler.ORIENTATION_VERTICAL));
132 					}
133 				}
134 			});
135 		}
136 
137 	}
138 
139 	/**
140 	 *
141 	 */
142 	@SuppressWarnings("serial")
143 	public static class ToggleGridItem extends JCheckBoxMenuItem {
144 		/**
145 		 *
146 		 */
ToggleGridItem(final BasicGraphEditor editor, String name)147 		public ToggleGridItem(final BasicGraphEditor editor, String name) {
148 			super(name);
149 			setSelected(true);
150 
151 			addActionListener(new ActionListener() {
152 				/**
153 				 *
154 				 */
155 				public void actionPerformed(ActionEvent e) {
156 					mxGraphComponent graphComponent = editor
157 							.getGraphComponent();
158 					mxGraph graph = graphComponent.getGraph();
159 					boolean enabled = !graph.isGridEnabled();
160 
161 					graph.setGridEnabled(enabled);
162 					graphComponent.setGridVisible(enabled);
163 					graphComponent.repaint();
164 					setSelected(enabled);
165 				}
166 			});
167 		}
168 	}
169 
170 	/**
171 	 *
172 	 */
173 	@SuppressWarnings("serial")
174 	public static class ToggleOutlineItem extends JCheckBoxMenuItem {
175 		/**
176 		 *
177 		 */
ToggleOutlineItem(final BasicGraphEditor editor, String name)178 		public ToggleOutlineItem(final BasicGraphEditor editor, String name) {
179 			super(name);
180 			setSelected(true);
181 
182 			addActionListener(new ActionListener() {
183 				/**
184 				 *
185 				 */
186 				public void actionPerformed(ActionEvent e) {
187 					final mxGraphOutline outline = editor.getGraphOutline();
188 					outline.setVisible(!outline.isVisible());
189 					outline.revalidate();
190 
191 					SwingUtilities.invokeLater(new Runnable() {
192 						/*
193 						 * (non-Javadoc)
194 						 *
195 						 * @see java.lang.Runnable#run()
196 						 */
197 						public void run() {
198 							if (outline.getParent() instanceof JSplitPane) {
199 								if (outline.isVisible()) {
200 									((JSplitPane) outline.getParent())
201 											.setDividerLocation(editor
202 													.getHeight() - 300);
203 									((JSplitPane) outline.getParent())
204 											.setDividerSize(6);
205 								} else {
206 									((JSplitPane) outline.getParent())
207 											.setDividerSize(0);
208 								}
209 							}
210 						}
211 					});
212 				}
213 			});
214 		}
215 	}
216 
217 	/**
218 	 *
219 	 */
220 	@SuppressWarnings("serial")
221 	public static class ExitAction extends AbstractAction {
222 
223 		/**
224 		 *
225 		 */
actionPerformed(ActionEvent e)226 		public void actionPerformed(ActionEvent e) {
227 			BasicGraphEditor editor = getEditor(e);
228 
229 			if (editor != null) {
230 				editor.exit();
231 			}
232 		}
233 
234 	}
235 
236 	/**
237 	 *
238 	 */
239 	@SuppressWarnings("serial")
240 	public static class StylesheetAction extends AbstractAction {
241 
242 		/**
243 		 *
244 		 */
245 		protected String stylesheet;
246 
247 		/**
248 		 *
249 		 */
StylesheetAction(String stylesheet)250 		public StylesheetAction(String stylesheet) {
251 			this.stylesheet = stylesheet;
252 		}
253 
254 		/**
255 		 *
256 		 */
actionPerformed(ActionEvent e)257 		public void actionPerformed(ActionEvent e) {
258 			if (e.getSource() instanceof mxGraphComponent) {
259 				mxGraphComponent graphComponent = (mxGraphComponent) e
260 						.getSource();
261 				mxGraph graph = graphComponent.getGraph();
262 				mxCodec codec = new mxCodec();
263 				Document doc = mxUtils.loadDocument(EditorActions.class
264 						.getResource(stylesheet).toString());
265 
266 				if (doc != null) {
267 					codec.decode(doc.getDocumentElement(), graph
268 							.getStylesheet());
269 					graph.refresh();
270 				}
271 			}
272 		}
273 
274 	}
275 
276 	/**
277 	 *
278 	 */
279 	@SuppressWarnings("serial")
280 	public static class ZoomPolicyAction extends AbstractAction {
281 		/**
282 		 *
283 		 */
284 		protected int zoomPolicy;
285 
286 		/**
287 		 *
288 		 */
ZoomPolicyAction(int zoomPolicy)289 		public ZoomPolicyAction(int zoomPolicy) {
290 			this.zoomPolicy = zoomPolicy;
291 		}
292 
293 		/**
294 		 *
295 		 */
actionPerformed(ActionEvent e)296 		public void actionPerformed(ActionEvent e) {
297 			if (e.getSource() instanceof mxGraphComponent) {
298 				mxGraphComponent graphComponent = (mxGraphComponent) e
299 						.getSource();
300 				graphComponent.setPageVisible(true);
301 				graphComponent.setZoomPolicy(zoomPolicy);
302 			}
303 		}
304 
305 	}
306 
307 	/**
308 	 *
309 	 */
310 	@SuppressWarnings("serial")
311 	public static class GridStyleAction extends AbstractAction {
312 		/**
313 		 *
314 		 */
315 		protected int style;
316 
317 		/**
318 		 *
319 		 */
GridStyleAction(int style)320 		public GridStyleAction(int style) {
321 			this.style = style;
322 		}
323 
324 		/**
325 		 *
326 		 */
actionPerformed(ActionEvent e)327 		public void actionPerformed(ActionEvent e) {
328 			if (e.getSource() instanceof mxGraphComponent) {
329 				mxGraphComponent graphComponent = (mxGraphComponent) e
330 						.getSource();
331 				graphComponent.setGridStyle(style);
332 				graphComponent.repaint();
333 			}
334 		}
335 
336 	}
337 
338 	/**
339 	 *
340 	 */
341 	@SuppressWarnings("serial")
342 	public static class GridColorAction extends AbstractAction {
343 
344 		/**
345 		 *
346 		 */
actionPerformed(ActionEvent e)347 		public void actionPerformed(ActionEvent e) {
348 			if (e.getSource() instanceof mxGraphComponent) {
349 				mxGraphComponent graphComponent = (mxGraphComponent) e
350 						.getSource();
351 				Color newColor = JColorChooser.showDialog(graphComponent,
352 						mxResources.get("gridColor"), graphComponent
353 								.getGridColor());
354 
355 				if (newColor != null) {
356 					graphComponent.setGridColor(newColor);
357 					graphComponent.repaint();
358 				}
359 			}
360 		}
361 
362 	}
363 
364 	/**
365 	 *
366 	 */
367 	@SuppressWarnings("serial")
368 	public static class ScaleAction extends AbstractAction {
369 
370 		/**
371 		 *
372 		 */
373 		protected double scale;
374 
375 		/**
376 		 *
377 		 */
ScaleAction(double scale)378 		public ScaleAction(double scale) {
379 			this.scale = scale;
380 		}
381 
382 		/**
383 		 *
384 		 */
actionPerformed(ActionEvent e)385 		public void actionPerformed(ActionEvent e) {
386 			if (e.getSource() instanceof mxGraphComponent) {
387 				mxGraphComponent graphComponent = (mxGraphComponent) e
388 						.getSource();
389 				double scale = this.scale;
390 
391 				if (scale == 0) {
392 					String value = (String) JOptionPane.showInputDialog(
393 							graphComponent, mxResources.get("value"),
394 							mxResources.get("scale") + " (%)",
395 							JOptionPane.PLAIN_MESSAGE, null, null, "");
396 
397 					if (value != null) {
398 						scale = Double.parseDouble(value.replace("%", "")) / 100;
399 					}
400 				}
401 
402 				if (scale > 0) {
403 					graphComponent.zoomTo(scale, graphComponent.isCenterZoom());
404 				}
405 			}
406 		}
407 
408 	}
409 
410 	/**
411 	 *
412 	 */
413 	@SuppressWarnings("serial")
414 	public static class PageSetupAction extends AbstractAction {
415 
416 		/**
417 		 *
418 		 */
actionPerformed(ActionEvent e)419 		public void actionPerformed(ActionEvent e) {
420 			if (e.getSource() instanceof mxGraphComponent) {
421 				mxGraphComponent graphComponent = (mxGraphComponent) e
422 						.getSource();
423 				PrinterJob pj = PrinterJob.getPrinterJob();
424 				PageFormat format = pj.pageDialog(graphComponent
425 						.getPageFormat());
426 
427 				if (format != null) {
428 					graphComponent.setPageFormat(format);
429 					graphComponent.zoomAndCenter();
430 				}
431 			}
432 		}
433 
434 	}
435 
436 	/**
437 	 *
438 	 */
439 	@SuppressWarnings("serial")
440 	public static class PrintAction extends AbstractAction {
441 
442 		/**
443 		 *
444 		 */
actionPerformed(ActionEvent e)445 		public void actionPerformed(ActionEvent e) {
446 			if (e.getSource() instanceof mxGraphComponent) {
447 				mxGraphComponent graphComponent = (mxGraphComponent) e
448 						.getSource();
449 				PrinterJob pj = PrinterJob.getPrinterJob();
450 
451 				if (pj.printDialog()) {
452 					PageFormat pf = graphComponent.getPageFormat();
453 					Paper paper = new Paper();
454 					double margin = 36;
455 					paper.setImageableArea(margin, margin, paper.getWidth()
456 							- margin * 2, paper.getHeight() - margin * 2);
457 					pf.setPaper(paper);
458 					pj.setPrintable(graphComponent, pf);
459 
460 					try {
461 						pj.print();
462 					} catch (PrinterException e2) {
463 						System.out.println(e2);
464 					}
465 				}
466 			}
467 		}
468 
469 	}
470 
471 	private static final String DIAGRAM_EXTENSION = ".mxe";
472 
473 	private interface ProgressListener {
474 
onProgress(int progress)475 		void onProgress(int progress);
476 	}
477 
478 	/**
479 	 *
480 	 */
481 	@SuppressWarnings("serial")
482 	public static class SaveAction extends AbstractAction {
483 
484 
485 		/**
486 		 *
487 		 */
488 		protected boolean showDialog;
489 
490 		/**
491 		 *
492 		 */
SaveAction(boolean showDialog)493 		public SaveAction(boolean showDialog) {
494 			this.showDialog = showDialog;
495 		}
496 
post( final BasicGraphEditor editor, final byte[] content, String fileName, String mimeType, ProxySelector proxySelector, final int offset, final int scale, final ProgressListener progressListener)497 		private HttpResponse post(
498 				final BasicGraphEditor editor,
499 				final byte[] content,
500 				String fileName,
501 				String mimeType,
502 				ProxySelector proxySelector,
503 				final int offset,
504 				final int scale,
505 				final ProgressListener progressListener) throws Exception {
506 
507 			String dokuHost = editor.getConfig().getDokuHost();
508 			if (dokuHost.endsWith(":80")) {
509 				dokuHost = dokuHost.substring(0, dokuHost.length()-3);
510 			}
511 			StringBuilder saveUrl = new StringBuilder(dokuHost);
512 			saveUrl.append(new String(Hex.decodeHex(editor.getConfig().getDokuBase().toCharArray())));
513 			saveUrl.append("lib/exe/mediamanager.php?");
514 //		            saveUrl.append("&"+editor.getConfig().getSessionName()+"="+editor.getConfig().getSessionId());
515 //		            saveUrl.append("&ns="+new String(URLCodec.encodeUrl(null, namespace.getBytes())));
516 //		            saveUrl.append("&sectok="+editor.getConfig().getSectok());
517 //		            saveUrl.append("&authtok="+editor.getConfig().getAuthtok());
518 //		            saveUrl.append("&ow=1");
519 			System.out.println(saveUrl);
520 	        HttpPost httppost = new HttpPost(saveUrl.toString());
521 
522 	        if (!httppost.containsHeader("Cookie")) {
523 	        	httppost.setHeader("Cookie", editor.getConfig().getCookies());
524 	        }
525 
526 	        httppost.setHeader("Pragma", "No-cache");
527 
528 		    MultipartEntity reqEntity = new MultipartEntity();
529 
530 		    reqEntity.addPart("sectok", new StringBody(editor.getConfig().getSectok()));
531 		    reqEntity.addPart("ow", new StringBody("1"));
532 
533 		    reqEntity.addPart("Filename", new StringBody(fileName));
534 
535             String namespace = editor.getConfig().getName();
536             int idx = namespace.lastIndexOf(":");
537             if (idx==-1) {
538             	namespace=":";
539             } else {
540             	namespace=":"+namespace.substring(0, idx);
541             }
542 
543 		    if (namespace!=null) {
544 			    reqEntity.addPart("ns", new StringBody(namespace));
545 		    }
546 
547 		    final long contentSize = content.length;
548 
549 		    InputStream countingFilter = new FilterInputStream(new ByteArrayInputStream(content)) {
550 
551 		    	private long counter;
552 
553 		    	private int inc(int incVal) {
554 		    		if (incVal!=-1) {
555 		    			counter+=incVal;
556 		    			progress();
557 		    		}
558 		    		return incVal;
559 		    	}
560 
561 		    	private long inc(long incVal) {
562 		    		if (incVal!=-1) {
563 		    			counter+=incVal;
564 		    			progress();
565 		    		}
566 		    		return incVal;
567 		    	}
568 
569 		    	private void progress() {
570 		    		System.out.println("-- Progress --> ["+Thread.currentThread()+"] "+counter+"/"+contentSize);
571 		    		progressListener.onProgress((int) (offset + scale*counter/contentSize));
572 		    	}
573 
574 		    	@Override
575 		    	public int read() throws IOException {
576 		    		return inc(super.read());
577 		    	}
578 
579 		    	@Override
580 		    	public int read(byte[] b) throws IOException {
581 		    		return inc(super.read(b));
582 		    	}
583 
584 		    	@Override
585 		    	public int read(byte[] b, int off, int len) throws IOException {
586 		    		return inc(super.read(b, off, len));
587 		    	}
588 
589 		    	@Override
590 		    	public long skip(long n) throws IOException {
591 		    		return inc(super.skip(n));
592 		    	}
593 
594 		    	@Override
595 		    	public void close() throws IOException {
596 		    		editor.status("Upload finished");
597 		    		super.close();
598 		    	}
599 		    };
600 
601 			InputStreamBody bin = new InputStreamBody(countingFilter, mimeType, fileName) {
602 
603 		    	@Override
604 		    	public long getContentLength() {
605 		    		return content.length;
606 		    	}
607 		    };
608 
609 		    reqEntity.addPart("Filedata", bin);
610 
611 		    httppost.setEntity(reqEntity);
612 
613 		    DefaultHttpClient httpClient = new DefaultHttpClient();
614 		    if (proxySelector!=null) {
615 		    	ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(
616 			        httpClient.getConnectionManager().getSchemeRegistry(),
617 			        proxySelector);
618 		    	httpClient.setRoutePlanner(routePlanner);
619 		    }
620 //					HttpHost proxy = new HttpHost("localhost", 8888);
621 //					httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
622 			return httpClient.execute(httppost);
623 		}
624 
625 		/**
626 		 *
627 		 */
actionPerformed(ActionEvent e)628 		public void actionPerformed(ActionEvent e) {
629 			final BasicGraphEditor editor = getEditor(e);
630 
631 			if (editor != null) {
632 				final mxGraphComponent graphComponent = editor.getGraphComponent();
633 				mxGraph graph = graphComponent.getGraph();
634 
635 				try {
636 					int idx = editor.getConfig().getName().lastIndexOf(":");
637 
638 					final String dName = idx==-1 ? editor.getConfig().getName() : editor.getConfig().getName().substring(idx+1);
639 
640 					// Saving to GIF
641 					Color bg = graphComponent.getBackground(); // Always transparent background.
642 
643 					// Saving image first
644 					final BufferedImage image = mxCellRenderer.createBufferedImage(
645 							graph, null, graph.getView().getScale(), bg,
646 							graphComponent.isAntiAlias(), null,
647 							graphComponent.getCanvas());
648 
649 					if (image != null) {
650 						// Saving image
651 						final ByteArrayOutputStream iBaos = new ByteArrayOutputStream();
652 						ImageIO.write(image, editor.getConfig().getImageFormat(), iBaos);
653 						iBaos.close();
654 
655 						// Saving to XML
656 						mxCodec codec = new mxCodec();
657 						String xml = mxUtils.getXml(codec.encode(graph.getModel()));
658 						final ByteArrayOutputStream baos = new ByteArrayOutputStream();
659 						OutputStreamWriter osw = new OutputStreamWriter(baos);
660 						osw.write(xml+"\n");
661 						osw.close();
662 
663 						// Uploading
664 						SwingWorker<Boolean, Long> task = new SwingWorker<Boolean, Long>() {
665 
666 							@Override
667 							protected Boolean doInBackground() throws Exception {
668 
669 								HttpResponse iResponse = post(
670 										editor,
671 										iBaos.toByteArray(),
672 										dName+"."+editor.getConfig().getImageFormat(),
673 										"application/octet-stream",
674 										editor.getConfig().getProxySelector(),
675 										0,
676 										50,
677 										new ProgressListener() {
678 
679 											@Override
680 											public void onProgress(int progress) {
681 												setProgress(progress);
682 											}
683 
684 										});
685 								if (iResponse.getStatusLine().getStatusCode()==HttpStatus.SC_OK) {
686 
687 									HttpResponse response = post(
688 											editor,
689 											baos.toByteArray(),
690 											dName+DIAGRAM_EXTENSION,
691 											"application/octet-stream",
692 											editor.getConfig().getProxySelector(),
693 											0,
694 											50,
695 											new ProgressListener() {
696 
697 												@Override
698 												public void onProgress(int progress) {
699 													setProgress(progress);
700 												}
701 
702 											});
703 
704 									System.out.println(response.getStatusLine());
705 								    if (response.getStatusLine().getStatusCode()==HttpStatus.SC_OK) {
706 								    	editor.setModified(false);
707 								    	return true;
708 								    } else {
709 								    	errorMessage = response.getStatusLine();
710 								    	errorTitle = mxResources.get("errorSaveDiagram");
711 								    	return false;
712 								    }
713 								} else {
714 							    	errorMessage = iResponse.getStatusLine();
715 							    	errorTitle = mxResources.get("errorSaveImage");
716 							    	return false;
717 								}
718 							}
719 
720 							private Object errorMessage;
721 							private String errorTitle;
722 
723 							protected void done() {
724 								if (errorMessage==null) {
725 									JOptionPane.showMessageDialog(graphComponent, mxResources.get("diagramSaved"));
726 								} else {
727 							    	JOptionPane.showMessageDialog(
728 							    			graphComponent,
729 											errorMessage,
730 											errorTitle,
731 											JOptionPane.ERROR_MESSAGE);
732 								}
733 
734 							};
735 
736 						};
737 						task.addPropertyChangeListener(new PropertyChangeListener() {
738 
739 						    public void propertyChange(PropertyChangeEvent evt) {
740 						        if ("progress" == evt.getPropertyName() ) {
741 						            int progress = (Integer) evt.getNewValue();
742 						            editor.status("Uploaded "+progress+"%");
743 						        }
744 
745 						    }
746 						});
747 						task.execute();
748 					} else {
749 						JOptionPane.showMessageDialog(graphComponent, mxResources.get("noImageData"));
750 					}
751 
752 				} catch (Exception ex) {
753 					ex.printStackTrace();
754 					JOptionPane.showMessageDialog(graphComponent,
755 							ex.toString(), mxResources.get("error"),
756 							JOptionPane.ERROR_MESSAGE);
757 				}
758 			}
759 		}
760 	}
761 
762 	/**
763 	 *
764 	 */
765 	@SuppressWarnings("serial")
766 	public static class SelectShortestPathAction extends AbstractAction {
767 
768 		/**
769 		 *
770 		 */
771 		protected boolean directed;
772 
773 		/**
774 		 *
775 		 */
SelectShortestPathAction(boolean directed)776 		public SelectShortestPathAction(boolean directed) {
777 			this.directed = directed;
778 		}
779 
780 		/**
781 		 *
782 		 */
actionPerformed(ActionEvent e)783 		public void actionPerformed(ActionEvent e) {
784 			if (e.getSource() instanceof mxGraphComponent) {
785 				mxGraphComponent graphComponent = (mxGraphComponent) e
786 						.getSource();
787 				mxGraph graph = graphComponent.getGraph();
788 				mxIGraphModel model = graph.getModel();
789 
790 				Object source = null;
791 				Object target = null;
792 
793 				Object[] cells = graph.getSelectionCells();
794 
795 				for (int i = 0; i < cells.length; i++) {
796 					if (model.isVertex(cells[i])) {
797 						if (source == null) {
798 							source = cells[i];
799 						} else if (target == null) {
800 							target = cells[i];
801 						}
802 					}
803 
804 					if (source != null && target != null) {
805 						break;
806 					}
807 				}
808 
809 				if (source != null && target != null) {
810 					int steps = graph.getChildEdges(graph.getDefaultParent()).length;
811 					Object[] path = mxGraphAnalysis.getInstance()
812 							.getShortestPath(graph, source, target,
813 									new mxDistanceCostFunction(), steps,
814 									directed);
815 					graph.setSelectionCells(path);
816 				} else {
817 					JOptionPane.showMessageDialog(graphComponent, mxResources
818 							.get("noSourceAndTargetSelected"));
819 				}
820 			}
821 		}
822 
823 	}
824 
825 	/**
826 	 *
827 	 */
828 	@SuppressWarnings("serial")
829 	public static class SelectSpanningTreeAction extends AbstractAction {
830 
831 		/**
832 		 *
833 		 */
834 		protected boolean directed;
835 
836 		/**
837 		 *
838 		 */
SelectSpanningTreeAction(boolean directed)839 		public SelectSpanningTreeAction(boolean directed) {
840 			this.directed = directed;
841 		}
842 
843 		/**
844 		 *
845 		 */
actionPerformed(ActionEvent e)846 		public void actionPerformed(ActionEvent e) {
847 			if (e.getSource() instanceof mxGraphComponent) {
848 				mxGraphComponent graphComponent = (mxGraphComponent) e
849 						.getSource();
850 				mxGraph graph = graphComponent.getGraph();
851 				mxIGraphModel model = graph.getModel();
852 
853 				Object parent = graph.getDefaultParent();
854 				Object[] cells = graph.getSelectionCells();
855 
856 				for (int i = 0; i < cells.length; i++) {
857 					if (model.getChildCount(cells[i]) > 0) {
858 						parent = cells[i];
859 						break;
860 					}
861 				}
862 
863 				Object[] v = graph.getChildVertices(parent);
864 				Object[] mst = mxGraphAnalysis.getInstance()
865 						.getMinimumSpanningTree(graph, v,
866 								new mxDistanceCostFunction(), directed);
867 				graph.setSelectionCells(mst);
868 			}
869 		}
870 
871 	}
872 
873 	/**
874 	 *
875 	 */
876 	@SuppressWarnings("serial")
877 	public static class ToggleDirtyAction extends AbstractAction {
878 
879 		/**
880 		 *
881 		 */
actionPerformed(ActionEvent e)882 		public void actionPerformed(ActionEvent e) {
883 			if (e.getSource() instanceof mxGraphComponent) {
884 				mxGraphComponent graphComponent = (mxGraphComponent) e
885 						.getSource();
886 				graphComponent.showDirtyRectangle = !graphComponent.showDirtyRectangle;
887 			}
888 		}
889 
890 	}
891 
892 	/**
893 	 *
894 	 */
895 	@SuppressWarnings("serial")
896 	public static class ToggleImagePreviewAction extends AbstractAction {
897 
898 		/**
899 		 *
900 		 */
actionPerformed(ActionEvent e)901 		public void actionPerformed(ActionEvent e) {
902 			if (e.getSource() instanceof mxGraphComponent) {
903 				mxGraphComponent graphComponent = (mxGraphComponent) e
904 						.getSource();
905 				graphComponent.getGraphHandler().setImagePreview(
906 						!graphComponent.getGraphHandler().isImagePreview());
907 			}
908 		}
909 
910 	}
911 
912 	/**
913 	 *
914 	 */
915 	@SuppressWarnings("serial")
916 	public static class ToggleConnectModeAction extends AbstractAction {
917 
918 		/**
919 		 *
920 		 */
actionPerformed(ActionEvent e)921 		public void actionPerformed(ActionEvent e) {
922 			if (e.getSource() instanceof mxGraphComponent) {
923 				mxGraphComponent graphComponent = (mxGraphComponent) e
924 						.getSource();
925 				mxConnectionHandler handler = graphComponent
926 						.getConnectionHandler();
927 				handler.setHandleEnabled(!handler.isHandleEnabled());
928 			}
929 		}
930 
931 	}
932 
933 	/**
934 	 *
935 	 */
936 	@SuppressWarnings("serial")
937 	public static class ToggleCreateTargetItem extends JCheckBoxMenuItem {
938 		/**
939 		 *
940 		 */
ToggleCreateTargetItem(final BasicGraphEditor editor, String name)941 		public ToggleCreateTargetItem(final BasicGraphEditor editor, String name) {
942 			super(name);
943 			setSelected(true);
944 
945 			addActionListener(new ActionListener() {
946 				/**
947 				 *
948 				 */
949 				public void actionPerformed(ActionEvent e) {
950 					mxGraphComponent graphComponent = editor
951 							.getGraphComponent();
952 
953 					if (graphComponent != null) {
954 						mxConnectionHandler handler = graphComponent
955 								.getConnectionHandler();
956 						handler.setCreateTarget(!handler.isCreateTarget());
957 						setSelected(handler.isCreateTarget());
958 					}
959 				}
960 			});
961 		}
962 	}
963 
964 	/**
965 	 *
966 	 */
967 	@SuppressWarnings("serial")
968 	public static class PromptPropertyAction extends AbstractAction {
969 		/**
970 		 *
971 		 */
972 		protected Object target;
973 
974 		/**
975 		 *
976 		 */
977 		protected String fieldname, message;
978 
979 		/**
980 		 *
981 		 */
PromptPropertyAction(Object target, String message)982 		public PromptPropertyAction(Object target, String message) {
983 			this(target, message, message);
984 		}
985 
986 		/**
987 		 *
988 		 */
PromptPropertyAction(Object target, String message, String fieldname)989 		public PromptPropertyAction(Object target, String message,
990 				String fieldname) {
991 			this.target = target;
992 			this.message = message;
993 			this.fieldname = fieldname;
994 		}
995 
996 		/**
997 		 *
998 		 */
actionPerformed(ActionEvent e)999 		public void actionPerformed(ActionEvent e) {
1000 			if (e.getSource() instanceof Component) {
1001 				try {
1002 					Method getter = target.getClass().getMethod(
1003 							"get" + fieldname);
1004 					Object current = getter.invoke(target);
1005 
1006 					// TODO: Support other atomic types
1007 					if (current instanceof Integer) {
1008 						Method setter = target.getClass().getMethod(
1009 								"set" + fieldname, new Class[] { int.class });
1010 
1011 						String value = (String) JOptionPane.showInputDialog(
1012 								(Component) e.getSource(), "Value", message,
1013 								JOptionPane.PLAIN_MESSAGE, null, null, current);
1014 
1015 						if (value != null) {
1016 							setter.invoke(target, Integer.parseInt(value));
1017 						}
1018 					}
1019 				} catch (Exception ex) {
1020 					ex.printStackTrace();
1021 				}
1022 			}
1023 
1024 			// Repaints the graph component
1025 			if (e.getSource() instanceof mxGraphComponent) {
1026 				mxGraphComponent graphComponent = (mxGraphComponent) e
1027 						.getSource();
1028 				graphComponent.repaint();
1029 			}
1030 		}
1031 
1032 	}
1033 
1034 	/**
1035 	 *
1036 	 */
1037 	@SuppressWarnings("serial")
1038 	public static class TogglePropertyItem extends JCheckBoxMenuItem {
1039 
1040 		/**
1041 		 *
1042 		 */
TogglePropertyItem(Object target, String name, String fieldname)1043 		public TogglePropertyItem(Object target, String name, String fieldname) {
1044 			this(target, name, fieldname, false);
1045 		}
1046 
1047 		/**
1048 		 *
1049 		 */
TogglePropertyItem(Object target, String name, String fieldname, boolean refresh)1050 		public TogglePropertyItem(Object target, String name, String fieldname,
1051 				boolean refresh) {
1052 			this(target, name, fieldname, refresh, null);
1053 		}
1054 
1055 		/**
1056 		 *
1057 		 */
TogglePropertyItem(final Object target, String name, final String fieldname, final boolean refresh, ActionListener listener)1058 		public TogglePropertyItem(final Object target, String name,
1059 				final String fieldname, final boolean refresh,
1060 				ActionListener listener) {
1061 			super(name);
1062 
1063 			// Since action listeners are processed last to first we add the
1064 			// given
1065 			// listener here which means it will be processed after the one
1066 			// below
1067 			if (listener != null) {
1068 				addActionListener(listener);
1069 			}
1070 
1071 			addActionListener(new ActionListener() {
1072 				/**
1073 				 *
1074 				 */
1075 				public void actionPerformed(ActionEvent e) {
1076 					execute(target, fieldname, refresh);
1077 				}
1078 			});
1079 
1080 			PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {
1081 
1082 				/*
1083 				 * (non-Javadoc)
1084 				 *
1085 				 * @see
1086 				 * java.beans.PropertyChangeListener#propertyChange(java.beans
1087 				 * .PropertyChangeEvent)
1088 				 */
1089 				public void propertyChange(PropertyChangeEvent evt) {
1090 					if (evt.getPropertyName().equalsIgnoreCase(fieldname)) {
1091 						update(target, fieldname);
1092 					}
1093 				}
1094 
1095 			};
1096 
1097 			if (target instanceof mxGraphComponent) {
1098 				((mxGraphComponent) target)
1099 						.addPropertyChangeListener(propertyChangeListener);
1100 			} else if (target instanceof mxGraph) {
1101 				((mxGraph) target)
1102 						.addPropertyChangeListener(propertyChangeListener);
1103 			}
1104 
1105 			update(target, fieldname);
1106 		}
1107 
1108 		/**
1109 		 *
1110 		 */
update(Object target, String fieldname)1111 		public void update(Object target, String fieldname) {
1112 			try {
1113 				Method getter = target.getClass().getMethod("is" + fieldname);
1114 				Object current = getter.invoke(target);
1115 
1116 				if (current instanceof Boolean) {
1117 					setSelected(((Boolean) current).booleanValue());
1118 				}
1119 			} catch (Exception e) {
1120 				e.printStackTrace();
1121 			}
1122 		}
1123 
1124 		/**
1125 		 *
1126 		 */
execute(Object target, String fieldname, boolean refresh)1127 		public void execute(Object target, String fieldname, boolean refresh) {
1128 			try {
1129 				Method getter = target.getClass().getMethod("is" + fieldname);
1130 				Method setter = target.getClass().getMethod("set" + fieldname,
1131 						new Class[] { boolean.class });
1132 
1133 				Object current = getter.invoke(target);
1134 
1135 				if (current instanceof Boolean) {
1136 					boolean value = !((Boolean) current).booleanValue();
1137 					setter.invoke(target, value);
1138 					setSelected(value);
1139 				}
1140 
1141 				if (refresh) {
1142 					mxGraph graph = null;
1143 
1144 					if (target instanceof mxGraph) {
1145 						graph = (mxGraph) target;
1146 					} else if (target instanceof mxGraphComponent) {
1147 						graph = ((mxGraphComponent) target).getGraph();
1148 					}
1149 
1150 					graph.refresh();
1151 				}
1152 			} catch (Exception e) {
1153 				e.printStackTrace();
1154 			}
1155 		}
1156 
1157 	}
1158 
1159 	/**
1160 	 *
1161 	 */
1162 	@SuppressWarnings("serial")
1163 	public static class HistoryAction extends AbstractAction {
1164 
1165 		/**
1166 		 *
1167 		 */
1168 		protected boolean undo;
1169 
1170 		/**
1171 		 *
1172 		 */
HistoryAction(boolean undo)1173 		public HistoryAction(boolean undo) {
1174 			this.undo = undo;
1175 		}
1176 
1177 		/**
1178 		 *
1179 		 */
actionPerformed(ActionEvent e)1180 		public void actionPerformed(ActionEvent e) {
1181 			BasicGraphEditor editor = getEditor(e);
1182 
1183 			if (editor != null) {
1184 				if (undo) {
1185 					editor.getUndoManager().undo();
1186 				} else {
1187 					editor.getUndoManager().redo();
1188 				}
1189 			}
1190 		}
1191 	}
1192 
1193 	/**
1194 	 *
1195 	 */
1196 	@SuppressWarnings("serial")
1197 	public static class FontStyleAction extends AbstractAction {
1198 		/**
1199 		 *
1200 		 */
1201 		protected boolean bold;
1202 
1203 		/**
1204 		 *
1205 		 */
FontStyleAction(boolean bold)1206 		public FontStyleAction(boolean bold) {
1207 			this.bold = bold;
1208 		}
1209 
1210 		/**
1211 		 *
1212 		 */
actionPerformed(ActionEvent e)1213 		public void actionPerformed(ActionEvent e) {
1214 			if (e.getSource() instanceof mxGraphComponent) {
1215 				mxGraphComponent graphComponent = (mxGraphComponent) e
1216 						.getSource();
1217 				Component editorComponent = null;
1218 
1219 				if (graphComponent.getCellEditor() instanceof mxCellEditor) {
1220 					editorComponent = ((mxCellEditor) graphComponent
1221 							.getCellEditor()).getEditor();
1222 				}
1223 
1224 				if (editorComponent instanceof JEditorPane) {
1225 					JEditorPane editorPane = (JEditorPane) editorComponent;
1226 					int start = editorPane.getSelectionStart();
1227 					int ende = editorPane.getSelectionEnd();
1228 					String text = editorPane.getSelectedText();
1229 
1230 					if (text == null) {
1231 						text = "";
1232 					}
1233 
1234 					try {
1235 						HTMLEditorKit editorKit = new HTMLEditorKit();
1236 						HTMLDocument document = (HTMLDocument) editorPane
1237 								.getDocument();
1238 						document.remove(start, (ende - start));
1239 						editorKit.insertHTML(document, start, ((bold) ? "<b>"
1240 								: "<i>")
1241 								+ text + ((bold) ? "</b>" : "</i>"), 0, 0,
1242 								(bold) ? HTML.Tag.B : HTML.Tag.I);
1243 					} catch (Exception ex) {
1244 						ex.printStackTrace();
1245 					}
1246 
1247 					editorPane.requestFocus();
1248 					editorPane.select(start, ende);
1249 				} else {
1250 					mxIGraphModel model = graphComponent.getGraph().getModel();
1251 					model.beginUpdate();
1252 					try {
1253 						graphComponent.stopEditing(false);
1254 						graphComponent.getGraph().toggleCellStyleFlags(
1255 								mxConstants.STYLE_FONTSTYLE,
1256 								(bold) ? mxConstants.FONT_BOLD
1257 										: mxConstants.FONT_ITALIC);
1258 					} finally {
1259 						model.endUpdate();
1260 					}
1261 				}
1262 			}
1263 		}
1264 	}
1265 
1266 	/**
1267 	 *
1268 	 */
1269 	@SuppressWarnings("serial")
1270 	public static class WarningAction extends AbstractAction {
1271 
1272 		/**
1273 		 *
1274 		 */
actionPerformed(ActionEvent e)1275 		public void actionPerformed(ActionEvent e) {
1276 			if (e.getSource() instanceof mxGraphComponent) {
1277 				mxGraphComponent graphComponent = (mxGraphComponent) e
1278 						.getSource();
1279 				Object[] cells = graphComponent.getGraph().getSelectionCells();
1280 
1281 				if (cells != null && cells.length > 0) {
1282 					String warning = JOptionPane.showInputDialog(mxResources
1283 							.get("enterWarningMessage"));
1284 
1285 					for (int i = 0; i < cells.length; i++) {
1286 						graphComponent.setCellWarning(cells[i], warning);
1287 					}
1288 				} else {
1289 					JOptionPane.showMessageDialog(graphComponent, mxResources
1290 							.get("noCellSelected"));
1291 				}
1292 			}
1293 		}
1294 	}
1295 
1296 	/**
1297 	 *
1298 	 */
1299 	@SuppressWarnings("serial")
1300 	public static class NewAction extends AbstractAction {
1301 
1302 		/**
1303 		 *
1304 		 */
actionPerformed(ActionEvent e)1305 		public void actionPerformed(ActionEvent e) {
1306 			BasicGraphEditor editor = getEditor(e);
1307 
1308 			if (editor != null) {
1309 				if (!editor.isModified() || JOptionPane.showConfirmDialog(editor, mxResources.get("loseChanges")) == JOptionPane.YES_OPTION) {
1310 					mxGraph graph = editor.getGraphComponent().getGraph();
1311 					// Check modified flag and display save dialog
1312 					mxCell root = new mxCell();
1313 					root.insert(new mxCell());
1314 					graph.getModel().setRoot(root);
1315 
1316 					editor.setModified(false);
1317 //					editor.setCurrentFile(null);
1318 				}
1319 			}
1320 		}
1321 	}
1322 
1323 	/**
1324 	 *
1325 	 */
1326 	@SuppressWarnings("serial")
1327 	public static class OpenAction extends AbstractAction {
1328 
1329 		/**
1330 		 *
1331 		 */
actionPerformed(ActionEvent e)1332 		public void actionPerformed(ActionEvent e) {
1333 			BasicGraphEditor editor = getEditor(e);
1334 
1335 			if (editor != null) {
1336 				if (!editor.isModified() || JOptionPane.showConfirmDialog(editor, mxResources.get("loseChanges")) == JOptionPane.YES_OPTION) {
1337 					mxGraph graph = mxGraphActions.getGraph(e);
1338 
1339 					if (graph != null && !editor.getConfig().isNew()) {
1340 						try {
1341 				            StringBuilder sourceUrl = new StringBuilder(editor.getConfig().getDokuHost()+new String(Hex.decodeHex(editor.getConfig().getDokuBase().toCharArray())));
1342 				            sourceUrl.append("lib/exe/fetch.php?media=");
1343 				            sourceUrl.append(editor.getConfig().getName());
1344 				            sourceUrl.append(DIAGRAM_EXTENSION+"#"+Long.toString(System.currentTimeMillis(), Character.MAX_RADIX));
1345 //				            sourceUrl.append("&"+editor.getConfig().getSessionName()+"="+editor.getConfig().getSessionId());
1346 //				            sourceUrl.append("&sectok="+editor.getConfig().getSectok());
1347 //				            sourceUrl.append("&authtok="+editor.getConfig().getAuthtok());
1348 
1349 					        URL requestURL = new URL(sourceUrl.toString());
1350 				            System.out.println(requestURL);
1351 					        URLConnection conn = requestURL.openConnection();
1352 					        conn.setRequestProperty("Cookie", editor.getConfig().getCookies());
1353 					        conn.setRequestProperty("Pragma", "No-cache");
1354 
1355 					        InputStream is = conn.getInputStream();
1356 
1357 				            DocumentBuilderFactory documentbuilderfactory = DocumentBuilderFactory.newInstance();
1358 				            DocumentBuilder documentbuilder = documentbuilderfactory.newDocumentBuilder();
1359 				            Document document = documentbuilder.parse(is);
1360 
1361 							mxCodec codec = new mxCodec(document);
1362 							codec.decode(document.getDocumentElement(), graph.getModel());
1363 
1364 							editor.setModified(false);
1365 						} catch (Exception ex) {
1366 					    	JOptionPane.showMessageDialog(
1367 					    			editor.getGraphComponent(),
1368 									ex.toString(),
1369 									mxResources.get("errorLoadDiagram"),
1370 									JOptionPane.ERROR_MESSAGE);
1371 							ex.printStackTrace();
1372 						}
1373 					}
1374 				}
1375 			}
1376 		}
1377 	}
1378 
1379 	/**
1380 	 *
1381 	 */
1382 	@SuppressWarnings("serial")
1383 	public static class ToggleAction extends AbstractAction {
1384 
1385 		/**
1386 		 *
1387 		 */
1388 		protected String key;
1389 
1390 		/**
1391 		 *
1392 		 */
1393 		protected boolean defaultValue;
1394 
1395 		/**
1396 		 *
1397 		 * @param key
1398 		 */
ToggleAction(String key)1399 		public ToggleAction(String key) {
1400 			this(key, false);
1401 		}
1402 
1403 		/**
1404 		 *
1405 		 * @param key
1406 		 */
ToggleAction(String key, boolean defaultValue)1407 		public ToggleAction(String key, boolean defaultValue) {
1408 			this.key = key;
1409 			this.defaultValue = defaultValue;
1410 		}
1411 
1412 		/**
1413 		 *
1414 		 */
actionPerformed(ActionEvent e)1415 		public void actionPerformed(ActionEvent e) {
1416 			mxGraph graph = mxGraphActions.getGraph(e);
1417 
1418 			if (graph != null) {
1419 				graph.toggleCellStyles(key, defaultValue);
1420 			}
1421 		}
1422 	}
1423 
1424 	/**
1425 	 *
1426 	 */
1427 	@SuppressWarnings("serial")
1428 	public static class SetLabelPositionAction extends AbstractAction {
1429 
1430 		/**
1431 		 *
1432 		 */
1433 		protected String labelPosition, alignment;
1434 
1435 		/**
1436 		 *
1437 		 * @param key
1438 		 */
SetLabelPositionAction(String labelPosition, String alignment)1439 		public SetLabelPositionAction(String labelPosition, String alignment) {
1440 			this.labelPosition = labelPosition;
1441 			this.alignment = alignment;
1442 		}
1443 
1444 		/**
1445 		 *
1446 		 */
actionPerformed(ActionEvent e)1447 		public void actionPerformed(ActionEvent e) {
1448 			mxGraph graph = mxGraphActions.getGraph(e);
1449 
1450 			if (graph != null && !graph.isSelectionEmpty()) {
1451 				graph.getModel().beginUpdate();
1452 				try {
1453 					// Checks the orientation of the alignment to use the
1454 					// correct constants
1455 					if (labelPosition.equals(mxConstants.ALIGN_LEFT)
1456 							|| labelPosition.equals(mxConstants.ALIGN_CENTER)
1457 							|| labelPosition.equals(mxConstants.ALIGN_RIGHT)) {
1458 						graph.setCellStyles(mxConstants.STYLE_LABEL_POSITION,
1459 								labelPosition);
1460 						graph.setCellStyles(mxConstants.STYLE_ALIGN, alignment);
1461 					} else {
1462 						graph.setCellStyles(
1463 								mxConstants.STYLE_VERTICAL_LABEL_POSITION,
1464 								labelPosition);
1465 						graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN,
1466 								alignment);
1467 					}
1468 				} finally {
1469 					graph.getModel().endUpdate();
1470 				}
1471 			}
1472 		}
1473 	}
1474 
1475 	/**
1476 	 *
1477 	 */
1478 	@SuppressWarnings("serial")
1479 	public static class SetStyleAction extends AbstractAction {
1480 
1481 		/**
1482 		 *
1483 		 */
1484 		protected String value;
1485 
1486 		/**
1487 		 *
1488 		 * @param key
1489 		 */
SetStyleAction(String value)1490 		public SetStyleAction(String value) {
1491 			this.value = value;
1492 		}
1493 
1494 		/**
1495 		 *
1496 		 */
actionPerformed(ActionEvent e)1497 		public void actionPerformed(ActionEvent e) {
1498 			mxGraph graph = mxGraphActions.getGraph(e);
1499 
1500 			if (graph != null && !graph.isSelectionEmpty()) {
1501 				graph.setCellStyle(value);
1502 			}
1503 		}
1504 	}
1505 
1506 	/**
1507 	 *
1508 	 */
1509 	@SuppressWarnings("serial")
1510 	public static class KeyValueAction extends AbstractAction {
1511 
1512 		/**
1513 		 *
1514 		 */
1515 		protected String key, value;
1516 
1517 		/**
1518 		 *
1519 		 * @param key
1520 		 */
KeyValueAction(String key)1521 		public KeyValueAction(String key) {
1522 			this(key, null);
1523 		}
1524 
1525 		/**
1526 		 *
1527 		 * @param key
1528 		 */
KeyValueAction(String key, String value)1529 		public KeyValueAction(String key, String value) {
1530 			this.key = key;
1531 			this.value = value;
1532 		}
1533 
1534 		/**
1535 		 *
1536 		 */
actionPerformed(ActionEvent e)1537 		public void actionPerformed(ActionEvent e) {
1538 			mxGraph graph = mxGraphActions.getGraph(e);
1539 
1540 			if (graph != null && !graph.isSelectionEmpty()) {
1541 				graph.setCellStyles(key, value);
1542 			}
1543 		}
1544 	}
1545 
1546 	/**
1547 	 *
1548 	 */
1549 	@SuppressWarnings("serial")
1550 	public static class PromptValueAction extends AbstractAction {
1551 
1552 		/**
1553 		 *
1554 		 */
1555 		protected String key, message;
1556 
1557 		/**
1558 		 *
1559 		 * @param key
1560 		 */
PromptValueAction(String key, String message)1561 		public PromptValueAction(String key, String message) {
1562 			this.key = key;
1563 			this.message = message;
1564 		}
1565 
1566 		/**
1567 		 *
1568 		 */
actionPerformed(ActionEvent e)1569 		public void actionPerformed(ActionEvent e) {
1570 			if (e.getSource() instanceof Component) {
1571 				mxGraph graph = mxGraphActions.getGraph(e);
1572 
1573 				if (graph != null && !graph.isSelectionEmpty()) {
1574 					String value = (String) JOptionPane.showInputDialog(
1575 							(Component) e.getSource(),
1576 							mxResources.get("value"), message,
1577 							JOptionPane.PLAIN_MESSAGE, null, null, "");
1578 
1579 					if (value != null) {
1580 						if (value.equals(mxConstants.NONE)) {
1581 							value = null;
1582 						}
1583 
1584 						graph.setCellStyles(key, value);
1585 					}
1586 				}
1587 			}
1588 		}
1589 	}
1590 
1591 	/**
1592 	 *
1593 	 */
1594 	@SuppressWarnings("serial")
1595 	public static class AlignCellsAction extends AbstractAction {
1596 
1597 		/**
1598 		 *
1599 		 */
1600 		protected String align;
1601 
1602 		/**
1603 		 *
1604 		 * @param key
1605 		 */
AlignCellsAction(String align)1606 		public AlignCellsAction(String align) {
1607 			this.align = align;
1608 		}
1609 
1610 		/**
1611 		 *
1612 		 */
actionPerformed(ActionEvent e)1613 		public void actionPerformed(ActionEvent e) {
1614 			mxGraph graph = mxGraphActions.getGraph(e);
1615 
1616 			if (graph != null && !graph.isSelectionEmpty()) {
1617 				graph.alignCells(align);
1618 			}
1619 		}
1620 	}
1621 
1622 	/**
1623 	 *
1624 	 */
1625 	@SuppressWarnings("serial")
1626 	public static class AutosizeAction extends AbstractAction {
1627 
1628 		/**
1629 		 *
1630 		 */
actionPerformed(ActionEvent e)1631 		public void actionPerformed(ActionEvent e) {
1632 			mxGraph graph = mxGraphActions.getGraph(e);
1633 
1634 			if (graph != null && !graph.isSelectionEmpty()) {
1635 				graph.updateCellSize(graph.getSelectionCell());
1636 			}
1637 		}
1638 	}
1639 
1640 	/**
1641 	 *
1642 	 */
1643 	@SuppressWarnings("serial")
1644 	public static class ColorAction extends AbstractAction {
1645 
1646 		/**
1647 		 *
1648 		 */
1649 		protected String name, key;
1650 
1651 		/**
1652 		 *
1653 		 * @param key
1654 		 */
ColorAction(String name, String key)1655 		public ColorAction(String name, String key) {
1656 			this.name = name;
1657 			this.key = key;
1658 		}
1659 
1660 		/**
1661 		 *
1662 		 */
actionPerformed(ActionEvent e)1663 		public void actionPerformed(ActionEvent e) {
1664 			if (e.getSource() instanceof mxGraphComponent) {
1665 				mxGraphComponent graphComponent = (mxGraphComponent) e
1666 						.getSource();
1667 				mxGraph graph = graphComponent.getGraph();
1668 
1669 				if (!graph.isSelectionEmpty()) {
1670 					Color newColor = JColorChooser.showDialog(graphComponent,
1671 							name, null);
1672 
1673 					if (newColor != null) {
1674 						graph.setCellStyles(key, mxUtils.hexString(newColor));
1675 					}
1676 				}
1677 			}
1678 		}
1679 	}
1680 
1681 	/**
1682 	 *
1683 	 */
1684 	@SuppressWarnings("serial")
1685 	public static class BackgroundImageAction extends AbstractAction {
1686 
1687 		/**
1688 		 *
1689 		 */
actionPerformed(ActionEvent e)1690 		public void actionPerformed(ActionEvent e) {
1691 			if (e.getSource() instanceof mxGraphComponent) {
1692 				mxGraphComponent graphComponent = (mxGraphComponent) e
1693 						.getSource();
1694 				String value = (String) JOptionPane.showInputDialog(
1695 						graphComponent, mxResources.get("backgroundImage"),
1696 						"URL", JOptionPane.PLAIN_MESSAGE, null, null,
1697 						"http://www.callatecs.com/images/background2.JPG");
1698 
1699 				if (value != null) {
1700 					if (value.length() == 0) {
1701 						graphComponent.setBackgroundImage(null);
1702 					} else {
1703 						graphComponent.setBackgroundImage(new ImageIcon(mxUtils
1704 								.loadImage(value)));
1705 					}
1706 
1707 					// Forces a repaint of the outline
1708 					graphComponent.getGraph().repaint();
1709 				}
1710 			}
1711 		}
1712 	}
1713 
1714 	/**
1715 	 *
1716 	 */
1717 	@SuppressWarnings("serial")
1718 	public static class BackgroundAction extends AbstractAction {
1719 
1720 		/**
1721 		 *
1722 		 */
actionPerformed(ActionEvent e)1723 		public void actionPerformed(ActionEvent e) {
1724 			if (e.getSource() instanceof mxGraphComponent) {
1725 				mxGraphComponent graphComponent = (mxGraphComponent) e
1726 						.getSource();
1727 				Color newColor = JColorChooser.showDialog(graphComponent,
1728 						mxResources.get("background"), null);
1729 
1730 				if (newColor != null) {
1731 					graphComponent.getViewport().setOpaque(false);
1732 					graphComponent.setBackground(newColor);
1733 				}
1734 
1735 				// Forces a repaint of the outline
1736 				graphComponent.getGraph().repaint();
1737 			}
1738 		}
1739 	}
1740 
1741 	/**
1742 	 *
1743 	 */
1744 	@SuppressWarnings("serial")
1745 	public static class PageBackgroundAction extends AbstractAction {
1746 
1747 		/**
1748 		 *
1749 		 */
actionPerformed(ActionEvent e)1750 		public void actionPerformed(ActionEvent e) {
1751 			if (e.getSource() instanceof mxGraphComponent) {
1752 				mxGraphComponent graphComponent = (mxGraphComponent) e
1753 						.getSource();
1754 				Color newColor = JColorChooser.showDialog(graphComponent,
1755 						mxResources.get("pageBackground"), null);
1756 
1757 				if (newColor != null) {
1758 					graphComponent.setPageBackgroundColor(newColor);
1759 				}
1760 
1761 				// Forces a repaint of the component
1762 				graphComponent.repaint();
1763 			}
1764 		}
1765 	}
1766 
1767 	/**
1768 	 *
1769 	 */
1770 	@SuppressWarnings("serial")
1771 	public static class StyleAction extends AbstractAction {
1772 
1773 		/**
1774 		 *
1775 		 */
actionPerformed(ActionEvent e)1776 		public void actionPerformed(ActionEvent e) {
1777 			if (e.getSource() instanceof mxGraphComponent) {
1778 				mxGraphComponent graphComponent = (mxGraphComponent) e
1779 						.getSource();
1780 				mxGraph graph = graphComponent.getGraph();
1781 				String initial = graph.getModel().getStyle(
1782 						graph.getSelectionCell());
1783 				String value = (String) JOptionPane.showInputDialog(
1784 						graphComponent, mxResources.get("style"), mxResources
1785 								.get("style"), JOptionPane.PLAIN_MESSAGE, null,
1786 						null, initial);
1787 
1788 				if (value != null) {
1789 					graph.setCellStyle(value);
1790 				}
1791 			}
1792 		}
1793 	}
1794 
1795 }
1796