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