# Coverage details for edu.uci.ics.jung.visualization.PluggableRenderer

Line | Hits | Source
--- | --- | ---
1 |  | `/*`
2 |  | `* Copyright (c) 2003, 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 |  | `package edu.uci.ics.jung.visualization;`
9 |  | ``
10 |  | `import java.awt.BasicStroke;`
11 |  | `import java.awt.Color;`
12 |  | `import java.awt.Component;`
13 |  | `import java.awt.Dimension;`
14 |  | `import java.awt.Font;`
15 |  | `import java.awt.Graphics;`
16 |  | `import java.awt.Graphics2D;`
17 |  | `import java.awt.Paint;`
18 |  | `import java.awt.Rectangle;`
19 |  | `import java.awt.Shape;`
20 |  | `import java.awt.Stroke;`
21 |  | `import java.awt.geom.AffineTransform;`
22 |  | `import java.awt.geom.Ellipse2D;`
23 |  | `import java.awt.geom.GeneralPath;`
24 |  | `import java.awt.geom.Line2D;`
25 |  | `import java.awt.geom.PathIterator;`
26 |  | `import java.awt.geom.Point2D;`
27 |  | `import java.awt.geom.Rectangle2D;`
28 |  | ``
29 |  | `import javax.swing.CellRendererPane;`
30 |  | `import javax.swing.Icon;`
31 |  | `import javax.swing.JComponent;`
32 |  | ``
33 |  | `import org.apache.commons.collections.Predicate;`
34 |  | `import org.apache.commons.collections.functors.TruePredicate;`
35 |  | ``
36 |  | `import edu.uci.ics.jung.graph.ArchetypeEdge;`
37 |  | `import edu.uci.ics.jung.graph.ArchetypeVertex;`
38 |  | `import edu.uci.ics.jung.graph.Edge;`
39 |  | `import edu.uci.ics.jung.graph.Graph;`
40 |  | `import edu.uci.ics.jung.graph.UndirectedEdge;`
41 |  | `import edu.uci.ics.jung.graph.Vertex;`
42 |  | `import edu.uci.ics.jung.graph.decorators.ConstantDirectionalEdgeValue;`
43 |  | `import edu.uci.ics.jung.graph.decorators.ConstantEdgeFontFunction;`
44 |  | `import edu.uci.ics.jung.graph.decorators.ConstantEdgePaintFunction;`
45 |  | `import edu.uci.ics.jung.graph.decorators.ConstantEdgeStringer;`
46 |  | `import edu.uci.ics.jung.graph.decorators.ConstantEdgeStrokeFunction;`
47 |  | `import edu.uci.ics.jung.graph.decorators.ConstantVertexAspectRatioFunction;`
48 |  | `import edu.uci.ics.jung.graph.decorators.ConstantVertexFontFunction;`
49 |  | `import edu.uci.ics.jung.graph.decorators.ConstantVertexSizeFunction;`
50 |  | `import edu.uci.ics.jung.graph.decorators.ConstantVertexStringer;`
51 |  | `import edu.uci.ics.jung.graph.decorators.ConstantVertexStrokeFunction;`
52 |  | `import edu.uci.ics.jung.graph.decorators.DirectionalEdgeArrowFunction;`
53 |  | `import edu.uci.ics.jung.graph.decorators.EdgeArrowFunction;`
54 |  | `import edu.uci.ics.jung.graph.decorators.EdgeColorFunction;`
55 |  | `import edu.uci.ics.jung.graph.decorators.EdgeFontFunction;`
56 |  | `import edu.uci.ics.jung.graph.decorators.EdgePaintFunction;`
57 |  | `import edu.uci.ics.jung.graph.decorators.EdgeShape;`
58 |  | `import edu.uci.ics.jung.graph.decorators.EdgeShapeFunction;`
59 |  | `import edu.uci.ics.jung.graph.decorators.EdgeStringer;`
60 |  | `import edu.uci.ics.jung.graph.decorators.EdgeStrokeFunction;`
61 |  | `import edu.uci.ics.jung.graph.decorators.EllipseVertexShapeFunction;`
62 |  | `import edu.uci.ics.jung.graph.decorators.NumberEdgeValue;`
63 |  | `import edu.uci.ics.jung.graph.decorators.PickableVertexPaintFunction;`
64 |  | `import edu.uci.ics.jung.graph.decorators.VertexColorFunction;`
65 |  | `import edu.uci.ics.jung.graph.decorators.VertexFontFunction;`
66 |  | `import edu.uci.ics.jung.graph.decorators.VertexIconFunction;`
67 |  | `import edu.uci.ics.jung.graph.decorators.VertexPaintFunction;`
68 |  | `import edu.uci.ics.jung.graph.decorators.VertexShapeFunction;`
69 |  | `import edu.uci.ics.jung.graph.decorators.VertexStringer;`
70 |  | `import edu.uci.ics.jung.graph.decorators.VertexStrokeFunction;`
71 |  | `import edu.uci.ics.jung.graph.predicates.EdgePredicate;`
72 |  | `import edu.uci.ics.jung.graph.predicates.SelfLoopEdgePredicate;`
73 |  | `import edu.uci.ics.jung.utils.Pair;`
74 |  | `import edu.uci.ics.jung.utils.ParallelEdgeIndexFunction;`
75 |  | `import edu.uci.ics.jung.utils.ParallelEdgeIndexSingleton;`
76 |  | `import edu.uci.ics.jung.visualization.transform.MutableAffineTransformer;`
77 |  | `import edu.uci.ics.jung.visualization.transform.MutableTransformer;`
78 |  | ``
79 |  | `/**`
80 |  | `* <p>A renderer with all sorts of buttons to press and dials to turn.`
81 |  | `* Using the appropriate methods, the user can override the default`
82 |  | `* properties/behaviors for vertex paint, stroke, shape, label, label font,`
83 |  | `* and label centering; and for edge paint, stroke, label, arrows, label font,`
84 |  | `* label positioning, and drawing.`
85 |  | `* </p>`
86 |  | `* <p>Notes on these decorators:`
87 |  | `* <ul>`
88 |  | `* <li/>The decorators are all orthogonal; changing one does not change the behavior of any`
89 |  | `* other (unless your decorator implementations depend on one another).`
90 |  | `* <li/>The default properties apply to each vertices/edges, but the decorators allow these`
91 |  | `* properties to be specified individually for each vertex/edge. See the documentation for`
92 |  | `* each of these decorators for specific instructions on their use.`
93 |  | `* <li/>Implementations of these decorator interfaces are provided that allow the user`
94 |  | `* to specify a single (constant) property to apply to all vertices/edges.`
95 |  | `* <li/>There are additional interfaces and classes that allow the size and aspect ratio`
96 |  | `* of the vertex shape to be independently manipulated, and that provide factory methods`
97 |  | `* for generating various standard shapes; see <code>SettableVertexShapeFunction</code>,`
98 |  | `* <code>AbstractVertexShapeFunction</code>, <code>VertexShapeFactory</code>, and the`
99 |  | `* sample <code>samples.graph.PluggableRendererDemo</code>.`
100 |  | `* <li/>This class provides default <code>Stroke</code> implementations for dotted and`
101 |  | `* dashed lines: the <code>DOTTED</code> and <code>DASHED</code> static constants,`
102 |  | `* respectively.`
103 |  | `* <li/>The <code>EdgeArrowPredicate</code> specifies the edges for which arrows`
104 |  | `* should be drawn; the <code>EdgeArrowFunction</code> specifies the shapes of`
105 |  | `* the arrowheads for those edges that pass the <code>EdgeArrowPredicate</code>.`
106 |  | `* <li/>If the specified vertex inclusion <code>Predicate</code> indicates that`
107 |  | `* vertex <code>v</code> is not to be drawn, none of its incident edges will be drawn either.`
108 |  | `* </ul>`
109 |  | `*`
110 |  | `* <p>By default, self-loops are drawn as circles.</p>`
111 |  | `*`
112 |  | `* <p>By default, undirected edges are drawn as straight lines, directed edges are`
113 |  | `* drawn as bent lines, and parallel edges are drawn on top`
114 |  | `* of one another.</p>`
115 |  | ``
116 |  | `* <p>Arrowheads are drawn so that the point of the arrow is at the boundary of the`
117 |  | `* vertex shapes. In the current implementation, finding the place`
118 |  | `* where arrows are drawn is fairly slow; for large graphs, this should`
119 |  | `* be turned off.</p>`
120 |  | `*`
121 |  | `* <p>Setting a stroke width other than 1, or using transparency,`
122 |  | `* may slow down rendering of the visualization.`
123 |  | `* </p>`
124 |  | `*`
125 |  | `* @author Danyel Fisher`
126 |  | `* @author Joshua O'Madadhain`
127 |  | `* @author Tom Nelson`
128 |  | `*/`
129 |  | `public class PluggableRenderer extends AbstractRenderer implements PickedInfo, HasShapeFunctions`
130 |  | `{`
131 |  | ``
132 | 0 | `protected float arrow_placement_tolerance = 1;`
133 | 0 | `protected final static float[] dotting = {1.0f, 3.0f};`
134 |  | `/**`
135 |  | `* A stroke for a dotted line: 1 pixel width, round caps, round joins, and an`
136 |  | `* array of {1.0f, 3.0f}.`
137 |  | `*/`
138 | 0 | `public final static Stroke DOTTED = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,`
139 |  | `BasicStroke.JOIN_ROUND, 1.0f, dotting, 0f);`
140 |  | ``
141 | 0 | `protected final static float[] dashing = {5.0f};`
142 |  | `/**`
143 |  | `* A stroke for a dashed line: 1 pixel width, square caps, beveled joins, and an`
144 |  | `* array of {5.0f}.`
145 |  | `*/`
146 | 0 | `public final static Stroke DASHED = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE,`
147 |  | `BasicStroke.JOIN_BEVEL, 1.0f, dashing, 0f);`
148 |  | ``
149 |  | `/**`
150 |  | `* Specifies the offset for the edge labels.`
151 |  | `*/`
152 |  | `public static final int LABEL_OFFSET = 10;`
153 |  | ``
154 |  | `/**`
155 |  | `* Specifies the maximum number of iterations to run the edge subdivision loop`
156 |  | `* in <code>getLastOutsideSegment</code>; this is done to fix the arrow`
157 |  | `* orientation problem noted in bug report #1450529.`
158 |  | `*/`
159 |  | `protected static final int MAX_ITERATIONS = 10;`
160 |  | ``
161 | 0 | `protected Predicate vertexIncludePredicate = TruePredicate.getInstance();`
162 | 0 | `protected VertexStrokeFunction vertexStrokeFunction =`
163 |  | `new ConstantVertexStrokeFunction(1.0f);`
164 | 0 | `protected VertexShapeFunction vertexShapeFunction =`
165 |  | `new EllipseVertexShapeFunction(`
166 |  | `new ConstantVertexSizeFunction(20),`
167 |  | `new ConstantVertexAspectRatioFunction(1.0f));`
168 | 0 | `protected VertexStringer vertexStringer =`
169 |  | `new ConstantVertexStringer(null);`
170 |  | `protected VertexIconFunction vertexIconFunction;`
171 | 0 | `protected VertexFontFunction vertexFontFunction =`
172 |  | `new ConstantVertexFontFunction(new Font("Helvetica", Font.PLAIN, 12));`
173 | 0 | `protected boolean centerVertexLabel = false;`
174 |  | ``
175 | 0 | `protected VertexPaintFunction vertexPaintFunction =`
176 |  | `new PickableVertexPaintFunction(this, Color.BLACK, Color.RED, Color.ORANGE);`
177 |  | ``
178 | 0 | `protected EdgeStringer edgeStringer =`
179 |  | `new ConstantEdgeStringer(null);`
180 | 0 | `protected EdgeStrokeFunction edgeStrokeFunction =`
181 |  | `new ConstantEdgeStrokeFunction(1.0f);`
182 | 0 | `protected EdgeArrowFunction edgeArrowFunction =`
183 |  | `new DirectionalEdgeArrowFunction(10, 8, 4);`
184 | 0 | `protected Predicate edgeArrowPredicate = Graph.DIRECTED_EDGE;`
185 | 0 | `protected Predicate edgeIncludePredicate = TruePredicate.getInstance();`
186 | 0 | `protected EdgeFontFunction edgeFontFunction =`
187 |  | `new ConstantEdgeFontFunction(new Font("Helvetica", Font.PLAIN, 12));`
188 | 0 | `protected NumberEdgeValue edgeLabelClosenessFunction =`
189 |  | `new ConstantDirectionalEdgeValue(0.5, 0.65);`
190 | 0 | `protected EdgeShapeFunction edgeShapeFunction =`
191 |  | `new EdgeShape.QuadCurve();`
192 | 0 | `protected EdgePaintFunction edgePaintFunction =`
193 |  | `new ConstantEdgePaintFunction(Color.black, null);`
194 | 0 | `protected ParallelEdgeIndexFunction parallelEdgeIndexFunction =`
195 |  | `ParallelEdgeIndexSingleton.getInstance();`
196 | 0 | `protected MutableTransformer viewTransformer = new MutableAffineTransformer();`
197 |  | ``
198 |  | `/**`
199 |  | `* the JComponent that this Renderer will display the graph on`
200 |  | `*/`
201 |  | `protected JComponent screenDevice;`
202 |  | ``
203 |  | `/**`
204 |  | `* The CellRendererPane is used here just as it is in JTree`
205 |  | `* and JTable, to allow a pluggable JLabel-based renderer for`
206 |  | `* Vertex and Edge label strings and icons.`
207 |  | `*/`
208 | 0 | `protected CellRendererPane rendererPane = new CellRendererPane();`
209 |  | ``
210 |  | `/**`
211 |  | `* A default GraphLabelRenderer - picked Vertex labels are`
212 |  | `* blue, picked edge labels are cyan`
213 |  | `*/`
214 | 0 | `protected GraphLabelRenderer graphLabelRenderer =`
215 |  | `new DefaultGraphLabelRenderer(Color.blue, Color.cyan);`
216 |  | ``
217 | 0 | `protected final static EdgePredicate self_loop = SelfLoopEdgePredicate.getInstance();`
218 |  | ``
219 |  | `public PluggableRenderer()`
220 | 0 | `{`
221 | 0 | `this.setEdgeShapeFunction(new EdgeShape.QuadCurve());`
222 | 0 | `}`
223 |  | ``
224 |  | `/**`
225 |  | `* @return Returns the edgeArrowFunction.`
226 |  | `*/`
227 |  | `public EdgeArrowFunction getEdgeArrowFunction() {`
228 | 0 | `return edgeArrowFunction;`
229 |  | `}`
230 |  | ``
231 |  | `/**`
232 |  | `* @return Returns the edgeArrowPredicate.`
233 |  | `*/`
234 |  | `public Predicate getEdgeArrowPredicate() {`
235 | 0 | `return edgeArrowPredicate;`
236 |  | `}`
237 |  | ``
238 |  | `/**`
239 |  | `* @return Returns the edgeFontFunction.`
240 |  | `*/`
241 |  | `public EdgeFontFunction getEdgeFontFunction() {`
242 | 0 | `return edgeFontFunction;`
243 |  | `}`
244 |  | ``
245 |  | `/**`
246 |  | `* @return Returns the edgeIncludePredicate.`
247 |  | `*/`
248 |  | `public Predicate getEdgeIncludePredicate() {`
249 | 0 | `return edgeIncludePredicate;`
250 |  | `}`
251 |  | ``
252 |  | `/**`
253 |  | `* @return Returns the edgeLabelClosenessFunction.`
254 |  | `*/`
255 |  | `public NumberEdgeValue getEdgeLabelClosenessFunction() {`
256 | 0 | `return edgeLabelClosenessFunction;`
257 |  | `}`
258 |  | ``
259 |  | `/**`
260 |  | `* @return Returns the edgePaintFunction.`
261 |  | `*/`
262 |  | `public EdgePaintFunction getEdgePaintFunction() {`
263 | 0 | `return edgePaintFunction;`
264 |  | `}`
265 |  | ``
266 |  | `/**`
267 |  | `* @return Returns the edgeStringer.`
268 |  | `*/`
269 |  | `public EdgeStringer getEdgeStringer() {`
270 | 0 | `return edgeStringer;`
271 |  | `}`
272 |  | ``
273 |  | `/**`
274 |  | `* @return Returns the edgeStrokeFunction.`
275 |  | `*/`
276 |  | `public EdgeStrokeFunction getEdgeStrokeFunction() {`
277 | 0 | `return edgeStrokeFunction;`
278 |  | `}`
279 |  | ``
280 |  | `/**`
281 |  | `* @return Returns the screenDevice.`
282 |  | `*/`
283 |  | `public JComponent getScreenDevice() {`
284 | 0 | `return screenDevice;`
285 |  | `}`
286 |  | ``
287 |  | `/**`
288 |  | `* @return Returns the vertexFontFunction.`
289 |  | `*/`
290 |  | `public VertexFontFunction getVertexFontFunction() {`
291 | 0 | `return vertexFontFunction;`
292 |  | `}`
293 |  | ``
294 |  | `/**`
295 |  | `* @return Returns the vertexIncludePredicate.`
296 |  | `*/`
297 |  | `public Predicate getVertexIncludePredicate() {`
298 | 0 | `return vertexIncludePredicate;`
299 |  | `}`
300 |  | ``
301 |  | `/**`
302 |  | `* @return Returns the vertexPaintFunction.`
303 |  | `*/`
304 |  | `public VertexPaintFunction getVertexPaintFunction() {`
305 | 0 | `return vertexPaintFunction;`
306 |  | `}`
307 |  | ``
308 |  | `/**`
309 |  | `* @return Returns the vertexStringer.`
310 |  | `*/`
311 |  | `public VertexStringer getVertexStringer() {`
312 | 0 | `return vertexStringer;`
313 |  | `}`
314 |  | ``
315 |  | `/**`
316 |  | `* @return Returns the vertexIconFunction`
317 |  | `*/`
318 |  | `public VertexIconFunction getVertexIconFunction() {`
319 | 0 | `return vertexIconFunction;`
320 |  | `}`
321 |  | ``
322 |  | `/**`
323 |  | `* @param vertexIconFunction The VertexIconFunction to set.`
324 |  | `*/`
325 |  | `public void setVertexIconFunction(VertexIconFunction vertexIconFunction) {`
326 | 0 | `this.vertexIconFunction = vertexIconFunction;`
327 | 0 | `}`
328 |  | ``
329 |  | `/**`
330 |  | `* @return Returns the vertexStrokeFunction.`
331 |  | `*/`
332 |  | `public VertexStrokeFunction getVertexStrokeFunction() {`
333 | 0 | `return vertexStrokeFunction;`
334 |  | `}`
335 |  | ``
336 |  | `/**`
337 |  | `* The screen device is the JComponent on which the renderer`
338 |  | `* will display the graph. It is used here to assist with removing`
339 |  | `* unnecessary calls to position and draw graph elements that will`
340 |  | `* not be visible in the display. It is also used as the container`
341 |  | `* for the CellRendererPane.`
342 |  | `* @param screenDevice`
343 |  | `*/`
344 |  | `public void setScreenDevice(JComponent screenDevice) {`
345 | 0 | `this.screenDevice = screenDevice;`
346 | 0 | `this.screenDevice.add(rendererPane);`
347 | 0 | `}`
348 |  | ``
349 |  | `/**`
350 |  | `* Specifies the smallest (squared) distance that an arrowhead`
351 |  | `* must be moved in order for the placement code to decide that`
352 |  | `* it's "close enough". Default value is 1.`
353 |  | `*/`
354 |  | `public void setArrowPlacementTolerance(float tolerance) {`
355 | 0 | `this.arrow_placement_tolerance = tolerance;`
356 | 0 | `}`
357 |  | ``
358 |  | `/**`
359 |  | `* Sets the <code>EdgeArrowFunction</code> that specifies the`
360 |  | `* <code>Shape</code> of the arrowheads for each edge.`
361 |  | `* The same shape will be used for both ends of an undirected`
362 |  | `* edge. The default arrow-drawing implementations assume that arrows`
363 |  | `* are drawn with their base on the y-axis, pointed left (in the negative`
364 |  | `* x-direction), centered on the x-axis.`
365 |  | `* Note that the <code>EdgeArrowFunction</code> must return a valid shape`
366 |  | `* for any edge for which the edge arrow <code>Predicate</code>`
367 |  | `* returns <code>true</code>.`
368 |  | `* <br>Default: wedge arrows for undirected edges, notched arrows for directed edges`
369 |  | `* (<code>DirectionalEdgeArrowFunction</code>)`
370 |  | `* @see edu.uci.ics.jung.decorators.EdgeArrowFunction`
371 |  | `* @see ArrowFactory`
372 |  | `*/`
373 |  | `public void setEdgeArrowFunction(EdgeArrowFunction eaf)`
374 |  | `{`
375 | 0 | `this.edgeArrowFunction = eaf;`
376 | 0 | `}`
377 |  | ``
378 |  | `/**`
379 |  | `* @return Returns the graphLabelRenderer.`
380 |  | `*/`
381 |  | `public GraphLabelRenderer getGraphLabelRenderer() {`
382 | 0 | `return graphLabelRenderer;`
383 |  | `}`
384 |  | `/**`
385 |  | `* @param graphLabelRenderer The graphLabelRenderer to set.`
386 |  | `*/`
387 |  | `public void setGraphLabelRenderer(GraphLabelRenderer graphLabelRenderer) {`
388 | 0 | `this.graphLabelRenderer = graphLabelRenderer;`
389 | 0 | `}`
390 |  | `/**`
391 |  | `* Sets the <code>EdgeArrowPredicate</code> that specifies whether`
392 |  | `* arrowheads should be drawn for each edge. If the predicate evaluates`
393 |  | `* to <code>true</code> for a specified edge, arrows should be drawn`
394 |  | `* for that edge.`
395 |  | `* <br>Default: only directed edges have arrows (<code>Graph.DIRECTED_EDGE</code> instance)`
396 |  | `* @see EdgeArrowFunction`
397 |  | `*/`
398 |  | `public void setEdgeArrowPredicate(Predicate p)`
399 |  | `{`
400 | 0 | `this.edgeArrowPredicate = p;`
401 | 0 | `}`
402 |  | ``
403 |  | `/**`
404 |  | `* Sets the <code>EdgeColorFunction</code> that specifies the paint to`
405 |  | `* draw each edge.`
406 |  | `* <br>Default: Color.BLACK`
407 |  | `* @see java.awt.Color`
408 |  | `* @deprecated Use setEdgePaintFunction instead`
409 |  | `*/`
410 |  | `public void setEdgeColorFunction(EdgeColorFunction ecf)`
411 |  | `{`
412 | 0 | `this.edgePaintFunction = new EdgeColorToEdgePaintFunctionConverter( ecf );`
413 | 0 | `}`
414 |  | ``
415 |  | ``
416 |  | `/**`
417 |  | `* Sets the <code>EdgeFontFunction</code> that specifies the font`
418 |  | `* to use for drawing each edge label. This can be used (for example) to`
419 |  | `* emphasize (or to de-emphasize) edges that have a specific property.`
420 |  | `* <br>Default: 12-point Helvetica`
421 |  | `* @see EdgeFontFunction`
422 |  | `*/`
423 |  | `public void setEdgeFontFunction(EdgeFontFunction eff)`
424 |  | `{`
425 | 0 | `this.edgeFontFunction = eff;`
426 | 0 | `}`
427 |  | ``
428 |  | `/**`
429 |  | `* Sets the <code>Predicate</code> that specifies whether each`
430 |  | `* edge should be drawn; only those edges for which this`
431 |  | `* predicate returns <code>true</code> will be drawn. This can be`
432 |  | `* used to selectively display only those edges that have a`
433 |  | `* specific property, such as a particular decoration or value, or`
434 |  | `* only those edges of a specific type (such as directed edges,`
435 |  | `* or everything except self-loops).`
436 |  | `* <br>Default: all edges drawn (<code>TruePredicate</code> instance)`
437 |  | `* @see org.apache.commons.collections.Predicate`
438 |  | `*/`
439 |  | `public void setEdgeIncludePredicate(Predicate p)`
440 |  | `{`
441 | 0 | `this.edgeIncludePredicate = p;`
442 | 0 | `}`
443 |  | ``
444 |  | `/**`
445 |  | `* Sets the <code>NumberEdgeValue</code> that specifies where to draw`
446 |  | `* the label for each edge. A value of 0 draws the label on top of`
447 |  | `* the edge's first vertex; a value of 1.0 draws the label on top`
448 |  | `* of the edge's second vertex; values between 0 and 1 split the`
449 |  | `* difference (i.e., a value of 0.5 draws the label halfway in between`
450 |  | `* the two vertices). The effect of values outside the range [0,1]`
451 |  | `* is undefined. This function is not used for self-loops.`
452 |  | `* <br>Default: 0.5 for undirected edges, 0.75 for directed edges`
453 |  | `* (<code>ConstantDirectionalEdgeValue</code>)`
454 |  | `* @see edu.uci.ics.jung.graph.decorators.NumberEdgeValue`
455 |  | `*/`
456 |  | `public void setEdgeLabelClosenessFunction(NumberEdgeValue nev)`
457 |  | `{`
458 | 0 | `this.edgeLabelClosenessFunction = nev;`
459 | 0 | `}`
460 |  | ``
461 |  | `/**`
462 |  | `* @param impl`
463 |  | `*/`
464 |  | `public void setEdgePaintFunction(EdgePaintFunction impl) {`
465 | 0 | `edgePaintFunction = impl;`
466 |  | ``
467 | 0 | `}`
468 |  | ``
469 |  | `/**`
470 |  | `* setter for the EdgeShapeFunction`
471 |  | `* @param impl`
472 |  | `*/`
473 |  | `public void setEdgeShapeFunction(EdgeShapeFunction impl) {`
474 | 0 | `edgeShapeFunction = impl;`
475 | 0 | `if(edgeShapeFunction instanceof EdgeShape.ParallelRendering) {`
476 | 0 | `((EdgeShape.ParallelRendering)edgeShapeFunction).setParallelEdgeIndexFunction(this.parallelEdgeIndexFunction);`
477 |  | `}`
478 | 0 | `}`
479 |  | ``
480 |  | `/**`
481 |  | `* @return Returns the EdgeShapeFunction that .`
482 |  | `*/`
483 |  | `public EdgeShapeFunction getEdgeShapeFunction() {`
484 | 0 | `return edgeShapeFunction;`
485 |  | `}`
486 |  | `/**`
487 |  | `* Sets the <code>EdgeStringer</code> that specifies the label to`
488 |  | `* draw for each edge.`
489 |  | `* <br>Default: no labels`
490 |  | `* (<code>ConstantEdgeStringer</code>)`
491 |  | `* @see edu.uci.ics.jung.graph.decorators.EdgeStringer`
492 |  | `*/`
493 |  | `public void setEdgeStringer(EdgeStringer es)`
494 |  | `{`
495 | 0 | `this.edgeStringer = es;`
496 | 0 | `}`
497 |  | ``
498 |  | `/**`
499 |  | `* Sets the <code>EdgeStrokeFunction</code> that specifies the`
500 |  | `* <code>Stroke</code> to use when drawing each edge.`
501 |  | `* <br>Default: 1-pixel-width basic stroke`
502 |  | `* (<code>ConstantEdgeStrokeFunction</code>)`
503 |  | `* @see java.awt.Stroke`
504 |  | `* @see EdgeStrokeFunction`
505 |  | `*/`
506 |  | `public void setEdgeStrokeFunction(EdgeStrokeFunction esf)`
507 |  | `{`
508 | 0 | `this.edgeStrokeFunction = esf;`
509 | 0 | `}`
510 |  | ``
511 |  | `/**`
512 |  | `* <p>Sets the <code>VertexPaintFunction</code> to the parameter`
513 |  | `* @see #setVertexPaintFunction(VertexPaintFunction)`
514 |  | `* @see VertexColorFunction`
515 |  | `* @see VertexColorToVertexPaintConverter`
516 |  | `* @deprecated Use setVertexPaintFunction with a VertexPaintFunction if you can`
517 |  | `*/`
518 |  | `public void setVertexColorFunction(VertexColorFunction vcf)`
519 |  | `{`
520 | 0 | `this.vertexPaintFunction = new VertexColorToVertexPaintConverter( vcf );`
521 | 0 | `}`
522 |  | ``
523 |  | `/**`
524 |  | `* <p>Sets the <code>VertexPaintFunction</code> which specifies the`
525 |  | `* draw (border and text) and fill (interior) Paint for each vertex.</p>`
526 |  | `* <p>If users want the <code>VertexPaintFunction</code> implementation`
527 |  | `* to highlight selected vertices, they should take this`
528 |  | `* PluggableRenderer instance as a constructor parameter, and call`
529 |  | `* the <code>isPicked</code> method on it to identify selected vertices.</p>`
530 |  | `* <p>Default: black borders, red foreground (selected vertex is orange).</p>`
531 |  | `*/`
532 |  | `public void setVertexPaintFunction( VertexPaintFunction vpf )`
533 |  | `{`
534 | 0 | `this.vertexPaintFunction = vpf;`
535 | 0 | `}`
536 |  | ``
537 |  | `/**`
538 |  | `* Returns the <code>VertexShapeFunction</code> currently being`
539 |  | `* used by this instance.`
540 |  | `*/`
541 |  | `public VertexShapeFunction getVertexShapeFunction()`
542 |  | `{`
543 | 0 | `return vertexShapeFunction;`
544 |  | `}`
545 |  | ``
546 |  | `/**`
547 |  | `* Sets the <code>VertexFontFunction</code> that specifies the font`
548 |  | `* to use for drawing each vertex label. This can be used (for example) to`
549 |  | `* emphasize (or to de-emphasize) vertices that have a specific property.`
550 |  | `* <br>Default: 12-point Helvetica`
551 |  | `* @see VertexFontFunction`
552 |  | `*/`
553 |  | `public void setVertexFontFunction(VertexFontFunction vff)`
554 |  | `{`
555 | 0 | `this.vertexFontFunction = vff;`
556 | 0 | `}`
557 |  | ``
558 |  | `/**`
559 |  | `* Sets the <code>Predicate</code> that specifies whether each`
560 |  | `* vertex should be drawn; only those vertices for which this`
561 |  | `* predicate returns <code>true</code> will be drawn. This can be`
562 |  | `* used to selectively display only those vertices that have a`
563 |  | `* specific property, such as a particular decoration or value.`
564 |  | `* <br>Default: all vertices drawn (<code>TruePredicate</code> instance)`
565 |  | `* @see org.apache.commons.collections.Predicate`
566 |  | `*/`
567 |  | `public void setVertexIncludePredicate(Predicate p)`
568 |  | `{`
569 | 0 | `this.vertexIncludePredicate = p;`
570 | 0 | `}`
571 |  | ``
572 |  | `/**`
573 |  | `* Specifies whether vertex labels are drawn centered on the vertex`
574 |  | `* position (<code>true</code>) or offset to one side (<code>false</code>).`
575 |  | `* <br>Default: offset`
576 |  | `*/`
577 |  | `public void setVertexLabelCentering(boolean b)`
578 |  | `{`
579 | 0 | `centerVertexLabel = b;`
580 | 0 | `}`
581 |  | ``
582 |  | `/**`
583 |  | `*`
584 |  | `* @return whether the vertex labels should be centered in the vertex`
585 |  | `*/`
586 |  | `public boolean getVertexLabelCentering()`
587 |  | `{`
588 | 0 | `return centerVertexLabel;`
589 |  | `}`
590 |  | ``
591 |  | `/**`
592 |  | `* Sets the <code>VertexShapeFunction</code>,`
593 |  | `* which specifies the <code>Shape</code> for each vertex.`
594 |  | `* Users that wish to independently change the size and`
595 |  | `* aspect ratio of a vertex's shape should take a look`
596 |  | `* at the <code>SettableVertexShapeFunction</code>`
597 |  | `* interface and the <code>AbstractVertexShapeFunction</code>`
598 |  | `* abstract class.`
599 |  | `* <br>Default: 8-pixel-diameter circle`
600 |  | `* (<code>EllipseVertexShapeFunction</code>)`
601 |  | `* @see java.awt.Shape`
602 |  | `* @see VertexShapeFunction`
603 |  | `*/`
604 |  | `public void setVertexShapeFunction(VertexShapeFunction vsf)`
605 |  | `{`
606 | 0 | `this.vertexShapeFunction = vsf;`
607 | 0 | `}`
608 |  | ``
609 |  | `/**`
610 |  | `* Sets the <code>VertexStringer</code> that specifies the label to`
611 |  | `* draw for each vertex.`
612 |  | `* <br>Default: no labels`
613 |  | `* (<code>ConstantVertexStringer</code>)`
614 |  | `* @see edu.uci.ics.jung.graph.decorators.VertexStringer`
615 |  | `*/`
616 |  | `public void setVertexStringer(VertexStringer vs)`
617 |  | `{`
618 | 0 | `this.vertexStringer = vs;`
619 | 0 | `}`
620 |  | ``
621 |  | `/**`
622 |  | `* Sets the <code>VertexStrokeFunction</code> which`
623 |  | `* specifies the <code>Stroke</code> to use when drawing`
624 |  | `* each vertex border.`
625 |  | `* <br>Default: 1-pixel-width basic stroke.`
626 |  | `* @see java.awt.Stroke`
627 |  | `* @see VertexStrokeFunction`
628 |  | `*/`
629 |  | `public void setVertexStrokeFunction(VertexStrokeFunction vsf)`
630 |  | `{`
631 | 0 | `this.vertexStrokeFunction = vsf;`
632 | 0 | `}`
633 |  | ``
634 |  | ``
635 |  | `/**`
636 |  | `* Paints <code>e</code>, whose endpoints are at <code>(x1,y1)</code>`
637 |  | `* and <code>(x2,y2)</code>, on the graphics context <code>g</code>.`
638 |  | `* Uses the paint and stroke specified by this instance's`
639 |  | `* <code>EdgeColorFunction</code> and <code>EdgeStrokeFunction</code>,`
640 |  | `* respectively. (If the paint is unspecified, the existing`
641 |  | `* paint for the graphics context is used; the same applies to stroke.)`
642 |  | `* The details of the actual rendering are delegated to`
643 |  | `* <code>drawSelfLoop</code> or <code>drawSimpleEdge</code>,`
644 |  | `* depending on the type of the edge.`
645 |  | `* Note that <code>(x1, y1)</code> is the location of`
646 |  | `* e.getEndpoints.getFirst() and <code>(x2, y2)</code> is the location of`
647 |  | `* e.getEndpoints.getSecond().`
648 |  | `*`
649 |  | `*/`
650 |  | `public void paintEdge(Graphics g, Edge e, int x1, int y1, int x2, int y2)`
651 |  | `{`
652 | 0 | `if (!edgeIncludePredicate.evaluate(e))`
653 | 0 | `return;`
654 |  | ``
655 |  | `// don't draw edge if either incident vertex is not drawn`
656 | 0 | `Pair endpoints = e.getEndpoints();`
657 | 0 | `Vertex v1 = (Vertex)endpoints.getFirst();`
658 | 0 | `Vertex v2 = (Vertex)endpoints.getSecond();`
659 | 0 | `if (!vertexIncludePredicate.evaluate(v1) ||`
660 |  | `!vertexIncludePredicate.evaluate(v2))`
661 | 0 | `return;`
662 |  | ``
663 | 0 | `Graphics2D g2d = (Graphics2D) g;`
664 |  | ``
665 | 0 | `Stroke new_stroke = edgeStrokeFunction.getStroke(e);`
666 | 0 | `Stroke old_stroke = g2d.getStroke();`
667 | 0 | `if (new_stroke != null)`
668 | 0 | `g2d.setStroke(new_stroke);`
669 |  | ``
670 | 0 | `drawSimpleEdge(g2d, e, x1, y1, x2, y2);`
671 |  | ``
672 |  | `// restore paint and stroke`
673 | 0 | `if (new_stroke != null)`
674 | 0 | `g2d.setStroke(old_stroke);`
675 |  | ``
676 | 0 | `}`
677 |  | ``
678 |  | `/**`
679 |  | `* Draws the edge <code>e</code>, whose endpoints are at <code>(x1,y1)</code>`
680 |  | `* and <code>(x2,y2)</code>, on the graphics context <code>g</code>.`
681 |  | `* The <code>Shape</code> provided by the <code>EdgeShapeFunction</code> instance`
682 |  | `* is scaled in the x-direction so that its width is equal to the distance between`
683 |  | `* <code>(x1,y1)</code> and <code>(x2,y2)</code>.`
684 |  | `*/`
685 |  | `protected void drawSimpleEdge(Graphics2D g, Edge e, int x1, int y1, int x2, int y2)`
686 |  | `{`
687 | 0 | `Pair endpoints = e.getEndpoints();`
688 | 0 | `Vertex v1 = (Vertex)endpoints.getFirst();`
689 | 0 | `Vertex v2 = (Vertex)endpoints.getSecond();`
690 | 0 | `boolean isLoop = v1.equals(v2);`
691 | 0 | `Shape s2 = vertexShapeFunction.getShape(v2);`
692 | 0 | `Shape edgeShape = edgeShapeFunction.getShape(e);`
693 |  | ``
694 | 0 | `boolean edgeHit = true;`
695 | 0 | `boolean arrowHit = true;`
696 | 0 | `Rectangle deviceRectangle = null;`
697 | 0 | `if(screenDevice != null) {`
698 | 0 | `Dimension d = screenDevice.getSize();`
699 | 0 | `if(d.width <= 0 || d.height <= 0) {`
700 | 0 | `d = screenDevice.getPreferredSize();`
701 |  | `}`
702 | 0 | `deviceRectangle = new Rectangle(0,0,d.width,d.height);`
703 |  | `}`
704 |  | ``
705 | 0 | `AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1);`
706 |  | ``
707 | 0 | `if(isLoop) {`
708 |  | `// this is a self-loop. scale it is larger than the vertex`
709 |  | `// it decorates and translate it so that its nadir is`
710 |  | `// at the center of the vertex.`
711 | 0 | `Rectangle2D s2Bounds = s2.getBounds2D();`
712 | 0 | `xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight());`
713 | 0 | `xform.translate(0, -edgeShape.getBounds2D().getWidth()/2);`
714 |  | `} else {`
715 |  | `// this is a normal edge. Rotate it to the angle between`
716 |  | `// vertex endpoints, then scale it to the distance between`
717 |  | `// the vertices`
718 | 0 | `float dx = x2-x1;`
719 | 0 | `float dy = y2-y1;`
720 | 0 | `float thetaRadians = (float) Math.atan2(dy, dx);`
721 | 0 | `xform.rotate(thetaRadians);`
722 | 0 | `float dist = (float) Math.sqrt(dx*dx + dy*dy);`
723 | 0 | `xform.scale(dist, 1.0);`
724 |  | `}`
725 |  | ``
726 | 0 | `edgeShape = xform.createTransformedShape(edgeShape);`
727 |  | ``
728 | 0 | `edgeHit = viewTransformer.transform(edgeShape).intersects(deviceRectangle);`
729 |  | ``
730 | 0 | `if(edgeHit == true) {`
731 |  | ``
732 | 0 | `Paint oldPaint = g.getPaint();`
733 |  | ``
734 |  | `// get Paints for filling and drawing`
735 |  | `// (filling is done first so that drawing and label use same Paint)`
736 | 0 | `Paint fill_paint = edgePaintFunction.getFillPaint(e);`
737 | 0 | `if (fill_paint != null)`
738 |  | `{`
739 | 0 | `g.setPaint(fill_paint);`
740 | 0 | `g.fill(edgeShape);`
741 |  | `}`
742 | 0 | `Paint draw_paint = edgePaintFunction.getDrawPaint(e);`
743 | 0 | `if (draw_paint != null)`
744 |  | `{`
745 | 0 | `g.setPaint(draw_paint);`
746 | 0 | `g.draw(edgeShape);`
747 |  | `}`
748 |  | ``
749 | 0 | `float scalex = (float)g.getTransform().getScaleX();`
750 | 0 | `float scaley = (float)g.getTransform().getScaleY();`
751 |  | `// see if arrows are too small to bother drawing`
752 | 0 | `if(scalex < .3 || scaley < .3) return;`
753 |  | ``
754 | 0 | `if (edgeArrowPredicate.evaluate(e)) {`
755 |  | ``
756 | 0 | `Shape destVertexShape =`
757 |  | `vertexShapeFunction.getShape((Vertex)e.getEndpoints().getSecond());`
758 | 0 | `AffineTransform xf = AffineTransform.getTranslateInstance(x2, y2);`
759 | 0 | `destVertexShape = xf.createTransformedShape(destVertexShape);`
760 |  | ``
761 | 0 | `arrowHit = viewTransformer.transform(destVertexShape).intersects(deviceRectangle);`
762 | 0 | `if(arrowHit) {`
763 |  | ``
764 |  | `AffineTransform at;`
765 | 0 | `if (edgeShape instanceof GeneralPath)`
766 | 0 | `at = getArrowTransform((GeneralPath)edgeShape, destVertexShape);`
767 |  | `else`
768 | 0 | `at = getArrowTransform(new GeneralPath(edgeShape), destVertexShape);`
769 | 0 | `if(at == null) return;`
770 | 0 | `Shape arrow = edgeArrowFunction.getArrow(e);`
771 | 0 | `arrow = at.createTransformedShape(arrow);`
772 |  | `// note that arrows implicitly use the edge's draw paint`
773 | 0 | `g.fill(arrow);`
774 |  | `}`
775 | 0 | `if (e instanceof UndirectedEdge) {`
776 | 0 | `Shape vertexShape =`
777 |  | `vertexShapeFunction.getShape((Vertex)e.getEndpoints().getFirst());`
778 | 0 | `xf = AffineTransform.getTranslateInstance(x1, y1);`
779 | 0 | `vertexShape = xf.createTransformedShape(vertexShape);`
780 |  | ``
781 | 0 | `arrowHit = viewTransformer.transform(vertexShape).intersects(deviceRectangle);`
782 |  | ``
783 | 0 | `if(arrowHit) {`
784 |  | `AffineTransform at;`
785 | 0 | `if (edgeShape instanceof GeneralPath)`
786 | 0 | `at = getReverseArrowTransform((GeneralPath)edgeShape, vertexShape, !isLoop);`
787 |  | `else`
788 | 0 | `at = getReverseArrowTransform(new GeneralPath(edgeShape), vertexShape, !isLoop);`
789 | 0 | `if(at == null) return;`
790 | 0 | `Shape arrow = edgeArrowFunction.getArrow(e);`
791 | 0 | `arrow = at.createTransformedShape(arrow);`
792 | 0 | `g.fill(arrow);`
793 |  | `}`
794 |  | `}`
795 |  | `}`
796 |  | `// use existing paint for text if no draw paint specified`
797 | 0 | `if (draw_paint == null)`
798 | 0 | `g.setPaint(oldPaint);`
799 | 0 | `String label = edgeStringer.getLabel(e);`
800 | 0 | `if (label != null) {`
801 | 0 | `labelEdge(g, e, label, x1, x2, y1, y2);`
802 |  | `}`
803 |  | ``
804 |  | ``
805 |  | `// restore old paint`
806 | 0 | `g.setPaint(oldPaint);`
807 |  | `}`
808 | 0 | `}`
809 |  | ``
810 |  | `/**`
811 |  | `* Returns a transform to position the arrowhead on this edge shape at the`
812 |  | `* point where it intersects the passed vertex shape.`
813 |  | `*/`
814 |  | `public AffineTransform getArrowTransform(GeneralPath edgeShape, Shape vertexShape) {`
815 | 0 | `float[] seg = new float[6];`
816 | 0 | `Point2D p1=null;`
817 | 0 | `Point2D p2=null;`
818 | 0 | `AffineTransform at = new AffineTransform();`
819 |  | `// when the PathIterator is done, switch to the line-subdivide`
820 |  | `// method to get the arrowhead closer.`
821 | 0 | `for(PathIterator i=edgeShape.getPathIterator(null,1); !i.isDone(); i.next()) {`
822 | 0 | `int ret = i.currentSegment(seg);`
823 | 0 | `if(ret == PathIterator.SEG_MOVETO) {`
824 | 0 | `p2 = new Point2D.Float(seg[0],seg[1]);`
825 | 0 | `} else if(ret == PathIterator.SEG_LINETO) {`
826 | 0 | `p1 = p2;`
827 | 0 | `p2 = new Point2D.Float(seg[0],seg[1]);`
828 | 0 | `if(vertexShape.contains(p2)) {`
829 | 0 | `at = getArrowTransform(new Line2D.Float(p1,p2),vertexShape);`
830 | 0 | `break;`
831 |  | `}`
832 |  | `}`
833 |  | `}`
834 | 0 | `return at;`
835 |  | `}`
836 |  | ``
837 |  | `/**`
838 |  | `* Returns a transform to position the arrowhead on this edge shape at the`
839 |  | `* point where it intersects the passed vertex shape.`
840 |  | `*/`
841 |  | `public AffineTransform getReverseArrowTransform(GeneralPath edgeShape, Shape vertexShape) {`
842 | 0 | `return getReverseArrowTransform(edgeShape, vertexShape, true);`
843 |  | `}`
844 |  | ``
845 |  | `/**`
846 |  | `* <p>Returns a transform to position the arrowhead on this edge shape at the`
847 |  | `* point where it intersects the passed vertex shape.</p>`
848 |  | `*`
849 |  | `* <p>The Loop edge is a special case because its staring point is not inside`
850 |  | `* the vertex. The passedGo flag handles this case.</p>`
851 |  | `*`
852 |  | `* @param edgeShape`
853 |  | `* @param vertexShape`
854 |  | `* @param passedGo - used only for Loop edges`
855 |  | `*/`
856 |  | `public AffineTransform getReverseArrowTransform(GeneralPath edgeShape, Shape vertexShape,`
857 |  | `boolean passedGo) {`
858 | 0 | `float[] seg = new float[6];`
859 | 0 | `Point2D p1=null;`
860 | 0 | `Point2D p2=null;`
861 |  | ``
862 | 0 | `AffineTransform at = new AffineTransform();`
863 | 0 | `for(PathIterator i=edgeShape.getPathIterator(null,1); !i.isDone(); i.next()) {`
864 | 0 | `int ret = i.currentSegment(seg);`
865 | 0 | `if(ret == PathIterator.SEG_MOVETO) {`
866 | 0 | `p2 = new Point2D.Float(seg[0],seg[1]);`
867 | 0 | `} else if(ret == PathIterator.SEG_LINETO) {`
868 | 0 | `p1 = p2;`
869 | 0 | `p2 = new Point2D.Float(seg[0],seg[1]);`
870 | 0 | `if(passedGo == false && vertexShape.contains(p2)) {`
871 | 0 | `passedGo = true;`
872 | 0 | `} else if(passedGo==true &&`
873 |  | `vertexShape.contains(p2)==false) {`
874 | 0 | `at = getReverseArrowTransform(new Line2D.Float(p1,p2),vertexShape);`
875 | 0 | `break;`
876 |  | `}`
877 |  | `}`
878 |  | `}`
879 | 0 | `return at;`
880 |  | `}`
881 |  | ``
882 |  | `/**`
883 |  | `* This is used for the arrow of a directed and for one of the`
884 |  | `* arrows for non-directed edges`
885 |  | `* Get a transform to place the arrow shape on the passed edge at the`
886 |  | `* point where it intersects the passed shape`
887 |  | `* @param edgeShape`
888 |  | `* @param vertexShape`
889 |  | `* @return`
890 |  | `*/`
891 |  | `public AffineTransform getArrowTransform(Line2D edgeShape, Shape vertexShape) {`
892 | 0 | `float dx = (float) (edgeShape.getX1()-edgeShape.getX2());`
893 | 0 | `float dy = (float) (edgeShape.getY1()-edgeShape.getY2());`
894 |  | `// iterate over the line until the edge shape will place the`
895 |  | `// arrowhead closer than 'arrowGap' to the vertex shape boundary`
896 | 0 | `while((dx*dx+dy*dy) > arrow_placement_tolerance) {`
897 |  | `try {`
898 | 0 | `edgeShape = getLastOutsideSegment(edgeShape, vertexShape);`
899 | 0 | `} catch(IllegalArgumentException e) {`
900 | 0 | `System.err.println(e.toString());`
901 | 0 | `return null;`
902 | 0 | `}`
903 | 0 | `dx = (float) (edgeShape.getX1()-edgeShape.getX2());`
904 | 0 | `dy = (float) (edgeShape.getY1()-edgeShape.getY2());`
905 |  | `}`
906 | 0 | `double atheta = Math.atan2(dx,dy)+Math.PI/2;`
907 | 0 | `AffineTransform at =`
908 |  | `AffineTransform.getTranslateInstance(edgeShape.getX1(), edgeShape.getY1());`
909 | 0 | `at.rotate(-atheta);`
910 | 0 | `return at;`
911 |  | `}`
912 |  | ``
913 |  | `/**`
914 |  | `* This is used for the reverse-arrow of a non-directed edge`
915 |  | `* get a transform to place the arrow shape on the passed edge at the`
916 |  | `* point where it intersects the passed shape`
917 |  | `* @param edgeShape`
918 |  | `* @param vertexShape`
919 |  | `* @return`
920 |  | `*/`
921 |  | `protected AffineTransform getReverseArrowTransform(Line2D edgeShape, Shape vertexShape) {`
922 | 0 | `float dx = (float) (edgeShape.getX1()-edgeShape.getX2());`
923 | 0 | `float dy = (float) (edgeShape.getY1()-edgeShape.getY2());`
924 |  | `// iterate over the line until the edge shape will place the`
925 |  | `// arrowhead closer than 'arrowGap' to the vertex shape boundary`
926 | 0 | `while((dx*dx+dy*dy) > arrow_placement_tolerance) {`
927 |  | `try {`
928 | 0 | `edgeShape = getFirstOutsideSegment(edgeShape, vertexShape);`
929 | 0 | `} catch(IllegalArgumentException e) {`
930 | 0 | `System.err.println(e.toString());`
931 | 0 | `return null;`
932 | 0 | `}`
933 | 0 | `dx = (float) (edgeShape.getX1()-edgeShape.getX2());`
934 | 0 | `dy = (float) (edgeShape.getY1()-edgeShape.getY2());`
935 |  | `}`
936 |  | `// calculate the angle for the arrowhead`
937 | 0 | `double atheta = Math.atan2(dx,dy)-Math.PI/2;`
938 | 0 | `AffineTransform at = AffineTransform.getTranslateInstance(edgeShape.getX1(),edgeShape.getY1());`
939 | 0 | `at.rotate(-atheta);`
940 | 0 | `return at;`
941 |  | `}`
942 |  | ``
943 |  | `/**`
944 |  | `* Passed Line's point2 must be inside the passed shape or`
945 |  | `* an IllegalArgumentException is thrown`
946 |  | `* @param line line to subdivide`
947 |  | `* @param shape shape to compare with line`
948 |  | `* @return a line that intersects the shape boundary`
949 |  | `* @throws IllegalArgumentException if the passed line's point1 is not inside the shape`
950 |  | `*/`
951 |  | `protected Line2D getLastOutsideSegment(Line2D line, Shape shape) {`
952 | 0 | `if(shape.contains(line.getP2())==false) {`
953 | 0 | `String errorString =`
954 |  | `"line end point: "+line.getP2()+" is not contained in shape: "+shape.getBounds2D();`
955 | 0 | `throw new IllegalArgumentException(errorString);`
956 |  | `//return null;`
957 |  | `}`
958 | 0 | `Line2D left = new Line2D.Double();`
959 | 0 | `Line2D right = new Line2D.Double();`
960 |  | `// subdivide the line until its left segment intersects`
961 |  | `// the shape boundary`
962 | 0 | `int iterations = 0;`
963 |  | `do {`
964 | 0 | `subdivide(line, left, right);`
965 | 0 | `line = right;`
966 | 0 | `} while(shape.contains(line.getP1())==false && iterations++ < MAX_ITERATIONS);`
967 |  | `// now that right is completely inside shape,`
968 |  | `// return left, which must be partially outside`
969 | 0 | `return left;`
970 |  | `}`
971 |  | ``
972 |  | `/**`
973 |  | `* Passed Line's point1 must be inside the passed shape or`
974 |  | `* an IllegalArgumentException is thrown`
975 |  | `* @param line line to subdivide`
976 |  | `* @param shape shape to compare with line`
977 |  | `* @return a line that intersects the shape boundary`
978 |  | `* @throws IllegalArgumentException if the passed line's point1 is not inside the shape`
979 |  | `*/`
980 |  | `protected Line2D getFirstOutsideSegment(Line2D line, Shape shape) {`
981 |  | ``
982 | 0 | `if(shape.contains(line.getP1())==false) {`
983 | 0 | `String errorString =`
984 |  | `"line start point: "+line.getP1()+" is not contained in shape: "+shape.getBounds2D();`
985 | 0 | `throw new IllegalArgumentException(errorString);`
986 |  | `}`
987 | 0 | `Line2D left = new Line2D.Float();`
988 | 0 | `Line2D right = new Line2D.Float();`
989 |  | `// subdivide the line until its right side intersects the`
990 |  | `// shape boundary`
991 |  | `do {`
992 | 0 | `subdivide(line, left, right);`
993 | 0 | `line = left;`
994 | 0 | `} while(shape.contains(line.getP2())==false);`
995 |  | `// now that left is completely inside shape,`
996 |  | `// return right, which must be partially outside`
997 | 0 | `return right;`
998 |  | `}`
999 |  | ``
1000 |  | `/**`
1001 |  | `* divide a Line2D into 2 new Line2Ds that are returned`
1002 |  | `* in the passed left and right instances, if non-null`
1003 |  | `* @param src the line to divide`
1004 |  | `* @param left the left side, or null`
1005 |  | `* @param right the right side, or null`
1006 |  | `*/`
1007 |  | `protected void subdivide(Line2D src,`
1008 |  | `Line2D left,`
1009 |  | `Line2D right) {`
1010 | 0 | `double x1 = src.getX1();`
1011 | 0 | `double y1 = src.getY1();`
1012 | 0 | `double x2 = src.getX2();`
1013 | 0 | `double y2 = src.getY2();`
1014 |  | ``
1015 | 0 | `double mx = x1 + (x2-x1)/2.0;`
1016 | 0 | `double my = y1 + (y2-y1)/2.0;`
1017 | 0 | `if (left != null) {`
1018 | 0 | `left.setLine(x1, y1, mx, my);`
1019 |  | `}`
1020 | 0 | `if (right != null) {`
1021 | 0 | `right.setLine(mx, my, x2, y2);`
1022 |  | `}`
1023 | 0 | `}`
1024 |  | ``
1025 |  | `public Component prepareRenderer(GraphLabelRenderer graphLabelRenderer, Object value,`
1026 |  | `boolean isSelected, Vertex vertex) {`
1027 | 0 | `return graphLabelRenderer.getGraphLabelRendererComponent(screenDevice, value,`
1028 |  | `vertexFontFunction.getFont(vertex), isSelected, vertex);`
1029 |  | `}`
1030 |  | ``
1031 |  | `public Component prepareRenderer(GraphLabelRenderer renderer, Object value,`
1032 |  | `boolean isSelected, Edge edge) {`
1033 | 0 | `return graphLabelRenderer.getGraphLabelRendererComponent(screenDevice, value,`
1034 |  | `edgeFontFunction.getFont(edge), isSelected, edge);`
1035 |  | `}`
1036 |  | ``
1037 |  | `/**`
1038 |  | `* Labels the specified non-self-loop edge with the specified label.`
1039 |  | `* Uses the font specified by this instance's`
1040 |  | `* <code>EdgeFontFunction</code>. (If the font is unspecified, the existing`
1041 |  | `* font for the graphics context is used.) Positions the`
1042 |  | `* label between the endpoints according to the coefficient returned`
1043 |  | `* by this instance's edge label closeness function.`
1044 |  | `*/`
1045 |  | `protected void labelEdge(Graphics2D g2d, Edge e, String label, int x1, int x2, int y1, int y2)`
1046 |  | `{`
1047 | 0 | `int distX = x2 - x1;`
1048 | 0 | `int distY = y2 - y1;`
1049 | 0 | `double totalLength = Math.sqrt(distX * distX + distY * distY);`
1050 |  | ``
1051 | 0 | `double closeness = edgeLabelClosenessFunction.getNumber(e).doubleValue();`
1052 |  | ``
1053 | 0 | `int posX = (int) (x1 + (closeness) * distX);`
1054 | 0 | `int posY = (int) (y1 + (closeness) * distY);`
1055 |  | ``
1056 | 0 | `int xDisplacement = (int) (LABEL_OFFSET * (distY / totalLength));`
1057 | 0 | `int yDisplacement = (int) (LABEL_OFFSET * (-distX / totalLength));`
1058 |  | ``
1059 | 0 | `Component component = prepareRenderer(graphLabelRenderer, label, isPicked(e), e);`
1060 |  | ``
1061 | 0 | `Dimension d = component.getPreferredSize();`
1062 |  | ``
1063 | 0 | `Shape edgeShape = edgeShapeFunction.getShape(e);`
1064 |  | ``
1065 | 0 | `double parallelOffset = 1;`
1066 |  | ``
1067 | 0 | `parallelOffset += parallelEdgeIndexFunction.getIndex(e);`
1068 |  | ``
1069 | 0 | `if(edgeShape instanceof Ellipse2D) {`
1070 | 0 | `parallelOffset += edgeShape.getBounds().getHeight();`
1071 | 0 | `parallelOffset = -parallelOffset;`
1072 |  | `}`
1073 |  | ``
1074 | 0 | `parallelOffset *= d.height;`
1075 |  | ``
1076 | 0 | `AffineTransform old = g2d.getTransform();`
1077 | 0 | `AffineTransform xform = new AffineTransform(old);`
1078 | 0 | `xform.translate(posX+xDisplacement, posY+yDisplacement);`
1079 | 0 | `double dx = x2 - x1;`
1080 | 0 | `double dy = y2 - y1;`
1081 | 0 | `if(graphLabelRenderer.isRotateEdgeLabels()) {`
1082 | 0 | `double theta = Math.atan2(dy, dx);`
1083 | 0 | `if(dx < 0) {`
1084 | 0 | `theta += Math.PI;`
1085 |  | `}`
1086 | 0 | `xform.rotate(theta);`
1087 |  | `}`
1088 | 0 | `if(dx < 0) {`
1089 | 0 | `parallelOffset = -parallelOffset;`
1090 |  | `}`
1091 |  | ``
1092 | 0 | `xform.translate(-d.width/2, -(d.height/2-parallelOffset));`
1093 | 0 | `g2d.setTransform(xform);`
1094 | 0 | `rendererPane.paintComponent(g2d, component, screenDevice,`
1095 |  | `0, 0,`
1096 |  | `d.width, d.height, true);`
1097 | 0 | `g2d.setTransform(old);`
1098 | 0 | `}`
1099 |  | ``
1100 |  | `/**`
1101 |  | `* Paints the vertex <code>v</code> at the location <code>(x,y)</code>`
1102 |  | `* on the graphics context <code>g_gen</code>. The vertex is painted`
1103 |  | `* using the shape returned by this instance's <code>VertexShapeFunction</code>,`
1104 |  | `* and the foreground and background (border) colors provided by this`
1105 |  | `* instance's <code>VertexColorFunction</code>. Delegates drawing the`
1106 |  | `* label (if any) for this vertex to <code>labelVertex</code>.`
1107 |  | `*/`
1108 |  | `public void paintVertex(Graphics g, Vertex v, int x, int y)`
1109 |  | `{`
1110 | 0 | `if (!vertexIncludePredicate.evaluate(v))`
1111 | 0 | `return;`
1112 |  | ``
1113 | 0 | `boolean vertexHit = true;`
1114 | 0 | `Rectangle deviceRectangle = null;`
1115 | 0 | `Graphics2D g2d = (Graphics2D)g;`
1116 | 0 | `if(screenDevice != null) {`
1117 | 0 | `Dimension d = screenDevice.getSize();`
1118 | 0 | `if(d.width <= 0 || d.height <= 0) {`
1119 | 0 | `d = screenDevice.getPreferredSize();`
1120 |  | `}`
1121 | 0 | `deviceRectangle = new Rectangle(`
1122 |  | `0,0,`
1123 |  | `d.width,d.height);`
1124 |  | `}`
1125 |  | ``
1126 |  | ``
1127 | 0 | `Stroke old_stroke = g2d.getStroke();`
1128 | 0 | `Stroke new_stroke = vertexStrokeFunction.getStroke(v);`
1129 | 0 | `if (new_stroke != null) {`
1130 | 0 | `g2d.setStroke(new_stroke);`
1131 |  | `}`
1132 |  | `// get the shape to be rendered`
1133 | 0 | `Shape s = vertexShapeFunction.getShape(v);`
1134 |  | ``
1135 |  | `// create a transform that translates to the location of`
1136 |  | `// the vertex to be rendered`
1137 | 0 | `AffineTransform xform = AffineTransform.getTranslateInstance(x,y);`
1138 |  | `// transform the vertex shape with xtransform`
1139 | 0 | `s = xform.createTransformedShape(s);`
1140 |  | ``
1141 | 0 | `vertexHit = viewTransformer.transform(s).intersects(deviceRectangle);`
1142 |  | ``
1143 | 0 | `if (vertexHit) {`
1144 |  | ``
1145 | 0 | `if (vertexIconFunction != null) {`
1146 | 0 | `paintIconForVertex(g2d, v, x, y);`
1147 |  | `} else {`
1148 | 0 | `paintShapeForVertex(g2d, v, s);`
1149 |  | `}`
1150 |  | ``
1151 | 0 | `if (new_stroke != null) {`
1152 | 0 | `g2d.setStroke(old_stroke);`
1153 |  | `}`
1154 | 0 | `String label = vertexStringer.getLabel(v);`
1155 | 0 | `if (label != null) {`
1156 | 0 | `labelVertex(g, v, label, x, y);`
1157 |  | `}`
1158 |  | `}`
1159 | 0 | `}`
1160 |  | ``
1161 |  | `public void paintShapeForVertex(Graphics2D g2d, Vertex v, Shape shape) {`
1162 | 0 | `Paint oldPaint = g2d.getPaint();`
1163 | 0 | `Paint fillPaint = vertexPaintFunction.getFillPaint(v);`
1164 | 0 | `if(fillPaint != null) {`
1165 | 0 | `g2d.setPaint(fillPaint);`
1166 | 0 | `g2d.fill(shape);`
1167 | 0 | `g2d.setPaint(oldPaint);`
1168 |  | `}`
1169 | 0 | `Paint drawPaint = vertexPaintFunction.getDrawPaint(v);`
1170 | 0 | `if(drawPaint != null) {`
1171 | 0 | `g2d.setPaint(drawPaint);`
1172 | 0 | `g2d.draw(shape);`
1173 | 0 | `g2d.setPaint(oldPaint);`
1174 |  | `}`
1175 | 0 | `}`
1176 |  | ``
1177 |  | `/**`
1178 |  | `* Paint <code>v</code>'s icon on <code>g</code> at <code>(x,y)</code>.`
1179 |  | `*/`
1180 |  | `public void paintIconForVertex(Graphics g, Vertex v, int x, int y) {`
1181 | 0 | `Icon icon = vertexIconFunction.getIcon(v);`
1182 | 0 | `if(icon == null) {`
1183 | 0 | `Shape s = AffineTransform.getTranslateInstance(x,y).`
1184 |  | `createTransformedShape(getVertexShapeFunction().getShape(v));`
1185 | 0 | `paintShapeForVertex((Graphics2D)g, v, s);`
1186 |  | `} else {`
1187 | 0 | `int xLoc = x - icon.getIconWidth()/2;`
1188 | 0 | `int yLoc = y - icon.getIconHeight()/2;`
1189 | 0 | `icon.paintIcon(screenDevice, g, xLoc, yLoc);`
1190 |  | `}`
1191 | 0 | `}`
1192 |  | ``
1193 |  | `/**`
1194 |  | `* Labels the specified vertex with the specified label.`
1195 |  | `* Uses the font specified by this instance's`
1196 |  | `* <code>VertexFontFunction</code>. (If the font is unspecified, the existing`
1197 |  | `* font for the graphics context is used.) If vertex label centering`
1198 |  | `* is active, the label is centered on the position of the vertex; otherwise`
1199 |  | `* the label is offset slightly.`
1200 |  | `*/`
1201 |  | `protected void labelVertex(Graphics g, Vertex v, String label, int x, int y)`
1202 |  | `{`
1203 | 0 | `Component component = prepareRenderer(graphLabelRenderer, label, isPicked(v), v);`
1204 |  | ``
1205 | 0 | `Dimension d = component.getPreferredSize();`
1206 |  | ``
1207 |  | `int h_offset;`
1208 |  | `int v_offset;`
1209 | 0 | `if (centerVertexLabel)`
1210 |  | `{`
1211 | 0 | `h_offset = -d.width / 2;`
1212 | 0 | `v_offset = -d.height / 2;`
1213 |  | ``
1214 |  | `}`
1215 |  | `else`
1216 |  | `{`
1217 | 0 | `Rectangle2D bounds = vertexShapeFunction.getShape(v).getBounds2D();`
1218 | 0 | `h_offset = (int)(bounds.getWidth() / 2) + 5;`
1219 | 0 | `v_offset = (int)(bounds.getHeight() / 2) + 5 -d.height;`
1220 |  | `}`
1221 |  | ``
1222 | 0 | `rendererPane.paintComponent(g, component, screenDevice, x+h_offset, y+v_offset,`
1223 |  | `d.width, d.height, true);`
1224 |  | ``
1225 | 0 | `}`
1226 |  | ``
1227 |  | `/**`
1228 |  | `* @see AbstractRenderer#isPicked(Vertex)`
1229 |  | `* @deprecated Use an independent PickedInfo instead of this version,`
1230 |  | `* which relies on the Renderer to supply an instance.`
1231 |  | `*/`
1232 |  | `public boolean isPicked(ArchetypeVertex v)`
1233 |  | `{`
1234 | 0 | `return super.isPicked(v);`
1235 |  | `}`
1236 |  | ``
1237 |  | `/**`
1238 |  | `* @see AbstractRenderer#isPicked(Edge)`
1239 |  | `* @deprecated Use an independent PickedInfo instead of this version,`
1240 |  | `* which relies on the Renderer to supply an instance.`
1241 |  | `*/`
1242 |  | `public boolean isPicked(ArchetypeEdge e) {`
1243 | 0 | `return super.isPicked(e);`
1244 |  | `}`
1245 |  | ``
1246 |  | `/**`
1247 |  | `* @return Returns the rendererPane.`
1248 |  | `*/`
1249 |  | `public CellRendererPane getRendererPane() {`
1250 | 0 | `return rendererPane;`
1251 |  | `}`
1252 |  | ``
1253 |  | `/**`
1254 |  | `* @param rendererPane The rendererPane to set.`
1255 |  | `*/`
1256 |  | `public void setRendererPane(CellRendererPane rendererPane) {`
1257 | 0 | `this.rendererPane = rendererPane;`
1258 | 0 | `}`
1259 |  | ``
1260 |  | `public ParallelEdgeIndexFunction getParallelEdgeIndexFunction() {`
1261 | 0 | `return parallelEdgeIndexFunction;`
1262 |  | `}`
1263 |  | ``
1264 |  | `public void setParallelEdgeIndexFunction(`
1265 |  | `ParallelEdgeIndexFunction parallelEdgeIndexFunction) {`
1266 | 0 | `this.parallelEdgeIndexFunction = parallelEdgeIndexFunction;`
1267 | 0 | `}`
1268 |  | ``
1269 |  | `public void setViewTransformer(MutableTransformer viewTransformer) {`
1270 | 0 | `this.viewTransformer = viewTransformer;`
1271 | 0 | `}`
1272 |  | `}`

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.