View Javadoc

1   /*
2    * Copyright (c) 2003, the JUNG Project and the Regents of the University of
3    * California All rights reserved.
4    * 
5    * This software is open-source under the BSD license; see either "license.txt"
6    * or http://jung.sourceforge.net/license.txt for a description.
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.GridLayout;
16  import java.awt.event.ActionEvent;
17  import java.awt.event.ActionListener;
18  import java.awt.event.ItemEvent;
19  import java.awt.event.ItemListener;
20  
21  import javax.swing.AbstractButton;
22  import javax.swing.BorderFactory;
23  import javax.swing.BoundedRangeModel;
24  import javax.swing.Box;
25  import javax.swing.ButtonGroup;
26  import javax.swing.DefaultBoundedRangeModel;
27  import javax.swing.JApplet;
28  import javax.swing.JButton;
29  import javax.swing.JCheckBox;
30  import javax.swing.JFrame;
31  import javax.swing.JLabel;
32  import javax.swing.JPanel;
33  import javax.swing.JRadioButton;
34  import javax.swing.JSlider;
35  import javax.swing.event.ChangeEvent;
36  import javax.swing.event.ChangeListener;
37  
38  import org.apache.commons.collections15.Transformer;
39  
40  import edu.uci.ics.jung.algorithms.layout.CircleLayout;
41  import edu.uci.ics.jung.algorithms.layout.Layout;
42  import edu.uci.ics.jung.graph.Graph;
43  import edu.uci.ics.jung.graph.SparseMultigraph;
44  import edu.uci.ics.jung.graph.util.EdgeType;
45  import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
46  import edu.uci.ics.jung.visualization.VisualizationViewer;
47  import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
48  import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
49  import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
50  import edu.uci.ics.jung.visualization.control.ScalingControl;
51  import edu.uci.ics.jung.visualization.decorators.AbstractEdgeShapeTransformer;
52  import edu.uci.ics.jung.visualization.decorators.ConstantDirectionalEdgeValueTransformer;
53  import edu.uci.ics.jung.visualization.decorators.EdgeShape;
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.renderers.EdgeLabelRenderer;
58  import edu.uci.ics.jung.visualization.renderers.VertexLabelRenderer;
59  
60  /**
61   * Demonstrates jung support for drawing edge labels that
62   * can be positioned at any point along the edge, and can
63   * be rotated to be parallel with the edge.
64   * 
65   * @author Tom Nelson
66   * 
67   */
68  public class EdgeLabelDemo extends JApplet {
69  
70      /**
71  	 * 
72  	 */
73  	private static final long serialVersionUID = -6077157664507049647L;
74  
75  	/**
76       * the graph
77       */
78      Graph<Integer,Number> graph;
79  
80      /**
81       * the visual component and renderer for the graph
82       */
83      VisualizationViewer<Integer,Number> vv;
84      
85      /**
86       */
87      VertexLabelRenderer vertexLabelRenderer;
88      EdgeLabelRenderer edgeLabelRenderer;
89      
90      ScalingControl scaler = new CrossoverScalingControl();
91      
92      /**
93       * create an instance of a simple graph with controls to
94       * demo the label positioning features
95       * 
96       */
97      @SuppressWarnings("serial")
98  	public EdgeLabelDemo() {
99          
100         // create a simple graph for the demo
101         graph = new SparseMultigraph<Integer,Number>();
102         Integer[] v = createVertices(3);
103         createEdges(v);
104         
105         Layout<Integer,Number> layout = new CircleLayout<Integer,Number>(graph);
106         vv =  new VisualizationViewer<Integer,Number>(layout, new Dimension(600,400));
107         vv.setBackground(Color.white);
108 
109         vertexLabelRenderer = vv.getRenderContext().getVertexLabelRenderer();
110         edgeLabelRenderer = vv.getRenderContext().getEdgeLabelRenderer();
111         
112         Transformer<Number,String> stringer = new Transformer<Number,String>(){
113             public String transform(Number e) {
114                 return "Edge:"+graph.getEndpoints(e).toString();
115             }
116         };
117         vv.getRenderContext().setEdgeLabelTransformer(stringer);
118         vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(vv.getPickedEdgeState(), Color.black, Color.cyan));
119         vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<Integer>(vv.getPickedVertexState(), Color.red, Color.yellow));
120         // add my listener for ToolTips
121         vv.setVertexToolTipTransformer(new ToStringLabeller<Integer>());
122         
123         // create a frome to hold the graph
124         final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
125         Container content = getContentPane();
126         content.add(panel);
127         
128         final DefaultModalGraphMouse<Integer,Number> graphMouse = new DefaultModalGraphMouse<Integer,Number>();
129         vv.setGraphMouse(graphMouse);
130         
131         JButton plus = new JButton("+");
132         plus.addActionListener(new ActionListener() {
133             public void actionPerformed(ActionEvent e) {
134                 scaler.scale(vv, 1.1f, vv.getCenter());
135             }
136         });
137         JButton minus = new JButton("-");
138         minus.addActionListener(new ActionListener() {
139             public void actionPerformed(ActionEvent e) {
140                 scaler.scale(vv, 1/1.1f, vv.getCenter());
141             }
142         });
143         
144         ButtonGroup radio = new ButtonGroup();
145         JRadioButton lineButton = new JRadioButton("Line");
146         lineButton.addItemListener(new ItemListener(){
147             public void itemStateChanged(ItemEvent e) {
148                 if(e.getStateChange() == ItemEvent.SELECTED) {
149                     vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<Integer,Number>());
150                     vv.repaint();
151                 }
152             }
153         });
154         
155         JRadioButton quadButton = new JRadioButton("QuadCurve");
156         quadButton.addItemListener(new ItemListener(){
157             public void itemStateChanged(ItemEvent e) {
158                 if(e.getStateChange() == ItemEvent.SELECTED) {
159                     vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.QuadCurve<Integer,Number>());
160                     vv.repaint();
161                 }
162             }
163         });
164         
165         JRadioButton cubicButton = new JRadioButton("CubicCurve");
166         cubicButton.addItemListener(new ItemListener(){
167             public void itemStateChanged(ItemEvent e) {
168                 if(e.getStateChange() == ItemEvent.SELECTED) {
169                     vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.CubicCurve<Integer,Number>());
170                     vv.repaint();
171                 }
172             }
173         });
174         radio.add(lineButton);
175         radio.add(quadButton);
176         radio.add(cubicButton);
177 
178         graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
179         
180         JCheckBox rotate = new JCheckBox("<html><center>EdgeType<p>Parallel</center></html>");
181         rotate.addItemListener(new ItemListener(){
182             public void itemStateChanged(ItemEvent e) {
183                 AbstractButton b = (AbstractButton)e.getSource();
184                 edgeLabelRenderer.setRotateEdgeLabels(b.isSelected());
185                 vv.repaint();
186             }
187         });
188         rotate.setSelected(true);
189         MutableDirectionalEdgeValue mv = new MutableDirectionalEdgeValue(.5, .7);
190         vv.getRenderContext().setEdgeLabelClosenessTransformer(mv);
191         JSlider directedSlider = new JSlider(mv.getDirectedModel()) {
192             public Dimension getPreferredSize() {
193                 Dimension d = super.getPreferredSize();
194                 d.width /= 2;
195                 return d;
196             }
197         };
198         JSlider undirectedSlider = new JSlider(mv.getUndirectedModel()) {
199             public Dimension getPreferredSize() {
200                 Dimension d = super.getPreferredSize();
201                 d.width /= 2;
202                 return d;
203             }
204         };
205         
206         JSlider edgeOffsetSlider = new JSlider(0,50) {
207             public Dimension getPreferredSize() {
208                 Dimension d = super.getPreferredSize();
209                 d.width /= 2;
210                 return d;
211             }
212         };
213         edgeOffsetSlider.addChangeListener(new ChangeListener() {
214 
215             public void stateChanged(ChangeEvent e) {
216                 JSlider s = (JSlider)e.getSource();
217                 AbstractEdgeShapeTransformer<Integer,Number> aesf = 
218                     (AbstractEdgeShapeTransformer<Integer,Number>)vv.getRenderContext().getEdgeShapeTransformer();
219                 aesf.setControlOffsetIncrement(s.getValue());
220                 vv.repaint();
221             }
222         	
223         });
224         
225         Box controls = Box.createHorizontalBox();
226 
227         JPanel zoomPanel = new JPanel(new GridLayout(0,1));
228         zoomPanel.setBorder(BorderFactory.createTitledBorder("Scale"));
229         zoomPanel.add(plus);
230         zoomPanel.add(minus);
231 
232         JPanel edgePanel = new JPanel(new GridLayout(0,1));
233         edgePanel.setBorder(BorderFactory.createTitledBorder("EdgeType Type"));
234         edgePanel.add(lineButton);
235         edgePanel.add(quadButton);
236         edgePanel.add(cubicButton);
237 
238         JPanel rotatePanel = new JPanel();
239         rotatePanel.setBorder(BorderFactory.createTitledBorder("Alignment"));
240         rotatePanel.add(rotate);
241 
242         JPanel labelPanel = new JPanel(new BorderLayout());
243         JPanel sliderPanel = new JPanel(new GridLayout(3,1));
244         JPanel sliderLabelPanel = new JPanel(new GridLayout(3,1));
245         JPanel offsetPanel = new JPanel(new BorderLayout());
246         offsetPanel.setBorder(BorderFactory.createTitledBorder("Offset"));
247         sliderPanel.add(directedSlider);
248         sliderPanel.add(undirectedSlider);
249         sliderPanel.add(edgeOffsetSlider);
250         sliderLabelPanel.add(new JLabel("Directed", JLabel.RIGHT));
251         sliderLabelPanel.add(new JLabel("Undirected", JLabel.RIGHT));
252         sliderLabelPanel.add(new JLabel("Edges", JLabel.RIGHT));
253         offsetPanel.add(sliderLabelPanel, BorderLayout.WEST);
254         offsetPanel.add(sliderPanel);
255         labelPanel.add(offsetPanel);
256         labelPanel.add(rotatePanel, BorderLayout.WEST);
257         
258         JPanel modePanel = new JPanel(new GridLayout(2,1));
259         modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode"));
260         modePanel.add(graphMouse.getModeComboBox());
261 
262         controls.add(zoomPanel);
263         controls.add(edgePanel);
264         controls.add(labelPanel);
265         controls.add(modePanel);
266         content.add(controls, BorderLayout.SOUTH);
267         quadButton.setSelected(true);
268     }
269     
270     /**
271      * subclassed to hold two BoundedRangeModel instances that
272      * are used by JSliders to move the edge label positions
273      * @author Tom Nelson
274      *
275      *
276      */
277     class MutableDirectionalEdgeValue extends ConstantDirectionalEdgeValueTransformer<Integer,Number> {
278         BoundedRangeModel undirectedModel = new DefaultBoundedRangeModel(5,0,0,10);
279         BoundedRangeModel directedModel = new DefaultBoundedRangeModel(7,0,0,10);
280         
281         public MutableDirectionalEdgeValue(double undirected, double directed) {
282             super(undirected, directed);
283             undirectedModel.setValue((int)(undirected*10));
284             directedModel.setValue((int)(directed*10));
285             
286             undirectedModel.addChangeListener(new ChangeListener(){
287                 public void stateChanged(ChangeEvent e) {
288                     setUndirectedValue(new Double(undirectedModel.getValue()/10f));
289                     vv.repaint();
290                 }
291             });
292             directedModel.addChangeListener(new ChangeListener(){
293                 public void stateChanged(ChangeEvent e) {
294                     setDirectedValue(new Double(directedModel.getValue()/10f));
295                     vv.repaint();
296                 }
297             });
298         }
299         /**
300          * @return Returns the directedModel.
301          */
302         public BoundedRangeModel getDirectedModel() {
303             return directedModel;
304         }
305 
306         /**
307          * @return Returns the undirectedModel.
308          */
309         public BoundedRangeModel getUndirectedModel() {
310             return undirectedModel;
311         }
312     }
313     
314     /**
315      * create some vertices
316      * @param count how many to create
317      * @return the Vertices in an array
318      */
319     private Integer[] createVertices(int count) {
320         Integer[] v = new Integer[count];
321         for (int i = 0; i < count; i++) {
322             v[i] = new Integer(i);
323             graph.addVertex(v[i]);
324         }
325         return v;
326     }
327 
328     /**
329      * create edges for this demo graph
330      * @param v an array of Vertices to connect
331      */
332     void createEdges(Integer[] v) {
333         graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED);
334         graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED);
335         graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED);
336         graph.addEdge(new Double(Math.random()), v[1], v[0], EdgeType.DIRECTED);
337         graph.addEdge(new Double(Math.random()), v[1], v[0], EdgeType.DIRECTED);
338         graph.addEdge(new Double(Math.random()), v[1], v[2]);
339         graph.addEdge(new Double(Math.random()), v[1], v[2]);
340     }
341 
342     /**
343      * a driver for this demo
344      */
345     public static void main(String[] args) {
346         JFrame frame = new JFrame();
347         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
348         Container content = frame.getContentPane();
349         content.add(new EdgeLabelDemo());
350         frame.pack();
351         frame.setVisible(true);
352     }
353 }