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.Graphics;
16  import java.awt.Graphics2D;
17  import java.awt.GridLayout;
18  import java.awt.Shape;
19  import java.awt.event.ActionEvent;
20  import java.awt.event.ActionListener;
21  import java.awt.event.ItemEvent;
22  import java.awt.event.ItemListener;
23  import java.awt.geom.Ellipse2D;
24  import java.awt.geom.Point2D;
25  import java.util.Collection;
26  import java.util.HashSet;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import javax.swing.BorderFactory;
31  import javax.swing.JApplet;
32  import javax.swing.JButton;
33  import javax.swing.JFrame;
34  import javax.swing.JMenuBar;
35  import javax.swing.JPanel;
36  import javax.swing.JRadioButton;
37  
38  import org.apache.commons.collections15.Factory;
39  
40  import edu.uci.ics.jung.algorithms.layout.PolarPoint;
41  import edu.uci.ics.jung.algorithms.layout.RadialTreeLayout;
42  import edu.uci.ics.jung.algorithms.layout.TreeLayout;
43  import edu.uci.ics.jung.graph.DelegateForest;
44  import edu.uci.ics.jung.graph.DelegateTree;
45  import edu.uci.ics.jung.graph.DirectedGraph;
46  import edu.uci.ics.jung.graph.DirectedSparseGraph;
47  import edu.uci.ics.jung.graph.Forest;
48  import edu.uci.ics.jung.graph.Tree;
49  import edu.uci.ics.jung.visualization.DefaultVisualizationModel;
50  import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
51  import edu.uci.ics.jung.visualization.Layer;
52  import edu.uci.ics.jung.visualization.VisualizationModel;
53  import edu.uci.ics.jung.visualization.VisualizationServer;
54  import edu.uci.ics.jung.visualization.VisualizationViewer;
55  import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
56  import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
57  import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse;
58  import edu.uci.ics.jung.visualization.control.ScalingControl;
59  import edu.uci.ics.jung.visualization.decorators.EdgeShape;
60  import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
61  import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
62  import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
63  import edu.uci.ics.jung.visualization.picking.PickedState;
64  import edu.uci.ics.jung.visualization.transform.LensSupport;
65  import edu.uci.ics.jung.visualization.transform.shape.HyperbolicShapeTransformer;
66  import edu.uci.ics.jung.visualization.transform.shape.ViewLensSupport;
67  
68  /**
69   * Shows a RadialTreeLayout view of a Forest.
70   * A hyperbolic projection lens may also be applied
71   * to the view
72   * 
73   * @author Tom Nelson
74   * 
75   */
76  @SuppressWarnings("serial")
77  public class RadialTreeLensDemo extends JApplet {
78  	
79  	Forest<String,Integer> graph;
80  
81  	Factory<DirectedGraph<String,Integer>> graphFactory = 
82  		new Factory<DirectedGraph<String,Integer>>() {
83  
84  		public DirectedGraph<String, Integer> create() {
85  			return new DirectedSparseGraph<String,Integer>();
86  		}
87  	};
88  
89  	Factory<Tree<String,Integer>> treeFactory =
90  		new Factory<Tree<String,Integer>> () {
91  
92  		public Tree<String, Integer> create() {
93  			return new DelegateTree<String,Integer>(graphFactory);
94  		}
95  	};
96  	Factory<Integer> edgeFactory = new Factory<Integer>() {
97  		int i=0;
98  		public Integer create() {
99  			return i++;
100 		}
101 	};
102 
103 	Factory<String> vertexFactory = new Factory<String>() {
104 		int i=0;
105 		public String create() {
106 			return "V"+i++;
107 		}
108 	};
109 
110 	VisualizationServer.Paintable rings;
111 
112 	String root;
113 
114 	TreeLayout<String,Integer> layout;
115 
116 	RadialTreeLayout<String,Integer> radialLayout;
117 
118 	/**
119 	 * the visual component and renderer for the graph
120 	 */
121 	VisualizationViewer<String,Integer> vv;
122 
123     /**
124      * provides a Hyperbolic lens for the view
125      */
126     LensSupport hyperbolicViewSupport;
127     
128     ScalingControl scaler;
129     
130     /**
131      * create an instance of a simple graph with controls to
132      * demo the zoomand hyperbolic features.
133      * 
134      */
135     public RadialTreeLensDemo() {
136         
137         // create a simple graph for the demo
138         // create a simple graph for the demo
139         graph = new DelegateForest<String,Integer>();
140 
141         createTree();
142         
143         layout = new TreeLayout<String,Integer>(graph);
144         radialLayout = new RadialTreeLayout<String,Integer>(graph);
145         radialLayout.setSize(new Dimension(600,600));
146 
147         Dimension preferredSize = new Dimension(600,600);
148         
149         final VisualizationModel<String,Integer> visualizationModel = 
150             new DefaultVisualizationModel<String,Integer>(radialLayout, preferredSize);
151         vv =  new VisualizationViewer<String,Integer>(visualizationModel, preferredSize);
152 
153         PickedState<String> ps = vv.getPickedVertexState();
154         PickedState<Integer> pes = vv.getPickedEdgeState();
155         vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<String>(ps, Color.red, Color.yellow));
156         vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Integer>(pes, Color.black, Color.cyan));
157         vv.setBackground(Color.white);
158         
159         vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<String>());
160         vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
161         
162         // add a listener for ToolTips
163         vv.setVertexToolTipTransformer(new ToStringLabeller<String>());
164         
165         Container content = getContentPane();
166         GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv);
167         content.add(gzsp);
168         
169         /**
170          * the regular graph mouse for the normal view
171          */
172         final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
173 
174         vv.setGraphMouse(graphMouse);
175         vv.addKeyListener(graphMouse.getModeKeyListener());
176         rings = new Rings();
177 		vv.addPreRenderPaintable(rings);
178 
179         hyperbolicViewSupport = 
180             new ViewLensSupport<String,Integer>(vv, new HyperbolicShapeTransformer(vv, 
181             		vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)), 
182                     new ModalLensGraphMouse());
183         
184         final ScalingControl scaler = new CrossoverScalingControl();
185 
186         JButton plus = new JButton("+");
187         plus.addActionListener(new ActionListener() {
188             public void actionPerformed(ActionEvent e) {
189                 scaler.scale(vv, 1.1f, vv.getCenter());
190             }
191         });
192         JButton minus = new JButton("-");
193         minus.addActionListener(new ActionListener() {
194             public void actionPerformed(ActionEvent e) {
195                 scaler.scale(vv, 1/1.1f, vv.getCenter());
196             }
197         });
198         
199         final JRadioButton hyperView = new JRadioButton("Hyperbolic View");
200         hyperView.addItemListener(new ItemListener(){
201             public void itemStateChanged(ItemEvent e) {
202                 hyperbolicViewSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
203             }
204         });
205 
206         graphMouse.addItemListener(hyperbolicViewSupport.getGraphMouse().getModeListener());
207         
208         JMenuBar menubar = new JMenuBar();
209         menubar.add(graphMouse.getModeMenu());
210         gzsp.setCorner(menubar);
211 
212         JPanel controls = new JPanel();
213         JPanel zoomControls = new JPanel(new GridLayout(2,1));
214         zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom"));
215         JPanel hyperControls = new JPanel(new GridLayout(3,2));
216         hyperControls.setBorder(BorderFactory.createTitledBorder("Examiner Lens"));
217         zoomControls.add(plus);
218         zoomControls.add(minus);
219         JPanel modeControls = new JPanel(new BorderLayout());
220         modeControls.setBorder(BorderFactory.createTitledBorder("Mouse Mode"));
221         modeControls.add(graphMouse.getModeComboBox());
222         hyperControls.add(hyperView);
223         
224         controls.add(zoomControls);
225         controls.add(hyperControls);
226         controls.add(modeControls);
227         content.add(controls, BorderLayout.SOUTH);
228     }
229 
230     private void createTree() {
231     	graph.addVertex("V0");
232     	graph.addEdge(edgeFactory.create(), "V0", "V1");
233     	graph.addEdge(edgeFactory.create(), "V0", "V2");
234     	graph.addEdge(edgeFactory.create(), "V1", "V4");
235     	graph.addEdge(edgeFactory.create(), "V2", "V3");
236     	graph.addEdge(edgeFactory.create(), "V2", "V5");
237     	graph.addEdge(edgeFactory.create(), "V4", "V6");
238     	graph.addEdge(edgeFactory.create(), "V4", "V7");
239     	graph.addEdge(edgeFactory.create(), "V3", "V8");
240     	graph.addEdge(edgeFactory.create(), "V6", "V9");
241     	graph.addEdge(edgeFactory.create(), "V4", "V10");
242     	
243        	graph.addVertex("A0");
244        	graph.addEdge(edgeFactory.create(), "A0", "A1");
245        	graph.addEdge(edgeFactory.create(), "A0", "A2");
246        	graph.addEdge(edgeFactory.create(), "A0", "A3");
247        	
248        	graph.addVertex("B0");
249     	graph.addEdge(edgeFactory.create(), "B0", "B1");
250     	graph.addEdge(edgeFactory.create(), "B0", "B2");
251     	graph.addEdge(edgeFactory.create(), "B1", "B4");
252     	graph.addEdge(edgeFactory.create(), "B2", "B3");
253     	graph.addEdge(edgeFactory.create(), "B2", "B5");
254     	graph.addEdge(edgeFactory.create(), "B4", "B6");
255     	graph.addEdge(edgeFactory.create(), "B4", "B7");
256     	graph.addEdge(edgeFactory.create(), "B3", "B8");
257     	graph.addEdge(edgeFactory.create(), "B6", "B9");
258        	
259     }
260 
261     class Rings implements VisualizationServer.Paintable {
262     	
263     	Collection<Double> depths;
264     	
265     	public Rings() {
266     		depths = getDepths();
267     	}
268     	
269     	private Collection<Double> getDepths() {
270     		Set<Double> depths = new HashSet<Double>();
271     		Map<String,PolarPoint> polarLocations = radialLayout.getPolarLocations();
272     		for(String v : graph.getVertices()) {
273     			PolarPoint pp = polarLocations.get(v);
274     			depths.add(pp.getRadius());
275     		}
276     		return depths;
277     	}
278 
279 		public void paint(Graphics g) {
280 			g.setColor(Color.gray);
281 			Graphics2D g2d = (Graphics2D)g;
282 			Point2D center = radialLayout.getCenter();
283 
284 			Ellipse2D ellipse = new Ellipse2D.Double();
285 			for(double d : depths) {
286 				ellipse.setFrameFromDiagonal(center.getX()-d, center.getY()-d, 
287 						center.getX()+d, center.getY()+d);
288 				Shape shape = 
289 					vv.getRenderContext().getMultiLayerTransformer().transform(ellipse);
290 //					vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).transform(ellipse);
291 				g2d.draw(shape);
292 			}
293 		}
294 
295 		public boolean useTransform() {
296 			return true;
297 		}
298     }
299 
300     /**
301      * a driver for this demo
302      */
303     public static void main(String[] args) {
304         JFrame f = new JFrame();
305         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
306         f.getContentPane().add(new RadialTreeLensDemo());
307         f.pack();
308         f.setVisible(true);
309     }
310 }