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.Font;
16 import java.awt.FontMetrics;
17 import java.awt.Graphics;
18 import java.awt.GridLayout;
19 import java.awt.Paint;
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.util.HashMap;
25 import java.util.Map;
26
27 import javax.swing.BorderFactory;
28 import javax.swing.ButtonGroup;
29 import javax.swing.Icon;
30 import javax.swing.ImageIcon;
31 import javax.swing.JApplet;
32 import javax.swing.JButton;
33 import javax.swing.JComboBox;
34 import javax.swing.JFrame;
35 import javax.swing.JMenu;
36 import javax.swing.JMenuBar;
37 import javax.swing.JPanel;
38 import javax.swing.JRadioButton;
39
40 import com.google.common.base.Function;
41 import com.google.common.base.Functions;
42
43 import edu.uci.ics.jung.algorithms.layout.FRLayout;
44 import edu.uci.ics.jung.graph.DirectedSparseGraph;
45 import edu.uci.ics.jung.graph.util.EdgeType;
46 import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
47 import edu.uci.ics.jung.visualization.LayeredIcon;
48 import edu.uci.ics.jung.visualization.VisualizationViewer;
49 import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
50 import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
51 import edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode;
52 import edu.uci.ics.jung.visualization.control.ScalingControl;
53 import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer;
54 import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
55 import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
56 import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
57 import edu.uci.ics.jung.visualization.decorators.VertexIconShapeTransformer;
58 import edu.uci.ics.jung.visualization.picking.PickedState;
59 import edu.uci.ics.jung.visualization.renderers.Checkmark;
60 import edu.uci.ics.jung.visualization.renderers.DefaultEdgeLabelRenderer;
61 import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer;
62 import edu.uci.ics.jung.visualization.transform.LayoutLensSupport;
63 import edu.uci.ics.jung.visualization.transform.LensSupport;
64 import edu.uci.ics.jung.visualization.transform.shape.MagnifyImageLensSupport;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public class LensVertexImageShaperDemo extends JApplet {
88
89
90
91
92 private static final long serialVersionUID = 5432239991020505763L;
93
94
95
96
97 DirectedSparseGraph<Number, Number> graph;
98
99
100
101
102 VisualizationViewer<Number,Number> vv;
103
104
105
106
107 String[] iconNames = {
108 "apple",
109 "os",
110 "x",
111 "linux",
112 "inputdevices",
113 "wireless",
114 "graphics3",
115 "gamespcgames",
116 "humor",
117 "music",
118 "privacy"
119 };
120
121 LensSupport viewSupport;
122 LensSupport modelSupport;
123 LensSupport magnifyLayoutSupport;
124 LensSupport magnifyViewSupport;
125
126
127
128
129
130 public LensVertexImageShaperDemo() {
131
132
133 graph = new DirectedSparseGraph<Number,Number>();
134 Number[] vertices = createVertices(11);
135
136
137 Map<Number,String> map = new HashMap<Number,String>();
138 for(int i=0; i<vertices.length; i++) {
139 map.put(vertices[i], iconNames[i%iconNames.length]);
140 }
141
142
143 Map<Number,Icon> iconMap = new HashMap<Number,Icon>();
144 for(int i=0; i<vertices.length; i++) {
145 String name = "/images/topic"+iconNames[i]+".gif";
146 try {
147 Icon icon =
148 new LayeredIcon(new ImageIcon(LensVertexImageShaperDemo.class.getResource(name)).getImage());
149 iconMap.put(vertices[i], icon);
150 } catch(Exception ex) {
151 System.err.println("You need slashdoticons.jar in your classpath to see the image "+name);
152 }
153 }
154
155 createEdges(vertices);
156
157 FRLayout<Number, Number> layout = new FRLayout<Number, Number>(graph);
158 layout.setMaxIterations(100);
159 vv = new VisualizationViewer<Number, Number>(layout, new Dimension(600,600));
160
161 Function<Number,Paint> vpf =
162 new PickableVertexPaintTransformer<Number>(vv.getPickedVertexState(), Color.white, Color.yellow);
163 vv.getRenderContext().setVertexFillPaintTransformer(vpf);
164 vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(vv.getPickedEdgeState(), Color.black, Color.cyan));
165
166 vv.setBackground(Color.white);
167
168 final Function<Number,String> vertexStringerImpl =
169 new VertexStringerImpl<Number>(map);
170 vv.getRenderContext().setVertexLabelTransformer(vertexStringerImpl);
171 vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.cyan));
172 vv.getRenderContext().setEdgeLabelRenderer(new DefaultEdgeLabelRenderer(Color.cyan));
173
174
175
176 final VertexIconShapeTransformer<Number> vertexImageShapeFunction =
177 new VertexIconShapeTransformer<Number>(new EllipseVertexShapeTransformer<Number>());
178
179 final Function<Number, Icon> vertexIconFunction = Functions.forMap(iconMap);
180
181 vertexImageShapeFunction.setIconMap(iconMap);
182
183 vv.getRenderContext().setVertexShapeTransformer(vertexImageShapeFunction);
184 vv.getRenderContext().setVertexIconTransformer(vertexIconFunction);
185
186
187
188
189 PickedState<Number> ps = vv.getPickedVertexState();
190 ps.addItemListener(new PickWithIconListener(vertexIconFunction));
191
192 vv.addPostRenderPaintable(new VisualizationViewer.Paintable(){
193 int x;
194 int y;
195 Font font;
196 FontMetrics metrics;
197 int swidth;
198 int sheight;
199 String str = "Thank You, slashdot.org, for the images!";
200
201 public void paint(Graphics g) {
202 Dimension d = vv.getSize();
203 if(font == null) {
204 font = new Font(g.getFont().getName(), Font.BOLD, 20);
205 metrics = g.getFontMetrics(font);
206 swidth = metrics.stringWidth(str);
207 sheight = metrics.getMaxAscent()+metrics.getMaxDescent();
208 x = (d.width-swidth)/2;
209 y = (int)(d.height-sheight*1.5);
210 }
211 g.setFont(font);
212 Color oldColor = g.getColor();
213 g.setColor(Color.lightGray);
214 g.drawString(str, x, y);
215 g.setColor(oldColor);
216 }
217 public boolean useTransform() {
218 return false;
219 }
220 });
221
222
223 vv.setVertexToolTipTransformer(new ToStringLabeller());
224
225 Container content = getContentPane();
226 final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
227 content.add(panel);
228
229 final DefaultModalGraphMouse<Number, Number> graphMouse
230 = new DefaultModalGraphMouse<Number, Number>();
231 vv.setGraphMouse(graphMouse);
232
233
234 final ScalingControl scaler = new CrossoverScalingControl();
235
236 JButton plus = new JButton("+");
237 plus.addActionListener(new ActionListener() {
238 public void actionPerformed(ActionEvent e) {
239 scaler.scale(vv, 1.1f, vv.getCenter());
240 }
241 });
242 JButton minus = new JButton("-");
243 minus.addActionListener(new ActionListener() {
244 public void actionPerformed(ActionEvent e) {
245 scaler.scale(vv, 1/1.1f, vv.getCenter());
246 }
247 });
248
249 JComboBox<Mode> modeBox = graphMouse.getModeComboBox();
250 JPanel modePanel = new JPanel();
251 modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode"));
252 modePanel.add(modeBox);
253
254 JPanel scaleGrid = new JPanel(new GridLayout(1,0));
255 scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom"));
256 JPanel controls = new JPanel();
257 scaleGrid.add(plus);
258 scaleGrid.add(minus);
259 controls.add(scaleGrid);
260
261 controls.add(modePanel);
262 content.add(controls, BorderLayout.SOUTH);
263
264 this.viewSupport = new MagnifyImageLensSupport<Number,Number>(vv);
265
266
267
268
269 this.modelSupport = new LayoutLensSupport<Number,Number>(vv);
270
271 graphMouse.addItemListener(modelSupport.getGraphMouse().getModeListener());
272 graphMouse.addItemListener(viewSupport.getGraphMouse().getModeListener());
273
274 ButtonGroup radio = new ButtonGroup();
275 JRadioButton none = new JRadioButton("None");
276 none.addItemListener(new ItemListener(){
277 public void itemStateChanged(ItemEvent e) {
278 if(viewSupport != null) {
279 viewSupport.deactivate();
280 }
281 if(modelSupport != null) {
282 modelSupport.deactivate();
283 }
284 }
285 });
286 none.setSelected(true);
287
288 JRadioButton hyperView = new JRadioButton("View");
289 hyperView.addItemListener(new ItemListener(){
290 public void itemStateChanged(ItemEvent e) {
291 viewSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
292 }
293 });
294
295 JRadioButton hyperModel = new JRadioButton("Layout");
296 hyperModel.addItemListener(new ItemListener(){
297 public void itemStateChanged(ItemEvent e) {
298 modelSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
299 }
300 });
301 radio.add(none);
302 radio.add(hyperView);
303 radio.add(hyperModel);
304
305 JMenuBar menubar = new JMenuBar();
306 JMenu modeMenu = graphMouse.getModeMenu();
307 menubar.add(modeMenu);
308
309 JPanel lensPanel = new JPanel(new GridLayout(2,0));
310 lensPanel.setBorder(BorderFactory.createTitledBorder("Lens"));
311 lensPanel.add(none);
312 lensPanel.add(hyperView);
313 lensPanel.add(hyperModel);
314 controls.add(lensPanel);
315 }
316
317
318
319
320
321
322
323
324
325 class VertexStringerImpl<V> implements Function<V,String> {
326
327 Map<V,String> map = new HashMap<V,String>();
328
329 boolean enabled = true;
330
331 public VertexStringerImpl(Map<V,String> map) {
332 this.map = map;
333 }
334
335
336
337
338 public String apply(V v) {
339 if(isEnabled()) {
340 return map.get(v);
341 } else {
342 return "";
343 }
344 }
345
346
347
348
349 public boolean isEnabled() {
350 return enabled;
351 }
352
353
354
355
356 public void setEnabled(boolean enabled) {
357 this.enabled = enabled;
358 }
359 }
360
361
362
363
364
365
366 private Number[] createVertices(int count) {
367 Number[] v = new Number[count];
368 for (int i = 0; i < count; i++) {
369 v[i] = new Integer(i);
370 graph.addVertex(v[i]);
371 }
372 return v;
373 }
374
375
376
377
378
379 void createEdges(Number[] v) {
380 graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED);
381 graph.addEdge(new Double(Math.random()), v[3], v[0], EdgeType.DIRECTED);
382 graph.addEdge(new Double(Math.random()), v[0], v[4], EdgeType.DIRECTED);
383 graph.addEdge(new Double(Math.random()), v[4], v[5], EdgeType.DIRECTED);
384 graph.addEdge(new Double(Math.random()), v[5], v[3], EdgeType.DIRECTED);
385 graph.addEdge(new Double(Math.random()), v[2], v[1], EdgeType.DIRECTED);
386 graph.addEdge(new Double(Math.random()), v[4], v[1], EdgeType.DIRECTED);
387 graph.addEdge(new Double(Math.random()), v[8], v[2], EdgeType.DIRECTED);
388 graph.addEdge(new Double(Math.random()), v[3], v[8], EdgeType.DIRECTED);
389 graph.addEdge(new Double(Math.random()), v[6], v[7], EdgeType.DIRECTED);
390 graph.addEdge(new Double(Math.random()), v[7], v[5], EdgeType.DIRECTED);
391 graph.addEdge(new Double(Math.random()), v[0], v[9], EdgeType.DIRECTED);
392 graph.addEdge(new Double(Math.random()), v[9], v[8], EdgeType.DIRECTED);
393 graph.addEdge(new Double(Math.random()), v[7], v[6], EdgeType.DIRECTED);
394 graph.addEdge(new Double(Math.random()), v[6], v[5], EdgeType.DIRECTED);
395 graph.addEdge(new Double(Math.random()), v[4], v[2], EdgeType.DIRECTED);
396 graph.addEdge(new Double(Math.random()), v[5], v[4], EdgeType.DIRECTED);
397 graph.addEdge(new Double(Math.random()), v[4], v[10], EdgeType.DIRECTED);
398 graph.addEdge(new Double(Math.random()), v[10], v[4], EdgeType.DIRECTED);
399 }
400
401 public static class PickWithIconListener implements ItemListener {
402 Function<Number, Icon> imager;
403 Icon checked;
404
405 public PickWithIconListener(Function<Number, Icon> imager) {
406 this.imager = imager;
407 checked = new Checkmark(Color.red);
408 }
409
410 public void itemStateChanged(ItemEvent e) {
411 Icon icon = imager.apply((Number)e.getItem());
412 if(icon != null && icon instanceof LayeredIcon) {
413 if(e.getStateChange() == ItemEvent.SELECTED) {
414 ((LayeredIcon)icon).add(checked);
415 } else {
416 ((LayeredIcon)icon).remove(checked);
417 }
418 }
419 }
420 }
421
422 public static void main(String[] args) {
423 JFrame frame = new JFrame();
424 Container content = frame.getContentPane();
425 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
426
427 content.add(new LensVertexImageShaperDemo());
428 frame.pack();
429 frame.setVisible(true);
430 }
431 }