1
2
3
4
5
6
7
8
9
10
11 package edu.uci.ics.jung.samples;
12
13 import java.awt.BasicStroke;
14 import java.awt.BorderLayout;
15 import java.awt.Color;
16 import java.awt.Component;
17 import java.awt.Dimension;
18 import java.awt.Font;
19 import java.awt.GradientPaint;
20 import java.awt.GridLayout;
21 import java.awt.Paint;
22 import java.awt.Shape;
23 import java.awt.Stroke;
24 import java.awt.event.ActionEvent;
25 import java.awt.event.ActionListener;
26 import java.awt.event.ItemEvent;
27 import java.awt.event.ItemListener;
28 import java.awt.event.MouseEvent;
29 import java.awt.event.MouseListener;
30 import java.awt.geom.Point2D;
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.Map;
35 import java.util.Set;
36
37 import javax.swing.AbstractAction;
38 import javax.swing.AbstractButton;
39 import javax.swing.BorderFactory;
40 import javax.swing.Box;
41 import javax.swing.ButtonGroup;
42 import javax.swing.JApplet;
43 import javax.swing.JButton;
44 import javax.swing.JCheckBox;
45 import javax.swing.JComboBox;
46 import javax.swing.JFrame;
47 import javax.swing.JPanel;
48 import javax.swing.JPopupMenu;
49 import javax.swing.JRadioButton;
50
51 import org.apache.commons.collections15.Factory;
52 import org.apache.commons.collections15.Predicate;
53 import org.apache.commons.collections15.Transformer;
54 import org.apache.commons.collections15.functors.ConstantTransformer;
55 import org.apache.commons.collections15.functors.MapTransformer;
56
57 import edu.uci.ics.jung.algorithms.generators.random.MixedRandomGraphGenerator;
58 import edu.uci.ics.jung.algorithms.layout.FRLayout;
59 import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
60 import edu.uci.ics.jung.algorithms.layout.Layout;
61 import edu.uci.ics.jung.algorithms.scoring.VoltageScorer;
62 import edu.uci.ics.jung.algorithms.scoring.util.VertexScoreTransformer;
63 import edu.uci.ics.jung.algorithms.util.SelfLoopEdgePredicate;
64 import edu.uci.ics.jung.graph.Graph;
65 import edu.uci.ics.jung.graph.SparseMultigraph;
66 import edu.uci.ics.jung.graph.util.Context;
67 import edu.uci.ics.jung.graph.util.EdgeType;
68 import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
69 import edu.uci.ics.jung.visualization.RenderContext;
70 import edu.uci.ics.jung.visualization.VisualizationViewer;
71 import edu.uci.ics.jung.visualization.control.AbstractPopupGraphMousePlugin;
72 import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
73 import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
74 import edu.uci.ics.jung.visualization.control.ScalingControl;
75 import edu.uci.ics.jung.visualization.decorators.AbstractVertexShapeTransformer;
76 import edu.uci.ics.jung.visualization.decorators.EdgeShape;
77 import edu.uci.ics.jung.visualization.decorators.GradientEdgePaintTransformer;
78 import edu.uci.ics.jung.visualization.decorators.NumberFormattingTransformer;
79 import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
80 import edu.uci.ics.jung.visualization.picking.PickedInfo;
81 import edu.uci.ics.jung.visualization.picking.PickedState;
82 import edu.uci.ics.jung.visualization.renderers.BasicEdgeArrowRenderingSupport;
83 import edu.uci.ics.jung.visualization.renderers.BasicEdgeRenderer;
84 import edu.uci.ics.jung.visualization.renderers.CenterEdgeArrowRenderingSupport;
85 import edu.uci.ics.jung.visualization.renderers.Renderer;
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 @SuppressWarnings("serial")
175 public class PluggableRendererDemo extends JApplet implements ActionListener
176 {
177 protected JCheckBox v_color;
178 protected JCheckBox e_color;
179 protected JCheckBox v_stroke;
180 protected JCheckBox e_uarrow_pred;
181 protected JCheckBox e_darrow_pred;
182 protected JCheckBox e_arrow_centered;
183 protected JCheckBox v_shape;
184 protected JCheckBox v_size;
185 protected JCheckBox v_aspect;
186 protected JCheckBox v_labels;
187 protected JRadioButton e_line;
188 protected JRadioButton e_bent;
189 protected JRadioButton e_wedge;
190 protected JRadioButton e_quad;
191 protected JRadioButton e_ortho;
192 protected JRadioButton e_cubic;
193 protected JCheckBox e_labels;
194 protected JCheckBox font;
195 protected JCheckBox e_show_d;
196 protected JCheckBox e_show_u;
197 protected JCheckBox v_small;
198 protected JCheckBox zoom_at_mouse;
199 protected JCheckBox fill_edges;
200
201 protected JRadioButton no_gradient;
202 protected JRadioButton gradient_relative;
203
204 protected static final int GRADIENT_NONE = 0;
205 protected static final int GRADIENT_RELATIVE = 1;
206 protected static int gradient_level = GRADIENT_NONE;
207
208 protected SeedFillColor<Integer> seedFillColor;
209 protected SeedDrawColor<Integer> seedDrawColor;
210 protected EdgeWeightStrokeFunction<Number> ewcs;
211 protected VertexStrokeHighlight<Integer,Number> vsh;
212 protected Transformer<Integer,String> vs;
213 protected Transformer<Integer,String> vs_none;
214 protected Transformer<Number,String> es;
215 protected Transformer<Number,String> es_none;
216 protected VertexFontTransformer<Integer> vff;
217 protected EdgeFontTransformer<Number> eff;
218 protected VertexShapeSizeAspect<Integer,Number> vssa;
219 protected DirectionDisplayPredicate<Integer,Number> show_edge;
220 protected DirectionDisplayPredicate<Integer,Number> show_arrow;
221 protected VertexDisplayPredicate<Integer,Number> show_vertex;
222 protected Predicate<Context<Graph<Integer,Number>,Number>> self_loop;
223 protected GradientPickedEdgePaintFunction<Integer,Number> edgeDrawPaint;
224 protected GradientPickedEdgePaintFunction<Integer,Number> edgeFillPaint;
225 protected final static Object VOLTAGE_KEY = "voltages";
226 protected final static Object TRANSPARENCY = "transparency";
227
228 protected Map<Number,Number> edge_weight = new HashMap<Number,Number>();
229 protected Transformer<Integer, Double> voltages;
230 protected Map<Integer,Number> transparency = new HashMap<Integer,Number>();
231
232 protected VisualizationViewer<Integer,Number> vv;
233 protected DefaultModalGraphMouse<Integer, Number> gm;
234 protected Set<Integer> seedVertices = new HashSet<Integer>();
235
236 public void start()
237 {
238 getContentPane().add( startFunction() );
239 }
240
241 public static void main(String[] s )
242 {
243 JFrame jf = new JFrame();
244 jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
245 JPanel jp = new PluggableRendererDemo().startFunction();
246 jf.getContentPane().add(jp);
247 jf.pack();
248 jf.setVisible(true);
249 }
250
251
252 public JPanel startFunction() {
253 Graph<Integer,Number> g = getGraph();
254
255 Layout<Integer,Number> layout = new FRLayout<Integer,Number>(g);
256
257 vv = new VisualizationViewer<Integer,Number>(layout);
258
259 PickedState<Integer> picked_state = vv.getPickedVertexState();
260
261
262 self_loop = new SelfLoopEdgePredicate<Integer,Number>();
263
264 seedFillColor = new SeedFillColor<Integer>(picked_state);
265 seedDrawColor = new SeedDrawColor<Integer>(picked_state);
266 ewcs =
267 new EdgeWeightStrokeFunction<Number>(edge_weight);
268 vsh = new VertexStrokeHighlight<Integer,Number>(g, picked_state);
269 vff = new VertexFontTransformer<Integer>();
270 eff = new EdgeFontTransformer<Number>();
271 vs_none = new ConstantTransformer(null);
272 es_none = new ConstantTransformer(null);
273 vssa = new VertexShapeSizeAspect<Integer,Number>(g, voltages);
274 show_edge = new DirectionDisplayPredicate<Integer,Number>(true, true);
275 show_arrow = new DirectionDisplayPredicate<Integer,Number>(true, false);
276 show_vertex = new VertexDisplayPredicate<Integer,Number>(false);
277
278
279 edgeDrawPaint =
280 new GradientPickedEdgePaintFunction<Integer,Number>(
281 new PickableEdgePaintTransformer<Number>(
282 vv.getPickedEdgeState(),Color.black,Color.cyan), vv);
283 edgeFillPaint =
284 new GradientPickedEdgePaintFunction<Integer,Number>(
285 new PickableEdgePaintTransformer<Number>(
286 vv.getPickedEdgeState(),Color.black,Color.cyan), vv);
287
288 vv.getRenderContext().setVertexFillPaintTransformer(seedFillColor);
289 vv.getRenderContext().setVertexDrawPaintTransformer(seedDrawColor);
290 vv.getRenderContext().setVertexStrokeTransformer(vsh);
291 vv.getRenderContext().setVertexLabelTransformer(vs_none);
292 vv.getRenderContext().setVertexFontTransformer(vff);
293 vv.getRenderContext().setVertexShapeTransformer(vssa);
294 vv.getRenderContext().setVertexIncludePredicate(show_vertex);
295
296 vv.getRenderContext().setEdgeDrawPaintTransformer( edgeDrawPaint );
297 vv.getRenderContext().setEdgeLabelTransformer(es_none);
298 vv.getRenderContext().setEdgeFontTransformer(eff);
299 vv.getRenderContext().setEdgeStrokeTransformer(ewcs);
300 vv.getRenderContext().setEdgeIncludePredicate(show_edge);
301 vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<Integer,Number>());
302 vv.getRenderContext().setEdgeArrowPredicate(show_arrow);
303
304 vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
305 vv.getRenderContext().setArrowDrawPaintTransformer(new ConstantTransformer(Color.black));
306 JPanel jp = new JPanel();
307 jp.setLayout(new BorderLayout());
308
309 vv.setBackground(Color.white);
310 GraphZoomScrollPane scrollPane = new GraphZoomScrollPane(vv);
311 jp.add(scrollPane);
312 gm = new DefaultModalGraphMouse<Integer, Number>();
313 vv.setGraphMouse(gm);
314 gm.add(new PopupGraphMousePlugin());
315
316 addBottomControls( jp );
317 vssa.setScaling(true);
318
319 vv.setVertexToolTipTransformer(new VoltageTips<Number>());
320 vv.setToolTipText("<html><center>Use the mouse wheel to zoom<p>Click and Drag the mouse to pan<p>Shift-click and Drag to Rotate</center></html>");
321
322
323
324 return jp;
325 }
326
327
328
329
330
331 public Graph<Integer,Number> getGraph() {
332 Factory<Graph<Integer,Number>> graphFactory =
333 new Factory<Graph<Integer,Number>>() {
334 public Graph<Integer,Number> create() {
335 return new SparseMultigraph<Integer,Number>();
336 }
337 };
338 Factory<Integer> vertexFactory =
339 new Factory<Integer>() {
340 int count;
341 public Integer create() {
342 return count++;
343 }};
344 Factory<Number> edgeFactory =
345 new Factory<Number>() {
346 int count;
347 public Number create() {
348 return count++;
349 }};
350 Graph<Integer,Number> g =
351 MixedRandomGraphGenerator.<Integer,Number>generateMixedRandomGraph(graphFactory, vertexFactory, edgeFactory,
352 edge_weight, 20, false, seedVertices);
353 es = new NumberFormattingTransformer<Number>(MapTransformer.getInstance(edge_weight));
354
355
356
357 if (seedVertices.size() < 2)
358 System.out.println("need at least 2 seeds (one source, one sink)");
359
360
361 boolean source = true;
362 Set<Integer> sources = new HashSet<Integer>();
363 Set<Integer> sinks = new HashSet<Integer>();
364 for(Integer v : seedVertices)
365 {
366 if (source)
367 sources.add(v);
368 else
369 sinks.add(v);
370 source = !source;
371 }
372 VoltageScorer<Integer, Number> voltage_scores =
373 new VoltageScorer<Integer, Number>(g,
374 MapTransformer.getInstance(edge_weight), sources, sinks);
375 voltage_scores.evaluate();
376 voltages = new VertexScoreTransformer<Integer, Double>(voltage_scores);
377 vs = new NumberFormattingTransformer<Integer>(voltages);
378
379 Collection<Integer> verts = g.getVertices();
380
381
382 for(Integer v : verts) {
383 transparency.put(v, new Double(0.9));
384 }
385
386
387 Integer v = verts.iterator().next();
388 Number e = new Float(Math.random());
389 edge_weight.put(e, e);
390 g.addEdge(e, v, v);
391 e = new Float(Math.random());
392 edge_weight.put(e, e);
393 g.addEdge(e, v, v);
394 return g;
395 }
396
397
398
399
400 @SuppressWarnings("serial")
401 protected void addBottomControls(final JPanel jp)
402 {
403 final JPanel control_panel = new JPanel();
404 jp.add(control_panel, BorderLayout.EAST);
405 control_panel.setLayout(new BorderLayout());
406 final Box vertex_panel = Box.createVerticalBox();
407 vertex_panel.setBorder(BorderFactory.createTitledBorder("Vertices"));
408 final Box edge_panel = Box.createVerticalBox();
409 edge_panel.setBorder(BorderFactory.createTitledBorder("Edges"));
410 final Box both_panel = Box.createVerticalBox();
411
412 control_panel.add(vertex_panel, BorderLayout.NORTH);
413 control_panel.add(edge_panel, BorderLayout.SOUTH);
414 control_panel.add(both_panel, BorderLayout.CENTER);
415
416
417 v_color = new JCheckBox("seed highlight");
418 v_color.addActionListener(this);
419 v_stroke = new JCheckBox("stroke highlight on selection");
420 v_stroke.addActionListener(this);
421 v_labels = new JCheckBox("show voltage values");
422 v_labels.addActionListener(this);
423 v_shape = new JCheckBox("shape by degree");
424 v_shape.addActionListener(this);
425 v_size = new JCheckBox("size by voltage");
426 v_size.addActionListener(this);
427 v_size.setSelected(true);
428 v_aspect = new JCheckBox("stretch by degree ratio");
429 v_aspect.addActionListener(this);
430 v_small = new JCheckBox("filter when degree < " + VertexDisplayPredicate.MIN_DEGREE);
431 v_small.addActionListener(this);
432
433 vertex_panel.add(v_color);
434 vertex_panel.add(v_stroke);
435 vertex_panel.add(v_labels);
436 vertex_panel.add(v_shape);
437 vertex_panel.add(v_size);
438 vertex_panel.add(v_aspect);
439 vertex_panel.add(v_small);
440
441
442 JPanel gradient_panel = new JPanel(new GridLayout(1, 0));
443 gradient_panel.setBorder(BorderFactory.createTitledBorder("Edge paint"));
444 no_gradient = new JRadioButton("Solid color");
445 no_gradient.addActionListener(this);
446 no_gradient.setSelected(true);
447
448
449 gradient_relative = new JRadioButton("Gradient");
450 gradient_relative.addActionListener(this);
451 ButtonGroup bg_grad = new ButtonGroup();
452 bg_grad.add(no_gradient);
453 bg_grad.add(gradient_relative);
454
455 gradient_panel.add(no_gradient);
456
457 gradient_panel.add(gradient_relative);
458
459 JPanel shape_panel = new JPanel(new GridLayout(3,2));
460 shape_panel.setBorder(BorderFactory.createTitledBorder("Edge shape"));
461 e_line = new JRadioButton("line");
462 e_line.addActionListener(this);
463 e_line.setSelected(true);
464
465
466 e_wedge = new JRadioButton("wedge");
467 e_wedge.addActionListener(this);
468 e_quad = new JRadioButton("quad curve");
469 e_quad.addActionListener(this);
470 e_cubic = new JRadioButton("cubic curve");
471 e_cubic.addActionListener(this);
472 e_ortho = new JRadioButton("orthogonal");
473 e_ortho.addActionListener(this);
474 ButtonGroup bg_shape = new ButtonGroup();
475 bg_shape.add(e_line);
476
477 bg_shape.add(e_wedge);
478 bg_shape.add(e_quad);
479 bg_shape.add(e_ortho);
480 bg_shape.add(e_cubic);
481 shape_panel.add(e_line);
482
483 shape_panel.add(e_wedge);
484 shape_panel.add(e_quad);
485 shape_panel.add(e_cubic);
486 shape_panel.add(e_ortho);
487 fill_edges = new JCheckBox("fill edge shapes");
488 fill_edges.setSelected(false);
489 fill_edges.addActionListener(this);
490 shape_panel.add(fill_edges);
491 shape_panel.setOpaque(true);
492 e_color = new JCheckBox("highlight edge weights");
493 e_color.addActionListener(this);
494 e_labels = new JCheckBox("show edge weight values");
495 e_labels.addActionListener(this);
496 e_uarrow_pred = new JCheckBox("undirected");
497 e_uarrow_pred.addActionListener(this);
498 e_darrow_pred = new JCheckBox("directed");
499 e_darrow_pred.addActionListener(this);
500 e_darrow_pred.setSelected(true);
501 e_arrow_centered = new JCheckBox("centered");
502 e_arrow_centered.addActionListener(this);
503 JPanel arrow_panel = new JPanel(new GridLayout(1,0));
504 arrow_panel.setBorder(BorderFactory.createTitledBorder("Show arrows"));
505 arrow_panel.add(e_uarrow_pred);
506 arrow_panel.add(e_darrow_pred);
507 arrow_panel.add(e_arrow_centered);
508
509 e_show_d = new JCheckBox("directed");
510 e_show_d.addActionListener(this);
511 e_show_d.setSelected(true);
512 e_show_u = new JCheckBox("undirected");
513 e_show_u.addActionListener(this);
514 e_show_u.setSelected(true);
515 JPanel show_edge_panel = new JPanel(new GridLayout(1,0));
516 show_edge_panel.setBorder(BorderFactory.createTitledBorder("Show edges"));
517 show_edge_panel.add(e_show_u);
518 show_edge_panel.add(e_show_d);
519
520 shape_panel.setAlignmentX(Component.LEFT_ALIGNMENT);
521 edge_panel.add(shape_panel);
522 gradient_panel.setAlignmentX(Component.LEFT_ALIGNMENT);
523 edge_panel.add(gradient_panel);
524 show_edge_panel.setAlignmentX(Component.LEFT_ALIGNMENT);
525 edge_panel.add(show_edge_panel);
526 arrow_panel.setAlignmentX(Component.LEFT_ALIGNMENT);
527 edge_panel.add(arrow_panel);
528
529 e_color.setAlignmentX(Component.LEFT_ALIGNMENT);
530 edge_panel.add(e_color);
531 e_labels.setAlignmentX(Component.LEFT_ALIGNMENT);
532 edge_panel.add(e_labels);
533
534
535 zoom_at_mouse = new JCheckBox("<html><center>zoom at mouse<p>(wheel only)</center></html>");
536 zoom_at_mouse.addActionListener(this);
537 zoom_at_mouse.setSelected(true);
538
539 final ScalingControl scaler = new CrossoverScalingControl();
540
541 JButton plus = new JButton("+");
542 plus.addActionListener(new ActionListener() {
543 public void actionPerformed(ActionEvent e) {
544 scaler.scale(vv, 1.1f, vv.getCenter());
545 }
546 });
547 JButton minus = new JButton("-");
548 minus.addActionListener(new ActionListener() {
549 public void actionPerformed(ActionEvent e) {
550 scaler.scale(vv, 1/1.1f, vv.getCenter());
551 }
552 });
553
554 JPanel zoomPanel = new JPanel();
555 zoomPanel.setBorder(BorderFactory.createTitledBorder("Zoom"));
556 plus.setAlignmentX(Component.CENTER_ALIGNMENT);
557 zoomPanel.add(plus);
558 minus.setAlignmentX(Component.CENTER_ALIGNMENT);
559 zoomPanel.add(minus);
560 zoom_at_mouse.setAlignmentX(Component.CENTER_ALIGNMENT);
561 zoomPanel.add(zoom_at_mouse);
562
563 JPanel fontPanel = new JPanel();
564
565 font = new JCheckBox("bold text");
566 font.addActionListener(this);
567 font.setAlignmentX(Component.CENTER_ALIGNMENT);
568 fontPanel.add(font);
569
570 both_panel.add(zoomPanel);
571 both_panel.add(fontPanel);
572
573 JComboBox modeBox = gm.getModeComboBox();
574 modeBox.setAlignmentX(Component.CENTER_ALIGNMENT);
575 JPanel modePanel = new JPanel(new BorderLayout()) {
576 public Dimension getMaximumSize() {
577 return getPreferredSize();
578 }
579 };
580 modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode"));
581 modePanel.add(modeBox);
582 JPanel comboGrid = new JPanel(new GridLayout(0,1));
583 comboGrid.add(modePanel);
584 fontPanel.add(comboGrid);
585
586
587 JComboBox cb = new JComboBox();
588 cb.addItem(Renderer.VertexLabel.Position.N);
589 cb.addItem(Renderer.VertexLabel.Position.NE);
590 cb.addItem(Renderer.VertexLabel.Position.E);
591 cb.addItem(Renderer.VertexLabel.Position.SE);
592 cb.addItem(Renderer.VertexLabel.Position.S);
593 cb.addItem(Renderer.VertexLabel.Position.SW);
594 cb.addItem(Renderer.VertexLabel.Position.W);
595 cb.addItem(Renderer.VertexLabel.Position.NW);
596 cb.addItem(Renderer.VertexLabel.Position.N);
597 cb.addItem(Renderer.VertexLabel.Position.CNTR);
598 cb.addItem(Renderer.VertexLabel.Position.AUTO);
599 cb.addItemListener(new ItemListener() {
600 public void itemStateChanged(ItemEvent e) {
601 Renderer.VertexLabel.Position position =
602 (Renderer.VertexLabel.Position)e.getItem();
603 vv.getRenderer().getVertexLabelRenderer().setPosition(position);
604 vv.repaint();
605 }});
606 cb.setSelectedItem(Renderer.VertexLabel.Position.SE);
607 JPanel positionPanel = new JPanel();
608 positionPanel.setBorder(BorderFactory.createTitledBorder("Label Position"));
609 positionPanel.add(cb);
610
611 comboGrid.add(positionPanel);
612
613 }
614
615 public void actionPerformed(ActionEvent e)
616 {
617 AbstractButton source = (AbstractButton)e.getSource();
618 if (source == v_color)
619 {
620 seedDrawColor.setSeedColoring(source.isSelected());
621 seedFillColor.setSeedColoring(source.isSelected());
622 }
623 else if (source == e_color)
624 {
625 ewcs.setWeighted(source.isSelected());
626 }
627 else if (source == v_stroke)
628 {
629 vsh.setHighlight(source.isSelected());
630 }
631 else if (source == v_labels)
632 {
633 if (source.isSelected())
634 vv.getRenderContext().setVertexLabelTransformer(vs);
635 else
636 vv.getRenderContext().setVertexLabelTransformer(vs_none);
637 }
638 else if (source == e_labels)
639 {
640 if (source.isSelected())
641 vv.getRenderContext().setEdgeLabelTransformer(es);
642 else
643 vv.getRenderContext().setEdgeLabelTransformer(es_none);
644 }
645 else if (source == e_uarrow_pred)
646 {
647 show_arrow.showUndirected(source.isSelected());
648 }
649 else if (source == e_darrow_pred)
650 {
651 show_arrow.showDirected(source.isSelected());
652 }
653 else if (source == e_arrow_centered)
654 {
655 if(source.isSelected())
656 {
657 vv.getRenderer().getEdgeRenderer().setEdgeArrowRenderingSupport(new CenterEdgeArrowRenderingSupport());
658 }
659 else
660 {
661 vv.getRenderer().getEdgeRenderer().setEdgeArrowRenderingSupport(new BasicEdgeArrowRenderingSupport());
662 }
663 }
664 else if (source == font)
665 {
666 vff.setBold(source.isSelected());
667 eff.setBold(source.isSelected());
668 }
669 else if (source == v_shape)
670 {
671 vssa.useFunnyShapes(source.isSelected());
672 }
673 else if (source == v_size)
674 {
675 vssa.setScaling(source.isSelected());
676 }
677 else if (source == v_aspect)
678 {
679 vssa.setStretching(source.isSelected());
680 }
681 else if (source == e_line)
682 {
683 if(source.isSelected())
684 {
685 vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<Integer,Number>());
686 }
687 }
688 else if (source == e_ortho)
689 {
690 if (source.isSelected())
691 vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Orthogonal<Integer,Number>());
692 }
693 else if (source == e_wedge)
694 {
695 if (source.isSelected())
696 vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Wedge<Integer,Number>(10));
697 }
698
699
700
701
702
703
704
705 else if (source == e_quad)
706 {
707 if(source.isSelected())
708 {
709 vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.QuadCurve<Integer,Number>());
710 }
711 }
712 else if (source == e_cubic)
713 {
714 if(source.isSelected())
715 {
716 vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.CubicCurve<Integer,Number>());
717 }
718 }
719 else if (source == e_show_d)
720 {
721 show_edge.showDirected(source.isSelected());
722 }
723 else if (source == e_show_u)
724 {
725 show_edge.showUndirected(source.isSelected());
726 }
727 else if (source == v_small)
728 {
729 show_vertex.filterSmall(source.isSelected());
730 }
731 else if(source == zoom_at_mouse)
732 {
733 gm.setZoomAtMouse(source.isSelected());
734 }
735 else if (source == no_gradient) {
736 if (source.isSelected()) {
737 gradient_level = GRADIENT_NONE;
738 }
739
740
741
742
743 }
744 else if (source == gradient_relative) {
745 if (source.isSelected()) {
746 gradient_level = GRADIENT_RELATIVE;
747 }
748 }
749 else if (source == fill_edges)
750 {
751 if(source.isSelected()) {
752 vv.getRenderContext().setEdgeFillPaintTransformer( edgeFillPaint );
753 } else {
754 vv.getRenderContext().setEdgeFillPaintTransformer( new ConstantTransformer(null) );
755 }
756
757 }
758 vv.repaint();
759 }
760
761 private final class SeedDrawColor<V> implements Transformer<V,Paint>
762 {
763 protected PickedInfo<V> pi;
764 protected final static float dark_value = 0.8f;
765 protected final static float light_value = 0.2f;
766 protected boolean seed_coloring;
767
768 public SeedDrawColor(PickedInfo<V> pi)
769 {
770 this.pi = pi;
771 seed_coloring = false;
772 }
773
774 public void setSeedColoring(boolean b)
775 {
776 this.seed_coloring = b;
777 }
778
779 public Paint transform(V v)
780 {
781 return Color.BLACK;
782 }
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804 }
805
806 private final class SeedFillColor<V> implements Transformer<V,Paint>
807 {
808 protected PickedInfo<V> pi;
809 protected final static float dark_value = 0.8f;
810 protected final static float light_value = 0.2f;
811 protected boolean seed_coloring;
812
813 public SeedFillColor(PickedInfo<V> pi)
814 {
815 this.pi = pi;
816 seed_coloring = false;
817 }
818
819 public void setSeedColoring(boolean b)
820 {
821 this.seed_coloring = b;
822 }
823
824
825
826
827
828
829 public Paint transform(V v)
830 {
831 float alpha = transparency.get(v).floatValue();
832 if (pi.isPicked(v))
833 {
834 return new Color(1f, 1f, 0, alpha);
835 }
836 else
837 {
838 if (seed_coloring && seedVertices.contains(v))
839 {
840 Color dark = new Color(0, 0, dark_value, alpha);
841 Color light = new Color(0, 0, light_value, alpha);
842 return new GradientPaint( 0, 0, dark, 10, 0, light, true);
843 }
844 else
845 return new Color(1f, 0, 0, alpha);
846 }
847
848 }
849 }
850
851 private final static class EdgeWeightStrokeFunction<E>
852 implements Transformer<E,Stroke>
853 {
854 protected static final Stroke basic = new BasicStroke(1);
855 protected static final Stroke heavy = new BasicStroke(2);
856 protected static final Stroke dotted = RenderContext.DOTTED;
857
858 protected boolean weighted = false;
859 protected Map<E,Number> edge_weight;
860
861 public EdgeWeightStrokeFunction(Map<E,Number> edge_weight)
862 {
863 this.edge_weight = edge_weight;
864 }
865
866 public void setWeighted(boolean weighted)
867 {
868 this.weighted = weighted;
869 }
870
871 public Stroke transform(E e)
872 {
873 if (weighted)
874 {
875 if (drawHeavy(e))
876 return heavy;
877 else
878 return dotted;
879 }
880 else
881 return basic;
882 }
883
884 protected boolean drawHeavy(E e)
885 {
886 double value = edge_weight.get(e).doubleValue();
887 if (value > 0.7)
888 return true;
889 else
890 return false;
891 }
892
893 }
894
895 private final static class VertexStrokeHighlight<V,E> implements
896 Transformer<V,Stroke>
897 {
898 protected boolean highlight = false;
899 protected Stroke heavy = new BasicStroke(5);
900 protected Stroke medium = new BasicStroke(3);
901 protected Stroke light = new BasicStroke(1);
902 protected PickedInfo<V> pi;
903 protected Graph<V,E> graph;
904
905 public VertexStrokeHighlight(Graph<V,E> graph, PickedInfo<V> pi)
906 {
907 this.graph = graph;
908 this.pi = pi;
909 }
910
911 public void setHighlight(boolean highlight)
912 {
913 this.highlight = highlight;
914 }
915
916 public Stroke transform(V v)
917 {
918 if (highlight)
919 {
920 if (pi.isPicked(v))
921 return heavy;
922 else
923 {
924 for(V w : graph.getNeighbors(v)) {
925
926
927
928 if (pi.isPicked(w))
929 return medium;
930 }
931 return light;
932 }
933 }
934 else
935 return light;
936 }
937
938 }
939
940 private final static class VertexFontTransformer<V>
941 implements Transformer<V,Font>
942 {
943 protected boolean bold = false;
944 Font f = new Font("Helvetica", Font.PLAIN, 12);
945 Font b = new Font("Helvetica", Font.BOLD, 12);
946
947 public void setBold(boolean bold)
948 {
949 this.bold = bold;
950 }
951
952 public Font transform(V v)
953 {
954 if (bold)
955 return b;
956 else
957 return f;
958 }
959 }
960
961 private final static class EdgeFontTransformer<E>
962 implements Transformer<E,Font>
963 {
964 protected boolean bold = false;
965 Font f = new Font("Helvetica", Font.PLAIN, 12);
966 Font b = new Font("Helvetica", Font.BOLD, 12);
967
968 public void setBold(boolean bold)
969 {
970 this.bold = bold;
971 }
972
973 public Font transform(E e)
974 {
975 if (bold)
976 return b;
977 else
978 return f;
979 }
980 }
981 private final static class DirectionDisplayPredicate<V,E>
982 implements Predicate<Context<Graph<V,E>,E>>
983
984 {
985 protected boolean show_d;
986 protected boolean show_u;
987
988 public DirectionDisplayPredicate(boolean show_d, boolean show_u)
989 {
990 this.show_d = show_d;
991 this.show_u = show_u;
992 }
993
994 public void showDirected(boolean b)
995 {
996 show_d = b;
997 }
998
999 public void showUndirected(boolean b)
1000 {
1001 show_u = b;
1002 }
1003
1004 public boolean evaluate(Context<Graph<V,E>,E> context)
1005 {
1006 Graph<V,E> graph = context.graph;
1007 E e = context.element;
1008 if (graph.getEdgeType(e) == EdgeType.DIRECTED && show_d) {
1009 return true;
1010 }
1011 if (graph.getEdgeType(e) == EdgeType.UNDIRECTED && show_u) {
1012 return true;
1013 }
1014 return false;
1015 }
1016 }
1017
1018 private final static class VertexDisplayPredicate<V,E>
1019 implements Predicate<Context<Graph<V,E>,V>>
1020
1021 {
1022 protected boolean filter_small;
1023 protected final static int MIN_DEGREE = 4;
1024
1025 public VertexDisplayPredicate(boolean filter)
1026 {
1027 this.filter_small = filter;
1028 }
1029
1030 public void filterSmall(boolean b)
1031 {
1032 filter_small = b;
1033 }
1034
1035 public boolean evaluate(Context<Graph<V,E>,V> context) {
1036 Graph<V,E> graph = context.graph;
1037 V v = context.element;
1038
1039 if (filter_small)
1040 return (graph.degree(v) >= MIN_DEGREE);
1041 else
1042 return true;
1043 }
1044 }
1045
1046
1047
1048
1049
1050
1051 private final static class VertexShapeSizeAspect<V,E>
1052 extends AbstractVertexShapeTransformer <V>
1053 implements Transformer<V,Shape> {
1054
1055 protected boolean stretch = false;
1056 protected boolean scale = false;
1057 protected boolean funny_shapes = false;
1058 protected Transformer<V,Double> voltages;
1059 protected Graph<V,E> graph;
1060
1061
1062 public VertexShapeSizeAspect(Graph<V,E> graphIn, Transformer<V,Double> voltagesIn)
1063 {
1064 this.graph = graphIn;
1065 this.voltages = voltagesIn;
1066 setSizeTransformer(new Transformer<V,Integer>() {
1067
1068 public Integer transform(V v) {
1069 if (scale)
1070 return (int)(voltages.transform(v) * 30) + 20;
1071 else
1072 return 20;
1073
1074 }});
1075 setAspectRatioTransformer(new Transformer<V,Float>() {
1076
1077 public Float transform(V v) {
1078 if (stretch) {
1079 return (float)(graph.inDegree(v) + 1) /
1080 (graph.outDegree(v) + 1);
1081 } else {
1082 return 1.0f;
1083 }
1084 }});
1085 }
1086
1087 public void setStretching(boolean stretch)
1088 {
1089 this.stretch = stretch;
1090 }
1091
1092 public void setScaling(boolean scale)
1093 {
1094 this.scale = scale;
1095 }
1096
1097 public void useFunnyShapes(boolean use)
1098 {
1099 this.funny_shapes = use;
1100 }
1101
1102 public Shape transform(V v)
1103 {
1104 if (funny_shapes)
1105 {
1106 if (graph.degree(v) < 5)
1107 {
1108 int sides = Math.max(graph.degree(v), 3);
1109 return factory.getRegularPolygon(v, sides);
1110 }
1111 else
1112 return factory.getRegularStar(v, graph.degree(v));
1113 }
1114 else
1115 return factory.getEllipse(v);
1116 }
1117 }
1118
1119
1120
1121
1122
1123 protected class PopupGraphMousePlugin extends AbstractPopupGraphMousePlugin
1124 implements MouseListener {
1125
1126 public PopupGraphMousePlugin() {
1127 this(MouseEvent.BUTTON3_MASK);
1128 }
1129 public PopupGraphMousePlugin(int modifiers) {
1130 super(modifiers);
1131 }
1132
1133
1134
1135
1136
1137
1138
1139 @SuppressWarnings("unchecked")
1140 protected void handlePopup(MouseEvent e) {
1141 final VisualizationViewer<Integer,Number> vv =
1142 (VisualizationViewer<Integer,Number>)e.getSource();
1143 Point2D p = e.getPoint();
1144
1145 GraphElementAccessor<Integer,Number> pickSupport = vv.getPickSupport();
1146 if(pickSupport != null) {
1147 final Integer v = pickSupport.getVertex(vv.getGraphLayout(), p.getX(), p.getY());
1148 if(v != null) {
1149 JPopupMenu popup = new JPopupMenu();
1150 popup.add(new AbstractAction("Decrease Transparency") {
1151 public void actionPerformed(ActionEvent e) {
1152 Double value = Math.min(1,
1153 transparency.get(v).doubleValue()+0.1);
1154 transparency.put(v, value);
1155
1156
1157
1158 vv.repaint();
1159 }
1160 });
1161 popup.add(new AbstractAction("Increase Transparency"){
1162 public void actionPerformed(ActionEvent e) {
1163 Double value = Math.max(0,
1164 transparency.get(v).doubleValue()-0.1);
1165 transparency.put(v, value);
1166
1167
1168 vv.repaint();
1169 }
1170 });
1171 popup.show(vv, e.getX(), e.getY());
1172 } else {
1173 final Number edge = pickSupport.getEdge(vv.getGraphLayout(), p.getX(), p.getY());
1174 if(edge != null) {
1175 JPopupMenu popup = new JPopupMenu();
1176 popup.add(new AbstractAction(edge.toString()) {
1177 public void actionPerformed(ActionEvent e) {
1178 System.err.println("got "+edge);
1179 }
1180 });
1181 popup.show(vv, e.getX(), e.getY());
1182
1183 }
1184 }
1185 }
1186 }
1187 }
1188
1189 public class VoltageTips<E>
1190 implements Transformer<Integer,String> {
1191
1192 public String transform(Integer vertex) {
1193 return "Voltage:"+voltages.transform(vertex);
1194 }
1195 }
1196
1197 public class GradientPickedEdgePaintFunction<V,E> extends GradientEdgePaintTransformer<V,E>
1198 {
1199 private Transformer<E,Paint> defaultFunc;
1200 protected boolean fill_edge = false;
1201 Predicate<Context<Graph<V,E>,E>> selfLoop = new SelfLoopEdgePredicate<V,E>();
1202
1203 public GradientPickedEdgePaintFunction(Transformer<E,Paint> defaultEdgePaintFunction,
1204 VisualizationViewer<V,E> vv)
1205 {
1206 super(Color.WHITE, Color.BLACK, vv);
1207 this.defaultFunc = defaultEdgePaintFunction;
1208 }
1209
1210 public void useFill(boolean b)
1211 {
1212 fill_edge = b;
1213 }
1214
1215 public Paint transform(E e) {
1216 if (gradient_level == GRADIENT_NONE) {
1217 return defaultFunc.transform(e);
1218 } else {
1219 return super.transform(e);
1220 }
1221 }
1222
1223 protected Color getColor2(E e)
1224 {
1225 return vv.getPickedEdgeState().isPicked(e)? Color.CYAN : c2;
1226 }
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236 }
1237
1238 }
1239