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