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 org.apache.commons.collections15.Transformer;
41
42 import edu.uci.ics.jung.algorithms.layout.FRLayout;
43 import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
44 import edu.uci.ics.jung.graph.util.EdgeType;
45 import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
46 import edu.uci.ics.jung.visualization.LayeredIcon;
47 import edu.uci.ics.jung.visualization.VisualizationServer;
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.ScalingControl;
52 import edu.uci.ics.jung.visualization.decorators.DefaultVertexIconTransformer;
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.jai.HyperbolicImageLensSupport;
59 import edu.uci.ics.jung.visualization.picking.PickedState;
60 import edu.uci.ics.jung.visualization.renderers.Checkmark;
61 import edu.uci.ics.jung.visualization.renderers.DefaultEdgeLabelRenderer;
62 import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer;
63 import edu.uci.ics.jung.visualization.transform.LayoutLensSupport;
64 import edu.uci.ics.jung.visualization.transform.LensSupport;
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 HyperbolicVertexImageShaperDemo extends JApplet {
88
89
90
91
92 private static final long serialVersionUID = 5432239991020505763L;
93
94
95
96
97 DirectedSparseMultigraph<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
124
125
126
127
128 public HyperbolicVertexImageShaperDemo() {
129
130
131 graph = new DirectedSparseMultigraph<Number,Number>();
132 Number[] vertices = createVertices(11);
133
134
135 Map<Number,String> map = new HashMap<Number,String>();
136 for(int i=0; i<vertices.length; i++) {
137 map.put(vertices[i], iconNames[i%iconNames.length]);
138 }
139
140
141 Map<Number,Icon> iconMap = new HashMap<Number,Icon>();
142 for(int i=0; i<vertices.length; i++) {
143 String name = "/images/topic"+iconNames[i]+".gif";
144 try {
145 Icon icon =
146 new LayeredIcon(new ImageIcon(HyperbolicVertexImageShaperDemo.class.getResource(name)).getImage());
147 iconMap.put(vertices[i], icon);
148 } catch(Exception ex) {
149 System.err.println("You need slashdoticons.jar in your classpath to see the image "+name);
150 }
151 }
152
153 createEdges(vertices);
154
155 FRLayout<Number, Number> layout = new FRLayout<Number, Number>(graph);
156 layout.setMaxIterations(100);
157 vv = new VisualizationViewer<Number, Number>(layout, new Dimension(400,400));
158
159 Transformer<Number,Paint> vpf =
160 new PickableVertexPaintTransformer<Number>(vv.getPickedVertexState(), Color.white, Color.yellow);
161 vv.getRenderContext().setVertexFillPaintTransformer(vpf);
162 vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(vv.getPickedEdgeState(), Color.black, Color.cyan));
163
164 vv.setBackground(Color.white);
165
166 final Transformer<Number,String> vertexStringerImpl =
167 new VertexStringerImpl<Number>(map);
168 vv.getRenderContext().setVertexLabelTransformer(vertexStringerImpl);
169 vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.cyan));
170 vv.getRenderContext().setEdgeLabelRenderer(new DefaultEdgeLabelRenderer(Color.cyan));
171
172
173
174 final VertexIconShapeTransformer<Number> vertexImageShapeFunction =
175 new VertexIconShapeTransformer<Number>(new EllipseVertexShapeTransformer<Number>());
176
177 final DefaultVertexIconTransformer<Number> vertexIconFunction =
178 new DefaultVertexIconTransformer<Number>();
179
180 vertexImageShapeFunction.setIconMap(iconMap);
181 vertexIconFunction.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 VisualizationServer.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<Number>());
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 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 HyperbolicImageLensSupport<Number,Number>(vv);
265 this.modelSupport = new LayoutLensSupport<Number,Number>(vv);
266
267 graphMouse.addItemListener(modelSupport.getGraphMouse().getModeListener());
268 graphMouse.addItemListener(viewSupport.getGraphMouse().getModeListener());
269
270 ButtonGroup radio = new ButtonGroup();
271 JRadioButton none = new JRadioButton("None");
272 none.addItemListener(new ItemListener(){
273 public void itemStateChanged(ItemEvent e) {
274 if(viewSupport != null) {
275 viewSupport.deactivate();
276 }
277 if(modelSupport != null) {
278 modelSupport.deactivate();
279 }
280 }
281 });
282 none.setSelected(true);
283
284 JRadioButton hyperView = new JRadioButton("View");
285 hyperView.addItemListener(new ItemListener(){
286 public void itemStateChanged(ItemEvent e) {
287 viewSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
288 }
289 });
290
291 JRadioButton hyperModel = new JRadioButton("Layout");
292 hyperModel.addItemListener(new ItemListener(){
293 public void itemStateChanged(ItemEvent e) {
294 modelSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
295 }
296 });
297 radio.add(none);
298 radio.add(hyperView);
299 radio.add(hyperModel);
300
301 JMenuBar menubar = new JMenuBar();
302 JMenu modeMenu = graphMouse.getModeMenu();
303 menubar.add(modeMenu);
304
305 JPanel lensPanel = new JPanel(new GridLayout(2,0));
306 lensPanel.setBorder(BorderFactory.createTitledBorder("Lens"));
307 lensPanel.add(none);
308 lensPanel.add(hyperView);
309 lensPanel.add(hyperModel);
310 controls.add(lensPanel);
311 }
312
313
314
315
316
317
318
319
320
321 class VertexStringerImpl<V> implements Transformer<V,String> {
322
323 Map<V, String> map = new HashMap<V, String>();
324
325 boolean enabled = true;
326
327 public VertexStringerImpl(Map<V,String> map) {
328 this.map = map;
329 }
330
331
332
333
334 public String transform(V v) {
335 if(isEnabled()) {
336 return map.get(v);
337 } else {
338 return "";
339 }
340 }
341
342
343
344
345 public boolean isEnabled() {
346 return enabled;
347 }
348
349
350
351
352 public void setEnabled(boolean enabled) {
353 this.enabled = enabled;
354 }
355 }
356
357
358
359
360
361
362 private Number[] createVertices(int count) {
363 Number[] v = new Number[count];
364 for (int i = 0; i < count; i++) {
365 v[i] = new Integer(i);
366 graph.addVertex(v[i]);
367 }
368 return v;
369 }
370
371
372
373
374
375 void createEdges(Number[] v) {
376 graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED);
377 graph.addEdge(new Double(Math.random()), v[3], v[0], EdgeType.DIRECTED);
378 graph.addEdge(new Double(Math.random()), v[0], v[4], EdgeType.DIRECTED);
379 graph.addEdge(new Double(Math.random()), v[4], v[5], EdgeType.DIRECTED);
380 graph.addEdge(new Double(Math.random()), v[5], v[3], EdgeType.DIRECTED);
381 graph.addEdge(new Double(Math.random()), v[2], v[1], EdgeType.DIRECTED);
382 graph.addEdge(new Double(Math.random()), v[4], v[1], EdgeType.DIRECTED);
383 graph.addEdge(new Double(Math.random()), v[8], v[2], EdgeType.DIRECTED);
384 graph.addEdge(new Double(Math.random()), v[3], v[8], EdgeType.DIRECTED);
385 graph.addEdge(new Double(Math.random()), v[6], v[7], EdgeType.DIRECTED);
386 graph.addEdge(new Double(Math.random()), v[7], v[5], EdgeType.DIRECTED);
387 graph.addEdge(new Double(Math.random()), v[0], v[9], EdgeType.DIRECTED);
388 graph.addEdge(new Double(Math.random()), v[9], v[8], EdgeType.DIRECTED);
389 graph.addEdge(new Double(Math.random()), v[7], v[6], EdgeType.DIRECTED);
390 graph.addEdge(new Double(Math.random()), v[6], v[5], EdgeType.DIRECTED);
391 graph.addEdge(new Double(Math.random()), v[4], v[2], EdgeType.DIRECTED);
392 graph.addEdge(new Double(Math.random()), v[5], v[4], EdgeType.DIRECTED);
393 graph.addEdge(new Double(Math.random()), v[4], v[10], EdgeType.DIRECTED);
394 graph.addEdge(new Double(Math.random()), v[10], v[4], EdgeType.DIRECTED);
395 }
396
397 public static class PickWithIconListener implements ItemListener {
398 DefaultVertexIconTransformer<Number> imager;
399 Icon checked;
400
401 public PickWithIconListener(DefaultVertexIconTransformer<Number> imager) {
402 this.imager = imager;
403 checked = new Checkmark(Color.red);
404 }
405
406 public void itemStateChanged(ItemEvent e) {
407 Icon icon = imager.transform((Number)e.getItem());
408 if(icon != null && icon instanceof LayeredIcon) {
409 if(e.getStateChange() == ItemEvent.SELECTED) {
410 ((LayeredIcon)icon).add(checked);
411 } else {
412 ((LayeredIcon)icon).remove(checked);
413 }
414 }
415 }
416 }
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 HyperbolicVertexImageShaperDemo());
428 frame.pack();
429 frame.setVisible(true);
430 }
431 }