View Javadoc

1   /*
2    * Copyright (c) 2003, the JUNG Project and the Regents of the University of
3    * California All rights reserved.
4    * 
5    * This software is open-source under the BSD license; see either "license.txt"
6    * or http://jung.sourceforge.net/license.txt for a description.
7    * 
8    */
9   package edu.uci.ics.jung.samples;
10  
11  import java.awt.BorderLayout;
12  import java.awt.Color;
13  import java.awt.Container;
14  import java.awt.Dimension;
15  import java.awt.Font;
16  import java.awt.FontMetrics;
17  import java.awt.Graphics;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.ActionListener;
20  import java.awt.event.MouseEvent;
21  
22  import javax.swing.ImageIcon;
23  import javax.swing.JButton;
24  import javax.swing.JFrame;
25  import javax.swing.JPanel;
26  
27  import org.apache.commons.collections15.Transformer;
28  import org.apache.commons.collections15.functors.ConstantTransformer;
29  
30  import edu.uci.ics.jung.algorithms.layout.KKLayout;
31  import edu.uci.ics.jung.graph.DirectedSparseGraph;
32  import edu.uci.ics.jung.graph.util.EdgeType;
33  import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
34  import edu.uci.ics.jung.visualization.Layer;
35  import edu.uci.ics.jung.visualization.VisualizationViewer;
36  import edu.uci.ics.jung.visualization.control.AbstractModalGraphMouse;
37  import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
38  import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
39  import edu.uci.ics.jung.visualization.control.GraphMouseListener;
40  import edu.uci.ics.jung.visualization.control.ScalingControl;
41  import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
42  import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer;
43  import edu.uci.ics.jung.visualization.renderers.Renderer;
44  import edu.uci.ics.jung.visualization.renderers.BasicVertexLabelRenderer.InsidePositioner;
45  
46  
47  /**
48   * Demonstrates the use of <code>GraphZoomScrollPane</code>.
49   * This class shows the <code>VisualizationViewer</code> zooming
50   * and panning capabilities, using horizontal and
51   * vertical scrollbars.
52   *
53   * <p>This demo also shows ToolTips on graph vertices and edges,
54   * and a key listener to change graph mouse modes.</p>
55   * 
56   * @author Tom Nelson
57   * 
58   */
59  public class GraphZoomScrollPaneDemo {
60  
61      /**
62       * the graph
63       */
64      DirectedSparseGraph<String, Number> graph;
65  
66      /**
67       * the visual component and renderer for the graph
68       */
69      VisualizationViewer<String, Number> vv;
70      
71      /**
72       * create an instance of a simple graph with controls to
73       * demo the zoom features.
74       * 
75       */
76      public GraphZoomScrollPaneDemo() {
77          
78          // create a simple graph for the demo
79          graph = new DirectedSparseGraph<String, Number>();
80          String[] v = createVertices(10);
81          createEdges(v);
82          
83          ImageIcon sandstoneIcon = null;
84          String imageLocation = "/images/Sandstone.jpg";
85          try {
86              	sandstoneIcon = 
87              	    new ImageIcon(getClass().getResource(imageLocation));
88          } catch(Exception ex) {
89              System.err.println("Can't load \""+imageLocation+"\"");
90          }
91          final ImageIcon icon = sandstoneIcon;
92          vv =  new VisualizationViewer<String,Number>(new KKLayout<String,Number>(graph));
93          
94          if(icon != null) {
95              vv.addPreRenderPaintable(new VisualizationViewer.Paintable(){
96                  public void paint(Graphics g) {
97                      Dimension d = vv.getSize();
98                      g.drawImage(icon.getImage(),0,0,d.width,d.height,vv);
99                  }
100                 public boolean useTransform() { return false; }
101             });
102         }
103         vv.addPostRenderPaintable(new VisualizationViewer.Paintable(){
104             int x;
105             int y;
106             Font font;
107             FontMetrics metrics;
108             int swidth;
109             int sheight;
110             String str = "GraphZoomScrollPane Demo";
111             
112             public void paint(Graphics g) {
113                 Dimension d = vv.getSize();
114                 if(font == null) {
115                     font = new Font(g.getFont().getName(), Font.BOLD, 30);
116                     metrics = g.getFontMetrics(font);
117                     swidth = metrics.stringWidth(str);
118                     sheight = metrics.getMaxAscent()+metrics.getMaxDescent();
119                     x = (d.width-swidth)/2;
120                     y = (int)(d.height-sheight*1.5);
121                 }
122                 g.setFont(font);
123                 Color oldColor = g.getColor();
124                 g.setColor(Color.lightGray);
125                 g.drawString(str, x, y);
126                 g.setColor(oldColor);
127             }
128             public boolean useTransform() {
129                 return false;
130             }
131         });
132 
133         vv.addGraphMouseListener(new TestGraphMouseListener<String>());
134         vv.getRenderer().setVertexRenderer(
135         		new GradientVertexRenderer<String,Number>(
136         				Color.white, Color.red, 
137         				Color.white, Color.blue,
138         				vv.getPickedVertexState(),
139         				false));
140         vv.getRenderContext().setEdgeDrawPaintTransformer(new ConstantTransformer(Color.lightGray));
141         vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
142         vv.getRenderContext().setArrowDrawPaintTransformer(new ConstantTransformer(Color.lightGray));
143         
144         // add my listeners for ToolTips
145         vv.setVertexToolTipTransformer(new ToStringLabeller<String>());
146         vv.setEdgeToolTipTransformer(new Transformer<Number,String>() {
147 			public String transform(Number edge) {
148 				return "E"+graph.getEndpoints(edge).toString();
149 			}});
150         
151         vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<String>());
152         vv.getRenderer().getVertexLabelRenderer().setPositioner(new InsidePositioner());
153         vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.AUTO);
154         vv.setForeground(Color.lightGray);
155         
156         // create a frome to hold the graph
157         final JFrame frame = new JFrame();
158         Container content = frame.getContentPane();
159         final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
160         content.add(panel);
161         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
162         final AbstractModalGraphMouse graphMouse = new DefaultModalGraphMouse<String,Number>();
163         vv.setGraphMouse(graphMouse);
164         
165         vv.addKeyListener(graphMouse.getModeKeyListener());
166         vv.setToolTipText("<html><center>Type 'p' for Pick mode<p>Type 't' for Transform mode");
167         
168         final ScalingControl scaler = new CrossoverScalingControl();
169 
170         JButton plus = new JButton("+");
171         plus.addActionListener(new ActionListener() {
172             public void actionPerformed(ActionEvent e) {
173                 scaler.scale(vv, 1.1f, vv.getCenter());
174             }
175         });
176         JButton minus = new JButton("-");
177         minus.addActionListener(new ActionListener() {
178             public void actionPerformed(ActionEvent e) {
179                 scaler.scale(vv, 1/1.1f, vv.getCenter());
180             }
181         });
182 
183         JButton reset = new JButton("reset");
184         reset.addActionListener(new ActionListener() {
185 
186 			public void actionPerformed(ActionEvent e) {
187 				vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity();
188 				vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).setToIdentity();
189 			}});
190 
191         JPanel controls = new JPanel();
192         controls.add(plus);
193         controls.add(minus);
194         controls.add(reset);
195         content.add(controls, BorderLayout.SOUTH);
196 
197         frame.pack();
198         frame.setVisible(true);
199     }
200     
201     /**
202      * create some vertices
203      * @param count how many to create
204      * @return the Vertices in an array
205      */
206     private String[] createVertices(int count) {
207         String[] v = new String[count];
208         for (int i = 0; i < count; i++) {
209         	v[i] = "V"+i;
210             graph.addVertex(v[i]);
211         }
212         return v;
213     }
214 
215     /**
216      * create edges for this demo graph
217      * @param v an array of Vertices to connect
218      */
219     void createEdges(String[] v) {
220         graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED);
221         graph.addEdge(new Double(Math.random()), v[0], v[3], EdgeType.DIRECTED);
222         graph.addEdge(new Double(Math.random()), v[0], v[4], EdgeType.DIRECTED);
223         graph.addEdge(new Double(Math.random()), v[4], v[5], EdgeType.DIRECTED);
224         graph.addEdge(new Double(Math.random()), v[3], v[5], EdgeType.DIRECTED);
225         graph.addEdge(new Double(Math.random()), v[1], v[2], EdgeType.DIRECTED);
226         graph.addEdge(new Double(Math.random()), v[1], v[4], EdgeType.DIRECTED);
227         graph.addEdge(new Double(Math.random()), v[8], v[2], EdgeType.DIRECTED);
228         graph.addEdge(new Double(Math.random()), v[3], v[8], EdgeType.DIRECTED);
229         graph.addEdge(new Double(Math.random()), v[6], v[7], EdgeType.DIRECTED);
230         graph.addEdge(new Double(Math.random()), v[7], v[5], EdgeType.DIRECTED);
231         graph.addEdge(new Double(Math.random()), v[0], v[9], EdgeType.DIRECTED);
232         graph.addEdge(new Double(Math.random()), v[9], v[8], EdgeType.DIRECTED);
233         graph.addEdge(new Double(Math.random()), v[7], v[6], EdgeType.DIRECTED);
234         graph.addEdge(new Double(Math.random()), v[6], v[5], EdgeType.DIRECTED);
235         graph.addEdge(new Double(Math.random()), v[4], v[2], EdgeType.DIRECTED);
236         graph.addEdge(new Double(Math.random()), v[5], v[4], EdgeType.DIRECTED);
237     }
238 
239     /**
240      * A nested class to demo the GraphMouseListener finding the
241      * right vertices after zoom/pan
242      */
243     static class TestGraphMouseListener<V> implements GraphMouseListener<V> {
244         
245     		public void graphClicked(V v, MouseEvent me) {
246     		    System.err.println("Vertex "+v+" was clicked at ("+me.getX()+","+me.getY()+")");
247     		}
248     		public void graphPressed(V v, MouseEvent me) {
249     		    System.err.println("Vertex "+v+" was pressed at ("+me.getX()+","+me.getY()+")");
250     		}
251     		public void graphReleased(V v, MouseEvent me) {
252     		    System.err.println("Vertex "+v+" was released at ("+me.getX()+","+me.getY()+")");
253     		}
254     }
255 
256     /**
257      * a driver for this demo
258      */
259     public static void main(String[] args) 
260     {
261         new GraphZoomScrollPaneDemo();
262     }
263 }