1
2
3
4
5
6
7
8
9
10 package edu.uci.ics.jung.visualization.renderers;
11
12 import java.awt.Dimension;
13 import java.awt.Paint;
14 import java.awt.Rectangle;
15 import java.awt.Shape;
16 import java.awt.Stroke;
17 import java.awt.geom.AffineTransform;
18 import java.awt.geom.GeneralPath;
19 import java.awt.geom.Point2D;
20 import java.awt.geom.Rectangle2D;
21
22 import javax.swing.JComponent;
23
24 import edu.uci.ics.jung.algorithms.layout.Layout;
25 import edu.uci.ics.jung.graph.Graph;
26 import edu.uci.ics.jung.graph.util.Context;
27 import edu.uci.ics.jung.graph.util.EdgeIndexFunction;
28 import edu.uci.ics.jung.graph.util.EdgeType;
29 import edu.uci.ics.jung.graph.util.Pair;
30 import edu.uci.ics.jung.visualization.Layer;
31 import edu.uci.ics.jung.visualization.RenderContext;
32 import edu.uci.ics.jung.visualization.decorators.EdgeShape;
33 import edu.uci.ics.jung.visualization.decorators.EdgeShape.IndexedRendering;
34 import edu.uci.ics.jung.visualization.transform.LensTransformer;
35 import edu.uci.ics.jung.visualization.transform.MutableTransformer;
36 import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator;
37
38 public class BasicEdgeRenderer<V,E> implements Renderer.Edge<V,E> {
39
40 protected EdgeArrowRenderingSupport edgeArrowRenderingSupport =
41 new BasicEdgeArrowRenderingSupport();
42
43 public void paintEdge(RenderContext<V,E> rc, Layout<V, E> layout, E e) {
44 GraphicsDecorator g2d = rc.getGraphicsContext();
45 Graph<V,E> graph = layout.getGraph();
46 if (!rc.getEdgeIncludePredicate().evaluate(Context.<Graph<V,E>,E>getInstance(graph,e)))
47 return;
48
49
50 Pair<V> endpoints = graph.getEndpoints(e);
51 V v1 = endpoints.getFirst();
52 V v2 = endpoints.getSecond();
53 if (!rc.getVertexIncludePredicate().evaluate(Context.<Graph<V,E>,V>getInstance(graph,v1)) ||
54 !rc.getVertexIncludePredicate().evaluate(Context.<Graph<V,E>,V>getInstance(graph,v2)))
55 return;
56
57 Stroke new_stroke = rc.getEdgeStrokeTransformer().transform(e);
58 Stroke old_stroke = g2d.getStroke();
59 if (new_stroke != null)
60 g2d.setStroke(new_stroke);
61
62 drawSimpleEdge(rc, layout, e);
63
64
65 if (new_stroke != null)
66 g2d.setStroke(old_stroke);
67
68 }
69
70
71
72
73
74
75
76
77 @SuppressWarnings("unchecked")
78 protected void drawSimpleEdge(RenderContext<V,E> rc, Layout<V,E> layout, E e) {
79
80 GraphicsDecorator g = rc.getGraphicsContext();
81 Graph<V,E> graph = layout.getGraph();
82 Pair<V> endpoints = graph.getEndpoints(e);
83 V v1 = endpoints.getFirst();
84 V v2 = endpoints.getSecond();
85
86 Point2D p1 = layout.transform(v1);
87 Point2D p2 = layout.transform(v2);
88 p1 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p1);
89 p2 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p2);
90 float x1 = (float) p1.getX();
91 float y1 = (float) p1.getY();
92 float x2 = (float) p2.getX();
93 float y2 = (float) p2.getY();
94
95 boolean isLoop = v1.equals(v2);
96 Shape s2 = rc.getVertexShapeTransformer().transform(v2);
97 Shape edgeShape = rc.getEdgeShapeTransformer().transform(Context.<Graph<V,E>,E>getInstance(graph, e));
98
99 boolean edgeHit = true;
100 boolean arrowHit = true;
101 Rectangle deviceRectangle = null;
102 JComponent vv = rc.getScreenDevice();
103 if(vv != null) {
104 Dimension d = vv.getSize();
105 deviceRectangle = new Rectangle(0,0,d.width,d.height);
106 }
107
108 AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1);
109
110 if(isLoop) {
111
112
113
114 Rectangle2D s2Bounds = s2.getBounds2D();
115 xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight());
116 xform.translate(0, -edgeShape.getBounds2D().getWidth()/2);
117 } else if(rc.getEdgeShapeTransformer() instanceof EdgeShape.Orthogonal) {
118 float dx = x2-x1;
119 float dy = y2-y1;
120 int index = 0;
121 if(rc.getEdgeShapeTransformer() instanceof IndexedRendering) {
122 EdgeIndexFunction<V,E> peif =
123 ((IndexedRendering<V,E>)rc.getEdgeShapeTransformer()).getEdgeIndexFunction();
124 index = peif.getIndex(graph, e);
125 index *= 20;
126 }
127 GeneralPath gp = new GeneralPath();
128 gp.moveTo(0,0);
129 if(x1 > x2) {
130 if(y1 > y2) {
131 gp.lineTo(0, index);
132 gp.lineTo(dx-index, index);
133 gp.lineTo(dx-index, dy);
134 gp.lineTo(dx, dy);
135 } else {
136 gp.lineTo(0, -index);
137 gp.lineTo(dx-index, -index);
138 gp.lineTo(dx-index, dy);
139 gp.lineTo(dx, dy);
140 }
141
142 } else {
143 if(y1 > y2) {
144 gp.lineTo(0, index);
145 gp.lineTo(dx+index, index);
146 gp.lineTo(dx+index, dy);
147 gp.lineTo(dx, dy);
148
149 } else {
150 gp.lineTo(0, -index);
151 gp.lineTo(dx+index, -index);
152 gp.lineTo(dx+index, dy);
153 gp.lineTo(dx, dy);
154
155 }
156
157 }
158
159 edgeShape = gp;
160
161 } else {
162
163
164
165 float dx = x2-x1;
166 float dy = y2-y1;
167 float thetaRadians = (float) Math.atan2(dy, dx);
168 xform.rotate(thetaRadians);
169 float dist = (float) Math.sqrt(dx*dx + dy*dy);
170 xform.scale(dist, 1.0);
171 }
172
173 edgeShape = xform.createTransformedShape(edgeShape);
174
175 MutableTransformer vt = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW);
176 if(vt instanceof LensTransformer) {
177 vt = ((LensTransformer)vt).getDelegate();
178 }
179 edgeHit = vt.transform(edgeShape).intersects(deviceRectangle);
180
181 if(edgeHit == true) {
182
183 Paint oldPaint = g.getPaint();
184
185
186
187 Paint fill_paint = rc.getEdgeFillPaintTransformer().transform(e);
188 if (fill_paint != null)
189 {
190 g.setPaint(fill_paint);
191 g.fill(edgeShape);
192 }
193 Paint draw_paint = rc.getEdgeDrawPaintTransformer().transform(e);
194 if (draw_paint != null)
195 {
196 g.setPaint(draw_paint);
197 g.draw(edgeShape);
198 }
199
200 float scalex = (float)g.getTransform().getScaleX();
201 float scaley = (float)g.getTransform().getScaleY();
202
203 if(scalex < .3 || scaley < .3) return;
204
205 if (rc.getEdgeArrowPredicate().evaluate(Context.<Graph<V,E>,E>getInstance(graph, e))) {
206
207 Stroke new_stroke = rc.getEdgeArrowStrokeTransformer().transform(e);
208 Stroke old_stroke = g.getStroke();
209 if (new_stroke != null)
210 g.setStroke(new_stroke);
211
212
213 Shape destVertexShape =
214 rc.getVertexShapeTransformer().transform(graph.getEndpoints(e).getSecond());
215
216 AffineTransform xf = AffineTransform.getTranslateInstance(x2, y2);
217 destVertexShape = xf.createTransformedShape(destVertexShape);
218
219 arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(destVertexShape).intersects(deviceRectangle);
220 if(arrowHit) {
221
222 AffineTransform at =
223 edgeArrowRenderingSupport.getArrowTransform(rc, edgeShape, destVertexShape);
224 if(at == null) return;
225 Shape arrow = rc.getEdgeArrowTransformer().transform(Context.<Graph<V,E>,E>getInstance(graph, e));
226 arrow = at.createTransformedShape(arrow);
227 g.setPaint(rc.getArrowFillPaintTransformer().transform(e));
228 g.fill(arrow);
229 g.setPaint(rc.getArrowDrawPaintTransformer().transform(e));
230 g.draw(arrow);
231 }
232 if (graph.getEdgeType(e) == EdgeType.UNDIRECTED) {
233 Shape vertexShape =
234 rc.getVertexShapeTransformer().transform(graph.getEndpoints(e).getFirst());
235 xf = AffineTransform.getTranslateInstance(x1, y1);
236 vertexShape = xf.createTransformedShape(vertexShape);
237
238 arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(vertexShape).intersects(deviceRectangle);
239
240 if(arrowHit) {
241 AffineTransform at = edgeArrowRenderingSupport.getReverseArrowTransform(rc, edgeShape, vertexShape, !isLoop);
242 if(at == null) return;
243 Shape arrow = rc.getEdgeArrowTransformer().transform(Context.<Graph<V,E>,E>getInstance(graph, e));
244 arrow = at.createTransformedShape(arrow);
245 g.setPaint(rc.getArrowFillPaintTransformer().transform(e));
246 g.fill(arrow);
247 g.setPaint(rc.getArrowDrawPaintTransformer().transform(e));
248 g.draw(arrow);
249 }
250 }
251
252 if (new_stroke != null)
253 g.setStroke(old_stroke);
254
255 }
256
257
258 g.setPaint(oldPaint);
259 }
260 }
261
262 public EdgeArrowRenderingSupport getEdgeArrowRenderingSupport() {
263 return edgeArrowRenderingSupport;
264 }
265
266 public void setEdgeArrowRenderingSupport(
267 EdgeArrowRenderingSupport edgeArrowRenderingSupport) {
268 this.edgeArrowRenderingSupport = edgeArrowRenderingSupport;
269 }
270 }