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.JComboBox;
34  import javax.swing.JFrame;
35  import javax.swing.JPanel;
36  import javax.swing.JToggleButton;
37  
38  import org.apache.commons.collections15.Factory;
39  import org.apache.commons.collections15.functors.ConstantTransformer;
40  
41  import edu.uci.ics.jung.algorithms.layout.PolarPoint;
42  import edu.uci.ics.jung.algorithms.layout.RadialTreeLayout;
43  import edu.uci.ics.jung.algorithms.layout.TreeLayout;
44  import edu.uci.ics.jung.graph.DirectedGraph;
45  import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
46  import edu.uci.ics.jung.graph.Forest;
47  import edu.uci.ics.jung.graph.DelegateForest;
48  import edu.uci.ics.jung.graph.DelegateTree;
49  import edu.uci.ics.jung.graph.Tree;
50  import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
51  import edu.uci.ics.jung.visualization.Layer;
52  import edu.uci.ics.jung.visualization.VisualizationServer;
53  import edu.uci.ics.jung.visualization.VisualizationViewer;
54  import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
55  import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
56  import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
57  import edu.uci.ics.jung.visualization.control.ScalingControl;
58  import edu.uci.ics.jung.visualization.decorators.EdgeShape;
59  import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
60  import edu.uci.ics.jung.visualization.layout.LayoutTransition;
61  import edu.uci.ics.jung.visualization.util.Animator;
62  
63  /**
64   * Demonsrates TreeLayout and RadialTreeLayout.
65   * @author Tom Nelson
66   * 
67   */
68  @SuppressWarnings("serial")
69  public class TreeLayoutDemo extends JApplet {
70  
71      /**
72       * the graph
73       */
74      Forest<String,Integer> graph;
75      
76      Factory<DirectedGraph<String,Integer>> graphFactory = 
77      	new Factory<DirectedGraph<String,Integer>>() {
78  
79  			public DirectedGraph<String, Integer> create() {
80  				return new DirectedSparseMultigraph<String,Integer>();
81  			}
82  		};
83  			
84  	Factory<Tree<String,Integer>> treeFactory =
85  		new Factory<Tree<String,Integer>> () {
86  
87  		public Tree<String, Integer> create() {
88  			return new DelegateTree<String,Integer>(graphFactory);
89  		}
90  	};
91  	
92  	Factory<Integer> edgeFactory = new Factory<Integer>() {
93  		int i=0;
94  		public Integer create() {
95  			return i++;
96  		}};
97      
98      Factory<String> vertexFactory = new Factory<String>() {
99      	int i=0;
100 		public String create() {
101 			return "V"+i++;
102 		}};
103 
104     /**
105      * the visual component and renderer for the graph
106      */
107     VisualizationViewer<String,Integer> vv;
108     
109     VisualizationServer.Paintable rings;
110     
111     String root;
112     
113     TreeLayout<String,Integer> treeLayout;
114     
115     RadialTreeLayout<String,Integer> radialLayout;
116 
117     public TreeLayoutDemo() {
118         
119         // create a simple graph for the demo
120         graph = new DelegateForest<String,Integer>();
121 
122         createTree();
123         
124         treeLayout = new TreeLayout<String,Integer>(graph);
125         radialLayout = new RadialTreeLayout<String,Integer>(graph);
126         radialLayout.setSize(new Dimension(600,600));
127         vv =  new VisualizationViewer<String,Integer>(treeLayout, new Dimension(600,600));
128         vv.setBackground(Color.white);
129         vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
130         vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
131         // add a listener for ToolTips
132         vv.setVertexToolTipTransformer(new ToStringLabeller());
133         vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
134         rings = new Rings();
135 
136         Container content = getContentPane();
137         final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
138         content.add(panel);
139         
140         final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
141 
142         vv.setGraphMouse(graphMouse);
143         
144         JComboBox modeBox = graphMouse.getModeComboBox();
145         modeBox.addItemListener(graphMouse.getModeListener());
146         graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
147 
148         final ScalingControl scaler = new CrossoverScalingControl();
149 
150         JButton plus = new JButton("+");
151         plus.addActionListener(new ActionListener() {
152             public void actionPerformed(ActionEvent e) {
153                 scaler.scale(vv, 1.1f, vv.getCenter());
154             }
155         });
156         JButton minus = new JButton("-");
157         minus.addActionListener(new ActionListener() {
158             public void actionPerformed(ActionEvent e) {
159                 scaler.scale(vv, 1/1.1f, vv.getCenter());
160             }
161         });
162         
163         JToggleButton radial = new JToggleButton("Radial");
164         radial.addItemListener(new ItemListener() {
165 
166 			public void itemStateChanged(ItemEvent e) {
167 				if(e.getStateChange() == ItemEvent.SELECTED) {
168 					
169 					LayoutTransition<String,Integer> lt =
170 						new LayoutTransition<String,Integer>(vv, treeLayout, radialLayout);
171 					Animator animator = new Animator(lt);
172 					animator.start();
173 					vv.getRenderContext().getMultiLayerTransformer().setToIdentity();
174 					vv.addPreRenderPaintable(rings);
175 				} else {
176 					LayoutTransition<String,Integer> lt =
177 						new LayoutTransition<String,Integer>(vv, radialLayout, treeLayout);
178 					Animator animator = new Animator(lt);
179 					animator.start();
180 					vv.getRenderContext().getMultiLayerTransformer().setToIdentity();
181 					vv.removePreRenderPaintable(rings);
182 				}
183 				vv.repaint();
184 			}});
185 
186         JPanel scaleGrid = new JPanel(new GridLayout(1,0));
187         scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom"));
188 
189         JPanel controls = new JPanel();
190         scaleGrid.add(plus);
191         scaleGrid.add(minus);
192         controls.add(radial);
193         controls.add(scaleGrid);
194         controls.add(modeBox);
195 
196         content.add(controls, BorderLayout.SOUTH);
197     }
198     
199     class Rings implements VisualizationServer.Paintable {
200     	
201     	Collection<Double> depths;
202     	
203     	public Rings() {
204     		depths = getDepths();
205     	}
206     	
207     	private Collection<Double> getDepths() {
208     		Set<Double> depths = new HashSet<Double>();
209     		Map<String,PolarPoint> polarLocations = radialLayout.getPolarLocations();
210     		for(String v : graph.getVertices()) {
211     			PolarPoint pp = polarLocations.get(v);
212     			depths.add(pp.getRadius());
213     		}
214     		return depths;
215     	}
216 
217 		public void paint(Graphics g) {
218 			g.setColor(Color.lightGray);
219 		
220 			Graphics2D g2d = (Graphics2D)g;
221 			Point2D center = radialLayout.getCenter();
222 
223 			Ellipse2D ellipse = new Ellipse2D.Double();
224 			for(double d : depths) {
225 				ellipse.setFrameFromDiagonal(center.getX()-d, center.getY()-d, 
226 						center.getX()+d, center.getY()+d);
227 				Shape shape = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).transform(ellipse);
228 				g2d.draw(shape);
229 			}
230 		}
231 
232 		public boolean useTransform() {
233 			return true;
234 		}
235     }
236     
237     /**
238      * 
239      */
240     private void createTree() {
241     	graph.addVertex("V0");
242     	graph.addEdge(edgeFactory.create(), "V0", "V1");
243     	graph.addEdge(edgeFactory.create(), "V0", "V2");
244     	graph.addEdge(edgeFactory.create(), "V1", "V4");
245     	graph.addEdge(edgeFactory.create(), "V2", "V3");
246     	graph.addEdge(edgeFactory.create(), "V2", "V5");
247     	graph.addEdge(edgeFactory.create(), "V4", "V6");
248     	graph.addEdge(edgeFactory.create(), "V4", "V7");
249     	graph.addEdge(edgeFactory.create(), "V3", "V8");
250     	graph.addEdge(edgeFactory.create(), "V6", "V9");
251     	graph.addEdge(edgeFactory.create(), "V4", "V10");
252     	
253        	graph.addVertex("A0");
254        	graph.addEdge(edgeFactory.create(), "A0", "A1");
255        	graph.addEdge(edgeFactory.create(), "A0", "A2");
256        	graph.addEdge(edgeFactory.create(), "A0", "A3");
257        	
258        	graph.addVertex("B0");
259     	graph.addEdge(edgeFactory.create(), "B0", "B1");
260     	graph.addEdge(edgeFactory.create(), "B0", "B2");
261     	graph.addEdge(edgeFactory.create(), "B1", "B4");
262     	graph.addEdge(edgeFactory.create(), "B2", "B3");
263     	graph.addEdge(edgeFactory.create(), "B2", "B5");
264     	graph.addEdge(edgeFactory.create(), "B4", "B6");
265     	graph.addEdge(edgeFactory.create(), "B4", "B7");
266     	graph.addEdge(edgeFactory.create(), "B3", "B8");
267     	graph.addEdge(edgeFactory.create(), "B6", "B9");
268        	
269     }
270 
271 
272     /**
273      * a driver for this demo
274      */
275     public static void main(String[] args) {
276         JFrame frame = new JFrame();
277         Container content = frame.getContentPane();
278         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
279 
280         content.add(new TreeLayoutDemo());
281         frame.pack();
282         frame.setVisible(true);
283     }
284 }