source: autoquest-core-usability-evaluation-test/src/main/java/de/ugoe/cs/autoquest/usability/sandboxapp/TaskTreeVisualizerDemoApp.java @ 1030

Last change on this file since 1030 was 1030, checked in by adeicke, 11 years ago

Initial commit.

  • Property svn:mime-type set to text/plain
File size: 13.0 KB
Line 
1
2package de.ugoe.cs.autoquest.usability.sandboxapp;
3
4/*
5 * Copyright (c) 2003, the JUNG Project and the Regents of the University of
6 * California All rights reserved.
7 *
8 * This software is open-source under the BSD license; see either "license.txt"
9 * or http://jung.sourceforge.net/license.txt for a description.
10 *
11 */
12
13import java.awt.BorderLayout;
14import java.awt.Color;
15import java.awt.Container;
16import java.awt.Dimension;
17import java.awt.Graphics;
18import java.awt.Graphics2D;
19import java.awt.GridLayout;
20import java.awt.Shape;
21import java.awt.event.ActionEvent;
22import java.awt.event.ActionListener;
23import java.awt.event.ItemEvent;
24import java.awt.event.ItemListener;
25import java.awt.geom.Ellipse2D;
26import java.awt.geom.Point2D;
27import java.util.Collection;
28import java.util.HashSet;
29import java.util.LinkedList;
30import java.util.Map;
31import java.util.Queue;
32import java.util.Set;
33
34import javax.swing.BorderFactory;
35import javax.swing.JApplet;
36import javax.swing.JButton;
37import javax.swing.JComboBox;
38import javax.swing.JFrame;
39import javax.swing.JPanel;
40import javax.swing.JToggleButton;
41
42import org.apache.commons.collections15.Factory;
43import org.apache.commons.collections15.Transformer;
44import org.apache.commons.collections15.functors.ConstantTransformer;
45
46import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTree;
47import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode;
48import de.ugoe.cs.autoquest.usability.testutil.GenerateTaskTreeUtil;
49import edu.uci.ics.jung.algorithms.layout.FRLayout;
50import edu.uci.ics.jung.algorithms.layout.PolarPoint;
51import edu.uci.ics.jung.algorithms.layout.RadialTreeLayout;
52import edu.uci.ics.jung.algorithms.layout.TreeLayout;
53import edu.uci.ics.jung.graph.DelegateForest;
54import edu.uci.ics.jung.graph.DelegateTree;
55import edu.uci.ics.jung.graph.DirectedGraph;
56import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
57import edu.uci.ics.jung.graph.Forest;
58import edu.uci.ics.jung.graph.Graph;
59import edu.uci.ics.jung.graph.Tree;
60import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
61import edu.uci.ics.jung.visualization.Layer;
62import edu.uci.ics.jung.visualization.VisualizationServer;
63import edu.uci.ics.jung.visualization.VisualizationViewer;
64import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
65import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
66import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
67import edu.uci.ics.jung.visualization.control.ScalingControl;
68import edu.uci.ics.jung.visualization.decorators.EdgeShape;
69import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer;
70import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
71import edu.uci.ics.jung.visualization.subLayout.TreeCollapser;
72
73/**
74 * Demonstrates "collapsing"/"expanding" of a tree's subtrees.
75 *
76 * @author Tom Nelson
77 *
78 */
79@SuppressWarnings("serial")
80public class TaskTreeVisualizerDemoApp extends JApplet {
81
82    private static final String fileToParse = "javatrace.xml";
83
84    public static void main(String[] args) {
85        JFrame frame = new JFrame();
86        Container content = frame.getContentPane();
87        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
88
89        content.add(new TaskTreeVisualizerDemoApp(fileToParse));
90        frame.pack();
91        frame.setVisible(true);
92    }
93
94    /**
95     * the graph
96     */
97    Forest<String, Integer> graph;
98
99    Factory<DirectedGraph<String, Integer>> graphFactory =
100        new Factory<DirectedGraph<String, Integer>>() {
101
102            public DirectedGraph<String, Integer> create() {
103                return new DirectedSparseMultigraph<String, Integer>();
104            }
105        };
106
107    Factory<Tree<String, Integer>> treeFactory = new Factory<Tree<String, Integer>>() {
108
109        public Tree<String, Integer> create() {
110            return new DelegateTree<String, Integer>(graphFactory);
111        }
112    };
113
114    Factory<Integer> edgeFactory = new Factory<Integer>() {
115        int i = 0;
116
117        public Integer create() {
118            return i++;
119        }
120    };
121
122    Factory<String> vertexFactory = new Factory<String>() {
123        int i = 0;
124
125        public String create() {
126            return "V" + i++;
127        }
128    };
129
130    /**
131     * the visual component and renderer for the graph
132     */
133    VisualizationViewer<String, Integer> vv;
134
135    VisualizationServer.Paintable rings;
136
137    String root;
138
139    TreeLayout<String, Integer> layout;
140    @SuppressWarnings("rawtypes")
141    FRLayout layout1;
142
143    TreeCollapser collapser;
144
145    RadialTreeLayout<String, Integer> radialLayout;
146
147    @SuppressWarnings({ "unchecked", "rawtypes" })
148    public TaskTreeVisualizerDemoApp(String filetoparse) {
149       
150        ITaskTree taskTree = GenerateTaskTreeUtil.getTaskTreeFromFile(filetoparse);
151       
152        // create a simple graph for the demo
153        graph = new DelegateForest<String, Integer>();
154
155        createTree(taskTree.getRoot().getChildren().get(0));
156
157        layout = new TreeLayout<String, Integer>(graph);
158        collapser = new TreeCollapser();
159
160        radialLayout = new RadialTreeLayout<String, Integer>(graph);
161        radialLayout.setSize(new Dimension(600, 600));
162        vv = new VisualizationViewer<String, Integer>(layout, new Dimension(600, 600));
163        vv.setBackground(Color.white);
164        vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
165        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
166        vv.getRenderContext().setVertexShapeTransformer(new ClusterVertexShapeFunction());
167        // add a listener for ToolTips
168        vv.setVertexToolTipTransformer(new ToStringLabeller());
169        vv.getRenderContext()
170            .setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
171        rings = new Rings();
172
173        Container content = getContentPane();
174        final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
175        content.add(panel);
176
177        final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
178
179        vv.setGraphMouse(graphMouse);
180
181        JComboBox modeBox = graphMouse.getModeComboBox();
182        modeBox.addItemListener(graphMouse.getModeListener());
183        graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
184
185        final ScalingControl scaler = new CrossoverScalingControl();
186
187        JButton plus = new JButton("+");
188        plus.addActionListener(new ActionListener() {
189            public void actionPerformed(ActionEvent e) {
190                scaler.scale(vv, 1.1f, vv.getCenter());
191            }
192        });
193        JButton minus = new JButton("-");
194        minus.addActionListener(new ActionListener() {
195            public void actionPerformed(ActionEvent e) {
196                scaler.scale(vv, 1 / 1.1f, vv.getCenter());
197            }
198        });
199
200        JToggleButton radial = new JToggleButton("Radial");
201        radial.addItemListener(new ItemListener() {
202
203            public void itemStateChanged(ItemEvent e) {
204                if (e.getStateChange() == ItemEvent.SELECTED) {
205                    // layout.setRadial(true);
206                    vv.setGraphLayout(radialLayout);
207                    vv.getRenderContext().getMultiLayerTransformer().setToIdentity();
208                    vv.addPreRenderPaintable(rings);
209                }
210                else {
211                    // layout.setRadial(false);
212                    vv.setGraphLayout(layout);
213                    vv.getRenderContext().getMultiLayerTransformer().setToIdentity();
214                    vv.removePreRenderPaintable(rings);
215                }
216                vv.repaint();
217            }
218        });
219
220        JButton collapse = new JButton("Collapse");
221        collapse.addActionListener(new ActionListener() {
222
223            public void actionPerformed(ActionEvent e) {
224                Collection picked = new HashSet(vv.getPickedVertexState().getPicked());
225                if (picked.size() == 1) {
226                    Object root = picked.iterator().next();
227                    Forest inGraph = (Forest) layout.getGraph();
228
229                    try {
230                        collapser.collapse(vv.getGraphLayout(), inGraph, root);
231                    }
232                    catch (InstantiationException e1) {
233                        // TODO Auto-generated catch block
234                        e1.printStackTrace();
235                    }
236                    catch (IllegalAccessException e1) {
237                        // TODO Auto-generated catch block
238                        e1.printStackTrace();
239                    }
240
241                    vv.getPickedVertexState().clear();
242                    vv.repaint();
243                }
244            }
245        });
246
247        JButton expand = new JButton("Expand");
248        expand.addActionListener(new ActionListener() {
249
250            public void actionPerformed(ActionEvent e) {
251                Collection picked = vv.getPickedVertexState().getPicked();
252                for (Object v : picked) {
253                    if (v instanceof Forest) {
254                        Forest inGraph = (Forest) layout.getGraph();
255                        collapser.expand(inGraph, (Forest) v);
256                    }
257                    vv.getPickedVertexState().clear();
258                    vv.repaint();
259                }
260            }
261        });
262
263        JPanel scaleGrid = new JPanel(new GridLayout(1, 0));
264        scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom"));
265
266        JPanel controls = new JPanel();
267        scaleGrid.add(plus);
268        scaleGrid.add(minus);
269        controls.add(radial);
270        controls.add(scaleGrid);
271        controls.add(modeBox);
272        controls.add(collapse);
273        controls.add(expand);
274        content.add(controls, BorderLayout.SOUTH);
275    }
276   
277    class Rings implements VisualizationServer.Paintable {
278
279        Collection<Double> depths;
280
281        public Rings() {
282            depths = getDepths();
283        }
284
285        private Collection<Double> getDepths() {
286            Set<Double> depths = new HashSet<Double>();
287            Map<String, PolarPoint> polarLocations = radialLayout.getPolarLocations();
288            for (String v : graph.getVertices()) {
289                PolarPoint pp = polarLocations.get(v);
290                depths.add(pp.getRadius());
291            }
292            return depths;
293        }
294
295        public void paint(Graphics g) {
296            g.setColor(Color.lightGray);
297
298            Graphics2D g2d = (Graphics2D) g;
299            Point2D center = radialLayout.getCenter();
300
301            Ellipse2D ellipse = new Ellipse2D.Double();
302            for (double d : depths) {
303                ellipse.setFrameFromDiagonal(center.getX() - d, center.getY() - d, center.getX() +
304                    d, center.getY() + d);
305                Shape shape =
306                    vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT)
307                        .transform(ellipse);
308                g2d.draw(shape);
309            }
310        }
311
312        public boolean useTransform() {
313            return true;
314        }
315    }
316
317    /**
318     * @param taskTree
319     *
320     */
321    private void createTree(ITaskTreeNode node) {
322        Queue<ITaskTreeNode> unvisitedNodes = new LinkedList<ITaskTreeNode>();
323        unvisitedNodes.add(node);
324        while (stillUnvisitedNodes(unvisitedNodes)) {
325            ITaskTreeNode node2 = unvisitedNodes.poll();
326            graph.addVertex(node2.toString());
327            for (ITaskTreeNode child : node2.getChildren()) {
328                graph.addEdge(edgeFactory.create(), node2.toString(), child.toString());
329                unvisitedNodes.add(child);
330            }
331        }
332    }
333
334    private boolean stillUnvisitedNodes(Queue<ITaskTreeNode> unvisitedNodes) {
335        return !unvisitedNodes.isEmpty();
336    }
337
338    /**
339     * a demo class that will create a vertex shape that is either a polygon or star. The number of
340     * sides corresponds to the number of vertices that were collapsed into the vertex represented
341     * by this shape.
342     *
343     * @author Tom Nelson
344     *
345     * @param <V>
346     */
347    class ClusterVertexShapeFunction<V> extends EllipseVertexShapeTransformer<V> {
348
349        ClusterVertexShapeFunction() {
350            setSizeTransformer(new ClusterVertexSizeFunction<V>(20));
351        }
352
353        @Override
354        public Shape transform(V v) {
355            if (v instanceof Graph) {
356                int size = ((Graph<?, ?>) v).getVertexCount();
357                if (size < 8) {
358                    int sides = Math.max(size, 3);
359                    return factory.getRegularPolygon(v, sides);
360                }
361                else {
362                    return factory.getRegularStar(v, size);
363                }
364            }
365            return super.transform(v);
366        }
367    }
368
369    /**
370     * A demo class that will make vertices larger if they represent a collapsed collection of
371     * original vertices
372     *
373     * @author Tom Nelson
374     *
375     * @param <V>
376     */
377    class ClusterVertexSizeFunction<V> implements Transformer<V, Integer> {
378        int size;
379
380        public ClusterVertexSizeFunction(Integer size) {
381            this.size = size;
382        }
383
384        public Integer transform(V v) {
385            if (v instanceof Graph) {
386                return 30;
387            }
388            return size;
389        }
390    }
391}
Note: See TracBrowser for help on using the repository browser.