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   package edu.uci.ics.jung.samples;
9   
10  import java.awt.BorderLayout;
11  import java.awt.Color;
12  import java.awt.Component;
13  import java.awt.GridLayout;
14  import java.awt.event.ActionEvent;
15  import java.awt.event.ActionListener;
16  import java.lang.reflect.Constructor;
17  import java.util.ArrayList;
18  import java.util.HashMap;
19  import java.util.HashSet;
20  import java.util.List;
21  
22  import javax.swing.DefaultListCellRenderer;
23  import javax.swing.JApplet;
24  import javax.swing.JButton;
25  import javax.swing.JComboBox;
26  import javax.swing.JFrame;
27  import javax.swing.JList;
28  import javax.swing.JPanel;
29  
30  import com.google.common.base.Supplier;
31  
32  import edu.uci.ics.jung.algorithms.generators.random.MixedRandomGraphGenerator;
33  import edu.uci.ics.jung.algorithms.layout.CircleLayout;
34  import edu.uci.ics.jung.algorithms.layout.FRLayout;
35  import edu.uci.ics.jung.algorithms.layout.ISOMLayout;
36  import edu.uci.ics.jung.algorithms.layout.KKLayout;
37  import edu.uci.ics.jung.algorithms.layout.Layout;
38  import edu.uci.ics.jung.algorithms.layout.SpringLayout;
39  import edu.uci.ics.jung.algorithms.layout.SpringLayout2;
40  import edu.uci.ics.jung.algorithms.layout.util.Relaxer;
41  import edu.uci.ics.jung.graph.Graph;
42  import edu.uci.ics.jung.graph.SparseMultigraph;
43  import edu.uci.ics.jung.graph.util.TestGraphs;
44  import edu.uci.ics.jung.visualization.VisualizationViewer;
45  import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
46  import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
47  import edu.uci.ics.jung.visualization.control.ScalingControl;
48  import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
49  import edu.uci.ics.jung.visualization.layout.LayoutTransition;
50  import edu.uci.ics.jung.visualization.util.Animator;
51  
52  
53  /**
54   * Demonstrates several of the graph layout algorithms.
55   * Allows the user to interactively select one of several graphs, and one of
56   * several layouts, and visualizes the combination.
57   * 
58   * @author Danyel Fisher
59   * @author Joshua O'Madadhain
60   */
61  @SuppressWarnings("serial")
62  public class ShowLayouts extends JApplet {
63      protected static Graph<? extends Object, ? extends Object>[] g_array;
64      protected static int graph_index;
65      protected static String[] graph_names = {"Two component graph", 
66          "Random mixed-mode graph", "Miscellaneous multicomponent graph", 
67          "Random directed acyclic graph", "One component graph", 
68          "Chain+isolate graph", "Trivial (disconnected) graph"};
69      
70  	public static class GraphChooser implements ActionListener
71      {
72  		private JComboBox<?> layout_combo;
73  
74  		public GraphChooser(JComboBox<?> layout_combo)
75          {
76              this.layout_combo = layout_combo;
77          }
78          
79          public void actionPerformed(ActionEvent e)
80          {
81  			JComboBox<?> cb = (JComboBox<?>)e.getSource();
82              graph_index = cb.getSelectedIndex();
83              layout_combo.setSelectedIndex(layout_combo.getSelectedIndex()); // rebuild the layout
84          }
85      }
86  
87      /**
88  	 * 
89  	 * @author danyelf
90  	 */
91  	
92  	private static final class LayoutChooser implements ActionListener
93      {
94          private final JComboBox<?> jcb;
95          private final VisualizationViewer<Integer,Number> vv;
96  
97          private LayoutChooser(JComboBox<?> jcb, VisualizationViewer<Integer,Number> vv)
98          {
99              super();
100             this.jcb = jcb;
101             this.vv = vv;
102         }
103 
104         @SuppressWarnings("unchecked")
105 		public void actionPerformed(ActionEvent arg0)
106         {
107             Object[] constructorArgs =
108                 { g_array[graph_index]};
109 
110 			Class<? extends Layout<Integer,Number>> layoutC = 
111                 (Class<? extends Layout<Integer,Number>>) jcb.getSelectedItem();
112             try
113             {
114                 Constructor<? extends Layout<Integer, Number>> constructor = layoutC
115                         .getConstructor(new Class[] {Graph.class});
116                 Object o = constructor.newInstance(constructorArgs);
117                 Layout<Integer,Number> l = (Layout<Integer,Number>) o;
118                 l.setInitializer(vv.getGraphLayout());
119                 l.setSize(vv.getSize());
120                 
121 				LayoutTransition<Integer,Number> lt =
122 					new LayoutTransition<Integer,Number>(vv, vv.getGraphLayout(), l);
123 				Animator animator = new Animator(lt);
124 				animator.start();
125 				vv.getRenderContext().getMultiLayerTransformer().setToIdentity();
126 				vv.repaint();
127                 
128             }
129             catch (Exception e)
130             {
131                 e.printStackTrace();
132             }
133         }
134     }
135 
136     @SuppressWarnings({ "rawtypes", "unchecked" })
137 	private static JPanel getGraphPanel()
138     {
139         g_array = 
140             (Graph<? extends Object,? extends Object>[])
141             new Graph<?,?>[graph_names.length];
142         
143         Supplier<Graph<Integer,Number>> graphFactory =
144     		new Supplier<Graph<Integer,Number>>() {
145     		public Graph<Integer,Number> get() {
146     			return new SparseMultigraph<Integer,Number>();
147     		}
148     	};
149 
150     	Supplier<Integer> vertexFactory = new Supplier<Integer>() {
151     			int count;
152 				public Integer get() {
153 					return count++;
154 				}};
155 				Supplier<Number> edgeFactory = new Supplier<Number>() {
156 			int count;
157 				public Number get() {
158 					return count++;
159 				}};
160 
161             
162         g_array[0] = TestGraphs.createTestGraph(false);
163         g_array[1] = MixedRandomGraphGenerator.generateMixedRandomGraph(graphFactory, 
164         		vertexFactory, edgeFactory, new HashMap<Number,Number>(), 20, new HashSet<Integer>());
165         g_array[2] = TestGraphs.getDemoGraph();
166         g_array[3] = TestGraphs.createDirectedAcyclicGraph(4, 4, 0.3);
167         g_array[4] = TestGraphs.getOneComponentGraph();
168         g_array[5] = TestGraphs.createChainPlusIsolates(18, 5);
169         g_array[6] = TestGraphs.createChainPlusIsolates(0, 20);
170 
171         Graph<? extends Object, ? extends Object> g = g_array[4]; // initial graph
172 
173         final VisualizationViewer<Integer,Number> vv = 
174             new VisualizationViewer<Integer,Number>(new FRLayout(g));
175         
176         vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<Integer>(vv.getPickedVertexState(), Color.red, Color.yellow));
177         
178         final DefaultModalGraphMouse<Integer,Number> graphMouse = new DefaultModalGraphMouse<Integer,Number>();
179         vv.setGraphMouse(graphMouse);
180         
181         final ScalingControl scaler = new CrossoverScalingControl();
182 
183         JButton plus = new JButton("+");
184         plus.addActionListener(new ActionListener() {
185             public void actionPerformed(ActionEvent e) {
186                 scaler.scale(vv, 1.1f, vv.getCenter());
187             }
188         });
189         JButton minus = new JButton("-");
190         minus.addActionListener(new ActionListener() {
191             public void actionPerformed(ActionEvent e) {
192                 scaler.scale(vv, 1/1.1f, vv.getCenter());
193             }
194         });
195         JButton reset = new JButton("reset");
196         reset.addActionListener(new ActionListener() {
197 			public void actionPerformed(ActionEvent e) {
198 				Layout<Integer,Number> layout = vv.getGraphLayout();
199 				layout.initialize();
200 				Relaxer relaxer = vv.getModel().getRelaxer();
201 				if(relaxer != null) {
202 //				if(layout instanceof IterativeContext) {
203 					relaxer.stop();
204 					relaxer.prerelax();
205 					relaxer.relax();
206 				}
207 			}});
208         
209         JComboBox modeBox = graphMouse.getModeComboBox();
210         modeBox.addItemListener(((DefaultModalGraphMouse<Integer,Number>)vv.getGraphMouse()).getModeListener());
211 
212         JPanel jp = new JPanel();
213         jp.setBackground(Color.WHITE);
214         jp.setLayout(new BorderLayout());
215         jp.add(vv, BorderLayout.CENTER);
216         Class[] combos = getCombos();
217         final JComboBox jcb = new JComboBox(combos);
218         // use a renderer to shorten the layout name presentation
219         jcb.setRenderer(new DefaultListCellRenderer() {
220             public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
221                 String valueString = value.toString();
222                 valueString = valueString.substring(valueString.lastIndexOf('.')+1);
223                 return super.getListCellRendererComponent(list, valueString, index, isSelected,
224                         cellHasFocus);
225             }
226         });
227         jcb.addActionListener(new LayoutChooser(jcb, vv));
228         jcb.setSelectedItem(FRLayout.class);
229 
230         JPanel control_panel = new JPanel(new GridLayout(2,1));
231         JPanel topControls = new JPanel();
232         JPanel bottomControls = new JPanel();
233         control_panel.add(topControls);
234         control_panel.add(bottomControls);
235         jp.add(control_panel, BorderLayout.NORTH);
236         
237         final JComboBox graph_chooser = new JComboBox(graph_names);
238         
239         graph_chooser.addActionListener(new GraphChooser(jcb));
240         
241         topControls.add(jcb);
242         topControls.add(graph_chooser);
243         bottomControls.add(plus);
244         bottomControls.add(minus);
245         bottomControls.add(modeBox);
246         bottomControls.add(reset);
247         return jp;
248     }
249 
250     public void start()
251     {
252         this.getContentPane().add(getGraphPanel());
253     }
254 
255     /**
256      * @return
257      */
258     @SuppressWarnings({ "unchecked", "rawtypes" })
259     private static Class<? extends Layout>[] getCombos()
260     {
261         List<Class<? extends Layout>> layouts = new ArrayList<Class<? extends Layout>>();
262         layouts.add(KKLayout.class);
263         layouts.add(FRLayout.class);
264         layouts.add(CircleLayout.class);
265         layouts.add(SpringLayout.class);
266         layouts.add(SpringLayout2.class);
267         layouts.add(ISOMLayout.class);
268         return layouts.toArray(new Class[0]);
269     }
270 
271     public static void main(String[] args)
272     {
273         JPanel jp = getGraphPanel();
274 
275         JFrame jf = new JFrame();
276         jf.getContentPane().add(jp);
277         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
278         jf.pack();
279         jf.setVisible(true);
280     }
281 }