1
2
3
4
5
6
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.AffineTransform;
25 import java.awt.geom.Ellipse2D;
26 import java.awt.geom.Point2D;
27
28 import javax.swing.BorderFactory;
29 import javax.swing.JApplet;
30 import javax.swing.JButton;
31 import javax.swing.JComboBox;
32 import javax.swing.JFrame;
33 import javax.swing.JPanel;
34 import javax.swing.JRadioButton;
35 import javax.swing.JToggleButton;
36
37 import com.google.common.base.Functions;
38 import com.google.common.base.Supplier;
39
40 import edu.uci.ics.jung.algorithms.layout.BalloonLayout;
41 import edu.uci.ics.jung.algorithms.layout.TreeLayout;
42 import edu.uci.ics.jung.graph.DelegateForest;
43 import edu.uci.ics.jung.graph.DelegateTree;
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.Tree;
48 import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
49 import edu.uci.ics.jung.visualization.Layer;
50 import edu.uci.ics.jung.visualization.VisualizationServer;
51 import edu.uci.ics.jung.visualization.VisualizationViewer;
52 import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
53 import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
54 import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
55 import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse;
56 import edu.uci.ics.jung.visualization.control.ScalingControl;
57 import edu.uci.ics.jung.visualization.decorators.EdgeShape;
58 import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
59 import edu.uci.ics.jung.visualization.layout.LayoutTransition;
60 import edu.uci.ics.jung.visualization.transform.LensSupport;
61 import edu.uci.ics.jung.visualization.transform.MutableTransformer;
62 import edu.uci.ics.jung.visualization.transform.MutableTransformerDecorator;
63 import edu.uci.ics.jung.visualization.transform.shape.HyperbolicShapeTransformer;
64 import edu.uci.ics.jung.visualization.transform.shape.ViewLensSupport;
65 import edu.uci.ics.jung.visualization.util.Animator;
66
67
68
69
70
71
72
73
74
75 @SuppressWarnings("serial")
76 public class BalloonLayoutDemo extends JApplet {
77
78
79
80
81 Forest<String,Integer> graph;
82
83 Supplier<DirectedGraph<String,Integer>> graphFactory =
84 new Supplier<DirectedGraph<String,Integer>>() {
85
86 public DirectedGraph<String, Integer> get() {
87 return new DirectedSparseMultigraph<String,Integer>();
88 }
89 };
90
91 Supplier<Tree<String,Integer>> treeFactory =
92 new Supplier<Tree<String,Integer>> () {
93
94 public Tree<String, Integer> get() {
95 return new DelegateTree<String,Integer>(graphFactory);
96 }
97 };
98
99 Supplier<Integer> edgeFactory = new Supplier<Integer>() {
100 int i=0;
101 public Integer get() {
102 return i++;
103 }};
104
105 Supplier<String> vertexFactory = new Supplier<String>() {
106 int i=0;
107 public String get() {
108 return "V"+i++;
109 }};
110
111
112
113
114 VisualizationViewer<String,Integer> vv;
115
116 VisualizationServer.Paintable rings;
117
118 String root;
119
120 TreeLayout<String,Integer> layout;
121
122 BalloonLayout<String,Integer> radialLayout;
123
124
125
126 LensSupport hyperbolicViewSupport;
127
128 public BalloonLayoutDemo() {
129
130
131 graph = new DelegateForest<String,Integer>();
132
133 createTree();
134
135 layout = new TreeLayout<String,Integer>(graph);
136 radialLayout = new BalloonLayout<String,Integer>(graph);
137 radialLayout.setSize(new Dimension(900,900));
138 vv = new VisualizationViewer<String,Integer>(layout, new Dimension(600,600));
139 vv.setBackground(Color.white);
140 vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.quadCurve(graph));
141 vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
142
143 vv.setVertexToolTipTransformer(new ToStringLabeller());
144 vv.getRenderContext().setArrowFillPaintTransformer(Functions.<Paint>constant(Color.lightGray));
145 rings = new Rings(radialLayout);
146
147 Container content = getContentPane();
148 final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
149 content.add(panel);
150
151 final DefaultModalGraphMouse<String, Integer> graphMouse =
152 new DefaultModalGraphMouse<String, Integer>();
153
154 vv.setGraphMouse(graphMouse);
155 vv.addKeyListener(graphMouse.getModeKeyListener());
156
157 hyperbolicViewSupport =
158 new ViewLensSupport<String,Integer>(vv, new HyperbolicShapeTransformer(vv,
159 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)),
160 new ModalLensGraphMouse());
161
162
163 graphMouse.addItemListener(hyperbolicViewSupport.getGraphMouse().getModeListener());
164
165 JComboBox<?> modeBox = graphMouse.getModeComboBox();
166 modeBox.addItemListener(graphMouse.getModeListener());
167 graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
168
169 final ScalingControl scaler = new CrossoverScalingControl();
170
171 vv.scaleToLayout(scaler);
172
173 JButton plus = new JButton("+");
174 plus.addActionListener(new ActionListener() {
175 public void actionPerformed(ActionEvent e) {
176 scaler.scale(vv, 1.1f, vv.getCenter());
177 }
178 });
179 JButton minus = new JButton("-");
180 minus.addActionListener(new ActionListener() {
181 public void actionPerformed(ActionEvent e) {
182 scaler.scale(vv, 1/1.1f, vv.getCenter());
183 }
184 });
185
186 JToggleButton radial = new JToggleButton("Balloon");
187 radial.addItemListener(new ItemListener() {
188
189 public void itemStateChanged(ItemEvent e) {
190 if(e.getStateChange() == ItemEvent.SELECTED) {
191
192 LayoutTransition<String,Integer> lt =
193 new LayoutTransition<String,Integer>(vv, layout, radialLayout);
194 Animator animator = new Animator(lt);
195 animator.start();
196 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity();
197 vv.addPreRenderPaintable(rings);
198 } else {
199
200 LayoutTransition<String,Integer> lt =
201 new LayoutTransition<String,Integer>(vv, radialLayout, layout);
202 Animator animator = new Animator(lt);
203 animator.start();
204 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity();
205 vv.removePreRenderPaintable(rings);
206 }
207 vv.repaint();
208 }});
209 final JRadioButton hyperView = new JRadioButton("Hyperbolic View");
210 hyperView.addItemListener(new ItemListener(){
211 public void itemStateChanged(ItemEvent e) {
212 hyperbolicViewSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
213 }
214 });
215
216 JPanel scaleGrid = new JPanel(new GridLayout(1,0));
217 scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom"));
218
219 JPanel controls = new JPanel();
220 scaleGrid.add(plus);
221 scaleGrid.add(minus);
222 controls.add(radial);
223 controls.add(scaleGrid);
224 controls.add(modeBox);
225 controls.add(hyperView);
226 content.add(controls, BorderLayout.SOUTH);
227 }
228
229 class Rings implements VisualizationServer.Paintable {
230
231 BalloonLayout<String,Integer> layout;
232
233 public Rings(BalloonLayout<String,Integer> layout) {
234 this.layout = layout;
235 }
236
237 public void paint(Graphics g) {
238 g.setColor(Color.gray);
239
240 Graphics2D g2d = (Graphics2D)g;
241
242 Ellipse2D ellipse = new Ellipse2D.Double();
243 for(String v : layout.getGraph().getVertices()) {
244 Double radius = layout.getRadii().get(v);
245 if(radius == null) continue;
246 Point2D p = layout.apply(v);
247 ellipse.setFrame(-radius, -radius, 2*radius, 2*radius);
248 AffineTransform at = AffineTransform.getTranslateInstance(p.getX(), p.getY());
249 Shape shape = at.createTransformedShape(ellipse);
250
251 MutableTransformer viewTransformer =
252 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW);
253
254 if(viewTransformer instanceof MutableTransformerDecorator) {
255 shape = vv.getRenderContext().getMultiLayerTransformer().transform(shape);
256 } else {
257 shape = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT,shape);
258 }
259
260 g2d.draw(shape);
261 }
262 }
263
264 public boolean useTransform() {
265 return true;
266 }
267 }
268
269
270
271
272 private void createTree() {
273
274 graph.addVertex("A0");
275 graph.addEdge(edgeFactory.get(), "A0", "B0");
276 graph.addEdge(edgeFactory.get(), "A0", "B1");
277 graph.addEdge(edgeFactory.get(), "A0", "B2");
278
279 graph.addEdge(edgeFactory.get(), "B0", "C0");
280 graph.addEdge(edgeFactory.get(), "B0", "C1");
281 graph.addEdge(edgeFactory.get(), "B0", "C2");
282 graph.addEdge(edgeFactory.get(), "B0", "C3");
283
284 graph.addEdge(edgeFactory.get(), "C2", "H0");
285 graph.addEdge(edgeFactory.get(), "C2", "H1");
286
287 graph.addEdge(edgeFactory.get(), "B1", "D0");
288 graph.addEdge(edgeFactory.get(), "B1", "D1");
289 graph.addEdge(edgeFactory.get(), "B1", "D2");
290
291 graph.addEdge(edgeFactory.get(), "B2", "E0");
292 graph.addEdge(edgeFactory.get(), "B2", "E1");
293 graph.addEdge(edgeFactory.get(), "B2", "E2");
294
295 graph.addEdge(edgeFactory.get(), "D0", "F0");
296 graph.addEdge(edgeFactory.get(), "D0", "F1");
297 graph.addEdge(edgeFactory.get(), "D0", "F2");
298
299 graph.addEdge(edgeFactory.get(), "D1", "G0");
300 graph.addEdge(edgeFactory.get(), "D1", "G1");
301 graph.addEdge(edgeFactory.get(), "D1", "G2");
302 graph.addEdge(edgeFactory.get(), "D1", "G3");
303 graph.addEdge(edgeFactory.get(), "D1", "G4");
304 graph.addEdge(edgeFactory.get(), "D1", "G5");
305 graph.addEdge(edgeFactory.get(), "D1", "G6");
306 graph.addEdge(edgeFactory.get(), "D1", "G7");
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326 }
327
328 public static void main(String[] args) {
329 JFrame frame = new JFrame();
330 Container content = frame.getContentPane();
331 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
332
333 content.add(new BalloonLayoutDemo());
334 frame.pack();
335 frame.setVisible(true);
336 }
337 }