1   package demo.yext.graphml;
2   
3   import java.awt.Dimension;
4   import java.awt.event.ActionEvent;
5   import java.awt.event.ActionListener;
6   import java.io.StringWriter;
7   
8   import javax.swing.AbstractAction;
9   import javax.swing.JComboBox;
10  import javax.swing.JMenu;
11  import javax.swing.JOptionPane;
12  import javax.swing.JScrollPane;
13  import javax.swing.JTextArea;
14  import javax.swing.JToolBar;
15  
16  import org.graphdrawing.graphml.GraphMLConstants;
17  import org.graphdrawing.graphml.writer.OutputHandler;
18  import org.graphdrawing.graphml.writer.XmlWriter;
19  import org.graphdrawing.graphml.writer.DomXmlWriter;
20  import org.graphdrawing.graphml.writer.GraphMLWriteException;
21  
22  
23  import y.module.YModule;
24  import y.util.D;
25  import y.util.DataProviderAdapter;
26  import yext.graphml.graph2D.GraphMLIOHandler;
27  import yext.graphml.processor.PostprocessorOutputHandler;
28  
29  
30  /**
31   * This demo centers around postprocessing actions that can be specified
32   * within a GraphML file. These actions allow to process 
33   * the parsed graph structure before it gets returned by the GraphML parser. 
34   * <p>
35   * A GraphML processor can be any instance of the yFiles module class YModule.
36   * The configuration of a processor is done by changing the values
37   * managed by the associated OptionHandler instance. This demo allows to configure
38   * a processor interactively. Furthermore, it can be used to display the GraphML
39   * representation of a processor module configuration. 
40   * When saving a file the XML representation of the current processor will be added
41   * to the output file as well. When loading this file again,
42   * the postprocessor will perform its action.
43   * </p>
44   */
45  public class PostprocessorDemo extends GraphMLDemo
46  {
47    YModule processorModule;
48    
49    /** 
50     * Creates a new instance of PostprocessorDemo 
51     */
52    public PostprocessorDemo()
53    {
54      //register a DataProvider that returns the selected
55      //processor module. This dataprovider is used by
56      //PostprocessorOutputHandler to lookup the postprocessors
57      //it should serialize.
58      view.getGraph2D().addDataProvider(PostprocessorOutputHandler.PROCESSORS_DPKEY,
59          new DataProviderAdapter() {
60            public Object get(Object graph)
61            {
62              return processorModule;
63            }
64          });
65   
66    }
67    
68    protected JToolBar createToolBar()
69    {
70      JToolBar jtb = super.createToolBar();
71      jtb.addSeparator();
72      
73      //a combo box that contains the class names of available
74      //postprocessors.  
75      final JComboBox combo = new JComboBox(new String[] {
76          "y.module.HierarchicLayoutModule",
77          "y.module.SmartOrganicLayoutModule",
78          "yext.graphml.processor.NodeSizeAdapter",
79          "yext.graphml.processor.BackgroundConfigurator"
80          }
81      );
82      
83      combo.setEditable(true);
84      jtb.add(combo);
85      combo.addActionListener(new ActionListener() {
86        public void actionPerformed(ActionEvent ev) {
87          String className = combo.getSelectedItem().toString();
88          try
89          {
90            processorModule = (YModule)Class.forName(className).newInstance();
91          } catch(Exception ex)
92          {
93            D.showError("Can't create instance of class " + className);
94          }
95        }
96      });
97      combo.setSelectedIndex(0);
98      
99      jtb.add(new ConfigureProcessorAction());
100     jtb.add(new ApplyProcessorAction());
101     jtb.add(new ShowProcessorAction());
102     
103     return jtb;
104   }
105 
106   protected JMenu createSampleGraphMenu() {
107     String[] resources = {
108       "resources/postprocessors/ant-build.graphml",
109       "resources/postprocessors/food-owl.graphml",
110     };
111     return createSampleGraphMenu(resources);
112   }
113 
114   /**
115    * Creates a GraphMLIOHandler that has additional output support for 
116    * GraphML postprocessors. 
117    */
118   protected GraphMLIOHandler createGraphMLIOHandler()
119   {
120     GraphMLIOHandler ioh = super.createGraphMLIOHandler();
121     OutputHandler pout = new PostprocessorOutputHandler();
122     ioh.getOutputHandlers(GraphMLConstants.SCOPE_GRAPH).add(pout);
123     return ioh;
124   }
125   
126   /**
127    * Actions that allows to configure the selected postprocessor interactively.
128    */
129   class ConfigureProcessorAction extends AbstractAction
130   {
131     ConfigureProcessorAction()
132     {
133       super("Configure...");
134     }
135     
136     public void actionPerformed(ActionEvent ev)
137     {
138       if(processorModule != null)
139       {
140         if(processorModule.getOptionHandler().showEditor())
141         {
142           processorModule.getOptionHandler().commitValues();
143         }
144       }
145     }
146   }
147 
148   /**
149    * Actions that applies the selected processor on the displayed graph.
150    */
151   class ApplyProcessorAction extends AbstractAction
152   {
153     ApplyProcessorAction()
154     {
155       super("Apply");
156     }
157     
158     public void actionPerformed(ActionEvent ev)
159     {
160       if(processorModule != null)
161       {
162         processorModule.start(view.getGraph2D());
163         view.updateView();
164       }
165     }
166   }
167   
168 
169   /**
170    * Actions that outputs the GraphML representation of the selected postprocessor
171    * in a separate window.
172    */
173   class ShowProcessorAction extends AbstractAction
174   {
175     ShowProcessorAction()
176     {
177       super("Show GraphML");
178     }
179     
180     public void actionPerformed(ActionEvent ev)
181     {
182       StringWriter sw = new StringWriter();
183       XmlWriter writer = new DomXmlWriter( sw );
184         writer.setWriteXmlDeclaration(false);
185         writer.addNamespace(GraphMLConstants.YWORKS_EXT_NS_URI, "y");
186         new PostprocessorOutputHandler().printDataOutput( null, view.getGraph2D(), null, writer );
187         sw.flush();
188         String xml = sw.toString();
189         JTextArea textArea = new JTextArea(xml);
190         JScrollPane scrollPane = new JScrollPane(textArea);
191         scrollPane.setPreferredSize(new Dimension(600,400));
192         JOptionPane.showMessageDialog(view, scrollPane);
193     }
194   }
195 
196   /**
197    * Launches this demo.
198    */
199   public static void main(String[] args)
200   {
201     initLnF();
202     final PostprocessorDemo demo = new PostprocessorDemo();
203     demo.start();
204   }
205 }
206