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