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 */
10package com.mxgraph.examples.swing.editor;
11
12import java.awt.Color;
13import java.awt.Component;
14import java.awt.event.ActionEvent;
15import java.awt.event.ActionListener;
16import java.awt.image.BufferedImage;
17import java.awt.print.PageFormat;
18import java.awt.print.Paper;
19import java.awt.print.PrinterException;
20import java.awt.print.PrinterJob;
21import java.beans.PropertyChangeEvent;
22import java.beans.PropertyChangeListener;
23import java.io.ByteArrayInputStream;
24import java.io.ByteArrayOutputStream;
25import java.io.FilterInputStream;
26import java.io.IOException;
27import java.io.InputStream;
28import java.io.OutputStreamWriter;
29import java.lang.reflect.Method;
30import java.net.ProxySelector;
31import java.net.URL;
32import java.net.URLConnection;
33
34import javax.imageio.ImageIO;
35import javax.swing.AbstractAction;
36import javax.swing.ImageIcon;
37import javax.swing.JCheckBoxMenuItem;
38import javax.swing.JColorChooser;
39import javax.swing.JEditorPane;
40import javax.swing.JOptionPane;
41import javax.swing.JSplitPane;
42import javax.swing.SwingUtilities;
43import javax.swing.SwingWorker;
44import javax.swing.text.html.HTML;
45import javax.swing.text.html.HTMLDocument;
46import javax.swing.text.html.HTMLEditorKit;
47import javax.xml.parsers.DocumentBuilder;
48import javax.xml.parsers.DocumentBuilderFactory;
49
50import org.apache.commons.codec.binary.Hex;
51import org.apache.http.HttpResponse;
52import org.apache.http.HttpStatus;
53import org.apache.http.client.methods.HttpPost;
54import org.apache.http.entity.mime.MultipartEntity;
55import org.apache.http.entity.mime.content.InputStreamBody;
56import org.apache.http.entity.mime.content.StringBody;
57import org.apache.http.impl.client.DefaultHttpClient;
58import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
59import org.w3c.dom.Document;
60
61import com.mxgraph.analysis.mxDistanceCostFunction;
62import com.mxgraph.analysis.mxGraphAnalysis;
63import com.mxgraph.io.mxCodec;
64import com.mxgraph.model.mxCell;
65import com.mxgraph.model.mxIGraphModel;
66import com.mxgraph.swing.mxGraphComponent;
67import com.mxgraph.swing.mxGraphOutline;
68import com.mxgraph.swing.handler.mxConnectionHandler;
69import com.mxgraph.swing.util.mxGraphActions;
70import com.mxgraph.swing.view.mxCellEditor;
71import com.mxgraph.util.mxCellRenderer;
72import com.mxgraph.util.mxConstants;
73import com.mxgraph.util.mxResources;
74import com.mxgraph.util.mxUtils;
75import com.mxgraph.view.mxGraph;
76
77/**
78 * @author Administrator
79 *
80 */
81public class EditorActions {
82
83	/**
84	 *
85	 * @param e
86	 * @return Returns the graph for the given action event.
87	 */
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		 */
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		 */
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		 */
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		 */
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		 */
250		public StylesheetAction(String stylesheet) {
251			this.stylesheet = stylesheet;
252		}
253
254		/**
255		 *
256		 */
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		 */
289		public ZoomPolicyAction(int zoomPolicy) {
290			this.zoomPolicy = zoomPolicy;
291		}
292
293		/**
294		 *
295		 */
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		 */
320		public GridStyleAction(int style) {
321			this.style = style;
322		}
323
324		/**
325		 *
326		 */
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		 */
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		 */
378		public ScaleAction(double scale) {
379			this.scale = scale;
380		}
381
382		/**
383		 *
384		 */
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		 */
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		 */
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
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		 */
493		public SaveAction(boolean showDialog) {
494			this.showDialog = showDialog;
495		}
496
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		 */
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, "GIF", 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+".gif",
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		 */
776		public SelectShortestPathAction(boolean directed) {
777			this.directed = directed;
778		}
779
780		/**
781		 *
782		 */
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		 */
839		public SelectSpanningTreeAction(boolean directed) {
840			this.directed = directed;
841		}
842
843		/**
844		 *
845		 */
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		 */
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		 */
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		 */
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		 */
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		 */
982		public PromptPropertyAction(Object target, String message) {
983			this(target, message, message);
984		}
985
986		/**
987		 *
988		 */
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		 */
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		 */
1043		public TogglePropertyItem(Object target, String name, String fieldname) {
1044			this(target, name, fieldname, false);
1045		}
1046
1047		/**
1048		 *
1049		 */
1050		public TogglePropertyItem(Object target, String name, String fieldname,
1051				boolean refresh) {
1052			this(target, name, fieldname, refresh, null);
1053		}
1054
1055		/**
1056		 *
1057		 */
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		 */
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		 */
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		 */
1173		public HistoryAction(boolean undo) {
1174			this.undo = undo;
1175		}
1176
1177		/**
1178		 *
1179		 */
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		 */
1206		public FontStyleAction(boolean bold) {
1207			this.bold = bold;
1208		}
1209
1210		/**
1211		 *
1212		 */
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		 */
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		 */
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		 */
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		 */
1399		public ToggleAction(String key) {
1400			this(key, false);
1401		}
1402
1403		/**
1404		 *
1405		 * @param key
1406		 */
1407		public ToggleAction(String key, boolean defaultValue) {
1408			this.key = key;
1409			this.defaultValue = defaultValue;
1410		}
1411
1412		/**
1413		 *
1414		 */
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		 */
1439		public SetLabelPositionAction(String labelPosition, String alignment) {
1440			this.labelPosition = labelPosition;
1441			this.alignment = alignment;
1442		}
1443
1444		/**
1445		 *
1446		 */
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		 */
1490		public SetStyleAction(String value) {
1491			this.value = value;
1492		}
1493
1494		/**
1495		 *
1496		 */
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		 */
1521		public KeyValueAction(String key) {
1522			this(key, null);
1523		}
1524
1525		/**
1526		 *
1527		 * @param key
1528		 */
1529		public KeyValueAction(String key, String value) {
1530			this.key = key;
1531			this.value = value;
1532		}
1533
1534		/**
1535		 *
1536		 */
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		 */
1561		public PromptValueAction(String key, String message) {
1562			this.key = key;
1563			this.message = message;
1564		}
1565
1566		/**
1567		 *
1568		 */
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		 */
1606		public AlignCellsAction(String align) {
1607			this.align = align;
1608		}
1609
1610		/**
1611		 *
1612		 */
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		 */
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		 */
1655		public ColorAction(String name, String key) {
1656			this.name = name;
1657			this.key = key;
1658		}
1659
1660		/**
1661		 *
1662		 */
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		 */
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		 */
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		 */
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		 */
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