# Coverage details for edu.uci.ics.jung.visualization.transform.shape.TransformingPluggableRenderer

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 Jul 11, 2005`
9 |  | `*/`
10 |  | ``
11 |  | `package edu.uci.ics.jung.visualization.transform.shape;`
12 |  | ``
13 |  | `import java.awt.Component;`
14 |  | `import java.awt.Dimension;`
15 |  | `import java.awt.Font;`
16 |  | `import java.awt.Graphics;`
17 |  | `import java.awt.Graphics2D;`
18 |  | `import java.awt.Paint;`
19 |  | `import java.awt.Rectangle;`
20 |  | `import java.awt.Shape;`
21 |  | `import java.awt.Stroke;`
22 |  | `import java.awt.geom.AffineTransform;`
23 |  | `import java.awt.geom.Ellipse2D;`
24 |  | `import java.awt.geom.GeneralPath;`
25 |  | `import java.awt.geom.Point2D;`
26 |  | `import java.awt.geom.Rectangle2D;`
27 |  | ``
28 |  | `import javax.swing.Icon;`
29 |  | ``
30 |  | `import edu.uci.ics.jung.graph.Edge;`
31 |  | `import edu.uci.ics.jung.graph.UndirectedEdge;`
32 |  | `import edu.uci.ics.jung.graph.Vertex;`
33 |  | `import edu.uci.ics.jung.graph.decorators.VertexIconFunction;`
34 |  | `import edu.uci.ics.jung.utils.Pair;`
35 |  | `import edu.uci.ics.jung.visualization.PluggableRenderer;`
36 |  | `import edu.uci.ics.jung.visualization.transform.HyperbolicTransformer;`
37 |  | `import edu.uci.ics.jung.visualization.transform.MutableAffineTransformer;`
38 |  | `import edu.uci.ics.jung.visualization.transform.Transformer;`
39 |  | ``
40 |  | `/**`
41 |  | `* a subclass to apply a TransformingGraphics to certain operations`
42 |  | `* @author Tom Nelson - RABA Technologies`
43 |  | `*`
44 |  | `*`
45 |  | `*/`
46 |  | `public class TransformingPluggableRenderer extends PluggableRendererDecorator {`
47 |  | ``
48 |  | `/**`
49 |  | `* the transformer`
50 |  | `*/`
51 |  | `Transformer transformer;`
52 |  | ``
53 |  | `/**`
54 |  | `* the Graphics wrapper that uses the transformer`
55 |  | `*/`
56 |  | `TransformingGraphics tg2d;`
57 |  | ``
58 |  | `/**`
59 |  | `* create an instance`
60 |  | `*`
61 |  | `*/`
62 |  | `public TransformingPluggableRenderer(PluggableRenderer delegate) {`
63 | 0 | `super(delegate);`
64 | 0 | `this.transformer = new MutableAffineTransformer();`
65 | 0 | `this.tg2d = new TransformingGraphics(transformer);`
66 | 0 | `}`
67 |  | ``
68 |  | `/**`
69 |  | `* @return Returns the transformer.`
70 |  | `*/`
71 |  | `public Transformer getTransformer() {`
72 | 0 | `return transformer;`
73 |  | `}`
74 |  | ``
75 |  | `/**`
76 |  | `* @param transformer The transformer to set.`
77 |  | `*/`
78 |  | `public void setTransformer(Transformer transformer) {`
79 | 0 | `this.transformer = transformer;`
80 | 0 | `this.tg2d.setTransformer(transformer);`
81 | 0 | `}`
82 |  | ``
83 |  | `/** (non-Javadoc)`
84 |  | `* override to wrap the passed Graphics2D in my TransformingGraphics,`
85 |  | `* then call overloaded drawSimpleEdge`
86 |  | `*/`
87 |  | `protected void drawSimpleEdge(Graphics2D g, Edge e, int x1, int y1, int x2, int y2) {`
88 | 0 | `this.tg2d.setDelegate(g);`
89 | 0 | `drawSimpleEdge(tg2d, e, x1, y1, x2, y2);`
90 | 0 | `}`
91 |  | `/**`
92 |  | `* overloaded to use TransformingGraphics`
93 |  | `* @param g`
94 |  | `* @param e`
95 |  | `* @param x1`
96 |  | `* @param y1`
97 |  | `* @param x2`
98 |  | `* @param y2`
99 |  | `*/`
100 |  | `protected void drawSimpleEdge(TransformingGraphics g, Edge e, int x1, int y1, int x2, int y2) {`
101 | 0 | `float flatness = 0;`
102 |  | ``
103 | 0 | `if(transformer instanceof HyperbolicTransformer) {`
104 | 0 | `HyperbolicTransformer ht = (HyperbolicTransformer)transformer;`
105 | 0 | `Ellipse2D hyperEllipse = ht.getEllipse();`
106 | 0 | `if(hyperEllipse.contains(x1,y1) || hyperEllipse.contains(x2,y2)) {`
107 | 0 | `flatness = .05f;`
108 |  | `}`
109 |  | `}`
110 | 0 | `Pair endpoints = e.getEndpoints();`
111 | 0 | `Vertex v1 = (Vertex)endpoints.getFirst();`
112 | 0 | `Vertex v2 = (Vertex)endpoints.getSecond();`
113 | 0 | `boolean isLoop = v1.equals(v2);`
114 | 0 | `Shape s2 = getVertexShapeFunction().getShape(v2);`
115 | 0 | `Shape edgeShape = getEdgeShapeFunction().getShape(e);`
116 |  | ``
117 | 0 | `boolean edgeHit = true;`
118 | 0 | `boolean arrowHit = true;`
119 | 0 | `Rectangle deviceRectangle = null;`
120 | 0 | `if(getScreenDevice() != null) {`
121 | 0 | `Dimension d = getScreenDevice().getSize();`
122 | 0 | `deviceRectangle = new Rectangle(0,0,d.width,d.height);`
123 |  | `}`
124 |  | ``
125 | 0 | `AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1);`
126 |  | ``
127 | 0 | `if(isLoop) {`
128 |  | `// this is a self-loop. scale it is larger than the vertex`
129 |  | `// it decorates and translate it so that its nadir is`
130 |  | `// at the center of the vertex.`
131 | 0 | `Rectangle2D s2Bounds = s2.getBounds2D();`
132 | 0 | `xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight());`
133 | 0 | `xform.translate(0, -edgeShape.getBounds2D().getWidth()/2);`
134 |  | `} else {`
135 |  | `// this is a normal edge. Rotate it to the angle between`
136 |  | `// vertex endpoints, then scale it to the distance between`
137 |  | `// the vertices`
138 | 0 | `float dx = x2-x1;`
139 | 0 | `float dy = y2-y1;`
140 | 0 | `float thetaRadians = (float) Math.atan2(dy, dx);`
141 | 0 | `xform.rotate(thetaRadians);`
142 | 0 | `float dist = (float) Math.sqrt(dx*dx + dy*dy);`
143 | 0 | `xform.scale(dist, 1.0);`
144 |  | `}`
145 |  | ``
146 | 0 | `edgeShape = xform.createTransformedShape(edgeShape);`
147 |  | ``
148 | 0 | `edgeHit = g.hit(deviceRectangle, edgeShape, true);`
149 |  | ``
150 | 0 | `if(edgeHit == true) {`
151 |  | ``
152 | 0 | `Paint oldPaint = g.getPaint();`
153 |  | ``
154 |  | `// get Paints for filling and drawing`
155 |  | `// (filling is done first so that drawing and label use same Paint)`
156 | 0 | `Paint fill_paint = getEdgePaintFunction().getFillPaint(e);`
157 | 0 | `if (fill_paint != null)`
158 |  | `{`
159 | 0 | `g.setPaint(fill_paint);`
160 | 0 | `g.fill(edgeShape, flatness);`
161 |  | `}`
162 | 0 | `Paint draw_paint = getEdgePaintFunction().getDrawPaint(e);`
163 | 0 | `if (draw_paint != null)`
164 |  | `{`
165 | 0 | `g.setPaint(draw_paint);`
166 | 0 | `g.draw(edgeShape, flatness);`
167 |  | `}`
168 |  | ``
169 | 0 | `float scalex = (float)g.getTransform().getScaleX();`
170 | 0 | `float scaley = (float)g.getTransform().getScaleY();`
171 |  | `// see if arrows are too small to bother drawing`
172 | 0 | `if(scalex < .3 || scaley < .3) return;`
173 |  | ``
174 | 0 | `if (getEdgeArrowPredicate().evaluate(e)) {`
175 |  | ``
176 | 0 | `Shape destVertexShape =`
177 |  | `getVertexShapeFunction().getShape((Vertex)e.getEndpoints().getSecond());`
178 | 0 | `AffineTransform xf = AffineTransform.getTranslateInstance(x2, y2);`
179 | 0 | `destVertexShape = xf.createTransformedShape(destVertexShape);`
180 |  | ``
181 | 0 | `arrowHit = g.hit(deviceRectangle, destVertexShape, true);`
182 |  | ``
183 | 0 | `if(arrowHit) {`
184 |  | ``
185 | 0 | `AffineTransform at =`
186 |  | `getArrowTransform((GeneralPath)edgeShape, destVertexShape);`
187 | 0 | `if(at == null) return;`
188 | 0 | `Shape arrow = getEdgeArrowFunction().getArrow(e);`
189 | 0 | `arrow = at.createTransformedShape(arrow);`
190 |  | `// note that arrows implicitly use the edge's draw paint`
191 | 0 | `g.fill(arrow);`
192 | 0 | `if (e instanceof UndirectedEdge) {`
193 | 0 | `Shape vertexShape =`
194 |  | `getVertexShapeFunction().getShape((Vertex)e.getEndpoints().getFirst());`
195 | 0 | `xf = AffineTransform.getTranslateInstance(x1, y1);`
196 | 0 | `vertexShape = xf.createTransformedShape(vertexShape);`
197 |  | ``
198 | 0 | `arrowHit = g.hit(deviceRectangle, vertexShape, true);`
199 | 0 | `if(arrowHit) {`
200 | 0 | `at = getReverseArrowTransform((GeneralPath)edgeShape, vertexShape, !isLoop);`
201 | 0 | `if(at == null) return;`
202 | 0 | `arrow = getEdgeArrowFunction().getArrow(e);`
203 | 0 | `arrow = at.createTransformedShape(arrow);`
204 | 0 | `g.fill(arrow);`
205 |  | `}`
206 |  | `}`
207 |  | `}`
208 |  | `}`
209 |  | `// use existing paint for text if no draw paint specified`
210 | 0 | `if (draw_paint == null)`
211 | 0 | `g.setPaint(oldPaint);`
212 | 0 | `String label = getEdgeStringer().getLabel(e);`
213 | 0 | `if (label != null) {`
214 | 0 | `labelEdge(g, e, label, x1, x2, y1, y2);`
215 |  | `}`
216 |  | ``
217 |  | ``
218 |  | `// restore old paint`
219 | 0 | `g.setPaint(oldPaint);`
220 |  | `}`
221 | 0 | `}`
222 |  | ``
223 |  | ``
224 |  | `/**`
225 |  | `* overridden to wrap passed Graphics2D in my TransformingGraphics, then call`
226 |  | `* overloaded labelEdge`
227 |  | `*/`
228 |  | `protected void labelEdge(Graphics2D g2d, Edge e, String label, int x1, int x2, int y1, int y2) {`
229 | 0 | `tg2d.setDelegate(g2d);`
230 | 0 | `labelEdge(tg2d, e, label, x1, x2, y1, y2);`
231 | 0 | `}`
232 |  | `/**`
233 |  | `* overloaded to use TransformingGraphics`
234 |  | `* @param g2d`
235 |  | `* @param e`
236 |  | `* @param label`
237 |  | `* @param x1`
238 |  | `* @param x2`
239 |  | `* @param y1`
240 |  | `* @param y2`
241 |  | `*/`
242 |  | `protected void labelEdge(TransformingGraphics g2d, Edge e, String label, int x1, int x2, int y1, int y2)`
243 |  | `{`
244 | 0 | `Point2D p = g2d.getTransformer().transform(new Point2D.Float(x1, y1));`
245 | 0 | `Point2D q = g2d.getTransformer().transform(new Point2D.Float(x2, y2));`
246 | 0 | `x1 = (int)p.getX();`
247 | 0 | `y1 = (int)p.getY();`
248 | 0 | `x2 = (int)q.getX();`
249 | 0 | `y2 = (int)q.getY();`
250 |  | ``
251 | 0 | `int distX = x2 - x1;`
252 | 0 | `int distY = y2 - y1;`
253 | 0 | `double totalLength = Math.sqrt(distX * distX + distY * distY);`
254 |  | ``
255 | 0 | `double closeness = getEdgeLabelClosenessFunction().getNumber(e).doubleValue();`
256 |  | ``
257 | 0 | `int posX = (int) (x1 + (closeness) * distX);`
258 | 0 | `int posY = (int) (y1 + (closeness) * distY);`
259 |  | ``
260 | 0 | `int xDisplacement = (int) (PluggableRenderer.LABEL_OFFSET * (distY / totalLength));`
261 | 0 | `int yDisplacement = (int) (PluggableRenderer.LABEL_OFFSET * (-distX / totalLength));`
262 |  | ``
263 | 0 | `Component component = prepareRenderer(getGraphLabelRenderer(), label, isPicked(e), e);`
264 | 0 | `Dimension d = component.getPreferredSize();`
265 |  | ``
266 | 0 | `Font font = getEdgeFontFunction().getFont(e);`
267 | 0 | `if(font != null)`
268 | 0 | `component.setFont(font);`
269 |  | ``
270 | 0 | `Shape edgeShape = getEdgeShapeFunction().getShape(e);`
271 |  | ``
272 | 0 | `double parallelOffset = 1;`
273 | 0 | `Integer parallelCount = (Integer)e.getUserDatum("parallelCount");`
274 | 0 | `if(parallelCount != null) {`
275 | 0 | `parallelOffset += parallelCount.intValue();`
276 |  | `}`
277 |  | ``
278 | 0 | `if(edgeShape instanceof Ellipse2D) {`
279 | 0 | `parallelOffset += edgeShape.getBounds().getHeight();`
280 | 0 | `parallelOffset = -parallelOffset;`
281 |  | `}`
282 |  | ``
283 | 0 | `parallelOffset *= d.height;`
284 |  | ``
285 | 0 | `AffineTransform old = g2d.getTransform();`
286 | 0 | `AffineTransform xform = new AffineTransform(old);`
287 | 0 | `xform.translate(posX+xDisplacement, posY+yDisplacement);`
288 | 0 | `if(getGraphLabelRenderer().isRotateEdgeLabels()) {`
289 |  | `// float thetaRadians = (float) Math.atan2(dy, dx);`
290 | 0 | `double dx = x2 - x1;`
291 | 0 | `double dy = y2 - y1;`
292 | 0 | `double theta = Math.atan2(dy, dx);`
293 | 0 | `if(dx < 0) {`
294 | 0 | `theta += Math.PI;`
295 | 0 | `parallelOffset = -parallelOffset;`
296 |  | `}`
297 | 0 | `xform.rotate(theta);`
298 |  | `}`
299 |  | ``
300 | 0 | `xform.translate(-d.width/2, -(d.height/2-parallelOffset));`
301 | 0 | `g2d.setTransform(xform);`
302 | 0 | `getRendererPane().paintComponent(g2d.getDelegate(), component, getScreenDevice(),`
303 |  | `0, 0,`
304 |  | `d.width, d.height, true);`
305 | 0 | `g2d.setTransform(old);`
306 | 0 | `}`
307 |  | ``
308 |  | `/**`
309 |  | `* overridden to wrap passed Graphics in my TransformingGraphics, then`
310 |  | `* call overloaded labelVertex`
311 |  | `*/`
312 |  | `protected void labelVertex(Graphics g, Vertex v, String label, int x, int y) {`
313 | 0 | `tg2d.setDelegate((Graphics2D)g);`
314 | 0 | `labelVertex(tg2d, v, label, x, y);`
315 | 0 | `}`
316 |  | `/**`
317 |  | `* overloaded to use TransformingGraphics`
318 |  | `* @param g`
319 |  | `* @param v`
320 |  | `* @param label`
321 |  | `* @param x`
322 |  | `* @param y`
323 |  | `*/`
324 |  | `protected void labelVertex(TransformingGraphics g, Vertex v, String label, int x, int y) {`
325 | 0 | `Component component = prepareRenderer(getGraphLabelRenderer(), label, isPicked(v), v);`
326 | 0 | `Font font = getVertexFontFunction().getFont(v);`
327 | 0 | `if (font != null)`
328 | 0 | `component.setFont(font);`
329 |  | ``
330 | 0 | `Dimension d = component.getPreferredSize();`
331 |  | ``
332 | 0 | `Point2D p = g.getTransformer().transform(new Point2D.Float(x, y));`
333 | 0 | `x = (int)p.getX();`
334 | 0 | `y = (int)p.getY();`
335 |  | ``
336 |  | `int h_offset;`
337 |  | `int v_offset;`
338 | 0 | `if (getVertexLabelCentering())`
339 |  | `{`
340 | 0 | `h_offset = -d.width / 2;`
341 | 0 | `v_offset = -d.height / 2;`
342 |  | ``
343 |  | `}`
344 |  | `else`
345 |  | `{`
346 | 0 | `Rectangle2D bounds = getVertexShapeFunction().getShape(v).getBounds2D();`
347 | 0 | `h_offset = (int)(bounds.getWidth() / 2) + 5;`
348 | 0 | `v_offset = (int)(bounds.getHeight() / 2) + 5 -d.height;`
349 |  | `}`
350 |  | ``
351 | 0 | `getRendererPane().paintComponent(g.getDelegate(), component, getScreenDevice(), x+h_offset, y+v_offset,`
352 |  | `d.width, d.height, true);`
353 |  | ``
354 | 0 | `}`
355 |  | ``
356 |  | `/**`
357 |  | `* overridded to wrap passed Graphics in TransformingGraphics then call`
358 |  | `* overloaded paintEdge`
359 |  | `*/`
360 |  | `public void paintEdge(Graphics g, Edge e, int x1, int y1, int x2, int y2) {`
361 | 0 | `this.tg2d.setDelegate((Graphics2D)g);`
362 | 0 | `paintEdge(tg2d, e, x1, y1, x2, y2);`
363 | 0 | `}`
364 |  | `/**`
365 |  | `* overloaded to use TransformingGraphics`
366 |  | `* @param g2d`
367 |  | `* @param e`
368 |  | `* @param x1`
369 |  | `* @param y1`
370 |  | `* @param x2`
371 |  | `* @param y2`
372 |  | `*/`
373 |  | `public void paintEdge(TransformingGraphics g2d, Edge e, int x1, int y1, int x2, int y2) {`
374 | 0 | `if (!getEdgeIncludePredicate().evaluate(e))`
375 | 0 | `return;`
376 |  | ``
377 |  | `// don't draw edge if either incident vertex is not drawn`
378 | 0 | `Pair endpoints = e.getEndpoints();`
379 | 0 | `Vertex v1 = (Vertex)endpoints.getFirst();`
380 | 0 | `Vertex v2 = (Vertex)endpoints.getSecond();`
381 | 0 | `if (!getVertexIncludePredicate().evaluate(v1) ||`
382 |  | `!getVertexIncludePredicate().evaluate(v2))`
383 | 0 | `return;`
384 |  | ``
385 | 0 | `Stroke new_stroke = getEdgeStrokeFunction().getStroke(e);`
386 | 0 | `Stroke old_stroke = g2d.getStroke();`
387 | 0 | `if (new_stroke != null)`
388 | 0 | `g2d.setStroke(new_stroke);`
389 |  | ``
390 | 0 | `drawSimpleEdge(g2d, e, x1, y1, x2, y2);`
391 |  | ``
392 |  | `// restore paint and stroke`
393 | 0 | `if (new_stroke != null)`
394 | 0 | `g2d.setStroke(old_stroke);`
395 |  | ``
396 | 0 | `}`
397 |  | ``
398 |  | `/**`
399 |  | `* overridden to wrap passed Graphics in TransformingGraphics then`
400 |  | `* call overloaded paintVertex`
401 |  | `*/`
402 |  | `public void paintVertex(Graphics g, Vertex v, int x, int y) {`
403 | 0 | `tg2d.setDelegate((Graphics2D)g);`
404 | 0 | `paintVertex(tg2d, v, x, y);`
405 | 0 | `}`
406 |  | `/**`
407 |  | `* overloaded to use TransformingGraphics`
408 |  | `* @param g2d`
409 |  | `* @param v`
410 |  | `* @param x`
411 |  | `* @param y`
412 |  | `*/`
413 |  | `public void paintVertex(TransformingGraphics g2d, Vertex v, int x, int y) {`
414 | 0 | `if (!getVertexIncludePredicate().evaluate(v))`
415 | 0 | `return;`
416 |  | ``
417 | 0 | `boolean vertexHit = true;`
418 | 0 | `Rectangle deviceRectangle = null;`
419 | 0 | `if(getScreenDevice() != null) {`
420 | 0 | `Dimension d = getScreenDevice().getSize();`
421 | 0 | `deviceRectangle = new Rectangle(0,0,d.width,d.height);`
422 |  | `}`
423 |  | ``
424 | 0 | `Stroke old_stroke = g2d.getStroke();`
425 | 0 | `Stroke new_stroke = getVertexStrokeFunction().getStroke(v);`
426 | 0 | `if (new_stroke != null) {`
427 | 0 | `g2d.setStroke(new_stroke);`
428 |  | `}`
429 |  | `// get the shape to be rendered`
430 | 0 | `Shape s = getVertexShapeFunction().getShape(v);`
431 |  | ``
432 |  | `// create a transform that translates to the location of`
433 |  | `// the vertex to be rendered`
434 | 0 | `AffineTransform xform = AffineTransform.getTranslateInstance(x,y);`
435 |  | `// transform the vertex shape with xtransform`
436 | 0 | `s = xform.createTransformedShape(s);`
437 |  | ``
438 |  | ``
439 | 0 | `vertexHit = g2d.hit(deviceRectangle, s, true);`
440 |  | ``
441 | 0 | `if (vertexHit) {`
442 | 0 | `VertexIconFunction imager = getVertexIconFunction();`
443 |  | ``
444 | 0 | `Icon icon = null;`
445 | 0 | `if (imager != null && (icon = imager.getIcon(v)) != null) {`
446 | 0 | `paintIconForVertex(g2d, icon, x, y);`
447 |  | `} else {`
448 | 0 | `paintShapeForVertex(g2d, v, s);`
449 |  | `}`
450 |  | ``
451 | 0 | `if (new_stroke != null) {`
452 | 0 | `g2d.setStroke(old_stroke);`
453 |  | `}`
454 | 0 | `String label = getVertexStringer().getLabel(v);`
455 | 0 | `if (label != null) {`
456 | 0 | `labelVertex(g2d, v, label, x, y);`
457 |  | `}`
458 |  | `}`
459 | 0 | `}`
460 |  | ``
461 |  | `protected void paintShapeForVertex(TransformingGraphics g2d, Vertex v, Shape shape) {`
462 | 0 | `Paint oldPaint = g2d.getPaint();`
463 | 0 | `Paint fillPaint = getVertexPaintFunction().getFillPaint(v);`
464 | 0 | `if(fillPaint != null) {`
465 | 0 | `g2d.setPaint(fillPaint);`
466 | 0 | `g2d.fill(shape);`
467 | 0 | `g2d.setPaint(oldPaint);`
468 |  | `}`
469 | 0 | `Paint drawPaint = getVertexPaintFunction().getDrawPaint(v);`
470 | 0 | `if(drawPaint != null) {`
471 | 0 | `g2d.setPaint(drawPaint);`
472 | 0 | `g2d.draw(shape);`
473 | 0 | `g2d.setPaint(oldPaint);`
474 |  | `}`
475 | 0 | `}`
476 |  | ``
477 |  | `public void paintIconForVertex(TransformingGraphics g, Icon icon, int x, int y) {`
478 | 0 | `if(icon != null) {`
479 | 0 | `int xLoc = x - icon.getIconWidth()/2;`
480 | 0 | `int yLoc = y - icon.getIconHeight()/2;`
481 | 0 | `icon.paintIcon(getScreenDevice(), g.getDelegate(), xLoc, yLoc);`
482 |  | `}`
483 | 0 | `}`
484 |  | `}`

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.