1   /****************************************************************************
2    **
3    ** This file is part of the yFiles extension package ySVG-2.1.
4    ** 
5    ** yWorks proprietary/confidential. Use is subject to license terms.
6    **
7    ** Redistribution of this file or of an unauthorized byte-code version
8    ** of this file is strictly forbidden.
9    **
10   ** Copyright (c) 2000-2007 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  
15  package demo.yext.svg;
16  
17  import y.base.DataProvider;
18  import y.io.GMLIOHandler;
19  import y.io.YGFIOHandler;
20  import y.option.OptionHandler;
21  import y.util.D;
22  import y.view.AreaZoomMode;
23  import y.view.EditMode;
24  import y.view.Graph2DPrinter;
25  import y.view.Graph2DView;
26  import y.view.Graph2DViewActions;
27  import y.view.Graph2DViewMouseWheelZoomListener;
28  import y.view.Selections;
29  import y.view.ViewMode;
30  
31  import javax.swing.AbstractAction;
32  import javax.swing.Action;
33  import javax.swing.ActionMap;
34  import javax.swing.ImageIcon;
35  import javax.swing.InputMap;
36  import javax.swing.JComponent;
37  import javax.swing.JFileChooser;
38  import javax.swing.JFrame;
39  import javax.swing.JMenu;
40  import javax.swing.JMenuBar;
41  import javax.swing.JPanel;
42  import javax.swing.JRootPane;
43  import javax.swing.JToolBar;
44  import javax.swing.UIManager;
45  import java.awt.BorderLayout;
46  import java.awt.Rectangle;
47  import java.awt.event.ActionEvent;
48  import java.awt.print.PageFormat;
49  import java.awt.print.PrinterJob;
50  import java.io.IOException;
51  import java.net.URL;
52  import java.util.Iterator;
53  
54  /**
55   * Demonstrates basic usage of the Graph2DView.
56   * <p/>
57   * Demonstrates how some actions can be performed on the view.
58   * The actions are:
59   * <ul>
60   * <li>Remove selected parts of the view content</li>
61   * <li>Zoom out of the view</li>
62   * <li>Zoom in on the view</li>
63   * <li>Zoom to the selected parts of the view content</li>
64   * <li>Fit view content to the size of the the view</li>
65   * <li>Print a graph</li>
66   * <li>Load a graph in GML and YGF format</li>
67   * <li>Save a graph in GML and YGF format</li>
68   * </ul>
69   * <p/>
70   * Additionally this demo shows how to set up the default edit mode
71   * to display tool tips over nodes.
72   */
73  public class ViewActionDemo extends JPanel {
74  
75    /**
76     * The view component of this demo.
77     */
78    protected Graph2DView view;
79    /**
80     * The view mode to be used with the view.
81     */
82    protected EditMode editMode;
83  
84  
85    public ViewActionDemo() {
86      setLayout(new BorderLayout());
87  
88      view = new Graph2DView();
89      view.setAntialiasedPainting(true);
90      view.getCanvasComponent().addMouseWheelListener(new Graph2DViewMouseWheelZoomListener());
91  
92      editMode = createEditMode();
93      if (editMode != null) {
94        view.addViewMode(editMode);
95      }
96  
97      Graph2DViewActions actions = new Graph2DViewActions(view);
98      ActionMap amap = actions.createActionMap();
99      amap.remove(Graph2DViewActions.DELETE_SELECTION);
100     InputMap imap = actions.createDefaultInputMap(amap);
101     view.getCanvasComponent().setActionMap(amap);
102     view.getCanvasComponent().setInputMap(JComponent.WHEN_FOCUSED, imap);
103 
104     add(view, BorderLayout.CENTER);
105     add(createToolBar(), BorderLayout.NORTH);
106   }
107 
108   protected EditMode createEditMode() {
109     final EditMode editMode = new EditMode();
110     editMode.showNodeTips(true);
111     return editMode;
112   }
113 
114   /**
115    * Creates a toolbar for this demo.
116    */
117   protected JToolBar createToolBar() {
118     JToolBar bar = new JToolBar();
119     bar.add(new AbstractAction("Clear", new ImageIcon(getClass().getResource("resource/New16.gif"))) {
120       public void actionPerformed(ActionEvent e) {
121         view.getGraph2D().clear();
122         view.updateView();
123       }
124     });
125     bar.add(new DeleteSelection());
126     bar.add(new Zoom(1.2));
127     bar.add(new Zoom(0.8));
128     bar.add(new ZoomArea());
129     bar.add(new FitContent());
130 
131     return bar;
132   }
133 
134   /**
135    * Create a menu bar for this demo.
136    */
137   protected JMenuBar createMenuBar() {
138     JMenuBar bar = new JMenuBar();
139     JMenu menu = new JMenu("File");
140     menu.add(createLoadAction());
141     menu.add(createSaveAction());
142     menu.add(new SaveSubsetAction());
143     menu.addSeparator();
144     menu.add(new PrintAction());
145     menu.addSeparator();
146     menu.add(new ExitAction());
147     bar.add(menu);
148     return bar;
149   }
150 
151   protected Action createLoadAction() {
152     return new LoadAction();
153   }
154 
155   protected Action createSaveAction() {
156     return new SaveAction();
157   }
158 
159   /**
160    * Creates an application frame for this demo and displays it.
161    * The given string is the title of the displayed frame.
162    */
163   public void start(final String title) {
164     JFrame frame = new JFrame(title);
165     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
166     addContentTo(frame.getRootPane());
167     frame.pack();
168     frame.setLocationRelativeTo(null);
169     frame.setVisible(true);
170   }
171 
172   /**
173    * Creates an application frame for this demo and displays it.
174    */
175   public void start() {
176     final Class clss = getClass();
177     final String title;
178     final Package pkg = clss.getPackage();
179     if (pkg == null) {
180       title = clss.getName();
181     } else {
182       title = clss.getName().substring(pkg.getName().length() + 1);
183     }
184     start(title);
185   }
186 
187   public final void addContentTo(final JRootPane rootPane) {
188     rootPane.setJMenuBar(createMenuBar());
189     rootPane.setContentPane(this);
190   }
191 
192   /**
193    * Initializes to a "nice" look and feel.
194    */
195   public static void initLnF() {
196     try {
197       if (!UIManager.getSystemLookAndFeelClassName().equals(
198           "com.sun.java.swing.plaf.motif.MotifLookAndFeel") &&
199           !UIManager.getSystemLookAndFeelClassName().equals(
200               "com.sun.java.swing.plaf.gtk.GTKLookAndFeel") &&
201           !UIManager.getSystemLookAndFeelClassName().equals(
202               UIManager.getLookAndFeel().getClass().getName())) {
203         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
204       }
205     }
206     catch (Exception e) {
207       e.printStackTrace();
208     }
209   }
210 
211   /**
212    * Launches this demo.
213    */
214   public static void main(String args[]) {
215     initLnF();
216     ViewActionDemo demo = new ViewActionDemo();
217     demo.start();
218   }
219 
220 
221   /**
222    * Action that prints the contents of the view
223    */
224   protected class PrintAction extends AbstractAction {
225     PageFormat pageFormat;
226     OptionHandler printOptions;
227 
228     public PrintAction() {
229       super("Print");
230 
231       //setup option handler
232       printOptions = new OptionHandler("Print Options");
233       printOptions.addInt("Poster Rows", 1);
234       printOptions.addInt("Poster Columns", 1);
235       printOptions.addBool("Add Poster Coords", false);
236       final String[] area = {"View", "Graph"};
237       printOptions.addEnum("Clip Area", area, 1);
238     }
239 
240     public void actionPerformed(ActionEvent e) {
241       Graph2DPrinter gprinter = new Graph2DPrinter(view);
242 
243       //show custom print dialog and adopt values
244       if (!printOptions.showEditor()) return;
245       gprinter.setPosterRows(printOptions.getInt("Poster Rows"));
246       gprinter.setPosterColumns(printOptions.getInt("Poster Columns"));
247       gprinter.setPrintPosterCoords(
248           printOptions.getBool("Add Poster Coords"));
249       if (printOptions.get("Clip Area").equals("Graph"))
250         gprinter.setClipType(Graph2DPrinter.CLIP_GRAPH);
251       else
252         gprinter.setClipType(Graph2DPrinter.CLIP_VIEW);
253 
254       //show default print dialogs
255       PrinterJob printJob = PrinterJob.getPrinterJob();
256       if (pageFormat == null) pageFormat = printJob.defaultPage();
257       PageFormat pf = printJob.pageDialog(pageFormat);
258       if (pf == pageFormat) return;
259       else pageFormat = pf;
260 
261       //setup printjob.
262       //Graph2DPrinter is of type Printable
263       printJob.setPrintable(gprinter, pageFormat);
264 
265       if (printJob.printDialog()) {
266         try {
267           printJob.print();
268         } catch (Exception ex) {
269           ex.printStackTrace();
270         }
271       }
272     }
273   }
274 
275   /**
276    * Action that terminates the application
277    */
278   protected class ExitAction extends AbstractAction {
279     ExitAction() {
280       super("Exit");
281     }
282 
283     public void actionPerformed(ActionEvent e) {
284 
285       System.exit(0);
286     }
287   }
288 
289   /**
290    * Action that saves the current graph to a file in YGF format.
291    */
292   protected class SaveAction extends AbstractAction {
293     JFileChooser chooser;
294 
295     public SaveAction() {
296       super("Save...");
297       chooser = null;
298     }
299 
300     public void actionPerformed(ActionEvent e) {
301       if (chooser == null) {
302         chooser = new JFileChooser();
303       }
304       if (chooser.showSaveDialog(ViewActionDemo.this) == JFileChooser.APPROVE_OPTION) {
305         String name = chooser.getSelectedFile().toString();
306         if (name.endsWith(".gml")) {
307           GMLIOHandler ioh = new GMLIOHandler();
308           try {
309             ioh.write(view.getGraph2D(), name);
310           } catch (IOException ioe) {
311             D.show(ioe);
312           }
313         } else {
314           if (!name.endsWith(".ygf")) name = name + ".ygf";
315           YGFIOHandler ioh = new YGFIOHandler();
316           try {
317             ioh.write(view.getGraph2D(), name);
318           } catch (IOException ioe) {
319             D.show(ioe);
320           }
321         }
322       }
323     }
324   }
325 
326   /**
327    * Action that saves the current subset of the graph to a file in YGF format.
328    */
329   protected class SaveSubsetAction extends AbstractAction {
330     JFileChooser chooser;
331 
332     public SaveSubsetAction() {
333       super("Save selection...");
334       chooser = null;
335     }
336 
337     public void actionPerformed(ActionEvent e) {
338       if (chooser == null) {
339         chooser = new JFileChooser();
340       }
341       if (chooser.showSaveDialog(ViewActionDemo.this) == JFileChooser.APPROVE_OPTION) {
342         String name = chooser.getSelectedFile().toString();
343         if (!name.endsWith(".ygf")) name = name + ".ygf";
344         YGFIOHandler ioh = new YGFIOHandler();
345         try {
346           DataProvider dp = Selections.createSelectionDataProvider(view.getGraph2D());
347           ioh.writeSubset(view.getGraph2D(), dp, name);
348         } catch (IOException ioe) {
349           D.show(ioe);
350         }
351       }
352     }
353   }
354 
355   /**
356    * Action that loads the current graph from a file in YGF format.
357    */
358   protected class LoadAction extends AbstractAction {
359     JFileChooser chooser;
360 
361     public LoadAction() {
362       super("Load...");
363       chooser = null;
364     }
365 
366     public void actionPerformed(ActionEvent e) {
367       if (chooser == null) {
368         chooser = new JFileChooser();
369       }
370       if (chooser.showOpenDialog(ViewActionDemo.this) == JFileChooser.APPROVE_OPTION) {
371         String name = chooser.getSelectedFile().toString();
372         if (name.endsWith(".gml")) {
373           GMLIOHandler ioh = new GMLIOHandler();
374           try {
375             view.getGraph2D().clear();
376             ioh.read(view.getGraph2D(), name);
377           } catch (IOException ioe) {
378             D.show(ioe);
379           }
380         } else {
381           if (!name.endsWith(".ygf")) name = name + ".ygf";
382           YGFIOHandler ioh = new YGFIOHandler();
383           try {
384             view.getGraph2D().clear();
385             ioh.read(view.getGraph2D(), name);
386           } catch (IOException ioe) {
387             D.show(ioe);
388           }
389         }
390         //force redisplay of view contents
391         view.fitContent();
392         view.getGraph2D().updateViews();
393       }
394     }
395   }
396 
397   /**
398    * Action that deletes the selected parts of the graph.
399    */
400   protected class DeleteSelection extends AbstractAction {
401     public DeleteSelection() {
402       super("Delete Selection");
403       URL imageURL = getClass().getResource("resource/Delete16.gif");
404       if (imageURL != null) {
405         this.putValue(Action.SMALL_ICON, new ImageIcon(imageURL));
406       }
407     }
408 
409     public void actionPerformed(ActionEvent e) {
410       view.getGraph2D().removeSelection();
411       view.getGraph2D().updateViews();
412     }
413   }
414 
415   /**
416    * Action that applies a specified zoom level to the view.
417    */
418   protected class Zoom extends AbstractAction {
419     double factor;
420 
421     public Zoom(double factor) {
422       super("Zoom " + (factor > 1.0 ? "In" : "Out"));
423       URL imageURL;
424       if (factor > 1.0d) {
425         imageURL = getClass().getResource("resource/ZoomIn16.gif");
426       } else {
427         imageURL = getClass().getResource("resource/ZoomOut16.gif");
428       }
429       if (imageURL != null) {
430         this.putValue(Action.SMALL_ICON, new ImageIcon(imageURL));
431       }
432       this.factor = factor;
433     }
434 
435     public void actionPerformed(ActionEvent e) {
436       view.setZoom(view.getZoom() * factor);
437       //optional code that adjusts the size of the
438       //view's world rectangle. The world rectangle
439       //defines the region of the canvas that is
440       //accessible by using the scrollbars of the view.
441       Rectangle box = view.getGraph2D().getBoundingBox();
442       view.setWorldRect(box.x - 20, box.y - 20, box.width + 40, box.height + 40);
443 
444       view.updateView();
445     }
446   }
447 
448   /**
449    * Action that fits the content nicely inside the view.
450    */
451   protected class FitContent extends AbstractAction {
452     public FitContent() {
453       super("Fit Content");
454       URL imageURL = getClass().getResource("resource/FitContent16.gif");
455       if (imageURL != null) {
456         this.putValue(Action.SMALL_ICON, new ImageIcon(imageURL));
457       }
458     }
459 
460     public void actionPerformed(ActionEvent e) {
461       view.fitContent();
462       view.updateView();
463     }
464   }
465 
466   /**
467    * Action that zooms the view to the selected box.
468    */
469   public class ZoomArea extends AbstractAction {
470     public ZoomArea() {
471       super("Zoom Area");
472       URL imageURL = getClass().getResource("resource/Zoom16.gif");
473       if (imageURL != null) {
474         this.putValue(Action.SMALL_ICON, new ImageIcon(imageURL));
475       }
476       this.putValue(Action.SHORT_DESCRIPTION, "Zoom Area");
477     }
478 
479     public void actionPerformed(ActionEvent e) {
480       Iterator viewModes = view.getViewModes();
481       while (viewModes.hasNext()) {
482         ViewMode viewMode = (ViewMode) viewModes.next();
483         if (viewMode instanceof EditMode) {
484           EditMode editMode = (EditMode) viewMode;
485           editMode.setChild(new AreaZoomMode(), null, null);
486         }
487       }
488     }
489   }
490 }
491