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