1   /****************************************************************************
2    **
3    ** This file is part of yFiles-2.9. 
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-2011 by yWorks GmbH, Vor dem Kreuzberg 28, 
11   ** 72070 Tuebingen, Germany. All rights reserved.
12   **
13   ***************************************************************************/
14  package demo.io.graphml;
15  
16  import y.io.GraphMLIOHandler;
17  import y.io.graphml.graph2d.PostprocessorOutputHandler;
18  import y.module.YModule;
19  import y.util.D;
20  import y.util.DataProviderAdapter;
21  
22  import javax.swing.AbstractAction;
23  import javax.swing.Action;
24  import javax.swing.JComboBox;
25  import javax.swing.JToolBar;
26  import java.awt.EventQueue;
27  import java.awt.event.ActionEvent;
28  import java.awt.event.ActionListener;
29  import java.util.Locale;
30  
31  /**
32   * This demo centers around postprocessing actions that can be specified
33   * within a GraphML file. These actions allow to process
34   * the parsed graph structure before it gets returned by the GraphML parser.
35   * <p>
36   * A GraphML processor can be any instance of the yFiles module class YModule.
37   * The configuration of a processor is done by changing the values
38   * managed by the associated OptionHandler instance. This demo allows to configure
39   * a processor interactively. Furthermore, it can be used to display the GraphML
40   * representation of a processor module configuration.
41   * When saving a file the XML representation of the current processor will be added
42   * to the output file as well. When loading this file again,
43   * the postprocessor will perform its action.
44   * </p>
45   *
46   * @see <a href="http://docs.yworks.com/yfiles/doc/developers-guide/graphml.html#graphml_postprocessors">Section yFiles GraphML Post-Processors</a> in the yFiles for Java Developer's Guide
47   */
48  public class PostprocessorDemo extends GraphMLDemo {
49  
50    private YModule processorModule;
51  
52    protected void loadInitialGraph() {
53      //register a DataProvider that returns the selected
54      //processor module. This dataprovider is used by
55      //PostprocessorOutputHandler to lookup the postprocessors
56      //it should serialize.
57      view.getGraph2D().addDataProvider(PostprocessorOutputHandler.PROCESSORS_DPKEY,
58          new DataProviderAdapter() {
59            public Object get(Object graph) {
60              return processorModule;
61            }
62          });
63  
64      loadGraph("resources/postprocessors/ant-build.graphml");
65    }
66  
67    protected JToolBar createToolBar() {
68      //a combo box that contains the class names of available
69      //postprocessors.
70      final JComboBox combo = new JComboBox(new String[]{
71          "y.module.IncrementalHierarchicLayoutModule",         
72          "y.module.SmartOrganicLayoutModule",                  
73          "demo.io.graphml.NodeSizeAdapter"
74      }
75      );
76      combo.setMaximumSize(combo.getPreferredSize());
77      combo.setEditable(true);
78      combo.addActionListener(new ActionListener() {
79        public void actionPerformed(ActionEvent e) {
80          String className = combo.getSelectedItem().toString();
81          try {
82            processorModule = (YModule) Class.forName(className).newInstance();
83          } catch (Exception ex) {
84            D.showError("Can't create instance of class " + className);
85          }
86        }
87      });
88      combo.setSelectedIndex(0);
89  
90      JToolBar jtb = super.createToolBar();
91      jtb.addSeparator();
92      jtb.add(createActionControl(new ApplyProcessorAction()));
93      jtb.addSeparator(TOOLBAR_SMALL_SEPARATOR);
94      jtb.add(combo);
95      jtb.addSeparator(TOOLBAR_SMALL_SEPARATOR);
96      jtb.add(createActionControl(new ConfigureProcessorAction()));
97  
98      return jtb;
99    }
100 
101   protected String[] getExampleResources() {
102     return new String[]{
103         "resources/postprocessors/ant-build.graphml",
104         "resources/postprocessors/food-owl.graphml",
105     };
106   }
107 
108   /**
109    * Creates a GraphMLIOHandler that has additional output support for
110    * GraphML postprocessors.
111    *
112    * Note that input support for PostProcessors is registered by default and
113    * need not be added manually.
114    */
115   protected GraphMLIOHandler createGraphMLIOHandler() {
116     GraphMLIOHandler ioh = super.createGraphMLIOHandler();
117     ioh.getGraphMLHandler().addOutputHandlerProvider(new PostprocessorOutputHandler());
118     return ioh;
119   }
120 
121   /**
122    * Actions that allows to configure the selected postprocessor interactively.
123    */
124   class ConfigureProcessorAction extends AbstractAction {
125     ConfigureProcessorAction() {
126       super("Settings...", getIconResource("resource/properties.png"));
127     }
128 
129     public void actionPerformed(ActionEvent e) {
130       if (processorModule != null) {
131         OptionSupport.showDialog(processorModule, view.getGraph2D(), false, view.getFrame());
132       }
133     }
134   }
135 
136   /**
137    * Actions that applies the selected processor on the displayed graph.
138    */
139   class ApplyProcessorAction extends AbstractAction {
140     ApplyProcessorAction() {
141       super("Postprocessor", SHARED_LAYOUT_ICON);
142       putValue(Action.SHORT_DESCRIPTION, "Run the current postprocessor");
143     }
144 
145     public void actionPerformed(ActionEvent e) {
146       if (processorModule != null) {
147         processorModule.start(view.getGraph2D());
148         view.updateView();
149       }
150     }
151   }
152 
153   /**
154    * Launches this demo.
155    */
156   public static void main(String[] args) {
157     EventQueue.invokeLater(new Runnable() {
158       public void run() {
159         Locale.setDefault(Locale.ENGLISH);
160         initLnF();
161         new PostprocessorDemo().start();
162       }
163     });
164   }
165 }
166