1 /* 2 * $Id: JGraphLayoutExample.java,v 1.2 2009/10/30 14:17:07 david Exp $ 3 * Copyright (c) 2001-2005, Gaudenz Alder 4 * 5 * All rights reserved. 6 * 7 * This file is licensed under the JGraph software license, a copy of which 8 * will have been provided to you in the file LICENSE at the root of your 9 * installation directory. If you are unable to locate this file please 10 * contact JGraph sales for another copy. 11 */ 12 package com.jgraph.layout; 13 14 import java.awt.Container; 15 import java.awt.event.ActionEvent; 16 import java.awt.event.ActionListener; 17 import java.awt.geom.Point2D; 18 import java.beans.DefaultPersistenceDelegate; 19 import java.beans.Encoder; 20 import java.beans.Expression; 21 import java.beans.PersistenceDelegate; 22 import java.beans.XMLDecoder; 23 import java.beans.XMLEncoder; 24 import java.io.BufferedInputStream; 25 import java.io.FileInputStream; 26 import java.io.FileNotFoundException; 27 import java.net.URL; 28 import java.util.Map; 29 30 import javax.swing.AbstractAction; 31 import javax.swing.Action; 32 import javax.swing.ImageIcon; 33 import javax.swing.JFileChooser; 34 import javax.swing.JFrame; 35 import javax.swing.JOptionPane; 36 import javax.swing.JToggleButton; 37 import javax.swing.JToolBar; 38 import javax.swing.JViewport; 39 40 import org.jgraph.JGraph; 41 import org.jgraph.event.GraphSelectionEvent; 42 import org.jgraph.graph.BasicMarqueeHandler; 43 import org.jgraph.graph.DefaultEdge; 44 import org.jgraph.graph.GraphModel; 45 46 import com.jgraph.example.GraphEdX; 47 import com.jgraph.layout.graph.JGraphSimpleLayout; 48 import com.jgraph.layout.hierarchical.JGraphHierarchicalLayout; 49 import com.jgraph.layout.organic.JGraphFastOrganicLayout; 50 import com.jgraph.layout.organic.JGraphOrganicLayout; 51 import com.jgraph.layout.organic.JGraphSelfOrganizingOrganicLayout; 52 import com.jgraph.layout.routing.JGraphParallelRouter; 53 import com.jgraph.layout.tree.JGraphCompactTreeLayout; 54 import com.jgraph.layout.tree.JGraphRadialTreeLayout; 55 import com.jgraph.layout.tree.JGraphTreeLayout; 56 57 /** 58 * An example applet that provides features for testing the JGraph Layout 59 * package. Sample data can be inserted, the layouts applied, cells moved while 60 * the layout auto-applied and morphs the cells into position. This example also 61 * supports grouping and expand/collapse. 62 */ 63 public class JGraphLayoutExample extends GraphEdX { 64 65 /** 66 * Global reference to the example layout cache. 67 */ 68 protected JGraphExampleLayoutCache layoutCache; 69 70 // Layout actions 71 protected Action[] layoutActions; 72 73 /** 74 * Button representing the auto layout feature 75 */ 76 protected JToggleButton autoLayoutButton; 77 78 /** 79 * Semaphore for autolayout. 80 */ 81 protected boolean isInsideLayout = false; 82 83 protected int edgeCount = 0; 84 85 /** 86 * Constructs a new example 87 */ JGraphLayoutExample()88 public JGraphLayoutExample() { 89 layoutCache = (JGraphExampleLayoutCache) graph.getGraphLayoutCache(); 90 // JGraphParallelRouter.setGraph(graph); 91 // Prepares layout actions 92 layoutCache.layout = new JGraphCompactTreeLayout(); 93 createLayoutActions(); 94 setJMenuBar(new JGraphLayoutExampleMenuBar(this, graphFactory)); 95 // Initializes actions states 96 valueChanged(null); 97 } 98 99 /** 100 * Show something interesting on start. 101 */ init()102 public void init() { 103 graphFactory.insertTreeSampleData(getGraph(), 104 createCellAttributes(new Point2D.Double(0, 0)), 105 createEdgeAttributes()); 106 try { 107 Thread.sleep(200); 108 } catch (InterruptedException e) { 109 // ignore 110 } 111 layoutActions[0].actionPerformed(null); 112 } 113 114 // Override parent method createGraph()115 protected JGraph createGraph() { 116 // Creates a model that does not allow disconnections 117 GraphModel model = new MyGraphModel(); 118 return new JGraphExampleGraph(model); 119 } 120 121 /** 122 * Hook from GraphEd to set attributes of a new edge 123 */ createEdgeAttributes()124 public Map createEdgeAttributes() { 125 Map map = super.createEdgeAttributes(); 126 // Adds a parallel edge router 127 // GraphConstants.setRouting(map, JGraphParallelRouter.getSharedInstance()); 128 return map; 129 } 130 131 // Hook for subclassers createDefaultEdge()132 protected DefaultEdge createDefaultEdge() { 133 return new DefaultEdge("Edge " + new Integer(edgeCount++)); 134 } 135 136 /** 137 * Creates the actions for the layouts 138 */ createLayoutActions()139 public void createLayoutActions() { 140 JGraphLayout circleLayout = new JGraphSimpleLayout( 141 JGraphSimpleLayout.TYPE_CIRCLE); 142 JGraphLayout isomLayout = new JGraphSelfOrganizingOrganicLayout(); 143 JGraphLayout frLayout = new JGraphFastOrganicLayout(); 144 JGraphLayout hierLayout = new JGraphHierarchicalLayout(); 145 layoutActions = new Action[] { 146 createLayoutAction("Compact Tree", "m", layoutCache.layout), 147 createLayoutAction("Tree", "t", new JGraphTreeLayout()), 148 // createLayoutAction("Organisational Chart", "t", new OrganizationalChart()), 149 createLayoutAction("Radial Tree", "r", 150 new JGraphRadialTreeLayout()), 151 createLayoutAction("ISOM", "i", isomLayout), 152 createLayoutAction("Organic", "o", new JGraphOrganicLayout()), 153 createLayoutAction("Fast Organic", "f", frLayout), 154 createLayoutAction("Hierarchical", "h", hierLayout), 155 createLayoutAction("Circle", "c", circleLayout), 156 createLayoutAction("Tilt", "l", new JGraphSimpleLayout( 157 JGraphSimpleLayout.TYPE_TILT, 100, 100)), 158 createLayoutAction("Random", "n", new JGraphSimpleLayout( 159 JGraphSimpleLayout.TYPE_RANDOM, 640, 480)) }; 160 } 161 162 /** 163 * action to apply a layout 164 * 165 * @param title 166 * the name of the layout 167 * @param shortcut 168 * the string representing the shortcut keyboard combination that 169 * invokes this action 170 * @param layout 171 * the layout itself 172 * @return the apply layout action 173 */ createLayoutAction(final String title, String shortcut, final JGraphLayout layout)174 public Action createLayoutAction(final String title, String shortcut, 175 final JGraphLayout layout) { 176 Action action = new AbstractAction(title) { 177 public void actionPerformed(ActionEvent e) { 178 layoutCache.layout = layout; 179 layoutCache.layout(null); 180 } 181 }; 182 action.putValue("shortcut", shortcut); 183 return action; 184 185 } 186 187 /** 188 * Updates buttons based on application state 189 */ valueChanged(GraphSelectionEvent e)190 public void valueChanged(GraphSelectionEvent e) { 191 super.valueChanged(e); 192 // Group Button only Enabled if a cell is selected 193 boolean enabled = !graph.isSelectionEmpty(); 194 boolean notEmpty = (graph.getModel().getRootCount() > 0); 195 // hide.setEnabled(enabled); 196 expand.setEnabled(enabled); 197 expandAll.setEnabled(enabled); 198 collapse.setEnabled(enabled); 199 configure.setEnabled(layoutCache != null && layoutCache.layout != null); 200 if (layoutActions != null) { 201 for (int i = 0; i < layoutActions.length; i++) { 202 layoutActions[i].setEnabled(notEmpty); 203 } 204 } 205 } 206 configureEncoder(XMLEncoder encoder)207 protected void configureEncoder(XMLEncoder encoder) { 208 super.configureEncoder(encoder); 209 encoder 210 .setPersistenceDelegate(JGraphExampleLayoutCache.class, 211 new DefaultPersistenceDelegate(new String[] { "model", 212 "factory", "cellViews", "hiddenCellViews", 213 "partial" })); 214 encoder.setPersistenceDelegate(JGraphExampleGraph.class, 215 new DefaultPersistenceDelegate(new String[] { "model", 216 "graphLayoutCache" })); 217 encoder.setPersistenceDelegate(JGraphParallelRouter.class, 218 new PersistenceDelegate() { 219 protected Expression instantiate(Object oldInstance, 220 Encoder out) { 221 return new Expression(oldInstance, 222 JGraphParallelRouter.class, 223 "getSharedInstance", null); 224 } 225 }); 226 } 227 228 /** 229 * Hook from GraphEd to add action button to the tool bar 230 */ createToolBar()231 public JToolBar createToolBar() { 232 JToolBar toolbar = super.createToolBar(); 233 234 // Configure layout 235 configure = new AbstractAction() { 236 public void actionPerformed(ActionEvent e) { 237 layoutCache.configureLayout(); 238 } 239 }; 240 URL url = getClass().getClassLoader().getResource( 241 "com/jgraph/layout/image/configure.gif"); 242 configure.putValue(Action.SMALL_ICON, new ImageIcon(url)); 243 configure.setEnabled(false); 244 toolbar.add(configure); 245 246 // AutoLayout toggle 247 autoLayoutButton = new JToggleButton(); 248 autoLayoutButton.setSelected(false); 249 url = getClass().getClassLoader().getResource( 250 "com/jgraph/layout/image/layout.gif"); 251 autoLayoutButton.setIcon(new ImageIcon(url)); 252 autoLayoutButton.addActionListener(new ActionListener() { 253 public void actionPerformed(ActionEvent e) { 254 layoutCache.autolayout = autoLayoutButton.isSelected(); 255 } 256 }); 257 toolbar.add(autoLayoutButton); 258 259 // JButton button = new JButton("My"); 260 // toolbar.add(button); 261 // button.addActionListener(new ActionListener() { 262 // 263 // public void actionPerformed(ActionEvent event) { 264 // // Add your code here 265 // } 266 // 267 // }); 268 return toolbar; 269 } 270 openFile()271 public void openFile() { 272 int returnValue = JFileChooser.CANCEL_OPTION; 273 initFileChooser(); 274 returnValue = fileChooser.showOpenDialog(graph); 275 if (returnValue == JFileChooser.APPROVE_OPTION) { 276 Container parent = graph.getParent(); 277 BasicMarqueeHandler marqueeHandler = graph.getMarqueeHandler(); 278 try { 279 uninstallListeners(graph); 280 parent.remove(graph); 281 XMLDecoder decoder = new XMLDecoder(new BufferedInputStream( 282 new FileInputStream(fileChooser.getSelectedFile()))); 283 graph = (JGraph) decoder.readObject(); 284 // Take the marquee handler from the original graph and 285 // use it in the new graph as well. 286 graph.setMarqueeHandler(marqueeHandler); 287 JGraphParallelRouter.setGraph(graph); 288 // Adds the component back into the component hierarchy 289 if (parent instanceof JViewport) { 290 JViewport viewPort = (JViewport) parent; 291 viewPort.setView(graph); 292 } else { 293 // Best effort... 294 parent.add(graph); 295 } 296 // graph.setMarqueeHandler(previousHandler); 297 // And reinstalls the listener 298 installListeners(graph); 299 } catch (FileNotFoundException e) { 300 JOptionPane.showMessageDialog(graph, e.getMessage(), "Error", 301 JOptionPane.ERROR_MESSAGE); 302 } 303 304 } 305 } 306 307 /** 308 * 309 * @return a String representing the version of this application 310 */ getVersion()311 protected String getVersion() { 312 return JGraph.VERSION; 313 } 314 315 /** 316 * Main method 317 */ main(String[] args)318 public static void main(String[] args) { 319 try { 320 // Switch off D3D because of Sun XOR painting bug 321 // See http://www.jgraph.com/forum/viewtopic.php?t=4066 322 System.setProperty("sun.java2d.d3d", "false"); 323 // Construct Frame 324 JFrame frame = new JFrame(JGraph.VERSION); 325 // Set Close Operation to Exit 326 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 327 // Add an Editor Panel 328 JGraphLayoutExample layoutExample = new JGraphLayoutExample(); 329 frame.getContentPane().add(layoutExample); 330 // Fetch URL to Icon Resource 331 URL jgraphUrl = JGraphLayoutExample.class.getClassLoader() 332 .getResource("org/jgraph/example/resources/jgraph.gif"); 333 // If Valid URL 334 if (jgraphUrl != null) { 335 // Load Icon 336 ImageIcon jgraphIcon = new ImageIcon(jgraphUrl); 337 // Use in Window 338 frame.setIconImage(jgraphIcon.getImage()); 339 } 340 // Set Default Size 341 frame.setSize(640, 480); 342 // Show Frame 343 frame.setVisible(true); 344 layoutExample.init(); 345 } catch (Exception e) { 346 e.printStackTrace(); 347 } 348 } 349 350 } 351