Line | Hits | Source |
---|---|---|
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 March 10, 2005 | |
9 | */ | |
10 | package edu.uci.ics.jung.graph.decorators; | |
11 | ||
12 | import java.awt.Shape; | |
13 | import java.awt.geom.AffineTransform; | |
14 | import java.awt.geom.CubicCurve2D; | |
15 | import java.awt.geom.Ellipse2D; | |
16 | import java.awt.geom.GeneralPath; | |
17 | import java.awt.geom.Line2D; | |
18 | import java.awt.geom.QuadCurve2D; | |
19 | ||
20 | import org.apache.commons.collections.Predicate; | |
21 | ||
22 | import edu.uci.ics.jung.graph.DirectedEdge; | |
23 | import edu.uci.ics.jung.graph.Edge; | |
24 | import edu.uci.ics.jung.graph.predicates.SelfLoopEdgePredicate; | |
25 | import edu.uci.ics.jung.utils.ParallelEdgeIndexFunction; | |
26 | import edu.uci.ics.jung.visualization.ArrowFactory; | |
27 | ||
28 | /** | |
29 | * An interface for decorators that return a | |
30 | * <code>Shape</code> for a specified edge. | |
31 | * | |
32 | * All edge shapes must be defined so that their endpoints are at | |
33 | * (0,0) and (1,0). They will be scaled, rotated and translated into | |
34 | * position by the PluggableRenderer. | |
35 | * | |
36 | * @author Tom Nelson | |
37 | */ | |
38 | 0 | public class EdgeShape { |
39 | ||
40 | /** | |
41 | * a convenience instance for other edge shapes to use | |
42 | * for self-loop edges where parallel instances will not | |
43 | * overlay each other. | |
44 | */ | |
45 | 0 | protected static Loop loop = new Loop(); |
46 | 0 | protected static Predicate is_self_loop = SelfLoopEdgePredicate.getInstance(); |
47 | ||
48 | /** | |
49 | * a convenience instance for other edge shapes to use | |
50 | * for self-loop edges where parallel instances overlay each | |
51 | * other | |
52 | */ | |
53 | 0 | protected static SimpleLoop simpleLoop = new SimpleLoop(); |
54 | ||
55 | /** | |
56 | * An edge shape that renders as a straight line between | |
57 | * the vertex endpoints. | |
58 | */ | |
59 | public static class Line extends AbstractEdgeShapeFunction { | |
60 | ||
61 | /** | |
62 | * Singleton instance of the Line2D edge shape | |
63 | */ | |
64 | private static Line2D instance = new Line2D.Float(0.0f, 0.0f, 1.0f, 0.0f); | |
65 | /** | |
66 | * Get the shape for this edge, returning either the | |
67 | * shared instance or, in the case of self-loop edges, the | |
68 | * SimpleLoop shared instance. | |
69 | */ | |
70 | public Shape getShape(Edge e) { | |
71 | ||
72 | if (is_self_loop.evaluate(e)) | |
73 | return simpleLoop.getShape(e); | |
74 | ||
75 | return instance; | |
76 | } | |
77 | } | |
78 | ||
79 | /** | |
80 | * An edge shape that renders as a bent-line between the | |
81 | * vertex endpoints. | |
82 | */ | |
83 | public static class BentLine extends AbstractEdgeShapeFunction implements ParallelRendering { | |
84 | ||
85 | /** | |
86 | * singleton instance of the BentLine shape | |
87 | */ | |
88 | private static GeneralPath instance = new GeneralPath(); | |
89 | ||
90 | protected ParallelEdgeIndexFunction parallelEdgeIndexFunction; | |
91 | ||
92 | public void setParallelEdgeIndexFunction(ParallelEdgeIndexFunction parallelEdgeIndexFunction) { | |
93 | this.parallelEdgeIndexFunction = parallelEdgeIndexFunction; | |
94 | loop.setParallelEdgeIndexFunction(parallelEdgeIndexFunction); | |
95 | } | |
96 | ||
97 | /** | |
98 | * Get the shape for this edge, returning either the | |
99 | * shared instance or, in the case of self-loop edges, the | |
100 | * Loop shared instance. | |
101 | */ | |
102 | public Shape getShape(Edge e) { | |
103 | if (is_self_loop.evaluate(e)) | |
104 | return loop.getShape(e); | |
105 | int index = 1; | |
106 | if(parallelEdgeIndexFunction != null) { | |
107 | index = parallelEdgeIndexFunction.getIndex(e); | |
108 | } | |
109 | float controlY = control_offset_increment + control_offset_increment*index; | |
110 | instance.reset(); | |
111 | instance.moveTo(0.0f, 0.0f); | |
112 | instance.lineTo(0.5f, controlY); | |
113 | instance.lineTo(1.0f, 1.0f); | |
114 | return instance; | |
115 | } | |
116 | ||
117 | } | |
118 | ||
119 | /** | |
120 | * An edge shape that renders as a QuadCurve between vertex | |
121 | * endpoints. | |
122 | */ | |
123 | public static class QuadCurve extends AbstractEdgeShapeFunction implements ParallelRendering { | |
124 | ||
125 | /** | |
126 | * singleton instance of the QuadCurve shape | |
127 | */ | |
128 | private static QuadCurve2D instance = new QuadCurve2D.Float(); | |
129 | ||
130 | protected ParallelEdgeIndexFunction parallelEdgeIndexFunction; | |
131 | ||
132 | public void setParallelEdgeIndexFunction(ParallelEdgeIndexFunction parallelEdgeIndexFunction) { | |
133 | this.parallelEdgeIndexFunction = parallelEdgeIndexFunction; | |
134 | loop.setParallelEdgeIndexFunction(parallelEdgeIndexFunction); | |
135 | } | |
136 | ||
137 | /** | |
138 | * Get the shape for this edge, returning either the | |
139 | * shared instance or, in the case of self-loop edges, the | |
140 | * Loop shared instance. | |
141 | */ | |
142 | public Shape getShape(Edge e) { | |
143 | if (is_self_loop.evaluate(e)) | |
144 | return loop.getShape(e); | |
145 | ||
146 | int index = 1; | |
147 | if(parallelEdgeIndexFunction != null) { | |
148 | index = parallelEdgeIndexFunction.getIndex(e); | |
149 | } | |
150 | ||
151 | float controlY = control_offset_increment + | |
152 | control_offset_increment * index; | |
153 | instance.setCurve(0.0f, 0.0f, 0.5f, controlY, 1.0f, 0.0f); | |
154 | return instance; | |
155 | } | |
156 | } | |
157 | ||
158 | /** | |
159 | * An edge shape that renders as a CubicCurve between vertex | |
160 | * endpoints. The two control points are at | |
161 | * (1/3*length, 2*controlY) and (2/3*length, controlY) | |
162 | * giving a 'spiral' effect. | |
163 | */ | |
164 | public static class CubicCurve extends AbstractEdgeShapeFunction implements ParallelRendering { | |
165 | ||
166 | /** | |
167 | * singleton instance of the CubicCurve edge shape | |
168 | */ | |
169 | private static CubicCurve2D instance = new CubicCurve2D.Float(); | |
170 | ||
171 | protected ParallelEdgeIndexFunction parallelEdgeIndexFunction; | |
172 | ||
173 | public void setParallelEdgeIndexFunction(ParallelEdgeIndexFunction parallelEdgeIndexFunction) { | |
174 | this.parallelEdgeIndexFunction = parallelEdgeIndexFunction; | |
175 | loop.setParallelEdgeIndexFunction(parallelEdgeIndexFunction); | |
176 | } | |
177 | ||
178 | /** | |
179 | * Get the shape for this edge, returning either the | |
180 | * shared instance or, in the case of self-loop edges, the | |
181 | * Loop shared instance. | |
182 | */ | |
183 | public Shape getShape(Edge e) { | |
184 | if (is_self_loop.evaluate(e)) | |
185 | return loop.getShape(e); | |
186 | ||
187 | int index = 1; | |
188 | if(parallelEdgeIndexFunction != null) { | |
189 | index = parallelEdgeIndexFunction.getIndex(e); | |
190 | } | |
191 | ||
192 | float controlY = control_offset_increment | |
193 | + control_offset_increment * index; | |
194 | instance.setCurve(0.0f, 0.0f, 0.33f, 2 * controlY, .66f, -controlY, | |
195 | 1.0f, 0.0f); | |
196 | return instance; | |
197 | } | |
198 | } | |
199 | ||
200 | /** | |
201 | * An edge shape that renders as a loop with its nadir at the center of the | |
202 | * vertex. Parallel instances will overlap. | |
203 | * | |
204 | * @author Tom Nelson - RABA Technologies | |
205 | */ | |
206 | public static class SimpleLoop extends AbstractEdgeShapeFunction { | |
207 | ||
208 | /** | |
209 | * singleton instance of the SimpleLoop shape | |
210 | */ | |
211 | private static Ellipse2D instance = new Ellipse2D.Float(-.5f, -.5f, 1, 1); | |
212 | ||
213 | /** | |
214 | * getter for the shape | |
215 | * @return the shared instance | |
216 | */ | |
217 | public Shape getShape(Edge e) { | |
218 | return instance; | |
219 | } | |
220 | } | |
221 | ||
222 | /** | |
223 | * An edge shape that renders as a loop with its nadir at the | |
224 | * center of the vertex. Parallel instances will not overlap. | |
225 | */ | |
226 | public static class Loop extends AbstractEdgeShapeFunction implements ParallelRendering { | |
227 | ||
228 | /** | |
229 | * singleton instance of the Loop shape | |
230 | */ | |
231 | private static Ellipse2D instance = new Ellipse2D.Float(); | |
232 | ||
233 | protected ParallelEdgeIndexFunction parallelEdgeIndexFunction; | |
234 | ||
235 | public void setParallelEdgeIndexFunction(ParallelEdgeIndexFunction parallelEdgeIndexFunction) { | |
236 | this.parallelEdgeIndexFunction = parallelEdgeIndexFunction; | |
237 | } | |
238 | ||
239 | ||
240 | /** | |
241 | * Get the shape for this edge, modifying the diameter in the | |
242 | * case of parallel edges, so they do not overlap | |
243 | */ | |
244 | public Shape getShape(Edge e) { | |
245 | int count = 1; | |
246 | if(parallelEdgeIndexFunction != null) { | |
247 | count = parallelEdgeIndexFunction.getIndex((Edge)e); | |
248 | } | |
249 | ||
250 | float x = -.5f; | |
251 | float y = -.5f; | |
252 | float diam = 1.f; | |
253 | diam += diam*count/2; | |
254 | x += x*count/2; | |
255 | y += y*count/2; | |
256 | instance.setFrame(x,y,diam,diam); | |
257 | return instance; | |
258 | } | |
259 | } | |
260 | ||
261 | /** | |
262 | * An edge shape that renders as an isosceles triangle whose | |
263 | * apex is at the destination vertex for directed edges, | |
264 | * and as a "bowtie" shape for undirected edges. | |
265 | * @author Joshua O'Madadhain | |
266 | */ | |
267 | public static class Wedge extends AbstractEdgeShapeFunction | |
268 | { | |
269 | private static GeneralPath triangle; | |
270 | private static GeneralPath bowtie; | |
271 | ||
272 | public Wedge(int width) | |
273 | { | |
274 | triangle = ArrowFactory.getWedgeArrow(width, 1); | |
275 | triangle.transform(AffineTransform.getTranslateInstance(1,0)); | |
276 | bowtie = new GeneralPath(GeneralPath.WIND_EVEN_ODD); | |
277 | bowtie.moveTo(0, width/2); | |
278 | bowtie.lineTo(1, -width/2); | |
279 | bowtie.lineTo(1, width/2); | |
280 | bowtie.lineTo(0, -width/2); | |
281 | bowtie.closePath(); | |
282 | } | |
283 | ||
284 | public Shape getShape(Edge e) | |
285 | { | |
286 | if (is_self_loop.evaluate(e)) | |
287 | return Loop.instance; | |
288 | else if (e instanceof DirectedEdge) | |
289 | return triangle; | |
290 | else | |
291 | return bowtie; | |
292 | } | |
293 | } | |
294 | ||
295 | 0 | public static interface ParallelRendering { |
296 | void setParallelEdgeIndexFunction(ParallelEdgeIndexFunction peif); | |
297 | } | |
298 | ||
299 | } |
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |