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