1
2
3
4
5
6
7
8
9 package edu.uci.ics.jung.samples;
10
11 import java.awt.BorderLayout;
12 import java.awt.Color;
13 import java.awt.Component;
14 import java.awt.Container;
15 import java.awt.Dimension;
16 import java.awt.GridLayout;
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 import java.awt.geom.Point2D;
22 import java.lang.reflect.Constructor;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import javax.swing.BorderFactory;
28 import javax.swing.Box;
29 import javax.swing.DefaultListCellRenderer;
30 import javax.swing.JApplet;
31 import javax.swing.JButton;
32 import javax.swing.JComboBox;
33 import javax.swing.JComponent;
34 import javax.swing.JFrame;
35 import javax.swing.JList;
36 import javax.swing.JOptionPane;
37 import javax.swing.JPanel;
38
39 import edu.uci.ics.jung.algorithms.layout.AggregateLayout;
40 import edu.uci.ics.jung.algorithms.layout.CircleLayout;
41 import edu.uci.ics.jung.algorithms.layout.FRLayout;
42 import edu.uci.ics.jung.algorithms.layout.KKLayout;
43 import edu.uci.ics.jung.algorithms.layout.Layout;
44 import edu.uci.ics.jung.algorithms.layout.SpringLayout;
45 import edu.uci.ics.jung.graph.Graph;
46 import edu.uci.ics.jung.graph.util.Pair;
47 import edu.uci.ics.jung.graph.util.TestGraphs;
48 import edu.uci.ics.jung.visualization.DefaultVisualizationModel;
49 import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
50 import edu.uci.ics.jung.visualization.VisualizationModel;
51 import edu.uci.ics.jung.visualization.VisualizationViewer;
52 import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
53 import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
54 import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
55 import edu.uci.ics.jung.visualization.control.ScalingControl;
56 import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer;
57 import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer;
58 import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
59 import edu.uci.ics.jung.visualization.picking.PickedState;
60
61
62
63
64
65
66
67
68
69
70
71 @SuppressWarnings("serial")
72 public class SubLayoutDemo extends JApplet {
73
74 String instructions =
75 "<html>"+
76 "Use the Layout combobox to select the "+
77 "<p>underlying layout."+
78 "<p>Use the SubLayout combobox to select "+
79 "<p>the type of layout for any clusters you create."+
80 "<p>To create clusters, use the mouse to select "+
81 "<p>multiple vertices, either by dragging a region, "+
82 "<p>or by shift-clicking on multiple vertices."+
83 "<p>After you select vertices, use the "+
84 "<p>Cluster Picked button to cluster them using the "+
85 "<p>layout and size specified in the Sublayout comboboxen."+
86 "<p>Use the Uncluster All button to remove all"+
87 "<p>clusters."+
88 "<p>You can drag the cluster with the mouse." +
89 "<p>Use the 'Picking'/'Transforming' combo-box to switch"+
90 "<p>between picking and transforming mode.</html>";
91
92
93
94 Graph<String,Number> graph;
95
96 Map<Graph<String,Number>,Dimension> sizes = new HashMap<Graph<String,Number>,Dimension>();
97
98 Class[] layoutClasses = new Class[]{CircleLayout.class,SpringLayout.class,FRLayout.class,KKLayout.class};
99
100
101
102 VisualizationViewer<String,Number> vv;
103
104 AggregateLayout<String,Number> clusteringLayout;
105
106 Dimension subLayoutSize;
107
108 PickedState<String> ps;
109
110 Class subLayoutType = CircleLayout.class;
111
112
113
114
115
116
117 public SubLayoutDemo() {
118
119
120 graph = TestGraphs.getOneComponentGraph();
121
122
123
124
125 clusteringLayout = new AggregateLayout<String,Number>(new FRLayout<String,Number>(graph));
126
127
128 Dimension preferredSize = new Dimension(600,600);
129 final VisualizationModel<String,Number> visualizationModel =
130 new DefaultVisualizationModel<String,Number>(clusteringLayout, preferredSize);
131 vv = new VisualizationViewer<String,Number>(visualizationModel, preferredSize);
132
133 ps = vv.getPickedVertexState();
134 vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer<Number>(vv.getPickedEdgeState(), Color.black, Color.red));
135 vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer<String>(vv.getPickedVertexState(),
136 Color.red, Color.yellow));
137 vv.setBackground(Color.white);
138
139
140 vv.setVertexToolTipTransformer(new ToStringLabeller());
141
142
143
144
145 final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
146
147 vv.setGraphMouse(graphMouse);
148
149 Container content = getContentPane();
150 GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv);
151 content.add(gzsp);
152
153 JComboBox modeBox = graphMouse.getModeComboBox();
154 modeBox.addItemListener(graphMouse.getModeListener());
155 graphMouse.setMode(ModalGraphMouse.Mode.PICKING);
156
157 final ScalingControl scaler = new CrossoverScalingControl();
158
159 JButton plus = new JButton("+");
160 plus.addActionListener(new ActionListener() {
161 public void actionPerformed(ActionEvent e) {
162 scaler.scale(vv, 1.1f, vv.getCenter());
163 }
164 });
165 JButton minus = new JButton("-");
166 minus.addActionListener(new ActionListener() {
167 public void actionPerformed(ActionEvent e) {
168 scaler.scale(vv, 1/1.1f, vv.getCenter());
169 }
170 });
171
172 JButton cluster = new JButton("Cluster Picked");
173 cluster.addActionListener(new ActionListener() {
174 public void actionPerformed(ActionEvent e) {
175 clusterPicked();
176 }});
177
178 JButton uncluster = new JButton("UnCluster All");
179 uncluster.addActionListener(new ActionListener() {
180 public void actionPerformed(ActionEvent e) {
181 uncluster();
182 }});
183
184 JComboBox layoutTypeComboBox = new JComboBox(layoutClasses);
185 layoutTypeComboBox.setRenderer(new DefaultListCellRenderer() {
186 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
187 String valueString = value.toString();
188 valueString = valueString.substring(valueString.lastIndexOf('.')+1);
189 return super.getListCellRendererComponent(list, valueString, index, isSelected,
190 cellHasFocus);
191 }
192 });
193 layoutTypeComboBox.setSelectedItem(FRLayout.class);
194 layoutTypeComboBox.addItemListener(new ItemListener() {
195
196 public void itemStateChanged(ItemEvent e) {
197 if(e.getStateChange() == ItemEvent.SELECTED) {
198 Class clazz = (Class)e.getItem();
199 try {
200 Layout<String,Number> layout = getLayoutFor(clazz, graph);
201 layout.setInitializer(vv.getGraphLayout());
202 clusteringLayout.setDelegate(layout);
203 vv.setGraphLayout(clusteringLayout);
204 } catch(Exception ex) {
205 ex.printStackTrace();
206 }
207 }
208 }});
209
210 JComboBox subLayoutTypeComboBox = new JComboBox(layoutClasses);
211
212 subLayoutTypeComboBox.setRenderer(new DefaultListCellRenderer() {
213 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
214 String valueString = value.toString();
215 valueString = valueString.substring(valueString.lastIndexOf('.')+1);
216 return super.getListCellRendererComponent(list, valueString, index, isSelected,
217 cellHasFocus);
218 }
219 });
220 subLayoutTypeComboBox.addItemListener(new ItemListener() {
221
222 public void itemStateChanged(ItemEvent e) {
223 if(e.getStateChange() == ItemEvent.SELECTED) {
224 subLayoutType = (Class)e.getItem();
225 }
226 }});
227
228 JComboBox subLayoutDimensionComboBox =
229 new JComboBox(new Dimension[]{
230 new Dimension(75,75),
231 new Dimension(100,100),
232 new Dimension(150,150),
233 new Dimension(200,200),
234 new Dimension(250,250),
235 new Dimension(300,300)
236 }
237 );
238 subLayoutDimensionComboBox.setRenderer(new DefaultListCellRenderer() {
239 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
240 String valueString = value.toString();
241 valueString = valueString.substring(valueString.lastIndexOf('['));
242 valueString = valueString.replaceAll("idth", "");
243 valueString = valueString.replaceAll("eight","");
244 return super.getListCellRendererComponent(list, valueString, index, isSelected,
245 cellHasFocus);
246 }
247 });
248 subLayoutDimensionComboBox.addItemListener(new ItemListener() {
249
250 public void itemStateChanged(ItemEvent e) {
251 if(e.getStateChange() == ItemEvent.SELECTED) {
252 subLayoutSize = (Dimension)e.getItem();
253 }
254 }});
255 subLayoutDimensionComboBox.setSelectedIndex(1);
256
257 JButton help = new JButton("Help");
258 help.addActionListener(new ActionListener() {
259 public void actionPerformed(ActionEvent e) {
260 JOptionPane.showMessageDialog((JComponent)e.getSource(), instructions, "Help", JOptionPane.PLAIN_MESSAGE);
261 }
262 });
263 Dimension space = new Dimension(20,20);
264 Box controls = Box.createVerticalBox();
265 controls.add(Box.createRigidArea(space));
266
267 JPanel zoomControls = new JPanel(new GridLayout(1,2));
268 zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom"));
269 zoomControls.add(plus);
270 zoomControls.add(minus);
271 heightConstrain(zoomControls);
272 controls.add(zoomControls);
273 controls.add(Box.createRigidArea(space));
274
275 JPanel clusterControls = new JPanel(new GridLayout(0,1));
276 clusterControls.setBorder(BorderFactory.createTitledBorder("Clustering"));
277 clusterControls.add(cluster);
278 clusterControls.add(uncluster);
279 heightConstrain(clusterControls);
280 controls.add(clusterControls);
281 controls.add(Box.createRigidArea(space));
282
283 JPanel layoutControls = new JPanel(new GridLayout(0,1));
284 layoutControls.setBorder(BorderFactory.createTitledBorder("Layout"));
285 layoutControls.add(layoutTypeComboBox);
286 heightConstrain(layoutControls);
287 controls.add(layoutControls);
288
289 JPanel subLayoutControls = new JPanel(new GridLayout(0,1));
290 subLayoutControls.setBorder(BorderFactory.createTitledBorder("SubLayout"));
291 subLayoutControls.add(subLayoutTypeComboBox);
292 subLayoutControls.add(subLayoutDimensionComboBox);
293 heightConstrain(subLayoutControls);
294 controls.add(subLayoutControls);
295 controls.add(Box.createRigidArea(space));
296
297 JPanel modePanel = new JPanel(new GridLayout(1,1));
298 modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode"));
299 modePanel.add(modeBox);
300 heightConstrain(modePanel);
301 controls.add(modePanel);
302 controls.add(Box.createRigidArea(space));
303
304 controls.add(help);
305 controls.add(Box.createVerticalGlue());
306 content.add(controls, BorderLayout.EAST);
307 }
308
309 private void heightConstrain(Component component) {
310 Dimension d = new Dimension(component.getMaximumSize().width,
311 component.getMinimumSize().height);
312 component.setMaximumSize(d);
313 }
314
315 private Layout getLayoutFor(Class layoutClass, Graph graph) throws Exception {
316 Object[] args = new Object[]{graph};
317 Constructor constructor = layoutClass.getConstructor(new Class[] {Graph.class});
318 return (Layout)constructor.newInstance(args);
319 }
320
321 private void clusterPicked() {
322 cluster(true);
323 }
324
325 private void uncluster() {
326 cluster(false);
327 }
328
329 private void cluster(boolean state) {
330 if(state == true) {
331
332 Collection<String> picked = ps.getPicked();
333 if(picked.size() > 1) {
334 Point2D center = new Point2D.Double();
335 double x = 0;
336 double y = 0;
337 for(String vertex : picked) {
338 Point2D p = clusteringLayout.transform(vertex);
339 x += p.getX();
340 y += p.getY();
341 }
342 x /= picked.size();
343 y /= picked.size();
344 center.setLocation(x,y);
345
346
347
348 Graph<String, Number> subGraph;
349 try {
350 subGraph = graph.getClass().newInstance();
351 for(String vertex : picked) {
352 subGraph.addVertex(vertex);
353 Collection<Number> incidentEdges = graph.getIncidentEdges(vertex);
354 for(Number edge : incidentEdges) {
355 Pair<String> endpoints = graph.getEndpoints(edge);
356 if(picked.containsAll(endpoints)) {
357
358 subGraph.addEdge(edge, endpoints.getFirst(), endpoints.getSecond());
359 }
360 }
361 }
362
363 Layout<String,Number> subLayout = getLayoutFor(subLayoutType, subGraph);
364 subLayout.setInitializer(vv.getGraphLayout());
365 subLayout.setSize(subLayoutSize);
366 clusteringLayout.put(subLayout,center);
367 vv.setGraphLayout(clusteringLayout);
368
369 } catch (Exception e) {
370 e.printStackTrace();
371 }
372 }
373 } else {
374
375 this.clusteringLayout.removeAll();
376 vv.setGraphLayout(clusteringLayout);
377 }
378 }
379
380
381
382
383 public static void main(String[] args) {
384 JFrame f = new JFrame();
385 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
386 f.getContentPane().add(new SubLayoutDemo());
387 f.pack();
388 f.setVisible(true);
389 }
390 }