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.Font;
16  import java.awt.GridLayout;
17  import java.awt.event.ActionEvent;
18  import java.awt.event.ActionListener;
19  
20  import javax.swing.BorderFactory;
21  import javax.swing.JApplet;
22  import javax.swing.JButton;
23  import javax.swing.JFrame;
24  import javax.swing.JLabel;
25  import javax.swing.JPanel;
26  
27  import org.apache.commons.collections15.functors.ConstantTransformer;
28  
29  import edu.uci.ics.jung.algorithms.layout.KKLayout;
30  import edu.uci.ics.jung.algorithms.layout.Layout;
31  import edu.uci.ics.jung.algorithms.layout.StaticLayout;
32  import edu.uci.ics.jung.algorithms.layout.TreeLayout;
33  import edu.uci.ics.jung.algorithms.shortestpath.MinimumSpanningForest2;
34  import edu.uci.ics.jung.graph.DelegateForest;
35  import edu.uci.ics.jung.graph.DelegateTree;
36  import edu.uci.ics.jung.graph.Forest;
37  import edu.uci.ics.jung.graph.Graph;
38  import edu.uci.ics.jung.graph.util.TestGraphs;
39  import edu.uci.ics.jung.visualization.DefaultVisualizationModel;
40  import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
41  import edu.uci.ics.jung.visualization.VisualizationModel;
42  import edu.uci.ics.jung.visualization.VisualizationViewer;
43  import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
44  import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
45  import edu.uci.ics.jung.visualization.control.ScalingControl;
46  import edu.uci.ics.jung.visualization.decorators.EdgeShape;
47  import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
48  import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
49  import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
50  import edu.uci.ics.jung.visualization.picking.MultiPickedState;
51  import edu.uci.ics.jung.visualization.picking.PickedState;
52  import edu.uci.ics.jung.visualization.renderers.Renderer;
53  import edu.uci.ics.jung.visualization.transform.MutableTransformer;
54  
55  /**
56   * Demonstrates a single graph with 3 layouts in 3 views.
57   * The first view is an undirected graph using KKLayout
58   * The second view show a TreeLayout view of a MinimumSpanningTree
59   * of the first graph. The third view shows the complete graph
60   * of the first view, using the layout positions of the 
61   * MinimumSpanningTree tree view.
62   * 
63   * @author Tom Nelson
64   * 
65   */
66  @SuppressWarnings("serial")
67  public class MinimumSpanningTreeDemo extends JApplet {
68  
69       /**
70       * the graph
71       */
72      Graph<String,Number> graph;
73      Forest<String,Number> tree;
74  
75      /**
76       * the visual components and renderers for the graph
77       */
78      VisualizationViewer<String,Number> vv0;
79      VisualizationViewer<String,Number> vv1;
80      VisualizationViewer<String,Number> vv2;
81  //    VisualizationViewer<String,Number> vv3;
82      
83      /**
84       * the normal transformer
85       */
86      MutableTransformer layoutTransformer;
87      
88      Dimension preferredSize = new Dimension(300,300);
89      Dimension preferredLayoutSize = new Dimension(400,400);
90      Dimension preferredSizeRect = new Dimension(500,250);
91      
92      /**
93       * create an instance of a simple graph in two views with controls to
94       * demo the zoom features.
95       * 
96       */
97      public MinimumSpanningTreeDemo() {
98          
99          // create a simple graph for the demo
100         // both models will share one graph
101         graph = 
102         	TestGraphs.getDemoGraph();
103         
104         MinimumSpanningForest2<String,Number> prim = 
105         	new MinimumSpanningForest2<String,Number>(graph,
106         		new DelegateForest<String,Number>(), DelegateTree.<String,Number>getFactory(),
107         		new ConstantTransformer(1.0));
108         
109         tree = prim.getForest();
110         
111         // create two layouts for the one graph, one layout for each model
112         Layout<String,Number> layout0 = new KKLayout<String,Number>(graph);
113         layout0.setSize(preferredLayoutSize);
114         Layout<String,Number> layout1 = new TreeLayout<String,Number>(tree);
115         Layout<String,Number> layout2 = new StaticLayout<String,Number>(graph, layout1);
116 
117         // create the two models, each with a different layout
118         VisualizationModel<String,Number> vm0 =
119             new DefaultVisualizationModel<String,Number>(layout0, preferredSize);
120         VisualizationModel<String,Number> vm1 =
121             new DefaultVisualizationModel<String,Number>(layout1, preferredSizeRect);
122         VisualizationModel<String,Number> vm2 = 
123             new DefaultVisualizationModel<String,Number>(layout2, preferredSizeRect);
124         	
125         // create the two views, one for each model
126         // they share the same renderer
127         vv0 = new VisualizationViewer<String,Number>(vm0, preferredSize);
128         vv1 = new VisualizationViewer<String,Number>(vm1, preferredSizeRect);
129         vv2 = new VisualizationViewer<String,Number>(vm2, preferredSizeRect);
130 
131 //        vv1.setRenderContext(vv2.getRenderContext());
132         
133         vv1.getRenderContext().setMultiLayerTransformer(vv0.getRenderContext().getMultiLayerTransformer());
134         vv2.getRenderContext().setMultiLayerTransformer(vv0.getRenderContext().getMultiLayerTransformer());
135 
136         vv1.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
137         
138         vv0.addChangeListener(vv1);
139         vv1.addChangeListener(vv2);
140         
141         vv0.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
142         vv2.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
143         
144         Color back = Color.decode("0xffffbb");
145         vv0.setBackground(back);
146         vv1.setBackground(back);
147         vv2.setBackground(back);
148         
149         vv0.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR);
150         vv0.setForeground(Color.darkGray);
151         vv1.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR);
152         vv1.setForeground(Color.darkGray);
153         vv2.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR);
154         vv2.setForeground(Color.darkGray);
155         
156         // share one PickedState between the two views
157         PickedState<String> ps = new MultiPickedState<String>();
158         vv0.setPickedVertexState(ps);
159         vv1.setPickedVertexState(ps);
160         vv2.setPickedVertexState(ps);
161 
162         PickedState<Number> pes = new MultiPickedState<Number>();
163         vv0.setPickedEdgeState(pes);
164         vv1.setPickedEdgeState(pes);
165         vv2.setPickedEdgeState(pes);
166 
167         
168         // set an edge paint function that will show picking for edges
169         vv0.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(vv0.getPickedEdgeState(), Color.black, Color.red));
170         vv0.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<String>(vv0.getPickedVertexState(),
171                 Color.red, Color.yellow));
172         vv1.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(vv1.getPickedEdgeState(), Color.black, Color.red));
173         vv1.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<String>(vv1.getPickedVertexState(),
174                 Color.red, Color.yellow));
175         
176         // add default listeners for ToolTips
177         vv0.setVertexToolTipTransformer(new ToStringLabeller());
178         vv1.setVertexToolTipTransformer(new ToStringLabeller());
179         vv2.setVertexToolTipTransformer(new ToStringLabeller());
180         
181         vv0.setLayout(new BorderLayout());
182         vv1.setLayout(new BorderLayout());
183         vv2.setLayout(new BorderLayout());
184         
185         Font font = vv0.getFont().deriveFont(Font.BOLD, 16);
186         JLabel vv0Label = new JLabel("<html>Original Graph<p>using KKLayout");
187         vv0Label.setFont(font);
188         JLabel vv1Label = new JLabel("Minimum Spanning Trees");
189         vv1Label.setFont(font);
190         JLabel vv2Label = new JLabel("Original Graph using TreeLayout");
191         vv2Label.setFont(font);
192         JPanel flow0 = new JPanel();
193         flow0.setOpaque(false);
194         JPanel flow1 = new JPanel();
195         flow1.setOpaque(false);
196         JPanel flow2 = new JPanel();
197         flow2.setOpaque(false);
198         flow0.add(vv0Label);
199         flow1.add(vv1Label);
200         flow2.add(vv2Label);
201         vv0.add(flow0, BorderLayout.NORTH);
202         vv1.add(flow1, BorderLayout.NORTH);
203         vv2.add(flow2, BorderLayout.NORTH);
204         
205 //        vv2.getRenderContext().setEdgeDrawPaintTransformer(new Transformer<Number,Paint>() {
206 //
207 //			public Paint transform(Number e) {
208 //				if(tree.getEdges().contains(e) == false) return Color.lightGray;
209 //				return Color.black;
210 //			}});
211         
212         Container content = getContentPane();
213         JPanel grid = new JPanel(new GridLayout(0,1));
214         JPanel panel = new JPanel(new BorderLayout());
215         panel.add(new GraphZoomScrollPane(vv0), BorderLayout.WEST);
216         grid.add(new GraphZoomScrollPane(vv1));
217         grid.add(new GraphZoomScrollPane(vv2));
218 //        panel.add(new GraphZoomScrollPane(vv3), BorderLayout.EAST);
219         panel.add(grid);
220 
221         content.add(panel);
222         
223         // create a GraphMouse for each view
224         DefaultModalGraphMouse gm0 = new DefaultModalGraphMouse();
225         DefaultModalGraphMouse gm1 = new DefaultModalGraphMouse();
226         DefaultModalGraphMouse gm2 = new DefaultModalGraphMouse();
227         DefaultModalGraphMouse gm3 = new DefaultModalGraphMouse();
228 
229         vv0.setGraphMouse(gm0);
230         vv1.setGraphMouse(gm1);
231         vv2.setGraphMouse(gm2);
232 //        vv3.setGraphMouse(gm3);
233 
234         // create zoom buttons for scaling the transformer that is
235         // shared between the two models.
236         final ScalingControl scaler = new CrossoverScalingControl();
237         
238         vv0.scaleToLayout(scaler);
239         vv1.scaleToLayout(scaler);
240         vv2.scaleToLayout(scaler);
241 //        vv3.scaleToLayout(scaler);
242 
243         JButton plus = new JButton("+");
244         plus.addActionListener(new ActionListener() {
245             public void actionPerformed(ActionEvent e) {
246                 scaler.scale(vv1, 1.1f, vv1.getCenter());
247             }
248         });
249         JButton minus = new JButton("-");
250         minus.addActionListener(new ActionListener() {
251             public void actionPerformed(ActionEvent e) {
252                 scaler.scale(vv1, 1/1.1f, vv1.getCenter());
253             }
254         });
255         
256         JPanel zoomPanel = new JPanel(new GridLayout(1,2));
257         zoomPanel.setBorder(BorderFactory.createTitledBorder("Zoom"));
258         
259         JPanel modePanel = new JPanel();
260         modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode"));
261         gm1.getModeComboBox().addItemListener(gm2.getModeListener());
262         gm1.getModeComboBox().addItemListener(gm0.getModeListener());
263         gm1.getModeComboBox().addItemListener(gm3.getModeListener());
264         modePanel.add(gm1.getModeComboBox());
265 
266         JPanel controls = new JPanel();
267         zoomPanel.add(plus);
268         zoomPanel.add(minus);
269         controls.add(zoomPanel);
270         controls.add(modePanel);
271         content.add(controls, BorderLayout.SOUTH);
272     }
273 
274     /**
275      * a driver for this demo
276      */
277     public static void main(String[] args) {
278         JFrame f = new JFrame();
279         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
280         f.getContentPane().add(new MinimumSpanningTreeDemo());
281         f.pack();
282         f.setVisible(true);
283     }
284 }