1 package prefuse.demos; 2 3 import java.awt.BorderLayout ; 4 import java.awt.Color ; 5 import java.awt.Component ; 6 import java.awt.Dimension ; 7 import java.awt.event.ActionEvent ; 8 import java.awt.event.ActionListener ; 9 import java.awt.event.WindowAdapter ; 10 import java.awt.event.WindowEvent ; 11 import java.awt.geom.Rectangle2D ; 12 13 import javax.swing.AbstractAction ; 14 import javax.swing.BorderFactory ; 15 import javax.swing.Box ; 16 import javax.swing.BoxLayout ; 17 import javax.swing.JButton ; 18 import javax.swing.JDialog ; 19 import javax.swing.JFrame ; 20 import javax.swing.JLabel ; 21 import javax.swing.JList ; 22 import javax.swing.JMenu ; 23 import javax.swing.JMenuBar ; 24 import javax.swing.JPanel ; 25 import javax.swing.JScrollPane ; 26 import javax.swing.JSplitPane ; 27 import javax.swing.KeyStroke ; 28 import javax.swing.ListSelectionModel ; 29 import javax.swing.event.ChangeEvent ; 30 import javax.swing.event.ChangeListener ; 31 import javax.swing.event.ListSelectionEvent ; 32 import javax.swing.event.ListSelectionListener ; 33 34 import prefuse.Display; 35 import prefuse.Visualization; 36 import prefuse.action.ActionList; 37 import prefuse.action.RepaintAction; 38 import prefuse.action.assignment.ColorAction; 39 import prefuse.action.filter.GraphDistanceFilter; 40 import prefuse.action.layout.graph.ForceDirectedLayout; 41 import prefuse.activity.Activity; 42 import prefuse.controls.DragControl; 43 import prefuse.controls.FocusControl; 44 import prefuse.controls.NeighborHighlightControl; 45 import prefuse.controls.PanControl; 46 import prefuse.controls.WheelZoomControl; 47 import prefuse.controls.ZoomControl; 48 import prefuse.controls.ZoomToFitControl; 49 import prefuse.data.Graph; 50 import prefuse.data.Table; 51 import prefuse.data.Tuple; 52 import prefuse.data.event.TupleSetListener; 53 import prefuse.data.io.GraphMLReader; 54 import prefuse.data.tuple.TupleSet; 55 import prefuse.render.DefaultRendererFactory; 56 import prefuse.render.LabelRenderer; 57 import prefuse.util.ColorLib; 58 import prefuse.util.GraphLib; 59 import prefuse.util.GraphicsLib; 60 import prefuse.util.display.DisplayLib; 61 import prefuse.util.display.ItemBoundsListener; 62 import prefuse.util.force.ForceSimulator; 63 import prefuse.util.io.IOLib; 64 import prefuse.util.ui.JForcePanel; 65 import prefuse.util.ui.JValueSlider; 66 import prefuse.util.ui.UILib; 67 import prefuse.visual.VisualGraph; 68 import prefuse.visual.VisualItem; 69 70 73 public class GraphView extends JPanel { 74 75 private static final String graph = "graph"; 76 private static final String nodes = "graph.nodes"; 77 private static final String edges = "graph.edges"; 78 79 private Visualization m_vis; 80 81 public GraphView(Graph g, String label) { 82 83 m_vis = new Visualization(); 85 86 89 LabelRenderer tr = new LabelRenderer(); 90 tr.setRoundedCorner(8, 8); 91 m_vis.setRendererFactory(new DefaultRendererFactory(tr)); 92 93 96 setGraph(g, label); 98 99 TupleSet focusGroup = m_vis.getGroup(Visualization.FOCUS_ITEMS); 101 focusGroup.addTupleSetListener(new TupleSetListener() { 102 public void tupleSetChanged(TupleSet ts, Tuple[] add, Tuple[] rem) 103 { 104 for ( int i=0; i<rem.length; ++i ) 105 ((VisualItem)rem[i]).setFixed(false); 106 for ( int i=0; i<add.length; ++i ) { 107 ((VisualItem)add[i]).setFixed(false); 108 ((VisualItem)add[i]).setFixed(true); 109 } 110 if ( ts.getTupleCount() == 0 ) { 111 ts.addTuple(rem[0]); 112 ((VisualItem)rem[0]).setFixed(false); 113 } 114 m_vis.run("draw"); 115 } 116 }); 117 118 119 120 123 int hops = 30; 124 final GraphDistanceFilter filter = new GraphDistanceFilter(graph, hops); 125 126 ColorAction fill = new ColorAction(nodes, 127 VisualItem.FILLCOLOR, ColorLib.rgb(200,200,255)); 128 fill.add(VisualItem.FIXED, ColorLib.rgb(255,100,100)); 129 fill.add(VisualItem.HIGHLIGHT, ColorLib.rgb(255,200,125)); 130 131 ActionList draw = new ActionList(); 132 draw.add(filter); 133 draw.add(fill); 134 draw.add(new ColorAction(nodes, VisualItem.STROKECOLOR, 0)); 135 draw.add(new ColorAction(nodes, VisualItem.TEXTCOLOR, ColorLib.rgb(0,0,0))); 136 draw.add(new ColorAction(edges, VisualItem.FILLCOLOR, ColorLib.gray(200))); 137 draw.add(new ColorAction(edges, VisualItem.STROKECOLOR, ColorLib.gray(200))); 138 139 ActionList animate = new ActionList(Activity.INFINITY); 140 animate.add(new ForceDirectedLayout(graph)); 141 animate.add(fill); 142 animate.add(new RepaintAction()); 143 144 m_vis.putAction("draw", draw); 148 m_vis.putAction("layout", animate); 149 150 m_vis.runAfter("draw", "layout"); 151 152 153 156 Display display = new Display(m_vis); 157 display.setSize(700,700); 158 display.pan(350, 350); 159 display.setForeground(Color.GRAY); 160 display.setBackground(Color.WHITE); 161 162 display.addControlListener(new FocusControl(1)); 164 display.addControlListener(new DragControl()); 165 display.addControlListener(new PanControl()); 166 display.addControlListener(new ZoomControl()); 167 display.addControlListener(new WheelZoomControl()); 168 display.addControlListener(new ZoomToFitControl()); 169 display.addControlListener(new NeighborHighlightControl()); 170 171 176 display.setForeground(Color.GRAY); 177 display.setBackground(Color.WHITE); 178 179 182 ForceSimulator fsim = ((ForceDirectedLayout)animate.get(0)).getForceSimulator(); 184 JForcePanel fpanel = new JForcePanel(fsim); 185 186 191 final JValueSlider slider = new JValueSlider("Distance", 0, hops, hops); 192 slider.addChangeListener(new ChangeListener () { 193 public void stateChanged(ChangeEvent e) { 194 filter.setDistance(slider.getValue().intValue()); 195 m_vis.run("draw"); 196 } 197 }); 198 slider.setBackground(Color.WHITE); 199 slider.setPreferredSize(new Dimension (300,30)); 200 slider.setMaximumSize(new Dimension (300,30)); 201 202 Box cf = new Box (BoxLayout.Y_AXIS); 203 cf.add(slider); 204 cf.setBorder(BorderFactory.createTitledBorder("Connectivity Filter")); 205 fpanel.add(cf); 206 207 209 fpanel.add(Box.createVerticalGlue()); 210 211 JSplitPane split = new JSplitPane (); 213 split.setLeftComponent(display); 214 split.setRightComponent(fpanel); 215 split.setOneTouchExpandable(true); 216 split.setContinuousLayout(false); 217 split.setDividerLocation(700); 218 219 m_vis.run("draw"); 221 222 add(split); 223 } 224 225 public void setGraph(Graph g, String label) { 226 DefaultRendererFactory drf = (DefaultRendererFactory) 228 m_vis.getRendererFactory(); 229 ((LabelRenderer)drf.getDefaultRenderer()).setTextField(label); 230 231 m_vis.removeGroup(graph); 233 VisualGraph vg = m_vis.addGraph(graph, g); 234 m_vis.setValue(edges, null, VisualItem.INTERACTIVE, Boolean.FALSE); 235 VisualItem f = (VisualItem)vg.getNode(0); 236 m_vis.getGroup(Visualization.FOCUS_ITEMS).setTuple(f); 237 f.setFixed(false); 238 } 239 240 243 public static void main(String [] args) { 244 UILib.setPlatformLookAndFeel(); 245 246 String datafile = null; 248 String label = "label"; 249 if ( args.length > 1 ) { 250 datafile = args[0]; 251 label = args[1]; 252 } 253 254 JFrame frame = demo(datafile, label); 255 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 256 } 257 258 public static JFrame demo() { 259 return demo((String )null, "label"); 260 } 261 262 public static JFrame demo(String datafile, String label) { 263 Graph g = null; 264 if ( datafile == null ) { 265 g = GraphLib.getGrid(15,15); 266 label = "label"; 267 } else { 268 try { 269 g = new GraphMLReader().readGraph(datafile); 270 } catch ( Exception e ) { 271 e.printStackTrace(); 272 System.exit(1); 273 } 274 } 275 return demo(g, label); 276 } 277 278 public static JFrame demo(Graph g, String label) { 279 final GraphView view = new GraphView(g, label); 280 281 JMenu dataMenu = new JMenu ("Data"); 283 dataMenu.add(new OpenGraphAction(view)); 284 dataMenu.add(new GraphMenuAction("Grid","ctrl 1",view) { 285 protected Graph getGraph() { 286 return GraphLib.getGrid(15,15); 287 } 288 }); 289 dataMenu.add(new GraphMenuAction("Clique","ctrl 2",view) { 290 protected Graph getGraph() { 291 return GraphLib.getClique(10); 292 } 293 }); 294 dataMenu.add(new GraphMenuAction("Honeycomb","ctrl 3",view) { 295 protected Graph getGraph() { 296 return GraphLib.getHoneycomb(5); 297 } 298 }); 299 dataMenu.add(new GraphMenuAction("Balanced Tree","ctrl 4",view) { 300 protected Graph getGraph() { 301 return GraphLib.getBalancedTree(3,5); 302 } 303 }); 304 dataMenu.add(new GraphMenuAction("Diamond Tree","ctrl 5",view) { 305 protected Graph getGraph() { 306 return GraphLib.getDiamondTree(3,3,3); 307 } 308 }); 309 JMenuBar menubar = new JMenuBar (); 310 menubar.add(dataMenu); 311 312 JFrame frame = new JFrame ("p r e f u s e | g r a p h v i e w"); 314 frame.setJMenuBar(menubar); 315 frame.setContentPane(view); 316 frame.pack(); 317 frame.setVisible(true); 318 319 frame.addWindowListener(new WindowAdapter () { 320 public void windowActivated(WindowEvent e) { 321 view.m_vis.run("layout"); 322 } 323 public void windowDeactivated(WindowEvent e) { 324 view.m_vis.cancel("layout"); 325 } 326 }); 327 328 return frame; 329 } 330 331 332 334 337 public abstract static class GraphMenuAction extends AbstractAction { 338 private GraphView m_view; 339 public GraphMenuAction(String name, String accel, GraphView view) { 340 m_view = view; 341 this.putValue(AbstractAction.NAME, name); 342 this.putValue(AbstractAction.ACCELERATOR_KEY, 343 KeyStroke.getKeyStroke(accel)); 344 } 345 public void actionPerformed(ActionEvent e) { 346 m_view.setGraph(getGraph(), "label"); 347 } 348 protected abstract Graph getGraph(); 349 } 350 351 public static class OpenGraphAction extends AbstractAction { 352 private GraphView m_view; 353 354 public OpenGraphAction(GraphView view) { 355 m_view = view; 356 this.putValue(AbstractAction.NAME, "Open File..."); 357 this.putValue(AbstractAction.ACCELERATOR_KEY, 358 KeyStroke.getKeyStroke("ctrl O")); 359 } 360 public void actionPerformed(ActionEvent e) { 361 Graph g = IOLib.getGraphFile(m_view); 362 if ( g == null ) return; 363 String label = getLabel(m_view, g); 364 if ( label != null ) { 365 m_view.setGraph(g, label); 366 } 367 } 368 public static String getLabel(Component c, Graph g) { 369 Table t = g.getNodeTable(); 371 int cc = t.getColumnCount(); 372 String [] names = new String [cc]; 373 for ( int i=0; i<cc; ++i ) 374 names[i] = t.getColumnName(i); 375 376 final String [] label = new String [1]; 378 379 while ( c != null && !(c instanceof JFrame ) ) { 382 c = c.getParent(); 383 } 384 final JDialog dialog = new JDialog ( 385 (JFrame )c, "Choose Label Field", true); 386 387 final JButton ok = new JButton ("OK"); 389 ok.setEnabled(false); 390 ok.addActionListener(new ActionListener () { 391 public void actionPerformed(ActionEvent e) { 392 dialog.setVisible(false); 393 } 394 }); 395 JButton cancel = new JButton ("Cancel"); 396 cancel.addActionListener(new ActionListener () { 397 public void actionPerformed(ActionEvent e) { 398 label[0] = null; 399 dialog.setVisible(false); 400 } 401 }); 402 403 final JList list = new JList (names); 405 list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 406 list.getSelectionModel().addListSelectionListener( 407 new ListSelectionListener () { 408 public void valueChanged(ListSelectionEvent e) { 409 int sel = list.getSelectedIndex(); 410 if ( sel >= 0 ) { 411 ok.setEnabled(true); 412 label[0] = (String )list.getModel().getElementAt(sel); 413 } else { 414 ok.setEnabled(false); 415 label[0] = null; 416 } 417 } 418 }); 419 JScrollPane scrollList = new JScrollPane (list); 420 421 JLabel title = new JLabel ("Choose a field to use for node labels:"); 422 423 Box bbox = new Box (BoxLayout.X_AXIS); 425 bbox.add(Box.createHorizontalStrut(5)); 426 bbox.add(Box.createHorizontalGlue()); 427 bbox.add(ok); 428 bbox.add(Box.createHorizontalStrut(5)); 429 bbox.add(cancel); 430 bbox.add(Box.createHorizontalStrut(5)); 431 432 JPanel panel = new JPanel (new BorderLayout ()); 434 panel.add(title, BorderLayout.NORTH); 435 panel.add(scrollList, BorderLayout.CENTER); 436 panel.add(bbox, BorderLayout.SOUTH); 437 panel.setBorder(BorderFactory.createEmptyBorder(5,2,2,2)); 438 439 dialog.setContentPane(panel); 441 dialog.pack(); 442 dialog.setLocationRelativeTo(c); 443 dialog.setVisible(true); 444 dialog.dispose(); 445 446 return label[0]; 448 } 449 } 450 451 public static class FitOverviewListener implements ItemBoundsListener { 452 private Rectangle2D m_bounds = new Rectangle2D.Double (); 453 private Rectangle2D m_temp = new Rectangle2D.Double (); 454 private double m_d = 15; 455 public void itemBoundsChanged(Display d) { 456 d.getItemBounds(m_temp); 457 GraphicsLib.expand(m_temp, 25/d.getScale()); 458 459 double dd = m_d/d.getScale(); 460 double xd = Math.abs(m_temp.getMinX()-m_bounds.getMinX()); 461 double yd = Math.abs(m_temp.getMinY()-m_bounds.getMinY()); 462 double wd = Math.abs(m_temp.getWidth()-m_bounds.getWidth()); 463 double hd = Math.abs(m_temp.getHeight()-m_bounds.getHeight()); 464 if ( xd>dd || yd>dd || wd>dd || hd>dd ) { 465 m_bounds.setFrame(m_temp); 466 DisplayLib.fitViewToBounds(d, m_bounds, 0); 467 } 468 } 469 } 470 471 } | Popular Tags |