1 47 48 package org.jfree.chart.annotations; 49 50 import java.awt.BasicStroke ; 51 import java.awt.Color ; 52 import java.awt.Graphics2D ; 53 import java.awt.Paint ; 54 import java.awt.Stroke ; 55 import java.awt.geom.GeneralPath ; 56 import java.awt.geom.Line2D ; 57 import java.awt.geom.Rectangle2D ; 58 import java.io.IOException ; 59 import java.io.ObjectInputStream ; 60 import java.io.ObjectOutputStream ; 61 import java.io.Serializable ; 62 63 import org.jfree.chart.axis.ValueAxis; 64 import org.jfree.chart.plot.Plot; 65 import org.jfree.chart.plot.PlotOrientation; 66 import org.jfree.chart.plot.PlotRenderingInfo; 67 import org.jfree.chart.plot.XYPlot; 68 import org.jfree.io.SerialUtilities; 69 import org.jfree.text.TextUtilities; 70 import org.jfree.ui.RectangleEdge; 71 import org.jfree.util.PublicCloneable; 72 73 89 90 public class XYPointerAnnotation extends XYTextAnnotation 91 implements Cloneable , PublicCloneable, 92 Serializable { 93 94 95 private static final long serialVersionUID = -4031161445009858551L; 96 97 98 public static final double DEFAULT_TIP_RADIUS = 10.0; 99 100 101 public static final double DEFAULT_BASE_RADIUS = 30.0; 102 103 104 public static final double DEFAULT_LABEL_OFFSET = 3.0; 105 106 107 public static final double DEFAULT_ARROW_LENGTH = 5.0; 108 109 110 public static final double DEFAULT_ARROW_WIDTH = 3.0; 111 112 113 private double angle; 114 115 119 private double tipRadius; 120 121 125 private double baseRadius; 126 127 128 private double arrowLength; 129 130 131 private double arrowWidth; 132 133 134 private transient Stroke arrowStroke; 135 136 137 private transient Paint arrowPaint; 138 139 140 private double labelOffset; 141 142 150 public XYPointerAnnotation(String label, double x, double y, double angle) { 151 152 super(label, x, y); 153 this.angle = angle; 154 this.tipRadius = DEFAULT_TIP_RADIUS; 155 this.baseRadius = DEFAULT_BASE_RADIUS; 156 this.arrowLength = DEFAULT_ARROW_LENGTH; 157 this.arrowWidth = DEFAULT_ARROW_WIDTH; 158 this.labelOffset = DEFAULT_LABEL_OFFSET; 159 this.arrowStroke = new BasicStroke (1.0f); 160 this.arrowPaint = Color.black; 161 162 } 163 164 169 public double getAngle() { 170 return this.angle; 171 } 172 173 178 public void setAngle(double angle) { 179 this.angle = angle; 180 } 181 182 187 public double getTipRadius() { 188 return this.tipRadius; 189 } 190 191 196 public void setTipRadius(double radius) { 197 this.tipRadius = radius; 198 } 199 200 205 public double getBaseRadius() { 206 return this.baseRadius; 207 } 208 209 214 public void setBaseRadius(double radius) { 215 this.baseRadius = radius; 216 } 217 218 223 public double getLabelOffset() { 224 return this.labelOffset; 225 } 226 227 233 public void setLabelOffset(double offset) { 234 this.labelOffset = offset; 235 } 236 237 242 public double getArrowLength() { 243 return this.arrowLength; 244 } 245 246 251 public void setArrowLength(double length) { 252 this.arrowLength = length; 253 } 254 255 260 public double getArrowWidth() { 261 return this.arrowWidth; 262 } 263 264 269 public void setArrowWidth(double width) { 270 this.arrowWidth = width; 271 } 272 273 278 public Stroke getArrowStroke() { 279 return this.arrowStroke; 280 } 281 282 287 public void setArrowStroke(Stroke stroke) { 288 if (stroke == null) { 289 throw new IllegalArgumentException ("Null 'stroke' not permitted."); 290 } 291 this.arrowStroke = stroke; 292 } 293 294 299 public Paint getArrowPaint() { 300 return this.arrowPaint; 301 } 302 303 308 public void setArrowPaint(Paint paint) { 309 this.arrowPaint = paint; 310 } 311 312 323 public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea, 324 ValueAxis domainAxis, ValueAxis rangeAxis, 325 int rendererIndex, 326 PlotRenderingInfo info) { 327 328 PlotOrientation orientation = plot.getOrientation(); 329 RectangleEdge domainEdge = Plot.resolveDomainAxisLocation( 330 plot.getDomainAxisLocation(), orientation 331 ); 332 RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation( 333 plot.getRangeAxisLocation(), orientation 334 ); 335 double j2DX = domainAxis.valueToJava2D(getX(), dataArea, domainEdge); 336 double j2DY = rangeAxis.valueToJava2D(getY(), dataArea, rangeEdge); 337 338 double startX = j2DX + Math.cos(this.angle) * this.baseRadius; 339 double startY = j2DY + Math.sin(this.angle) * this.baseRadius; 340 341 double endX = j2DX + Math.cos(this.angle) * this.tipRadius; 342 double endY = j2DY + Math.sin(this.angle) * this.tipRadius; 343 344 double arrowBaseX = endX + Math.cos(this.angle) * this.arrowLength; 345 double arrowBaseY = endY + Math.sin(this.angle) * this.arrowLength; 346 347 double arrowLeftX = arrowBaseX 348 + Math.cos(this.angle + Math.PI / 2.0) * this.arrowWidth; 349 double arrowLeftY = arrowBaseY 350 + Math.sin(this.angle + Math.PI / 2.0) * this.arrowWidth; 351 352 double arrowRightX = arrowBaseX 353 - Math.cos(this.angle + Math.PI / 2.0) * this.arrowWidth; 354 double arrowRightY = arrowBaseY 355 - Math.sin(this.angle + Math.PI / 2.0) * this.arrowWidth; 356 357 GeneralPath arrow = new GeneralPath (); 358 arrow.moveTo((float) endX, (float) endY); 359 arrow.lineTo((float) arrowLeftX, (float) arrowLeftY); 360 arrow.lineTo((float) arrowRightX, (float) arrowRightY); 361 arrow.closePath(); 362 363 g2.setStroke(this.arrowStroke); 364 g2.setPaint(this.arrowPaint); 365 Line2D line = new Line2D.Double (startX, startY, endX, endY); 366 g2.draw(line); 367 g2.fill(arrow); 368 369 g2.setFont(getFont()); 371 g2.setPaint(getPaint()); 372 double labelX = j2DX 373 + Math.cos(this.angle) * (this.baseRadius + this.labelOffset); 374 double labelY = j2DY 375 + Math.sin(this.angle) * (this.baseRadius + this.labelOffset); 376 Rectangle2D hotspot = TextUtilities.drawAlignedString( 377 getText(), 378 g2, 379 (float) labelX, 380 (float) labelY, 381 getTextAnchor() 382 ); 383 384 String toolTip = getToolTipText(); 385 String url = getURL(); 386 if (toolTip != null || url != null) { 387 addEntity(info, hotspot, rendererIndex, toolTip, url); 388 } 389 390 } 391 392 399 public boolean equals(Object object) { 400 401 if (object == null) { 402 return false; 403 } 404 405 if (object == this) { 406 return true; 407 } 408 409 if (object instanceof XYPointerAnnotation) { 410 411 XYPointerAnnotation a = (XYPointerAnnotation) object; 412 boolean b0 = (this.angle == a.angle); 413 boolean b1 = (this.tipRadius == a.tipRadius); 414 boolean b2 = (this.baseRadius == a.baseRadius); 415 boolean b3 = (this.arrowLength == a.arrowLength); 416 boolean b4 = (this.arrowWidth == a.arrowWidth); 417 boolean b5 = (this.arrowPaint.equals(a.arrowPaint)); 418 boolean b6 = (this.arrowStroke.equals(a.arrowStroke)); 419 boolean b7 = (this.labelOffset == a.labelOffset); 420 return b0 && b1 && b2 && b3 && b4 && b5 && b6 && b7; 421 } 422 423 return false; 424 425 } 426 427 434 public Object clone() throws CloneNotSupportedException { 435 return super.clone(); 436 } 437 438 445 private void writeObject(ObjectOutputStream stream) throws IOException { 446 stream.defaultWriteObject(); 447 SerialUtilities.writePaint(this.arrowPaint, stream); 448 SerialUtilities.writeStroke(this.arrowStroke, stream); 449 } 450 451 459 private void readObject(ObjectInputStream stream) 460 throws IOException , ClassNotFoundException { 461 stream.defaultReadObject(); 462 this.arrowPaint = SerialUtilities.readPaint(stream); 463 this.arrowStroke = SerialUtilities.readStroke(stream); 464 } 465 466 } 467 | Popular Tags |