1
2
3
4
5
6
7
8
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
46
47 public Position getPosition() {
48 return position;
49 }
50
51
52
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
66
67
68
69
70
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
191
192 public Positioner getPositioner() {
193 return positioner;
194 }
195
196
197
198
199 public void setPositioner(Positioner positioner) {
200 this.positioner = positioner;
201 }
202 }