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.FontMetrics;
16 import java.awt.Graphics;
17 import java.awt.Graphics2D;
18 import java.awt.GridLayout;
19 import java.awt.Insets;
20 import java.awt.Rectangle;
21 import java.awt.Shape;
22 import java.awt.event.ActionEvent;
23 import java.awt.event.ActionListener;
24 import java.awt.event.ItemEvent;
25 import java.awt.event.ItemListener;
26 import java.awt.geom.AffineTransform;
27 import java.awt.geom.Point2D;
28 import java.awt.geom.Rectangle2D;
29 import java.util.HashMap;
30 import java.util.Map;
31
32 import javax.swing.BorderFactory;
33 import javax.swing.Box;
34 import javax.swing.ButtonGroup;
35 import javax.swing.Icon;
36 import javax.swing.JApplet;
37 import javax.swing.JButton;
38 import javax.swing.JComponent;
39 import javax.swing.JFrame;
40 import javax.swing.JLabel;
41 import javax.swing.JMenuBar;
42 import javax.swing.JPanel;
43 import javax.swing.JRadioButton;
44 import javax.swing.plaf.basic.BasicLabelUI;
45
46 import org.apache.commons.collections15.Transformer;
47 import org.apache.commons.collections15.TransformerUtils;
48 import org.apache.commons.collections15.functors.ConstantTransformer;
49
50 import edu.uci.ics.jung.algorithms.layout.FRLayout;
51 import edu.uci.ics.jung.algorithms.layout.Layout;
52 import edu.uci.ics.jung.algorithms.layout.StaticLayout;
53 import edu.uci.ics.jung.graph.Graph;
54 import edu.uci.ics.jung.graph.SparseGraph;
55 import edu.uci.ics.jung.graph.util.TestGraphs;
56 import edu.uci.ics.jung.visualization.DefaultVisualizationModel;
57 import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
58 import edu.uci.ics.jung.visualization.Layer;
59 import edu.uci.ics.jung.visualization.VisualizationModel;
60 import edu.uci.ics.jung.visualization.VisualizationViewer;
61 import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
62 import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
63 import edu.uci.ics.jung.visualization.control.LensMagnificationGraphMousePlugin;
64 import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse;
65 import edu.uci.ics.jung.visualization.control.ScalingControl;
66 import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
67 import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
68 import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
69 import edu.uci.ics.jung.visualization.picking.PickedState;
70 import edu.uci.ics.jung.visualization.transform.HyperbolicTransformer;
71 import edu.uci.ics.jung.visualization.transform.LayoutLensSupport;
72 import edu.uci.ics.jung.visualization.transform.LensSupport;
73 import edu.uci.ics.jung.visualization.transform.MagnifyTransformer;
74 import edu.uci.ics.jung.visualization.transform.shape.HyperbolicShapeTransformer;
75 import edu.uci.ics.jung.visualization.transform.shape.MagnifyShapeTransformer;
76 import edu.uci.ics.jung.visualization.transform.shape.ViewLensSupport;
77
78
79
80
81
82
83
84
85
86
87
88
89 @SuppressWarnings("serial")
90 public class LensDemo extends JApplet {
91
92
93
94
95 Graph<String,Number> graph;
96
97 Layout<String,Number> graphLayout;
98
99
100
101
102 Graph<String,Number> grid;
103
104 Layout<String,Number> gridLayout;
105
106
107
108
109 VisualizationViewer<String,Number> vv;
110
111
112
113
114 LensSupport hyperbolicViewSupport;
115
116
117
118 LensSupport magnifyViewSupport;
119
120
121
122
123 LensSupport hyperbolicLayoutSupport;
124
125
126
127 LensSupport magnifyLayoutSupport;
128
129 ScalingControl scaler;
130
131
132
133
134
135
136 public LensDemo() {
137
138
139 graph = TestGraphs.getOneComponentGraph();
140
141 graphLayout = new FRLayout<String,Number>(graph);
142 ((FRLayout)graphLayout).setMaxIterations(1000);
143
144 Dimension preferredSize = new Dimension(600,600);
145 Map<String,Point2D> map = new HashMap<String,Point2D>();
146 Transformer<String,Point2D> vlf =
147 TransformerUtils.mapTransformer(map);
148 grid = this.generateVertexGrid(map, preferredSize, 25);
149 gridLayout = new StaticLayout<String,Number>(grid, vlf, preferredSize);
150
151 final VisualizationModel<String,Number> visualizationModel =
152 new DefaultVisualizationModel<String,Number>(graphLayout, preferredSize);
153 vv = new VisualizationViewer<String,Number>(visualizationModel, preferredSize);
154
155 PickedState<String> ps = vv.getPickedVertexState();
156 PickedState<Number> pes = vv.getPickedEdgeState();
157 vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<String>(ps, Color.red, Color.yellow));
158 vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(pes, Color.black, Color.cyan));
159 vv.setBackground(Color.white);
160
161 vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
162
163 final Transformer<String,Shape> ovals = vv.getRenderContext().getVertexShapeTransformer();
164 final Transformer<String,Shape> squares =
165 new ConstantTransformer(new Rectangle2D.Float(-10,-10,20,20));
166
167
168 vv.setVertexToolTipTransformer(new ToStringLabeller());
169
170 Container content = getContentPane();
171 GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv);
172 content.add(gzsp);
173
174
175
176
177 final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
178
179 vv.setGraphMouse(graphMouse);
180 vv.addKeyListener(graphMouse.getModeKeyListener());
181
182 hyperbolicViewSupport =
183 new ViewLensSupport<String,Number>(vv, new HyperbolicShapeTransformer(vv,
184 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)),
185 new ModalLensGraphMouse());
186 hyperbolicLayoutSupport =
187 new LayoutLensSupport<String,Number>(vv, new HyperbolicTransformer(vv,
188 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT)),
189 new ModalLensGraphMouse());
190 magnifyViewSupport =
191 new ViewLensSupport<String,Number>(vv, new MagnifyShapeTransformer(vv,
192 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)),
193 new ModalLensGraphMouse(new LensMagnificationGraphMousePlugin(1.f, 6.f, .2f)));
194 magnifyLayoutSupport =
195 new LayoutLensSupport<String,Number>(vv, new MagnifyTransformer(vv,
196 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT)),
197 new ModalLensGraphMouse(new LensMagnificationGraphMousePlugin(1.f, 6.f, .2f)));
198 hyperbolicLayoutSupport.getLensTransformer().setLensShape(hyperbolicViewSupport.getLensTransformer().getLensShape());
199 magnifyViewSupport.getLensTransformer().setLensShape(hyperbolicLayoutSupport.getLensTransformer().getLensShape());
200 magnifyLayoutSupport.getLensTransformer().setLensShape(magnifyViewSupport.getLensTransformer().getLensShape());
201
202 final ScalingControl scaler = new CrossoverScalingControl();
203
204 JButton plus = new JButton("+");
205 plus.addActionListener(new ActionListener() {
206 public void actionPerformed(ActionEvent e) {
207 scaler.scale(vv, 1.1f, vv.getCenter());
208 }
209 });
210 JButton minus = new JButton("-");
211 minus.addActionListener(new ActionListener() {
212 public void actionPerformed(ActionEvent e) {
213 scaler.scale(vv, 1/1.1f, vv.getCenter());
214 }
215 });
216
217 ButtonGroup radio = new ButtonGroup();
218 JRadioButton normal = new JRadioButton("None");
219 normal.addItemListener(new ItemListener() {
220 public void itemStateChanged(ItemEvent e) {
221 if(e.getStateChange() == ItemEvent.SELECTED) {
222 if(hyperbolicViewSupport != null) {
223 hyperbolicViewSupport.deactivate();
224 }
225 if(hyperbolicLayoutSupport != null) {
226 hyperbolicLayoutSupport.deactivate();
227 }
228 if(magnifyViewSupport != null) {
229 magnifyViewSupport.deactivate();
230 }
231 if(magnifyLayoutSupport != null) {
232 magnifyLayoutSupport.deactivate();
233 }
234 }
235 }
236 });
237
238 final JRadioButton hyperView = new JRadioButton("Hyperbolic View");
239 hyperView.addItemListener(new ItemListener(){
240 public void itemStateChanged(ItemEvent e) {
241 hyperbolicViewSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
242 }
243 });
244 final JRadioButton hyperModel = new JRadioButton("Hyperbolic Layout");
245 hyperModel.addItemListener(new ItemListener(){
246 public void itemStateChanged(ItemEvent e) {
247 hyperbolicLayoutSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
248 }
249 });
250 final JRadioButton magnifyView = new JRadioButton("Magnified View");
251 magnifyView.addItemListener(new ItemListener(){
252 public void itemStateChanged(ItemEvent e) {
253 magnifyViewSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
254 }
255 });
256 final JRadioButton magnifyModel = new JRadioButton("Magnified Layout");
257 magnifyModel.addItemListener(new ItemListener(){
258 public void itemStateChanged(ItemEvent e) {
259 magnifyLayoutSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
260 }
261 });
262 JLabel modeLabel = new JLabel(" Mode Menu >>");
263 modeLabel.setUI(new VerticalLabelUI(false));
264 radio.add(normal);
265 radio.add(hyperModel);
266 radio.add(hyperView);
267 radio.add(magnifyModel);
268 radio.add(magnifyView);
269 normal.setSelected(true);
270
271 graphMouse.addItemListener(hyperbolicLayoutSupport.getGraphMouse().getModeListener());
272 graphMouse.addItemListener(hyperbolicViewSupport.getGraphMouse().getModeListener());
273 graphMouse.addItemListener(magnifyLayoutSupport.getGraphMouse().getModeListener());
274 graphMouse.addItemListener(magnifyViewSupport.getGraphMouse().getModeListener());
275
276 ButtonGroup graphRadio = new ButtonGroup();
277 JRadioButton graphButton = new JRadioButton("Graph");
278 graphButton.setSelected(true);
279 graphButton.addItemListener(new ItemListener() {
280
281 public void itemStateChanged(ItemEvent e) {
282 if(e.getStateChange() == ItemEvent.SELECTED) {
283 visualizationModel.setGraphLayout(graphLayout);
284 vv.getRenderContext().setVertexShapeTransformer(ovals);
285 vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
286 vv.repaint();
287 }
288 }});
289 JRadioButton gridButton = new JRadioButton("Grid");
290 gridButton.addItemListener(new ItemListener() {
291
292 public void itemStateChanged(ItemEvent e) {
293 if(e.getStateChange() == ItemEvent.SELECTED) {
294 visualizationModel.setGraphLayout(gridLayout);
295 vv.getRenderContext().setVertexShapeTransformer(squares);
296 vv.getRenderContext().setVertexLabelTransformer(new ConstantTransformer(null));
297 vv.repaint();
298 }
299 }});
300 graphRadio.add(graphButton);
301 graphRadio.add(gridButton);
302
303 JPanel modePanel = new JPanel(new GridLayout(3,1));
304 modePanel.setBorder(BorderFactory.createTitledBorder("Display"));
305 modePanel.add(graphButton);
306 modePanel.add(gridButton);
307
308 JMenuBar menubar = new JMenuBar();
309 menubar.add(graphMouse.getModeMenu());
310 gzsp.setCorner(menubar);
311
312
313 Box controls = Box.createHorizontalBox();
314 JPanel zoomControls = new JPanel(new GridLayout(2,1));
315 zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom"));
316 JPanel hyperControls = new JPanel(new GridLayout(3,2));
317 hyperControls.setBorder(BorderFactory.createTitledBorder("Examiner Lens"));
318 zoomControls.add(plus);
319 zoomControls.add(minus);
320
321 hyperControls.add(normal);
322 hyperControls.add(new JLabel());
323
324 hyperControls.add(hyperModel);
325 hyperControls.add(magnifyModel);
326
327 hyperControls.add(hyperView);
328 hyperControls.add(magnifyView);
329
330 controls.add(zoomControls);
331 controls.add(hyperControls);
332 controls.add(modePanel);
333 controls.add(modeLabel);
334 content.add(controls, BorderLayout.SOUTH);
335 }
336
337 private Graph<String,Number> generateVertexGrid(Map<String,Point2D> vlf,
338 Dimension d, int interval) {
339 int count = d.width/interval * d.height/interval;
340 Graph<String,Number> graph = new SparseGraph<String,Number>();
341 for(int i=0; i<count; i++) {
342 int x = interval*i;
343 int y = x / d.width * interval;
344 x %= d.width;
345
346 Point2D location = new Point2D.Float(x, y);
347 String vertex = "v"+i;
348 vlf.put(vertex, location);
349 graph.addVertex(vertex);
350 }
351 return graph;
352 }
353
354 static class VerticalLabelUI extends BasicLabelUI
355 {
356 static {
357 labelUI = new VerticalLabelUI(false);
358 }
359
360 protected boolean clockwise;
361 VerticalLabelUI( boolean clockwise )
362 {
363 super();
364 this.clockwise = clockwise;
365 }
366
367
368 public Dimension getPreferredSize(JComponent c)
369 {
370 Dimension dim = super.getPreferredSize(c);
371 return new Dimension( dim.height, dim.width );
372 }
373
374 private static Rectangle paintIconR = new Rectangle();
375 private static Rectangle paintTextR = new Rectangle();
376 private static Rectangle paintViewR = new Rectangle();
377 private static Insets paintViewInsets = new Insets(0, 0, 0, 0);
378
379 public void paint(Graphics g, JComponent c)
380 {
381
382
383 JLabel label = (JLabel)c;
384 String text = label.getText();
385 Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();
386
387 if ((icon == null) && (text == null)) {
388 return;
389 }
390
391 FontMetrics fm = g.getFontMetrics();
392 paintViewInsets = c.getInsets(paintViewInsets);
393
394 paintViewR.x = paintViewInsets.left;
395 paintViewR.y = paintViewInsets.top;
396
397
398 paintViewR.height = c.getWidth() - (paintViewInsets.left + paintViewInsets.right);
399 paintViewR.width = c.getHeight() - (paintViewInsets.top + paintViewInsets.bottom);
400
401 paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
402 paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;
403
404 String clippedText =
405 layoutCL(label, fm, text, icon, paintViewR, paintIconR, paintTextR);
406
407 Graphics2D g2 = (Graphics2D) g;
408 AffineTransform tr = g2.getTransform();
409 if( clockwise )
410 {
411 g2.rotate( Math.PI / 2 );
412 g2.translate( 0, - c.getWidth() );
413 }
414 else
415 {
416 g2.rotate( - Math.PI / 2 );
417 g2.translate( - c.getHeight(), 0 );
418 }
419
420 if (icon != null) {
421 icon.paintIcon(c, g, paintIconR.x, paintIconR.y);
422 }
423
424 if (text != null) {
425 int textX = paintTextR.x;
426 int textY = paintTextR.y + fm.getAscent();
427
428 if (label.isEnabled()) {
429 paintEnabledText(label, g, clippedText, textX, textY);
430 }
431 else {
432 paintDisabledText(label, g, clippedText, textX, textY);
433 }
434 }
435
436
437 g2.setTransform( tr );
438 }
439 }
440
441
442
443
444
445
446
447 public static void main(String[] args) {
448 JFrame f = new JFrame();
449 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
450 f.getContentPane().add(new LensDemo());
451 f.pack();
452 f.setVisible(true);
453 }
454 }