Coverage details for edu.uci.ics.jung.visualization.VisualizationViewer

LineHitsSource
1 /*
2 * Copyright (c) 2003, the JUNG Project and the Regents of the University
3 * of California
4 * All rights reserved.
5 *
6 * This software is open-source under the BSD license; see either
7 * "license.txt" or
8 * http://jung.sourceforge.net/license.txt for a description.
9 */
10 package edu.uci.ics.jung.visualization;
11  
12 import java.awt.Dimension;
13 import java.awt.Graphics;
14 import java.awt.Graphics2D;
15 import java.awt.RenderingHints;
16 import java.awt.event.ComponentAdapter;
17 import java.awt.event.ComponentEvent;
18 import java.awt.event.ItemEvent;
19 import java.awt.event.ItemListener;
20 import java.awt.event.MouseAdapter;
21 import java.awt.event.MouseEvent;
22 import java.awt.event.MouseListener;
23 import java.awt.event.MouseMotionListener;
24 import java.awt.event.MouseWheelEvent;
25 import java.awt.event.MouseWheelListener;
26 import java.awt.geom.AffineTransform;
27 import java.awt.geom.Point2D;
28 import java.awt.image.BufferedImage;
29 import java.util.ArrayList;
30 import java.util.ConcurrentModificationException;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35  
36 import javax.swing.JPanel;
37 import javax.swing.ToolTipManager;
38 import javax.swing.event.ChangeEvent;
39 import javax.swing.event.ChangeListener;
40 import javax.swing.event.EventListenerList;
41  
42 import edu.uci.ics.jung.graph.Edge;
43 import edu.uci.ics.jung.graph.Vertex;
44 import edu.uci.ics.jung.graph.decorators.ToolTipFunction;
45 import edu.uci.ics.jung.graph.decorators.ToolTipFunctionAdapter;
46 import edu.uci.ics.jung.utils.ChangeEventSupport;
47 import edu.uci.ics.jung.utils.DefaultChangeEventSupport;
48 import edu.uci.ics.jung.visualization.transform.LayoutTransformer;
49 import edu.uci.ics.jung.visualization.transform.MutableAffineTransformer;
50 import edu.uci.ics.jung.visualization.transform.MutableTransformer;
51 import edu.uci.ics.jung.visualization.transform.Transformer;
52 import edu.uci.ics.jung.visualization.transform.ViewTransformer;
53  
54 /**
55  * A class that maintains many of the details necessary for creating
56  * visualizations of graphs.
57  *
58  * @author Joshua O'Madadhain
59  * @author Tom Nelson
60  * @author Danyel Fisher
61  */
62 public class VisualizationViewer extends JPanel
63                 implements Transformer, LayoutTransformer, ViewTransformer,
64                 HasGraphLayout, ChangeListener, ChangeEventSupport{
65  
660    protected ChangeEventSupport changeSupport =
67         new DefaultChangeEventSupport(this);
68  
69     /**
70      * holds the state of this View
71      */
72     protected VisualizationModel model;
73  
74     /**
75      * handles the actual drawing of graph elements
76      */
77     protected Renderer renderer;
78     
79     /** should be set to user-defined class to provide
80      * tooltips on the graph elements
81      */
82     protected ToolTipFunction toolTipFunction;
83     
84     /**
85      * rendering hints used in drawing. Anti-aliasing is on
86      * by default
87      */
880    protected Map renderingHints = new HashMap();
89         
90     /**
91      * pluggable support for picking graph elements by
92      * finding them based on their coordinates. Typically
93      * used in mouse events.
94      */
95     protected PickSupport pickSupport;
96     
97     /**
98      * holds the state of which elements of the graph are
99      * currently 'picked'
100      */
101     protected PickedState pickedState;
102     
103     /**
104      * a listener used to cause pick events to result in
105      * repaints, even if they come from another view
106      */
107     protected ItemListener pickEventListener;
108     
109     /**
110      * an offscreen image to render the graph
111      * Used if doubleBuffered is set to true
112      */
113     protected BufferedImage offscreen;
114     
115     /**
116      * graphics context for the offscreen image
117      * Used if doubleBuffered is set to true
118      */
119     protected Graphics2D offscreenG2d;
120     
121     /**
122      * user-settable choice to use the offscreen image
123      * or not. 'false' by default
124      */
125     protected boolean doubleBuffered;
126     
127     /**
128      * Provides support for mutating the AffineTransform that
129      * is supplied to the rendering Graphics2D
130      */
1310    protected MutableTransformer viewTransformer =
132         new MutableAffineTransformer(new AffineTransform());
133     
1340    protected MutableTransformer layoutTransformer =
135         new MutableAffineTransformer(new AffineTransform());
136     
137     /**
138      * a collection of user-implementable functions to render under
139      * the topology (before the graph is rendered)
140      */
1410    protected List preRenderers = new ArrayList();
142     
143     /**
144      * a collection of user-implementable functions to render over the
145      * topology (after the graph is rendered)
146      */
1470    protected List postRenderers = new ArrayList();
148     
149     /**
150      * provides MouseListener, MouseMotionListener, and MouseWheelListener
151      * events to the graph
152      */
153     protected GraphMouse graphMouse;
154     
155     /**
156      * if true, then when the View is resized, the current Layout
157      * is resized to the same size.
158      */
159 // protected boolean lockLayoutToViewSize;
160     
1610    protected Map locationMap = new HashMap();
162  
163     /**
164      * Create an instance with passed parameters.
165      *
166      * @param layout The Layout to apply, with its associated Graph
167      * @param renderer The Renderer to draw it with
168      */
169     public VisualizationViewer(Layout layout, Renderer renderer) {
1700        this(new DefaultVisualizationModel(layout), renderer);
1710    }
172     
173     /**
174      * Create an instance with passed parameters.
175      *
176      * @param layout The Layout to apply, with its associated Graph
177      * @param renderer The Renderer to draw it with
178      * @param preferredSize the preferred size of this View
179      */
180     public VisualizationViewer(Layout layout, Renderer renderer, Dimension preferredSize) {
1810        this(new DefaultVisualizationModel(layout, preferredSize), renderer, preferredSize);
1820    }
183     
184     /**
185      * Create an instance with passed parameters.
186      *
187      * @param model
188      * @param renderer
189      */
190     public VisualizationViewer(VisualizationModel model, Renderer renderer) {
1910        this(model, renderer, new Dimension(600,600));
1920    }
193     /**
194      * Create an instance with passed parameters.
195      *
196      * @param model
197      * @param renderer
198      * @param preferredSize initial preferred size of the view
199      */
200     public VisualizationViewer(VisualizationModel model, Renderer renderer,
2010            Dimension preferredSize) {
2020        this.model = model;
2030        model.addChangeListener(this);
2040        setDoubleBuffered(false);
2050        this.addComponentListener(new VisualizationListener(this));
206  
2070        setPickSupport(new ClassicPickSupport());
2080        setPickedState(new MultiPickedState());
2090        setRenderer(renderer);
2100        renderer.setPickedKey(pickedState);
211         
2120        setPreferredSize(preferredSize);
2130        renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
2140        initMouseClicker();
2150        scaleToLayout(model.getGraphLayout().getCurrentSize());
2160        this.layoutTransformer.addChangeListener(this);
2170        this.viewTransformer.addChangeListener(this);
2180    }
219     
220     /**
221      * set whether this class uses its offscreen image or not. If
222      * true, then doubleBuffering in the superclass is set to 'false'
223      */
224     public void setDoubleBuffered(boolean doubleBuffered) {
2250        this.doubleBuffered = doubleBuffered;
2260    }
227     
228     /**
229      * whether this class uses double buffering. The superclass
230      * will be the opposite state.
231      */
232     public boolean isDoubleBuffered() {
2330        return doubleBuffered;
234     }
235     
236     /**
237      * Ensure that, if doubleBuffering is enabled, the offscreen
238      * image buffer exists and is the correct size.
239      * @param d
240      */
241     protected void checkOffscreenImage(Dimension d) {
2420        if(doubleBuffered) {
2430            if(offscreen == null || offscreen.getWidth() != d.width || offscreen.getHeight() != d.height) {
2440                offscreen = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
2450                offscreenG2d = offscreen.createGraphics();
246             }
247         }
2480    }
249     
250     /**
251      * @return Returns the model.
252      */
253     public VisualizationModel getModel() {
2540        return model;
255     }
256     /**
257      * @param model The model to set.
258      */
259     public void setModel(VisualizationModel model) {
2600        this.model = model;
2610    }
262     /**
263      * In response to changes from the model, repaint the
264      * view, then fire an event to any listeners.
265      * Examples of listeners are the GraphZoomScrollPane and
266      * the BirdsEyeVisualizationViewer
267      */
268     public void stateChanged(ChangeEvent e) {
2690        repaint();
2700        fireStateChanged();
2710    }
272     
273     /**
274      * Creates a default mouseClicker behavior: a default.
275      * @see GraphMouseImpl
276      * @deprecated replaced by setGraphMouse()
277      */
278     protected void initMouseClicker() {
279         // GraphMouseImpl will give original behavior
2800        setGraphMouse(new GraphMouseImpl() );
2810    }
282     
283     /**
284      * convenience pass-thru to model
285      * @param scb
286      */
287     public void setTextCallback(StatusCallback scb) {
2880        model.setTextCallback(scb);
2890    }
290     
291     /**
292      * a setter for the GraphMouse. This will remove any
293      * previous GraphMouse (including the one that
294      * is added in the initMouseClicker method.
295      * @param graphMouse new value
296      */
297     public void setGraphMouse(GraphMouse graphMouse) {
2980        this.graphMouse = graphMouse;
2990        MouseListener[] ml = getMouseListeners();
3000        for(int i=0; i<ml.length; i++) {
3010            if(ml[i] instanceof GraphMouse) {
3020                removeMouseListener(ml[i]);
303             }
304         }
3050        MouseMotionListener[] mml = getMouseMotionListeners();
3060        for(int i=0; i<mml.length; i++) {
3070            if(mml[i] instanceof GraphMouse) {
3080                removeMouseMotionListener(mml[i]);
309             }
310         }
3110        MouseWheelListener[] mwl = getMouseWheelListeners();
3120        for(int i=0; i<mwl.length; i++) {
3130            if(mwl[i] instanceof GraphMouse) {
3140                removeMouseWheelListener(mwl[i]);
315             }
316         }
3170        addMouseListener(graphMouse);
3180        addMouseMotionListener(graphMouse);
3190        addMouseWheelListener(graphMouse);
3200    }
321     
322     /**
323      * @return the current <code>GraphMouse</code>
324      */
325     public GraphMouse getGraphMouse() {
3260        return graphMouse;
327     }
328  
329     /**
330      * Sets the showing Renderer to be the input Renderer. Also
331      * tells the Renderer to refer to this visualizationviewer
332      * as a PickedKey. (Because Renderers maintain a small
333      * amount of state, such as the PickedKey, it is important
334      * to create a separate instance for each VV instance.)
335      */
336     public void setRenderer(Renderer r) {
3370        this.renderer = r;
3380        if(renderer instanceof PluggableRenderer) {
3390            PluggableRenderer pr = (PluggableRenderer)renderer;
3400            pr.setScreenDevice(this);
3410            pr.setViewTransformer(getViewTransformer());
342             
3430            if(pickSupport instanceof ShapePickSupport) {
3440                ((ShapePickSupport)pickSupport).setHasShapes((HasShapeFunctions)renderer);
345             }
346         }
347         
3480        r.setPickedKey(pickedState);
3490        repaint();
3500    }
351     
352     /**
353      * Returns the renderer used by this instance.
354      */
355     public Renderer getRenderer() {
3560        return renderer;
357     }
358  
359     /**
360      * Removes the current graph layout, and adds a new one.
361      * @param layout the new layout to set
362      */
363     public void setGraphLayout(Layout layout) {
3640        setGraphLayout(layout, true);
3650    }
366     /**
367      * Removes the current graph layout, and adds a new one,
368      * optionally re-scaling the view to show the entire layout
369      * @param layout the new layout to set
370      * @param scaleToLayout whether to scale the view to show the whole layout
371      */
372     public void setGraphLayout(Layout layout, boolean scaleToLayout) {
373  
3740        Dimension viewSize = getSize();
3750        if(viewSize.width <= 0 || viewSize.height <= 0) {
3760            viewSize = getPreferredSize();
377         }
3780        model.setGraphLayout(layout, viewSize);
3790        if(scaleToLayout) scaleToLayout(layout.getCurrentSize());
3800    }
381     
382     protected void scaleToLayout(Dimension layoutSize) {
3830        Dimension viewSize = getSize();
3840        if(viewSize.width == 0 || viewSize.height == 0) {
3850            viewSize = getPreferredSize();
386         }
3870        float scalex = (float)viewSize.width/layoutSize.width;
3880        float scaley = (float)viewSize.height/layoutSize.height;
3890        float scale = 1;
3900        if(scalex - 1 < scaley - 1) {
3910                scale = scalex;
392         } else {
3930                scale = scaley;
394         }
395         // set scale to show the entire graph layout
3960        viewTransformer.setScale(scale, scale, new Point2D.Float());
3970    }
398     
399     /**
400      * Returns the current graph layout.
401      * Passes thru to the model
402      */
403     public Layout getGraphLayout() {
4040            return model.getGraphLayout();
405     }
406     
407     /**
408      * This is the interface for adding a mouse listener. The GEL
409      * will be called back with mouse clicks on vertices.
410      * @param gel
411      */
412     public void addGraphMouseListener( GraphMouseListener gel ) {
4130        addMouseListener( new MouseListenerTranslator( gel, this ));
4140    }
415     
416     /**
417      * Pre-relaxes and starts a visRunner thread
418      * Passes thru to the model
419      */
420     public synchronized void init() {
4210        model.init();
4220    }
423  
424     /**
425      * Restarts layout, then calls init();
426      * passes thru to the model
427      */
428     public synchronized void restart() {
4290        model.restart();
4300    }
431  
432     /**
433      *
434      * @see javax.swing.JComponent#setVisible(boolean)
435      */
436     public void setVisible(boolean aFlag) {
4370        super.setVisible(aFlag);
4380        model.getGraphLayout().resize(this.getSize());
4390    }
440  
441     /**
442      * convenience pass-thru to the model
443      */
444     public void prerelax() {
4450        model.prerelax();
4460    }
447  
448     /**
449      * convenience pass-thru to the model
450      */
451     protected synchronized void start() {
4520        model.start();
4530    }
454  
455     /**
456      * convenience pass-thru to the model
457      *
458      */
459     public synchronized void suspend() {
4600        model.suspend();
4610    }
462  
463     /**
464      * convenience pass-thru to the model
465      *
466      */
467     public synchronized void unsuspend() {
4680        model.unsuspend();
4690    }
470  
471     /**
472      * @deprecated Use <code>getPickedState.isPicked(e)</code>.
473      */
474     public boolean isPicked(Vertex v) {
4750        return pickedState.isPicked(v);
476     }
477     
478     /**
479      * @deprecated Use <code>getPickedState.isPicked(e)</code>.
480      */
481     public boolean isPicked(Edge e) {
4820        return pickedState.isPicked(e);
483     }
484     
485     /**
486      * @deprecated Use <code>getPickedState.pick(picked, b)</code>.
487      */
488     protected void pick(Vertex picked, boolean b)
489     {
4900        pickedState.pick(picked, b);
4910    }
492  
4930    long[] relaxTimes = new long[5];
4940    long[] paintTimes = new long[5];
4950    int relaxIndex = 0;
4960    int paintIndex = 0;
497     double paintfps, relaxfps;
498     
499     /**
500      * Returns a flag that says whether the visRunner thread is running. If
501      * it is not, then you may need to restart the thread.
502      */
503     public boolean isVisRunnerRunning() {
5040        return model.isVisRunnerRunning();
505     }
506  
507     /**
508      * setter for the scale
509      * fires a PropertyChangeEvent with the AffineTransforms representing
510      * the previous and new values for scale and offset
511      * @deprecated access via getViewTransformer method
512      * @param scalex
513      * @param scaley
514      */
515     public void scale(double scalex, double scaley) {
5160        scale(scalex, scaley, null);
5170    }
518     /**
519      * have the model scale the graph with the passed parameters.
520      * If 'from' is null, use the center of this View as the
521      * center to scale from
522      * @deprecated access via getViewTransformer method
523      * @param scalex
524      * @param scaley
525      * @param from
526      */
527     public void scale(double scalex, double scaley, Point2D from) {
5280        if(from == null) {
5290            from = getCenter();
530         }
5310        viewTransformer.scale(scalex, scaley, from);
5320    }
533     
534     /**
535      * have the model replace the transform scale values with the
536      * passed parameters
537      * @deprecated access via getViewTransformer method
538      * @param scalex
539      * @param scaley
540      */
541     public void setScale(double scalex, double scaley) {
5420        setScale(scalex, scaley, null);
5430    }
544     
545     /**
546      * Have the model replace the transform scale values with the
547      * passed parameters. If 'from' is null, use this View's center
548      * as the center to scale from.
549      * @deprecated access via getViewTransformer method
550      * @param scalex
551      * @param scaley
552      */
553     public void setScale(double scalex, double scaley, Point2D from) {
5540        viewTransformer.setScale(scalex, scaley, from);
5550    }
556     
557     /**
558      * getter for scalex
559      * @deprecated access via getViewTransformer method
560      * @return scalex
561      */
562     public double getScaleX() {
5630        return viewTransformer.getScaleX();
564     }
565     
566     /**
567      * getter for scaley
568      * @deprecated access via getViewTransformer method
569      */
570     public double getScaleY() {
5710        return viewTransformer.getScaleY();
572     }
573     
574     /**
575      * getter for offsetx
576      * @deprecated use getTranslateX
577      */
578     public double getOffsetX() {
5790        return getTranslateX();
580     }
581     /**
582      * gets the translateX from the model
583      * @deprecated access via getViewTransformer method
584      * @return the translateX
585      */
586     public double getTranslateX() {
5870        return viewTransformer.getTranslateX();
588     }
589     
590     /**
591      * getter for offsety
592      * @deprecated use getTranslateY()
593      */
594     public double getOffsetY() {
5950        return getTranslateY();
596     }
597     
598     /**
599      * gets the translateY from the model
600      * @deprecated access via getViewTransformer method
601      * @return the translateY
602      */
603     public double getTranslateY() {
6040        return viewTransformer.getTranslateY();
605     }
606     
607     /**
608      * set the offset values that will be used in the
609      * translation component of the graph rendering transform.
610      * Changes the transform to the identity transform, then
611      * sets the translation conponents to the passed values
612      * Fires a PropertyChangeEvent with the AffineTransforms representing
613      * the previous and new values for the transform
614      * @deprecated use setTranslate(double, offset, double offset)
615      * @param offsetx
616      * @param offsety
617      */
618     public void setOffset(double offsetx, double offsety) {
6190        setTranslate(offsetx, offsety);
6200    }
621     
622     /**
623      * sets the translate x,y in the model
624      * previous translate values are lost
625      * @deprecated access via getViewTransformer method
626      * @param tx
627      * @param ty
628      */
629     public void setTranslate(double tx, double ty) {
6300        viewTransformer.setTranslate(tx, ty);
6310    }
632     
633     /**
634      * Translates the model's current transform by tX and ty.
635      * @deprecated access via getViewTransformer method
636      */
637     public void translate(double tx, double ty) {
6380        viewTransformer.translate(tx, ty);
6390    }
640     
641     /**
642      * Transform the mouse point with the inverse transform
643      * of the VisualizationViewer. This maps from screen coordinates
644      * to graph coordinates.
645      * @param p the point to transform (typically, a mouse point)
646      * @return a transformed Point2D
647      */
648     public Point2D inverseTransform(Point2D p) {
6490        return layoutTransformer.inverseTransform(inverseViewTransform(p));
650     }
651     
652     public Point2D inverseViewTransform(Point2D p) {
6530        return viewTransformer.inverseTransform(p);
654     }
655  
656     public Point2D inverseLayoutTransform(Point2D p) {
6570        return layoutTransformer.inverseTransform(p);
658     }
659  
660     /**
661      * Transform the mouse point with the current transform
662      * of the VisualizationViewer. This maps from graph coordinates
663      * to screen coordinates.
664      * @param p the point to transform
665      * @return a transformed Point2D
666      */
667     public Point2D transform(Point2D p) {
668         // transform with vv transform
6690        return viewTransformer.transform(layoutTransform(p));
670     }
671     
672     public Point2D viewTransform(Point2D p) {
6730        return viewTransformer.transform(p);
674     }
675     
676     public Point2D layoutTransform(Point2D p) {
6770        return layoutTransformer.transform(p);
678     }
679     
680     /**
681      * @param transformer The transformer to set.
682      */
683     public void setViewTransformer(MutableTransformer transformer) {
6840        this.viewTransformer.removeChangeListener(this);
6850        this.viewTransformer = transformer;
6860        this.viewTransformer.addChangeListener(this);
6870        if(renderer instanceof PluggableRenderer) {
6880            ((PluggableRenderer)renderer).setViewTransformer(transformer);
689         }
6900    }
691  
692     public void setLayoutTransformer(MutableTransformer transformer) {
6930        this.layoutTransformer.removeChangeListener(this);
6940        this.layoutTransformer = transformer;
6950        this.layoutTransformer.addChangeListener(this);
6960    }
697  
698     public MutableTransformer getViewTransformer() {
6990        return viewTransformer;
700     }
701  
702     public MutableTransformer getLayoutTransformer() {
7030        return layoutTransformer;
704     }
705  
706     /**
707      * @return Returns the renderingHints.
708      */
709     public Map getRenderingHints() {
7100        return renderingHints;
711     }
712     /**
713      * @param renderingHints The renderingHints to set.
714      */
715     public void setRenderingHints(Map renderingHints) {
7160        this.renderingHints = renderingHints;
7170    }
718     
719     protected synchronized void paintComponent(Graphics g) {
7200        super.paintComponent(g);
721  
7220        checkOffscreenImage(getSize());
7230        model.start();
724  
7250        Graphics2D g2d = (Graphics2D)g;
7260        if(doubleBuffered) {
7270            renderGraph(offscreenG2d);
7280            g2d.drawImage(offscreen, null, 0, 0);
729         } else {
7300            renderGraph(g2d);
731         }
7320    }
733     
734     protected void renderGraph(Graphics2D g2d) {
735  
7360        Layout layout = model.getGraphLayout();
737  
7380        g2d.setRenderingHints(renderingHints);
739         
7400        long start = System.currentTimeMillis();
741         
742         // the size of the VisualizationViewer
7430        Dimension d = getSize();
744         
745         // clear the offscreen image
7460        g2d.setColor(getBackground());
7470        g2d.fillRect(0,0,d.width,d.height);
748  
7490        AffineTransform oldXform = g2d.getTransform();
7500        AffineTransform newXform = new AffineTransform(oldXform);
7510        newXform.concatenate(viewTransformer.getTransform());
752         
7530        g2d.setTransform(newXform);
754  
755         // if there are preRenderers set, paint them
7560        for(Iterator iterator=preRenderers.iterator(); iterator.hasNext(); ) {
7570            Paintable paintable = (Paintable)iterator.next();
7580            if(paintable.useTransform()) {
7590                paintable.paint(g2d);
760             } else {
7610                g2d.setTransform(oldXform);
7620                paintable.paint(g2d);
7630                g2d.setTransform(newXform);
764             }
765         }
766         
7670        locationMap.clear();
768         
769         // paint all the edges
770         try {
7710        for (Iterator iter = layout.getGraph().getEdges().iterator();
7720        iter.hasNext();
773         ) {
7740            Edge e = (Edge) iter.next();
7750            Vertex v1 = (Vertex) e.getEndpoints().getFirst();
7760            Vertex v2 = (Vertex) e.getEndpoints().getSecond();
777             
7780            Point2D p = (Point2D) locationMap.get(v1);
7790            if(p == null) {
780                 
7810                p = layout.getLocation(v1);
7820                p = layoutTransformer.transform(p);
7830                locationMap.put(v1, p);
784             }
7850            Point2D q = (Point2D) locationMap.get(v2);
7860            if(q == null) {
7870                q = layout.getLocation(v2);
7880                q = layoutTransformer.transform(q);
7890                locationMap.put(v2, q);
790             }
791  
7920            if(p != null && q != null) {
7930                renderer.paintEdge(
794                         g2d,
795                         e,
796                         (int) p.getX(),
797                         (int) p.getY(),
798                         (int) q.getX(),
799                         (int) q.getY());
800             }
801         }
8020        } catch(ConcurrentModificationException cme) {
8030            repaint();
8040        }
805         
806         // paint all the vertices
807         try {
8080        for (Iterator iter = layout.getGraph().getVertices().iterator();
8090        iter.hasNext();
810         ) {
811             
8120            Vertex v = (Vertex) iter.next();
8130            Point2D p = (Point2D) locationMap.get(v);
8140            if(p == null) {
8150                p = layout.getLocation(v);
8160                p = layoutTransformer.transform(p);
8170                locationMap.put(v, p);
818             }
8190            if(p != null) {
8200                renderer.paintVertex(
821                         g2d,
822                         v,
823                         (int) p.getX(),
824                         (int) p.getY());
825             }
826         }
8270        } catch(ConcurrentModificationException cme) {
8280            repaint();
8290        }
830         
8310        long delta = System.currentTimeMillis() - start;
8320        paintTimes[paintIndex++] = delta;
8330        paintIndex = paintIndex % paintTimes.length;
8340        paintfps = average(paintTimes);
835         
836         // if there are postRenderers set, do it
8370        for(Iterator iterator=postRenderers.iterator(); iterator.hasNext(); ) {
8380            Paintable paintable = (Paintable)iterator.next();
8390            if(paintable.useTransform()) {
8400                paintable.paint(g2d);
841             } else {
8420                g2d.setTransform(oldXform);
8430                paintable.paint(g2d);
8440                g2d.setTransform(newXform);
845             }
846         }
8470        g2d.setTransform(oldXform);
8480    }
849  
850     /**
851      * Returns the double average of a number of long values.
852      * @param paintTimes an array of longs
853      * @return the average of the doubles
854      */
855     protected double average(long[] paintTimes) {
8560        double l = 0;
8570        for (int i = 0; i < paintTimes.length; i++) {
8580            l += paintTimes[i];
859         }
8600        return l / paintTimes.length;
861     }
862  
863     /**
864      * VisualizationListener reacts to changes in the size of the
865      * VisualizationViewer. When the size changes, it ensures
866      * that the offscreen image is sized properly.
867      * If the layout is locked to this view size, then the layout
868      * is also resized to be the same as the view size.
869      *
870      *
871      */
872     protected class VisualizationListener extends ComponentAdapter {
873         protected VisualizationViewer vv;
874         public VisualizationListener(VisualizationViewer vv) {
875             this.vv = vv;
876         }
877  
878         /**
879          * create a new offscreen image for the graph
880          * whenever the window is resied
881          */
882         public void componentResized(ComponentEvent e) {
883             Dimension d = vv.getSize();
884             if(d.width <= 0 || d.height <= 0) return;
885             checkOffscreenImage(d);
886         // if(getLockLayoutToViewSize()) {
887                 // model.resizeLayout(vv.getSize());
888         // }
889                 repaint();
890         }
891     }
892  
893     /**
894      * convenience pass-thru to model
895      */
896     public synchronized void stop() {
8970        model.stop();
8980    }
899  
900     /**
901      * sets the tooltip listener to the user's defined implementation
902      * of ToolTipListener
903      * @param listener the listener to ser
904      */
905     public void setToolTipListener(ToolTipListener listener) {
9060        if(listener instanceof ToolTipFunction) {
9070            setToolTipFunction((ToolTipFunction)listener);
908         } else {
9090            setToolTipFunction(new ToolTipListenerWrapper(listener));
910         }
9110    }
912  
913     public void setToolTipFunction(ToolTipFunction toolTipFunction) {
9140        this.toolTipFunction = toolTipFunction;
9150        ToolTipManager.sharedInstance().registerComponent(this);
9160    }
917     /**
918      * called by the superclass to display tooltips
919      */
920     public String getToolTipText(MouseEvent event) {
9210        if(toolTipFunction != null) {
9220            if(toolTipFunction instanceof ToolTipListenerWrapper) {
9230                return toolTipFunction.getToolTipText(event);
924             }
9250            Point2D p = inverseViewTransform(event.getPoint());
9260            Vertex vertex = pickSupport.getVertex(p.getX(), p.getY());
9270            if(vertex != null) {
9280                return toolTipFunction.getToolTipText(vertex);
929             }
9300            Edge edge = pickSupport.getEdge(p.getX(), p.getY());
9310            if(edge != null) {
9320                return toolTipFunction.getToolTipText(edge);
933             }
9340            return toolTipFunction.getToolTipText(event);
935         }
9360        return super.getToolTipText(event);
937     }
938  
939     /**
940      * The interface for the tool tip listener. Implement this
941      * interface to add custom tool tip to the graph elements.
942      * See sample code for examples
943      */
944     public interface ToolTipListener {
945             String getToolTipText(MouseEvent event);
946     }
947     
948     /**
949      * used internally to wrap any legacy ToolTipListener
950      * implementations so they can be used as a ToolTipFunction
951      * @author Tom Nelson - RABA Technologies
952      *
953      *
954      */
955     protected static class ToolTipListenerWrapper extends ToolTipFunctionAdapter {
956         ToolTipListener listener;
957         public ToolTipListenerWrapper(ToolTipListener listener) {
958             this.listener = listener;
959         }
960         public String getToolTipText(MouseEvent e) {
961             return listener.getToolTipText(e);
962         }
963     }
964     
965     /**
966      * an interface for the preRender and postRender
967      */
968     public interface Paintable {
969         public void paint(Graphics g);
970         public boolean useTransform();
971     }
972  
973     /**
974      * a convenience type to represent a class that
975      * processes all types of mouse events for the graph
976      */
977     public interface GraphMouse extends MouseListener, MouseMotionListener, MouseWheelListener {}
978     
979     /**
980      * this is the original GraphMouse class, renamed to use GraphMouse as the interface name,
981      * and updated to correctly apply the vv transform to the point point
982      *
983      */
984     protected final class GraphMouseImpl extends MouseAdapter implements GraphMouse {
985         protected Vertex picked;
986         
987         public void mousePressed(MouseEvent e) {
988             
989             Point2D p = inverseViewTransform(e.getPoint());
990  
991             Vertex v = pickSupport.getVertex(p.getX(), p.getY());
992             if (v == null) {
993                 return;
994             }
995             picked = v;
996             pick(picked, true);
997             model.getGraphLayout().forceMove(picked, p.getX(), p.getY());
998             repaint();
999         }
1000         public void mouseReleased(MouseEvent e) {
1001             if (picked == null)
1002                 return;
1003             pick(picked, false);
1004             picked = null;
1005             repaint();
1006         }
1007         public void mouseDragged(MouseEvent e) {
1008             if (picked == null)
1009                 return;
1010             Point2D p = inverseViewTransform(e.getPoint());
1011  
1012             model.getGraphLayout().forceMove(picked, p.getX(), p.getY());
1013             repaint();
1014         }
1015         
1016         public void mouseMoved(MouseEvent e) {
1017             return;
1018         }
1019         /**
1020          * @see java.awt.event.MouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent)
1021          */
1022         public void mouseWheelMoved(MouseWheelEvent e) {
1023             return;
1024         }
1025     }
1026     
1027     /**
1028      * @param paintable The paintable to add.
1029      */
1030     public void addPreRenderPaintable(Paintable paintable) {
10310        if(preRenderers == null) {
10320            preRenderers = new ArrayList();
1033         }
10340        preRenderers.add(paintable);
10350    }
1036     
1037     /**
1038      * @param paintable The paintable to remove.
1039      */
1040     public void removePreRenderPaintable(Paintable paintable) {
10410        if(preRenderers != null) {
10420            preRenderers.remove(paintable);
1043         }
10440    }
1045     
1046     /**
1047      * @param paintable The paintable to add.
1048      */
1049     public void addPostRenderPaintable(Paintable paintable) {
10500        if(postRenderers == null) {
10510            postRenderers = new ArrayList();
1052         }
10530        postRenderers.add(paintable);
10540    }
1055     
1056     /**
1057      * @param paintable The paintable to remove.
1058      */
1059    public void removePostRenderPaintable(Paintable paintable) {
10600        if(postRenderers != null) {
10610            postRenderers.remove(paintable);
1062         }
10630    }
1064  
1065     /**
1066      * Adds a <code>ChangeListener</code>.
1067      * @param l the listener to be added
1068      */
1069     public void addChangeListener(ChangeListener l) {
10700        changeSupport.addChangeListener(l);
10710    }
1072     
1073     /**
1074      * Removes a ChangeListener.
1075      * @param l the listener to be removed
1076      */
1077     public void removeChangeListener(ChangeListener l) {
10780        changeSupport.removeChangeListener(l);
10790    }
1080     
1081     /**
1082      * Returns an array of all the <code>ChangeListener</code>s added
1083      * with addChangeListener().
1084      *
1085      * @return all of the <code>ChangeListener</code>s added or an empty
1086      * array if no listeners have been added
1087      */
1088     public ChangeListener[] getChangeListeners() {
10890        return changeSupport.getChangeListeners();
1090     }
1091  
1092     /**
1093      * Notifies all listeners that have registered interest for
1094      * notification on this event type. The event instance
1095      * is lazily created.
1096      * @see EventListenerList
1097      */
1098     public void fireStateChanged() {
10990        changeSupport.fireStateChanged();
11000    }
1101     
1102     /**
1103      * @return Returns the pickedState.
1104      */
1105     public PickedState getPickedState() {
11060        return pickedState;
1107     }
1108     /**
1109      * @param pickedState The pickedState to set.
1110      */
1111     public void setPickedState(PickedState pickedState) {
11120        if(pickEventListener != null && this.pickedState != null) {
11130            this.pickedState.removeItemListener(pickEventListener);
1114         }
11150        this.pickedState = pickedState;
11160        if(renderer != null) {
11170            renderer.setPickedKey(pickedState);
1118         }
11190        if(pickEventListener == null) {
11200            pickEventListener = new ItemListener() {
1121  
1122                 public void itemStateChanged(ItemEvent e) {
1123                     repaint();
1124                 }
1125             };
1126         }
11270        pickedState.addItemListener(pickEventListener);
11280    }
1129     
1130     /**
1131      * @return Returns the pickSupport.
1132      */
1133     public PickSupport getPickSupport() {
11340        return pickSupport;
1135     }
1136     /**
1137      * @param pickSupport The pickSupport to set.
1138      */
1139     public void setPickSupport(PickSupport pickSupport) {
11400        this.pickSupport = pickSupport;
11410        this.pickSupport.setHasGraphLayout(this);
11420        if(pickSupport instanceof ShapePickSupport && renderer instanceof HasShapeFunctions) {
11430            ((ShapePickSupport)pickSupport).setHasShapes((HasShapeFunctions)renderer);
11440            ((ShapePickSupport)pickSupport).setLayoutTransformer(this);
1145         }
11460    }
1147     
1148     public Point2D getCenter() {
11490        Dimension d = getSize();
11500        return new Point2D.Float(d.width/2, d.height/2);
1151     }
1152 }

this report was generated by version 1.0.5 of jcoverage.
visit www.jcoverage.com for updates.

copyright © 2003, jcoverage ltd. all rights reserved.
Java is a trademark of Sun Microsystems, Inc. in the United States and other countries.