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 com.google.common.base.Function;
47 import com.google.common.base.Functions;
48
49 import edu.uci.ics.jung.algorithms.layout.FRLayout;
50 import edu.uci.ics.jung.algorithms.layout.Layout;
51 import edu.uci.ics.jung.algorithms.layout.StaticLayout;
52 import edu.uci.ics.jung.graph.Graph;
53 import edu.uci.ics.jung.graph.SparseGraph;
54 import edu.uci.ics.jung.graph.util.TestGraphs;
55 import edu.uci.ics.jung.visualization.DefaultVisualizationModel;
56 import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
57 import edu.uci.ics.jung.visualization.Layer;
58 import edu.uci.ics.jung.visualization.VisualizationModel;
59 import edu.uci.ics.jung.visualization.VisualizationViewer;
60 import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
61 import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
62 import edu.uci.ics.jung.visualization.control.LensMagnificationGraphMousePlugin;
63 import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse;
64 import edu.uci.ics.jung.visualization.control.ScalingControl;
65 import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
66 import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
67 import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
68 import edu.uci.ics.jung.visualization.picking.PickedState;
69 import edu.uci.ics.jung.visualization.transform.HyperbolicTransformer;
70 import edu.uci.ics.jung.visualization.transform.LayoutLensSupport;
71 import edu.uci.ics.jung.visualization.transform.LensSupport;
72 import edu.uci.ics.jung.visualization.transform.MagnifyTransformer;
73 import edu.uci.ics.jung.visualization.transform.shape.HyperbolicShapeTransformer;
74 import edu.uci.ics.jung.visualization.transform.shape.MagnifyShapeTransformer;
75 import edu.uci.ics.jung.visualization.transform.shape.ViewLensSupport;
76
77
78
79
80
81
82
83
84
85
86
87
88 @SuppressWarnings("serial")
89 public class LensDemo extends JApplet {
90
91
92
93
94 Graph<String,Number> graph;
95
96 FRLayout<String,Number> graphLayout;
97
98
99
100
101 Graph<String,Number> grid;
102
103 Layout<String,Number> gridLayout;
104
105
106
107
108 VisualizationViewer<String,Number> vv;
109
110
111
112
113 LensSupport hyperbolicViewSupport;
114
115
116
117 LensSupport magnifyViewSupport;
118
119
120
121
122 LensSupport hyperbolicLayoutSupport;
123
124
125
126 LensSupport magnifyLayoutSupport;
127
128 ScalingControl scaler;
129
130
131
132
133
134
135 public LensDemo() {
136
137
138 graph = TestGraphs.getOneComponentGraph();
139
140 graphLayout = new FRLayout<String,Number>(graph);
141 graphLayout.setMaxIterations(1000);
142
143 Dimension preferredSize = new Dimension(600,600);
144 Map<String,Point2D> map = new HashMap<String,Point2D>();
145 Function<String,Point2D> vlf =
146 Functions.forMap(map);
147 grid = this.generateVertexGrid(map, preferredSize, 25);
148 gridLayout = new StaticLayout<String,Number>(grid, vlf, preferredSize);
149
150 final VisualizationModel<String,Number> visualizationModel =
151 new DefaultVisualizationModel<String,Number>(graphLayout, preferredSize);
152 vv = new VisualizationViewer<String,Number>(visualizationModel, preferredSize);
153
154 PickedState<String> ps = vv.getPickedVertexState();
155 PickedState<Number> pes = vv.getPickedEdgeState();
156 vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<String>(ps, Color.red, Color.yellow));
157 vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(pes, Color.black, Color.cyan));
158 vv.setBackground(Color.white);
159
160 vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
161
162 final Function<? super String,Shape> ovals = vv.getRenderContext().getVertexShapeTransformer();
163 final Function<? super String,Shape> squares =
164 Functions.<Shape>constant(new Rectangle2D.Float(-10,-10,20,20));
165
166
167 vv.setVertexToolTipTransformer(new ToStringLabeller());
168
169 Container content = getContentPane();
170 GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv);
171 content.add(gzsp);
172
173
174
175
176 final DefaultModalGraphMouse<String,Number> graphMouse
177 = new DefaultModalGraphMouse<String,Number>();
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(
286 new ToStringLabeller());
287 vv.repaint();
288 }
289 }});
290 JRadioButton gridButton = new JRadioButton("Grid");
291 gridButton.addItemListener(new ItemListener() {
292
293 public void itemStateChanged(ItemEvent e) {
294 if(e.getStateChange() == ItemEvent.SELECTED) {
295 visualizationModel.setGraphLayout(gridLayout);
296 vv.getRenderContext().setVertexShapeTransformer(squares);
297 vv.getRenderContext().setVertexLabelTransformer(Functions.<String>constant(null));
298 vv.repaint();
299 }
300 }});
301 graphRadio.add(graphButton);
302 graphRadio.add(gridButton);
303
304 JPanel modePanel = new JPanel(new GridLayout(3,1));
305 modePanel.setBorder(BorderFactory.createTitledBorder("Display"));
306 modePanel.add(graphButton);
307 modePanel.add(gridButton);
308
309 JMenuBar menubar = new JMenuBar();
310 menubar.add(graphMouse.getModeMenu());
311 gzsp.setCorner(menubar);
312
313
314 Box controls = Box.createHorizontalBox();
315 JPanel zoomControls = new JPanel(new GridLayout(2,1));
316 zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom"));
317 JPanel hyperControls = new JPanel(new GridLayout(3,2));
318 hyperControls.setBorder(BorderFactory.createTitledBorder("Examiner Lens"));
319 zoomControls.add(plus);
320 zoomControls.add(minus);
321
322 hyperControls.add(normal);
323 hyperControls.add(new JLabel());
324
325 hyperControls.add(hyperModel);
326 hyperControls.add(magnifyModel);
327
328 hyperControls.add(hyperView);
329 hyperControls.add(magnifyView);
330
331 controls.add(zoomControls);
332 controls.add(hyperControls);
333 controls.add(modePanel);
334 controls.add(modeLabel);
335 content.add(controls, BorderLayout.SOUTH);
336 }
337
338 private Graph<String,Number> generateVertexGrid(Map<String,Point2D> vlf,
339 Dimension d, int interval) {
340 int count = d.width/interval * d.height/interval;
341 Graph<String,Number> graph = new SparseGraph<String,Number>();
342 for(int i=0; i<count; i++) {
343 int x = interval*i;
344 int y = x / d.width * interval;
345 x %= d.width;
346
347 Point2D location = new Point2D.Float(x, y);
348 String vertex = "v"+i;
349 vlf.put(vertex, location);
350 graph.addVertex(vertex);
351 }
352 return graph;
353 }
354
355 static class VerticalLabelUI extends BasicLabelUI
356 {
357 static {
358 labelUI = new VerticalLabelUI(false);
359 }
360
361 protected boolean clockwise;
362 VerticalLabelUI( boolean clockwise )
363 {
364 super();
365 this.clockwise = clockwise;
366 }
367
368
369 public Dimension getPreferredSize(JComponent c)
370 {
371 Dimension dim = super.getPreferredSize(c);
372 return new Dimension( dim.height, dim.width );
373 }
374
375 private static Rectangle paintIconR = new Rectangle();
376 private static Rectangle paintTextR = new Rectangle();
377 private static Rectangle paintViewR = new Rectangle();
378 private static Insets paintViewInsets = new Insets(0, 0, 0, 0);
379
380 public void paint(Graphics g, JComponent c)
381 {
382
383
384 JLabel label = (JLabel)c;
385 String text = label.getText();
386 Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();
387
388 if ((icon == null) && (text == null)) {
389 return;
390 }
391
392 FontMetrics fm = g.getFontMetrics();
393 paintViewInsets = c.getInsets(paintViewInsets);
394
395 paintViewR.x = paintViewInsets.left;
396 paintViewR.y = paintViewInsets.top;
397
398
399 paintViewR.height = c.getWidth() - (paintViewInsets.left + paintViewInsets.right);
400 paintViewR.width = c.getHeight() - (paintViewInsets.top + paintViewInsets.bottom);
401
402 paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
403 paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;
404
405 String clippedText =
406 layoutCL(label, fm, text, icon, paintViewR, paintIconR, paintTextR);
407
408 Graphics2D g2 = (Graphics2D) g;
409 AffineTransform tr = g2.getTransform();
410 if( clockwise )
411 {
412 g2.rotate( Math.PI / 2 );
413 g2.translate( 0, - c.getWidth() );
414 }
415 else
416 {
417 g2.rotate( - Math.PI / 2 );
418 g2.translate( - c.getHeight(), 0 );
419 }
420
421 if (icon != null) {
422 icon.paintIcon(c, g, paintIconR.x, paintIconR.y);
423 }
424
425 if (text != null) {
426 int textX = paintTextR.x;
427 int textY = paintTextR.y + fm.getAscent();
428
429 if (label.isEnabled()) {
430 paintEnabledText(label, g, clippedText, textX, textY);
431 }
432 else {
433 paintDisabledText(label, g, clippedText, textX, textY);
434 }
435 }
436
437
438 g2.setTransform( tr );
439 }
440 }
441
442 public static void main(String[] args) {
443 JFrame f = new JFrame();
444 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
445 f.getContentPane().add(new LensDemo());
446 f.pack();
447 f.setVisible(true);
448 }
449 }