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

Last change on this file since 1040 was 1040, checked in by adeicke, 11 years ago
  • Removed lombok related annotations and util class
  • Added comments and formating due to match project defaults
  • 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(
148        { "unchecked", "rawtypes" })
149    public TaskTreeVisualizerDemoApp(String filetoparse) {
150
151        ITaskTree taskTree = GenerateTaskTreeUtil.getTaskTreeFromFile(filetoparse);
152
153        // create a simple graph for the demo
154        graph = new DelegateForest<String, Integer>();
155
156        createTree(taskTree.getRoot().getChildren().get(0));
157
158        layout = new TreeLayout<String, Integer>(graph);
159        collapser = new TreeCollapser();
160
161        radialLayout = new RadialTreeLayout<String, Integer>(graph);
162        radialLayout.setSize(new Dimension(600, 600));
163        vv = new VisualizationViewer<String, Integer>(layout, new Dimension(600, 600));
164        vv.setBackground(Color.white);
165        vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
166        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
167        vv.getRenderContext().setVertexShapeTransformer(new ClusterVertexShapeFunction());
168        // add a listener for ToolTips
169        vv.setVertexToolTipTransformer(new ToStringLabeller());
170        vv.getRenderContext()
171            .setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
172        rings = new Rings();
173
174        Container content = getContentPane();
175        final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
176        content.add(panel);
177
178        final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
179
180        vv.setGraphMouse(graphMouse);
181
182        JComboBox modeBox = graphMouse.getModeComboBox();
183        modeBox.addItemListener(graphMouse.getModeListener());
184        graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
185
186        final ScalingControl scaler = new CrossoverScalingControl();
187
188        JButton plus = new JButton("+");
189        plus.addActionListener(new ActionListener() {
190            public void actionPerformed(ActionEvent e) {
191                scaler.scale(vv, 1.1f, vv.getCenter());
192            }
193        });
194        JButton minus = new JButton("-");
195        minus.addActionListener(new ActionListener() {
196            public void actionPerformed(ActionEvent e) {
197                scaler.scale(vv, 1 / 1.1f, vv.getCenter());
198            }
199        });
200
201        JToggleButton radial = new JToggleButton("Radial");
202        radial.addItemListener(new ItemListener() {
203
204            public void itemStateChanged(ItemEvent e) {
205                if (e.getStateChange() == ItemEvent.SELECTED) {
206                    // layout.setRadial(true);
207                    vv.setGraphLayout(radialLayout);
208                    vv.getRenderContext().getMultiLayerTransformer().setToIdentity();
209                    vv.addPreRenderPaintable(rings);
210                }
211                else {
212                    // layout.setRadial(false);
213                    vv.setGraphLayout(layout);
214                    vv.getRenderContext().getMultiLayerTransformer().setToIdentity();
215                    vv.removePreRenderPaintable(rings);
216                }
217                vv.repaint();
218            }
219        });
220
221        JButton collapse = new JButton("Collapse");
222        collapse.addActionListener(new ActionListener() {
223
224            public void actionPerformed(ActionEvent e) {
225                Collection picked = new HashSet(vv.getPickedVertexState().getPicked());
226                if (picked.size() == 1) {
227                    Object root = picked.iterator().next();
228                    Forest inGraph = (Forest) layout.getGraph();
229
230                    try {
231                        collapser.collapse(vv.getGraphLayout(), inGraph, root);
232                    }
233                    catch (InstantiationException e1) {
234                        // TODO Auto-generated catch block
235                        e1.printStackTrace();
236                    }
237                    catch (IllegalAccessException e1) {
238                        // TODO Auto-generated catch block
239                        e1.printStackTrace();
240                    }
241
242                    vv.getPickedVertexState().clear();
243                    vv.repaint();
244                }
245            }
246        });
247
248        JButton expand = new JButton("Expand");
249        expand.addActionListener(new ActionListener() {
250
251            public void actionPerformed(ActionEvent e) {
252                Collection picked = vv.getPickedVertexState().getPicked();
253                for (Object v : picked) {
254                    if (v instanceof Forest) {
255                        Forest inGraph = (Forest) layout.getGraph();
256                        collapser.expand(inGraph, (Forest) v);
257                    }
258                    vv.getPickedVertexState().clear();
259                    vv.repaint();
260                }
261            }
262        });
263
264        JPanel scaleGrid = new JPanel(new GridLayout(1, 0));
265        scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom"));
266
267        JPanel controls = new JPanel();
268        scaleGrid.add(plus);
269        scaleGrid.add(minus);
270        controls.add(radial);
271        controls.add(scaleGrid);
272        controls.add(modeBox);
273        controls.add(collapse);
274        controls.add(expand);
275        content.add(controls, BorderLayout.SOUTH);
276    }
277
278    class Rings implements VisualizationServer.Paintable {
279
280        Collection<Double> depths;
281
282        public Rings() {
283            depths = getDepths();
284        }
285
286        private Collection<Double> getDepths() {
287            Set<Double> depths = new HashSet<Double>();
288            Map<String, PolarPoint> polarLocations = radialLayout.getPolarLocations();
289            for (String v : graph.getVertices()) {
290                PolarPoint pp = polarLocations.get(v);
291                depths.add(pp.getRadius());
292            }
293            return depths;
294        }
295
296        public void paint(Graphics g) {
297            g.setColor(Color.lightGray);
298
299            Graphics2D g2d = (Graphics2D) g;
300            Point2D center = radialLayout.getCenter();
301
302            Ellipse2D ellipse = new Ellipse2D.Double();
303            for (double d : depths) {
304                ellipse.setFrameFromDiagonal(center.getX() - d, center.getY() - d, center.getX() +
305                    d, center.getY() + d);
306                Shape shape =
307                    vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT)
308                        .transform(ellipse);
309                g2d.draw(shape);
310            }
311        }
312
313        public boolean useTransform() {
314            return true;
315        }
316    }
317
318    /**
319     * @param taskTree
320     *
321     */
322    private void createTree(ITaskTreeNode node) {
323        Queue<ITaskTreeNode> unvisitedNodes = new LinkedList<ITaskTreeNode>();
324        unvisitedNodes.add(node);
325        while (stillUnvisitedNodes(unvisitedNodes)) {
326            ITaskTreeNode node2 = unvisitedNodes.poll();
327            graph.addVertex(node2.toString());
328            for (ITaskTreeNode child : node2.getChildren()) {
329                graph.addEdge(edgeFactory.create(), node2.toString(), child.toString());
330                unvisitedNodes.add(child);
331            }
332        }
333    }
334
335    private boolean stillUnvisitedNodes(Queue<ITaskTreeNode> unvisitedNodes) {
336        return !unvisitedNodes.isEmpty();
337    }
338
339    /**
340     * a demo class that will create a vertex shape that is either a polygon or star. The number of
341     * sides corresponds to the number of vertices that were collapsed into the vertex represented
342     * by this shape.
343     *
344     * @author Tom Nelson
345     *
346     * @param <V>
347     */
348    class ClusterVertexShapeFunction<V> extends EllipseVertexShapeTransformer<V> {
349
350        ClusterVertexShapeFunction() {
351            setSizeTransformer(new ClusterVertexSizeFunction<V>(20));
352        }
353
354        @Override
355        public Shape transform(V v) {
356            if (v instanceof Graph) {
357                int size = ((Graph<?, ?>) v).getVertexCount();
358                if (size < 8) {
359                    int sides = Math.max(size, 3);
360                    return factory.getRegularPolygon(v, sides);
361                }
362                else {
363                    return factory.getRegularStar(v, size);
364                }
365            }
366            return super.transform(v);
367        }
368    }
369
370    /**
371     * A demo class that will make vertices larger if they represent a collapsed collection of
372     * original vertices
373     *
374     * @author Tom Nelson
375     *
376     * @param <V>
377     */
378    class ClusterVertexSizeFunction<V> implements Transformer<V, Integer> {
379        int size;
380
381        public ClusterVertexSizeFunction(Integer size) {
382            this.size = size;
383        }
384
385        public Integer transform(V v) {
386            if (v instanceof Graph) {
387                return 30;
388            }
389            return size;
390        }
391    }
392}
Note: See TracBrowser for help on using the repository browser.