1   /****************************************************************************
2    * This demo file is part of yFiles for Java 2.14.
3    * Copyright (c) 2000-2017 by yWorks GmbH, Vor dem Kreuzberg 28,
4    * 72070 Tuebingen, Germany. All rights reserved.
5    * 
6    * yFiles demo files exhibit yFiles for Java functionalities. Any redistribution
7    * of demo files in source code or binary form, with or without
8    * modification, is not permitted.
9    * 
10   * Owners of a valid software license for a yFiles for Java version that this
11   * demo is shipped with are allowed to use the demo source code as basis
12   * for their own yFiles for Java powered applications. Use of such programs is
13   * governed by the rights and conditions as set out in the yFiles for Java
14   * license agreement.
15   * 
16   * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESS OR IMPLIED
17   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19   * NO EVENT SHALL yWorks BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21   * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   *
27   ***************************************************************************/
28  package demo.io.graphml;
29  
30  import y.io.GraphMLIOHandler;
31  import y.io.graphml.graph2d.PostprocessorOutputHandler;
32  import y.module.YModule;
33  import y.util.D;
34  import y.util.DataProviderAdapter;
35  
36  import javax.swing.AbstractAction;
37  import javax.swing.Action;
38  import javax.swing.JComboBox;
39  import javax.swing.JToolBar;
40  import java.awt.EventQueue;
41  import java.awt.event.ActionEvent;
42  import java.awt.event.ActionListener;
43  import java.util.Locale;
44  
45  /**
46   * This demo centers around postprocessing actions that can be specified
47   * within a GraphML file. These actions allow to process
48   * the parsed graph structure before it gets returned by the GraphML parser.
49   * <p>
50   * A GraphML processor can be any instance of the yFiles module class YModule.
51   * The configuration of a processor is done by changing the values
52   * managed by the associated OptionHandler instance. This demo allows to configure
53   * a processor interactively. Furthermore, it can be used to display the GraphML
54   * representation of a processor module configuration.
55   * When saving a file the XML representation of the current processor will be added
56   * to the output file as well. When loading this file again,
57   * the postprocessor will perform its action.
58   * </p>
59   *
60   * @see <a href="http://docs.yworks.com/yfiles/doc/api/index.html#/dguide/graphml#graphml_postprocessors" target="_blank">Section yFiles GraphML Post-Processors</a> in the yFiles for Java Developer's Guide
61   * @deprecated Client code should explicitly implement post-processing steps.
62   */
63  public class PostprocessorDemo extends GraphMLDemo {
64  
65    private YModule processorModule;
66  
67    protected void loadInitialGraph() {
68      //register a DataProvider that returns the selected
69      //processor module. This dataprovider is used by
70      //PostprocessorOutputHandler to lookup the postprocessors
71      //it should serialize.
72      view.getGraph2D().addDataProvider(PostprocessorOutputHandler.PROCESSORS_DPKEY,
73          new DataProviderAdapter() {
74            public Object get(Object graph) {
75              return processorModule;
76            }
77          });
78  
79      loadGraph("resources/postprocessors/ant-build.graphml");
80    }
81  
82    protected JToolBar createToolBar() {
83      //a combo box that contains the class names of available
84      //postprocessors.
85      final JComboBox combo = new JComboBox(new String[]{
86          "y.module.IncrementalHierarchicLayoutModule",         
87          "y.module.SmartOrganicLayoutModule",                  
88          "demo.io.graphml.NodeSizeAdapter"
89      }
90      );
91      combo.setMaximumSize(combo.getPreferredSize());
92      combo.setEditable(true);
93      combo.addActionListener(new ActionListener() {
94        public void actionPerformed(ActionEvent e) {
95          String className = combo.getSelectedItem().toString();
96          try {
97            processorModule = (YModule) Class.forName(className).newInstance();
98          } catch (Exception ex) {
99            D.showError("Can't create instance of class " + className);
100         }
101       }
102     });
103     combo.setSelectedIndex(0);
104 
105     JToolBar jtb = super.createToolBar();
106     jtb.addSeparator();
107     jtb.add(createActionControl(new ApplyProcessorAction()));
108     jtb.addSeparator(TOOLBAR_SMALL_SEPARATOR);
109     jtb.add(combo);
110     jtb.addSeparator(TOOLBAR_SMALL_SEPARATOR);
111     jtb.add(createActionControl(new ConfigureProcessorAction()));
112 
113     return jtb;
114   }
115 
116   protected String[] getExampleResources() {
117     return new String[]{
118         "resources/postprocessors/ant-build.graphml",
119         "resources/postprocessors/food-owl.graphml",
120     };
121   }
122 
123   /**
124    * Creates a GraphMLIOHandler that has additional output support for
125    * GraphML postprocessors.
126    *
127    * Note that input support for PostProcessors is registered by default and
128    * need not be added manually.
129    */
130   protected GraphMLIOHandler createGraphMLIOHandler() {
131     GraphMLIOHandler ioh = super.createGraphMLIOHandler();
132     ioh.getGraphMLHandler().addOutputHandlerProvider(new PostprocessorOutputHandler());
133     return ioh;
134   }
135 
136   /**
137    * Actions that allows to configure the selected postprocessor interactively.
138    */
139   class ConfigureProcessorAction extends AbstractAction {
140     ConfigureProcessorAction() {
141       super("Settings...", getIconResource("resource/properties.png"));
142     }
143 
144     public void actionPerformed(ActionEvent e) {
145       if (processorModule != null) {
146         OptionSupport.showDialog(processorModule, view.getGraph2D(), false, view.getFrame());
147       }
148     }
149   }
150 
151   /**
152    * Actions that applies the selected processor on the displayed graph.
153    */
154   class ApplyProcessorAction extends AbstractAction {
155     ApplyProcessorAction() {
156       super("Postprocessor", SHARED_LAYOUT_ICON);
157       putValue(Action.SHORT_DESCRIPTION, "Run the current postprocessor");
158     }
159 
160     public void actionPerformed(ActionEvent e) {
161       if (processorModule != null) {
162         processorModule.start(view.getGraph2D());
163         view.updateView();
164       }
165     }
166   }
167 
168   /**
169    * Launches this demo.
170    */
171   public static void main(String[] args) {
172     EventQueue.invokeLater(new Runnable() {
173       public void run() {
174         Locale.setDefault(Locale.ENGLISH);
175         initLnF();
176         new PostprocessorDemo().start();
177       }
178     });
179   }
180 }
181