View Javadoc

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 Aug 23, 2005
9    */
10  package edu.uci.ics.jung.visualization.renderers;
11  
12  
13  import java.awt.Component;
14  import java.awt.Dimension;
15  import java.awt.Point;
16  import java.awt.Shape;
17  import java.awt.geom.AffineTransform;
18  import java.awt.geom.Point2D;
19  import java.awt.geom.Rectangle2D;
20  
21  import edu.uci.ics.jung.algorithms.layout.Layout;
22  import edu.uci.ics.jung.graph.Graph;
23  import edu.uci.ics.jung.graph.util.Context;
24  import edu.uci.ics.jung.visualization.Layer;
25  import edu.uci.ics.jung.visualization.RenderContext;
26  import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer;
27  import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator;
28  import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer;
29  import edu.uci.ics.jung.visualization.transform.shape.TransformingGraphics;
30  
31  public class BasicVertexLabelRenderer<V,E> implements Renderer.VertexLabel<V,E> {
32  
33  	protected Position position = Position.SE;
34  	private Positioner positioner = new OutsidePositioner();
35  	
36  	public BasicVertexLabelRenderer() {
37  		super();
38  	}
39  
40  	public BasicVertexLabelRenderer(Position position) {
41  		this.position = position;
42  	}
43  
44  	/**
45  	 * @return the position
46  	 */
47  	public Position getPosition() {
48  		return position;
49  	}
50  
51  	/**
52  	 * @param position the position to set
53  	 */
54  	public void setPosition(Position position) {
55  		this.position = position;
56  	}
57  
58  	public Component prepareRenderer(RenderContext<V,E> rc, VertexLabelRenderer graphLabelRenderer, Object value, 
59  			boolean isSelected, V vertex) {
60  		return rc.getVertexLabelRenderer().<V>getVertexLabelRendererComponent(rc.getScreenDevice(), value, 
61  				rc.getVertexFontTransformer().transform(vertex), isSelected, vertex);
62  	}
63  
64  	/**
65  	 * Labels the specified vertex with the specified label.  
66  	 * Uses the font specified by this instance's 
67  	 * <code>VertexFontFunction</code>.  (If the font is unspecified, the existing
68  	 * font for the graphics context is used.)  If vertex label centering
69  	 * is active, the label is centered on the position of the vertex; otherwise
70       * the label is offset slightly.
71       */
72      public void labelVertex(RenderContext<V,E> rc, Layout<V,E> layout, V v, String label) {
73      	Graph<V,E> graph = layout.getGraph();
74          if (rc.getVertexIncludePredicate().evaluate(Context.<Graph<V,E>,V>getInstance(graph,v)) == false) {
75          	return;
76          }
77          Point2D pt = layout.transform(v);
78          pt = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, pt);
79  
80          float x = (float) pt.getX();
81          float y = (float) pt.getY();
82  
83          Component component = prepareRenderer(rc, rc.getVertexLabelRenderer(), label,
84          		rc.getPickedVertexState().isPicked(v), v);
85          GraphicsDecorator g = rc.getGraphicsContext();
86          Dimension d = component.getPreferredSize();
87          AffineTransform xform = AffineTransform.getTranslateInstance(x, y);
88          
89      	Shape shape = rc.getVertexShapeTransformer().transform(v);
90      	shape = xform.createTransformedShape(shape);
91      	if(rc.getGraphicsContext() instanceof TransformingGraphics) {
92      		BidirectionalTransformer transformer = ((TransformingGraphics)rc.getGraphicsContext()).getTransformer();
93      		if(transformer instanceof ShapeTransformer) {
94      			ShapeTransformer shapeTransformer = (ShapeTransformer)transformer;
95      			shape = shapeTransformer.transform(shape);
96      		}
97      	}
98      	Rectangle2D bounds = shape.getBounds2D();
99  
100     	Point p = null;
101     	if(position == Position.AUTO) {
102     		Dimension vvd = rc.getScreenDevice().getSize();
103     		if(vvd.width == 0 || vvd.height == 0) {
104     			vvd = rc.getScreenDevice().getPreferredSize();
105     		}
106     		p = getAnchorPoint(bounds, d, positioner.getPosition(x, y, vvd));
107     	} else {
108     		p = getAnchorPoint(bounds, d, position);
109     	}
110         g.draw(component, rc.getRendererPane(), p.x, p.y, d.width, d.height, true);
111     }
112     
113     protected Point getAnchorPoint(Rectangle2D vertexBounds, Dimension labelSize, Position position) {
114     	double x;
115     	double y;
116     	int offset = 5;
117     	switch(position) {
118     	
119     	case N:
120     		x = vertexBounds.getCenterX()-labelSize.width/2;
121     		y = vertexBounds.getMinY()-offset - labelSize.height;
122     		return new Point((int)x,(int)y);
123 
124     	case NE:
125     		x = vertexBounds.getMaxX()+offset;
126     		y = vertexBounds.getMinY()-offset-labelSize.height;
127     		return new Point((int)x,(int)y);
128 
129     	case E:
130     		x = vertexBounds.getMaxX()+offset;
131     		y = vertexBounds.getCenterY()-labelSize.height/2;
132     		return new Point((int)x,(int)y);
133 
134     	case SE:
135     		x = vertexBounds.getMaxX()+offset;
136     		y = vertexBounds.getMaxY()+offset;
137     		return new Point((int)x,(int)y);
138 
139     	case S:
140     		x = vertexBounds.getCenterX()-labelSize.width/2;
141     		y = vertexBounds.getMaxY()+offset;
142     		return new Point((int)x,(int)y);
143 
144     	case SW:
145     		x = vertexBounds.getMinX()-offset-labelSize.width;
146     		y = vertexBounds.getMaxY()+offset;
147     		return new Point((int)x,(int)y);
148 
149     	case W:
150     		x = vertexBounds.getMinX()-offset-labelSize.width;
151     		y = vertexBounds.getCenterY()-labelSize.height/2;
152     		return new Point((int)x,(int)y);
153 
154     	case NW:
155     		x = vertexBounds.getMinX()-offset-labelSize.width;
156     		y = vertexBounds.getMinY()-offset-labelSize.height;
157     		return new Point((int)x,(int)y);
158 
159     	case CNTR:
160     		x = vertexBounds.getCenterX()-labelSize.width/2;
161     		y = vertexBounds.getCenterY()-labelSize.height/2;
162     		return new Point((int)x,(int)y);
163 
164     	default:
165     		return new Point();
166     	}
167     	
168     }
169     public static class InsidePositioner implements Positioner {
170     	public Position getPosition(float x, float y, Dimension d) {
171     		int cx = d.width/2;
172     		int cy = d.height/2;
173     		if(x > cx && y > cy) return Position.NW;
174     		if(x > cx && y < cy) return Position.SW;
175     		if(x < cx && y > cy) return Position.NE;
176     		return Position.SE;
177     	}
178     }
179     public static class OutsidePositioner implements Positioner {
180     	public Position getPosition(float x, float y, Dimension d) {
181     		int cx = d.width/2;
182     		int cy = d.height/2;
183     		if(x > cx && y > cy) return Position.SE;
184     		if(x > cx && y < cy) return Position.NE;
185     		if(x < cx && y > cy) return Position.SW;
186     		return Position.NW;
187     	}
188     }
189 	/**
190 	 * @return the positioner
191 	 */
192 	public Positioner getPositioner() {
193 		return positioner;
194 	}
195 
196 	/**
197 	 * @param positioner the positioner to set
198 	 */
199 	public void setPositioner(Positioner positioner) {
200 		this.positioner = positioner;
201 	}
202 }