KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > prefuse > demos > AggregateDemo


1 /**
2  * Copyright (c) 2004-2006 Regents of the University of California.
3  * See "license-prefuse.txt" for licensing terms.
4  */

5 package prefuse.demos;
6
7 import java.awt.Cursor JavaDoc;
8 import java.awt.event.MouseEvent JavaDoc;
9 import java.awt.geom.Point2D JavaDoc;
10 import java.awt.geom.Rectangle2D JavaDoc;
11 import java.util.Iterator JavaDoc;
12
13 import javax.swing.JFrame JavaDoc;
14 import javax.swing.SwingUtilities JavaDoc;
15
16 import prefuse.Constants;
17 import prefuse.Display;
18 import prefuse.Visualization;
19 import prefuse.action.ActionList;
20 import prefuse.action.RepaintAction;
21 import prefuse.action.assignment.ColorAction;
22 import prefuse.action.assignment.DataColorAction;
23 import prefuse.action.layout.Layout;
24 import prefuse.action.layout.graph.ForceDirectedLayout;
25 import prefuse.activity.Activity;
26 import prefuse.controls.ControlAdapter;
27 import prefuse.controls.PanControl;
28 import prefuse.controls.ZoomControl;
29 import prefuse.data.Graph;
30 import prefuse.data.Node;
31 import prefuse.render.DefaultRendererFactory;
32 import prefuse.render.PolygonRenderer;
33 import prefuse.render.Renderer;
34 import prefuse.render.ShapeRenderer;
35 import prefuse.util.ColorLib;
36 import prefuse.util.GraphicsLib;
37 import prefuse.visual.AggregateItem;
38 import prefuse.visual.AggregateTable;
39 import prefuse.visual.VisualGraph;
40 import prefuse.visual.VisualItem;
41
42
43 /**
44  * Demo application showcasing the use of AggregateItems to
45  * visualize groupings of nodes with in a graph visualization.
46  *
47  * This class uses the AggregateLayout class to compute bounding
48  * polygons for each aggregate and the AggregateDragControl to
49  * enable drags of both nodes and node aggregates.
50  *
51  * @author <a HREF="http://jheer.org">jeffrey heer</a>
52  */

53 public class AggregateDemo extends Display {
54
55     public static final String JavaDoc GRAPH = "graph";
56     public static final String JavaDoc NODES = "graph.nodes";
57     public static final String JavaDoc EDGES = "graph.edges";
58     public static final String JavaDoc AGGR = "aggregates";
59     
60     public AggregateDemo() {
61         // initialize display and data
62
super(new Visualization());
63         initDataGroups();
64         
65         // set up the renderers
66
// draw the nodes as basic shapes
67
Renderer nodeR = new ShapeRenderer(20);
68         // draw aggregates as polygons with curved edges
69
Renderer polyR = new PolygonRenderer(Constants.POLY_TYPE_CURVE);
70         ((PolygonRenderer)polyR).setCurveSlack(0.15f);
71         
72         DefaultRendererFactory drf = new DefaultRendererFactory();
73         drf.setDefaultRenderer(nodeR);
74         drf.add("ingroup('aggregates')", polyR);
75         m_vis.setRendererFactory(drf);
76         
77         // set up the visual operators
78
// first set up all the color actions
79
ColorAction nStroke = new ColorAction(NODES, VisualItem.STROKECOLOR);
80         nStroke.setDefaultColor(ColorLib.gray(100));
81         nStroke.add("_hover", ColorLib.gray(50));
82         
83         ColorAction nFill = new ColorAction(NODES, VisualItem.FILLCOLOR);
84         nFill.setDefaultColor(ColorLib.gray(255));
85         nFill.add("_hover", ColorLib.gray(200));
86         
87         ColorAction nEdges = new ColorAction(EDGES, VisualItem.STROKECOLOR);
88         nEdges.setDefaultColor(ColorLib.gray(100));
89         
90         ColorAction aStroke = new ColorAction(AGGR, VisualItem.STROKECOLOR);
91         aStroke.setDefaultColor(ColorLib.gray(200));
92         aStroke.add("_hover", ColorLib.rgb(255,100,100));
93         
94         int[] palette = new int[] {
95             ColorLib.rgba(255,200,200,150),
96             ColorLib.rgba(200,255,200,150),
97             ColorLib.rgba(200,200,255,150)
98         };
99         ColorAction aFill = new DataColorAction(AGGR, "id",
100                 Constants.NOMINAL, VisualItem.FILLCOLOR, palette);
101         
102         // bundle the color actions
103
ActionList colors = new ActionList();
104         colors.add(nStroke);
105         colors.add(nFill);
106         colors.add(nEdges);
107         colors.add(aStroke);
108         colors.add(aFill);
109         
110         // now create the main layout routine
111
ActionList layout = new ActionList(Activity.INFINITY);
112         layout.add(colors);
113         layout.add(new ForceDirectedLayout(GRAPH, true));
114         layout.add(new AggregateLayout(AGGR));
115         layout.add(new RepaintAction());
116         m_vis.putAction("layout", layout);
117         
118         // set up the display
119
setSize(500,500);
120         pan(250, 250);
121         setHighQuality(true);
122         addControlListener(new AggregateDragControl());
123         addControlListener(new ZoomControl());
124         addControlListener(new PanControl());
125         
126         // set things running
127
m_vis.run("layout");
128     }
129     
130     private void initDataGroups() {
131         // create sample graph
132
// 9 nodes broken up into 3 interconnected cliques
133
Graph g = new Graph();
134         for ( int i=0; i<3; ++i ) {
135             Node n1 = g.addNode();
136             Node n2 = g.addNode();
137             Node n3 = g.addNode();
138             g.addEdge(n1, n2);
139             g.addEdge(n1, n3);
140             g.addEdge(n2, n3);
141         }
142         g.addEdge(0, 3);
143         g.addEdge(3, 6);
144         g.addEdge(6, 0);
145         
146         // add visual data groups
147
VisualGraph vg = m_vis.addGraph(GRAPH, g);
148         m_vis.setInteractive(EDGES, null, false);
149         m_vis.setValue(NODES, null, VisualItem.SHAPE,
150                 new Integer JavaDoc(Constants.SHAPE_ELLIPSE));
151         
152         AggregateTable at = m_vis.addAggregates(AGGR);
153         at.addColumn(VisualItem.POLYGON, float[].class);
154         at.addColumn("id", int.class);
155         
156         // add nodes to aggregates
157
// create an aggregate for each 3-clique of nodes
158
Iterator JavaDoc nodes = vg.nodes();
159         for ( int i=0; i<3; ++i ) {
160             AggregateItem aitem = (AggregateItem)at.addItem();
161             aitem.setInt("id", i);
162             for ( int j=0; j<3; ++j ) {
163                 aitem.addItem((VisualItem)nodes.next());
164             }
165         }
166     }
167     
168     public static void main(String JavaDoc[] argv) {
169         JFrame JavaDoc frame = demo();
170         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
171         frame.setVisible(true);
172     }
173     
174     public static JFrame JavaDoc demo() {
175         AggregateDemo ad = new AggregateDemo();
176         JFrame JavaDoc frame = new JFrame JavaDoc("p r e f u s e | a g g r e g a t e d");
177         frame.getContentPane().add(ad);
178         frame.pack();
179         return frame;
180     }
181     
182 } // end of class AggregateDemo
183

184
185 /**
186  * Layout algorithm that computes a convex hull surrounding
187  * aggregate items and saves it in the "_polygon" field.
188  */

189 class AggregateLayout extends Layout {
190     
191     private int m_margin = 5; // convex hull pixel margin
192
private double[] m_pts; // buffer for computing convex hulls
193

194     public AggregateLayout(String JavaDoc aggrGroup) {
195         super(aggrGroup);
196     }
197     
198     /**
199      * @see edu.berkeley.guir.prefuse.action.Action#run(edu.berkeley.guir.prefuse.ItemRegistry, double)
200      */

201     public void run(double frac) {
202         
203         AggregateTable aggr = (AggregateTable)m_vis.getGroup(m_group);
204         // do we have any to process?
205
int num = aggr.getTupleCount();
206         if ( num == 0 ) return;
207         
208         // update buffers
209
int maxsz = 0;
210         for ( Iterator JavaDoc aggrs = aggr.tuples(); aggrs.hasNext(); )
211             maxsz = Math.max(maxsz, 4*2*
212                     ((AggregateItem)aggrs.next()).getAggregateSize());
213         if ( m_pts == null || maxsz > m_pts.length ) {
214             m_pts = new double[maxsz];
215         }
216         
217         // compute and assign convex hull for each aggregate
218
Iterator JavaDoc aggrs = m_vis.visibleItems(m_group);
219         while ( aggrs.hasNext() ) {
220             AggregateItem aitem = (AggregateItem)aggrs.next();
221
222             int idx = 0;
223             if ( aitem.getAggregateSize() == 0 ) continue;
224             VisualItem item = null;
225             Iterator JavaDoc iter = aitem.items();
226             while ( iter.hasNext() ) {
227                 item = (VisualItem)iter.next();
228                 if ( item.isVisible() ) {
229                     addPoint(m_pts, idx, item, m_margin);
230                     idx += 2*4;
231                 }
232             }
233             // if no aggregates are visible, do nothing
234
if ( idx == 0 ) continue;
235
236             // compute convex hull
237
double[] nhull = GraphicsLib.convexHull(m_pts, idx);
238             
239             // prepare viz attribute array
240
float[] fhull = (float[])aitem.get(VisualItem.POLYGON);
241             if ( fhull == null || fhull.length < nhull.length )
242                 fhull = new float[nhull.length];
243             else if ( fhull.length > nhull.length )
244                 fhull[nhull.length] = Float.NaN;
245             
246             // copy hull values
247
for ( int j=0; j<nhull.length; j++ )
248                 fhull[j] = (float)nhull[j];
249             aitem.set(VisualItem.POLYGON, fhull);
250             aitem.setValidated(false); // force invalidation
251
}
252     }
253     
254     private static void addPoint(double[] pts, int idx,
255                                  VisualItem item, int growth)
256     {
257         Rectangle2D JavaDoc b = item.getBounds();
258         double minX = (b.getMinX())-growth, minY = (b.getMinY())-growth;
259         double maxX = (b.getMaxX())+growth, maxY = (b.getMaxY())+growth;
260         pts[idx] = minX; pts[idx+1] = minY;
261         pts[idx+2] = minX; pts[idx+3] = maxY;
262         pts[idx+4] = maxX; pts[idx+5] = minY;
263         pts[idx+6] = maxX; pts[idx+7] = maxY;
264     }
265     
266 } // end of class AggregateLayout
267

268
269 /**
270  * Interactive drag control that is "aggregate-aware"
271  */

272 class AggregateDragControl extends ControlAdapter {
273
274     private VisualItem activeItem;
275     protected Point2D JavaDoc down = new Point2D.Double JavaDoc();
276     protected Point2D JavaDoc temp = new Point2D.Double JavaDoc();
277     protected boolean dragged;
278     
279     /**
280      * Creates a new drag control that issues repaint requests as an item
281      * is dragged.
282      */

283     public AggregateDragControl() {
284     }
285         
286     /**
287      * @see prefuse.controls.Control#itemEntered(prefuse.visual.VisualItem, java.awt.event.MouseEvent)
288      */

289     public void itemEntered(VisualItem item, MouseEvent JavaDoc e) {
290         Display d = (Display)e.getSource();
291         d.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
292         activeItem = item;
293         if ( !(item instanceof AggregateItem) )
294             setFixed(item, true);
295     }
296     
297     /**
298      * @see prefuse.controls.Control#itemExited(prefuse.visual.VisualItem, java.awt.event.MouseEvent)
299      */

300     public void itemExited(VisualItem item, MouseEvent JavaDoc e) {
301         if ( activeItem == item ) {
302             activeItem = null;
303             setFixed(item, false);
304         }
305         Display d = (Display)e.getSource();
306         d.setCursor(Cursor.getDefaultCursor());
307     }
308     
309     /**
310      * @see prefuse.controls.Control#itemPressed(prefuse.visual.VisualItem, java.awt.event.MouseEvent)
311      */

312     public void itemPressed(VisualItem item, MouseEvent JavaDoc e) {
313         if (!SwingUtilities.isLeftMouseButton(e)) return;
314         dragged = false;
315         Display d = (Display)e.getComponent();
316         d.getAbsoluteCoordinate(e.getPoint(), down);
317         if ( item instanceof AggregateItem )
318             setFixed(item, true);
319     }
320     
321     /**
322      * @see prefuse.controls.Control#itemReleased(prefuse.visual.VisualItem, java.awt.event.MouseEvent)
323      */

324     public void itemReleased(VisualItem item, MouseEvent JavaDoc e) {
325         if (!SwingUtilities.isLeftMouseButton(e)) return;
326         if ( dragged ) {
327             activeItem = null;
328             setFixed(item, false);
329             dragged = false;
330         }
331     }
332     
333     /**
334      * @see prefuse.controls.Control#itemDragged(prefuse.visual.VisualItem, java.awt.event.MouseEvent)
335      */

336     public void itemDragged(VisualItem item, MouseEvent JavaDoc e) {
337         if (!SwingUtilities.isLeftMouseButton(e)) return;
338         dragged = true;
339         Display d = (Display)e.getComponent();
340         d.getAbsoluteCoordinate(e.getPoint(), temp);
341         double dx = temp.getX()-down.getX();
342         double dy = temp.getY()-down.getY();
343         
344         move(item, dx, dy);
345         
346         down.setLocation(temp);
347     }
348
349     protected static void setFixed(VisualItem item, boolean fixed) {
350         if ( item instanceof AggregateItem ) {
351             Iterator JavaDoc items = ((AggregateItem)item).items();
352             while ( items.hasNext() ) {
353                 setFixed((VisualItem)items.next(), fixed);
354             }
355         } else {
356             item.setFixed(fixed);
357         }
358     }
359     
360     protected static void move(VisualItem item, double dx, double dy) {
361         if ( item instanceof AggregateItem ) {
362             Iterator JavaDoc items = ((AggregateItem)item).items();
363             while ( items.hasNext() ) {
364                 move((VisualItem)items.next(), dx, dy);
365             }
366         } else {
367             double x = item.getX();
368             double y = item.getY();
369             item.setStartX(x); item.setStartY(y);
370             item.setX(x+dx); item.setY(y+dy);
371             item.setEndX(x+dx); item.setEndY(y+dy);
372         }
373     }
374     
375 } // end of class AggregateDragControl
Popular Tags