Coverage details for edu.uci.ics.jung.visualization.transform.shape.TransformingPluggableRenderer

LineHitsSource
1 /*
2  * Copyright (c) 2005, the JUNG Project and the Regents of the University of
3  * California All rights reserved.
4  *
5  * This software is open-source under the BSD license; see either "license.txt"
6  * or http://jung.sourceforge.net/license.txt for a description.
7  *
8  * Created on Jul 11, 2005
9  */
10  
11 package edu.uci.ics.jung.visualization.transform.shape;
12  
13 import java.awt.Component;
14 import java.awt.Dimension;
15 import java.awt.Font;
16 import java.awt.Graphics;
17 import java.awt.Graphics2D;
18 import java.awt.Paint;
19 import java.awt.Rectangle;
20 import java.awt.Shape;
21 import java.awt.Stroke;
22 import java.awt.geom.AffineTransform;
23 import java.awt.geom.Ellipse2D;
24 import java.awt.geom.GeneralPath;
25 import java.awt.geom.Point2D;
26 import java.awt.geom.Rectangle2D;
27  
28 import javax.swing.Icon;
29  
30 import edu.uci.ics.jung.graph.Edge;
31 import edu.uci.ics.jung.graph.UndirectedEdge;
32 import edu.uci.ics.jung.graph.Vertex;
33 import edu.uci.ics.jung.graph.decorators.VertexIconFunction;
34 import edu.uci.ics.jung.utils.Pair;
35 import edu.uci.ics.jung.visualization.PluggableRenderer;
36 import edu.uci.ics.jung.visualization.transform.HyperbolicTransformer;
37 import edu.uci.ics.jung.visualization.transform.MutableAffineTransformer;
38 import edu.uci.ics.jung.visualization.transform.Transformer;
39  
40 /**
41  * a subclass to apply a TransformingGraphics to certain operations
42  * @author Tom Nelson - RABA Technologies
43  *
44  *
45  */
46 public class TransformingPluggableRenderer extends PluggableRendererDecorator {
47     
48     /**
49      * the transformer
50      */
51     Transformer transformer;
52     
53     /**
54      * the Graphics wrapper that uses the transformer
55      */
56     TransformingGraphics tg2d;
57     
58     /**
59      * create an instance
60      *
61      */
62     public TransformingPluggableRenderer(PluggableRenderer delegate) {
630        super(delegate);
640        this.transformer = new MutableAffineTransformer();
650        this.tg2d = new TransformingGraphics(transformer);
660    }
67     
68     /**
69      * @return Returns the transformer.
70      */
71     public Transformer getTransformer() {
720        return transformer;
73     }
74  
75     /**
76      * @param transformer The transformer to set.
77      */
78     public void setTransformer(Transformer transformer) {
790        this.transformer = transformer;
800        this.tg2d.setTransformer(transformer);
810    }
82  
83     /** (non-Javadoc)
84      * override to wrap the passed Graphics2D in my TransformingGraphics,
85      * then call overloaded drawSimpleEdge
86      */
87     protected void drawSimpleEdge(Graphics2D g, Edge e, int x1, int y1, int x2, int y2) {
880        this.tg2d.setDelegate(g);
890        drawSimpleEdge(tg2d, e, x1, y1, x2, y2);
900    }
91     /**
92      * overloaded to use TransformingGraphics
93      * @param g
94      * @param e
95      * @param x1
96      * @param y1
97      * @param x2
98      * @param y2
99      */
100     protected void drawSimpleEdge(TransformingGraphics g, Edge e, int x1, int y1, int x2, int y2) {
1010        float flatness = 0;
102         
1030        if(transformer instanceof HyperbolicTransformer) {
1040            HyperbolicTransformer ht = (HyperbolicTransformer)transformer;
1050            Ellipse2D hyperEllipse = ht.getEllipse();
1060            if(hyperEllipse.contains(x1,y1) || hyperEllipse.contains(x2,y2)) {
1070                flatness = .05f;
108             }
109         }
1100        Pair endpoints = e.getEndpoints();
1110        Vertex v1 = (Vertex)endpoints.getFirst();
1120        Vertex v2 = (Vertex)endpoints.getSecond();
1130        boolean isLoop = v1.equals(v2);
1140        Shape s2 = getVertexShapeFunction().getShape(v2);
1150        Shape edgeShape = getEdgeShapeFunction().getShape(e);
116         
1170        boolean edgeHit = true;
1180        boolean arrowHit = true;
1190        Rectangle deviceRectangle = null;
1200        if(getScreenDevice() != null) {
1210            Dimension d = getScreenDevice().getSize();
1220            deviceRectangle = new Rectangle(0,0,d.width,d.height);
123         }
124         
1250        AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1);
126         
1270        if(isLoop) {
128             // this is a self-loop. scale it is larger than the vertex
129             // it decorates and translate it so that its nadir is
130             // at the center of the vertex.
1310            Rectangle2D s2Bounds = s2.getBounds2D();
1320            xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight());
1330            xform.translate(0, -edgeShape.getBounds2D().getWidth()/2);
134         } else {
135             // this is a normal edge. Rotate it to the angle between
136             // vertex endpoints, then scale it to the distance between
137             // the vertices
1380            float dx = x2-x1;
1390            float dy = y2-y1;
1400            float thetaRadians = (float) Math.atan2(dy, dx);
1410            xform.rotate(thetaRadians);
1420            float dist = (float) Math.sqrt(dx*dx + dy*dy);
1430            xform.scale(dist, 1.0);
144         }
145         
1460        edgeShape = xform.createTransformedShape(edgeShape);
147         
1480        edgeHit = g.hit(deviceRectangle, edgeShape, true);
149         
1500        if(edgeHit == true) {
151             
1520            Paint oldPaint = g.getPaint();
153             
154             // get Paints for filling and drawing
155             // (filling is done first so that drawing and label use same Paint)
1560            Paint fill_paint = getEdgePaintFunction().getFillPaint(e);
1570            if (fill_paint != null)
158             {
1590                g.setPaint(fill_paint);
1600                g.fill(edgeShape, flatness);
161             }
1620            Paint draw_paint = getEdgePaintFunction().getDrawPaint(e);
1630            if (draw_paint != null)
164             {
1650                g.setPaint(draw_paint);
1660                g.draw(edgeShape, flatness);
167             }
168             
1690            float scalex = (float)g.getTransform().getScaleX();
1700            float scaley = (float)g.getTransform().getScaleY();
171             // see if arrows are too small to bother drawing
1720            if(scalex < .3 || scaley < .3) return;
173             
1740            if (getEdgeArrowPredicate().evaluate(e)) {
175                 
1760                Shape destVertexShape =
177                     getVertexShapeFunction().getShape((Vertex)e.getEndpoints().getSecond());
1780                AffineTransform xf = AffineTransform.getTranslateInstance(x2, y2);
1790                destVertexShape = xf.createTransformedShape(destVertexShape);
180  
1810                arrowHit = g.hit(deviceRectangle, destVertexShape, true);
182  
1830                if(arrowHit) {
184                     
1850                    AffineTransform at =
186                         getArrowTransform((GeneralPath)edgeShape, destVertexShape);
1870                    if(at == null) return;
1880                    Shape arrow = getEdgeArrowFunction().getArrow(e);
1890                    arrow = at.createTransformedShape(arrow);
190                     // note that arrows implicitly use the edge's draw paint
1910                    g.fill(arrow);
1920                    if (e instanceof UndirectedEdge) {
1930                        Shape vertexShape =
194                             getVertexShapeFunction().getShape((Vertex)e.getEndpoints().getFirst());
1950                        xf = AffineTransform.getTranslateInstance(x1, y1);
1960                        vertexShape = xf.createTransformedShape(vertexShape);
197  
1980                        arrowHit = g.hit(deviceRectangle, vertexShape, true);
1990                        if(arrowHit) {
2000                            at = getReverseArrowTransform((GeneralPath)edgeShape, vertexShape, !isLoop);
2010                            if(at == null) return;
2020                            arrow = getEdgeArrowFunction().getArrow(e);
2030                            arrow = at.createTransformedShape(arrow);
2040                            g.fill(arrow);
205                         }
206                     }
207                 }
208             }
209                 // use existing paint for text if no draw paint specified
2100                if (draw_paint == null)
2110                    g.setPaint(oldPaint);
2120                String label = getEdgeStringer().getLabel(e);
2130                if (label != null) {
2140                    labelEdge(g, e, label, x1, x2, y1, y2);
215                 }
216             
217             
218             // restore old paint
2190            g.setPaint(oldPaint);
220         }
2210    }
222  
223  
224     /**
225      * overridden to wrap passed Graphics2D in my TransformingGraphics, then call
226      * overloaded labelEdge
227      */
228     protected void labelEdge(Graphics2D g2d, Edge e, String label, int x1, int x2, int y1, int y2) {
2290        tg2d.setDelegate(g2d);
2300        labelEdge(tg2d, e, label, x1, x2, y1, y2);
2310    }
232     /**
233      * overloaded to use TransformingGraphics
234      * @param g2d
235      * @param e
236      * @param label
237      * @param x1
238      * @param x2
239      * @param y1
240      * @param y2
241      */
242     protected void labelEdge(TransformingGraphics g2d, Edge e, String label, int x1, int x2, int y1, int y2)
243     {
2440        Point2D p = g2d.getTransformer().transform(new Point2D.Float(x1, y1));
2450        Point2D q = g2d.getTransformer().transform(new Point2D.Float(x2, y2));
2460        x1 = (int)p.getX();
2470        y1 = (int)p.getY();
2480        x2 = (int)q.getX();
2490        y2 = (int)q.getY();
250         
2510        int distX = x2 - x1;
2520        int distY = y2 - y1;
2530        double totalLength = Math.sqrt(distX * distX + distY * distY);
254  
2550        double closeness = getEdgeLabelClosenessFunction().getNumber(e).doubleValue();
256  
2570        int posX = (int) (x1 + (closeness) * distX);
2580        int posY = (int) (y1 + (closeness) * distY);
259  
2600        int xDisplacement = (int) (PluggableRenderer.LABEL_OFFSET * (distY / totalLength));
2610        int yDisplacement = (int) (PluggableRenderer.LABEL_OFFSET * (-distX / totalLength));
262         
2630        Component component = prepareRenderer(getGraphLabelRenderer(), label, isPicked(e), e);
2640        Dimension d = component.getPreferredSize();
265         
2660        Font font = getEdgeFontFunction().getFont(e);
2670        if(font != null)
2680            component.setFont(font);
269         
2700        Shape edgeShape = getEdgeShapeFunction().getShape(e);
271         
2720        double parallelOffset = 1;
2730        Integer parallelCount = (Integer)e.getUserDatum("parallelCount");
2740        if(parallelCount != null) {
2750            parallelOffset += parallelCount.intValue();
276         }
277  
2780        if(edgeShape instanceof Ellipse2D) {
2790            parallelOffset += edgeShape.getBounds().getHeight();
2800            parallelOffset = -parallelOffset;
281         }
282         
2830        parallelOffset *= d.height;
284         
2850        AffineTransform old = g2d.getTransform();
2860        AffineTransform xform = new AffineTransform(old);
2870        xform.translate(posX+xDisplacement, posY+yDisplacement);
2880        if(getGraphLabelRenderer().isRotateEdgeLabels()) {
289             // float thetaRadians = (float) Math.atan2(dy, dx);
2900            double dx = x2 - x1;
2910            double dy = y2 - y1;
2920            double theta = Math.atan2(dy, dx);
2930            if(dx < 0) {
2940                theta += Math.PI;
2950                parallelOffset = -parallelOffset;
296             }
2970            xform.rotate(theta);
298         }
299         
3000        xform.translate(-d.width/2, -(d.height/2-parallelOffset));
3010        g2d.setTransform(xform);
3020        getRendererPane().paintComponent(g2d.getDelegate(), component, getScreenDevice(),
303                 0, 0,
304                 d.width, d.height, true);
3050        g2d.setTransform(old);
3060    }
307  
308     /**
309      * overridden to wrap passed Graphics in my TransformingGraphics, then
310      * call overloaded labelVertex
311      */
312     protected void labelVertex(Graphics g, Vertex v, String label, int x, int y) {
3130        tg2d.setDelegate((Graphics2D)g);
3140        labelVertex(tg2d, v, label, x, y);
3150    }
316     /**
317      * overloaded to use TransformingGraphics
318      * @param g
319      * @param v
320      * @param label
321      * @param x
322      * @param y
323      */
324     protected void labelVertex(TransformingGraphics g, Vertex v, String label, int x, int y) {
3250        Component component = prepareRenderer(getGraphLabelRenderer(), label, isPicked(v), v);
3260        Font font = getVertexFontFunction().getFont(v);
3270        if (font != null)
3280            component.setFont(font);
329         
3300        Dimension d = component.getPreferredSize();
331         
3320        Point2D p = g.getTransformer().transform(new Point2D.Float(x, y));
3330        x = (int)p.getX();
3340        y = (int)p.getY();
335         
336         int h_offset;
337         int v_offset;
3380        if (getVertexLabelCentering())
339         {
3400            h_offset = -d.width / 2;
3410            v_offset = -d.height / 2;
342  
343         }
344         else
345         {
3460            Rectangle2D bounds = getVertexShapeFunction().getShape(v).getBounds2D();
3470            h_offset = (int)(bounds.getWidth() / 2) + 5;
3480            v_offset = (int)(bounds.getHeight() / 2) + 5 -d.height;
349         }
350         
3510        getRendererPane().paintComponent(g.getDelegate(), component, getScreenDevice(), x+h_offset, y+v_offset,
352                 d.width, d.height, true);
353         
3540    }
355  
356     /**
357      * overridded to wrap passed Graphics in TransformingGraphics then call
358      * overloaded paintEdge
359      */
360     public void paintEdge(Graphics g, Edge e, int x1, int y1, int x2, int y2) {
3610        this.tg2d.setDelegate((Graphics2D)g);
3620        paintEdge(tg2d, e, x1, y1, x2, y2);
3630    }
364     /**
365      * overloaded to use TransformingGraphics
366      * @param g2d
367      * @param e
368      * @param x1
369      * @param y1
370      * @param x2
371      * @param y2
372      */
373     public void paintEdge(TransformingGraphics g2d, Edge e, int x1, int y1, int x2, int y2) {
3740        if (!getEdgeIncludePredicate().evaluate(e))
3750            return;
376         
377         // don't draw edge if either incident vertex is not drawn
3780        Pair endpoints = e.getEndpoints();
3790        Vertex v1 = (Vertex)endpoints.getFirst();
3800        Vertex v2 = (Vertex)endpoints.getSecond();
3810        if (!getVertexIncludePredicate().evaluate(v1) ||
382             !getVertexIncludePredicate().evaluate(v2))
3830            return;
384         
3850        Stroke new_stroke = getEdgeStrokeFunction().getStroke(e);
3860        Stroke old_stroke = g2d.getStroke();
3870        if (new_stroke != null)
3880            g2d.setStroke(new_stroke);
389         
3900        drawSimpleEdge(g2d, e, x1, y1, x2, y2);
391  
392         // restore paint and stroke
3930        if (new_stroke != null)
3940            g2d.setStroke(old_stroke);
395  
3960    }
397  
398     /**
399      * overridden to wrap passed Graphics in TransformingGraphics then
400      * call overloaded paintVertex
401      */
402     public void paintVertex(Graphics g, Vertex v, int x, int y) {
4030        tg2d.setDelegate((Graphics2D)g);
4040        paintVertex(tg2d, v, x, y);
4050    }
406     /**
407      * overloaded to use TransformingGraphics
408      * @param g2d
409      * @param v
410      * @param x
411      * @param y
412      */
413     public void paintVertex(TransformingGraphics g2d, Vertex v, int x, int y) {
4140        if (!getVertexIncludePredicate().evaluate(v))
4150            return;
416         
4170        boolean vertexHit = true;
4180        Rectangle deviceRectangle = null;
4190        if(getScreenDevice() != null) {
4200            Dimension d = getScreenDevice().getSize();
4210            deviceRectangle = new Rectangle(0,0,d.width,d.height);
422         }
423         
4240        Stroke old_stroke = g2d.getStroke();
4250        Stroke new_stroke = getVertexStrokeFunction().getStroke(v);
4260        if (new_stroke != null) {
4270            g2d.setStroke(new_stroke);
428         }
429         // get the shape to be rendered
4300        Shape s = getVertexShapeFunction().getShape(v);
431         
432         // create a transform that translates to the location of
433         // the vertex to be rendered
4340        AffineTransform xform = AffineTransform.getTranslateInstance(x,y);
435         // transform the vertex shape with xtransform
4360        s = xform.createTransformedShape(s);
437         
438  
4390        vertexHit = g2d.hit(deviceRectangle, s, true);
440  
4410        if (vertexHit) {
4420            VertexIconFunction imager = getVertexIconFunction();
443  
4440                Icon icon = null;
4450            if (imager != null && (icon = imager.getIcon(v)) != null) {
4460                paintIconForVertex(g2d, icon, x, y);
447             } else {
4480                paintShapeForVertex(g2d, v, s);
449             }
450  
4510            if (new_stroke != null) {
4520                g2d.setStroke(old_stroke);
453             }
4540            String label = getVertexStringer().getLabel(v);
4550            if (label != null) {
4560                labelVertex(g2d, v, label, x, y);
457             }
458         }
4590    }
460     
461     protected void paintShapeForVertex(TransformingGraphics g2d, Vertex v, Shape shape) {
4620        Paint oldPaint = g2d.getPaint();
4630        Paint fillPaint = getVertexPaintFunction().getFillPaint(v);
4640        if(fillPaint != null) {
4650            g2d.setPaint(fillPaint);
4660            g2d.fill(shape);
4670            g2d.setPaint(oldPaint);
468         }
4690        Paint drawPaint = getVertexPaintFunction().getDrawPaint(v);
4700        if(drawPaint != null) {
4710            g2d.setPaint(drawPaint);
4720            g2d.draw(shape);
4730            g2d.setPaint(oldPaint);
474         }
4750    }
476  
477     public void paintIconForVertex(TransformingGraphics g, Icon icon, int x, int y) {
4780         if(icon != null) {
4790             int xLoc = x - icon.getIconWidth()/2;
4800             int yLoc = y - icon.getIconHeight()/2;
4810             icon.paintIcon(getScreenDevice(), g.getDelegate(), xLoc, yLoc);
482          }
4830     }
484 }

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.