| 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. |