1 42 43 package org.jfree.chart.annotations; 44 45 import java.awt.BasicStroke ; 46 import java.awt.Color ; 47 import java.awt.Graphics2D ; 48 import java.awt.Paint ; 49 import java.awt.Stroke ; 50 import java.awt.geom.GeneralPath ; 51 import java.awt.geom.Line2D ; 52 import java.awt.geom.Rectangle2D ; 53 import java.io.IOException ; 54 import java.io.ObjectInputStream ; 55 import java.io.ObjectOutputStream ; 56 import java.io.Serializable ; 57 58 import org.jfree.chart.axis.CategoryAxis; 59 import org.jfree.chart.axis.ValueAxis; 60 import org.jfree.chart.plot.CategoryPlot; 61 import org.jfree.chart.plot.Plot; 62 import org.jfree.chart.plot.PlotOrientation; 63 import org.jfree.data.category.CategoryDataset; 64 import org.jfree.io.SerialUtilities; 65 import org.jfree.text.TextUtilities; 66 import org.jfree.ui.RectangleEdge; 67 import org.jfree.util.ObjectUtilities; 68 import org.jfree.util.PublicCloneable; 69 70 85 public class CategoryPointerAnnotation extends CategoryTextAnnotation 86 implements Cloneable , PublicCloneable, 87 Serializable { 88 89 90 private static final long serialVersionUID = -4031161445009858551L; 91 92 93 public static final double DEFAULT_TIP_RADIUS = 10.0; 94 95 96 public static final double DEFAULT_BASE_RADIUS = 30.0; 97 98 99 public static final double DEFAULT_LABEL_OFFSET = 3.0; 100 101 102 public static final double DEFAULT_ARROW_LENGTH = 5.0; 103 104 105 public static final double DEFAULT_ARROW_WIDTH = 3.0; 106 107 108 private double angle; 109 110 114 private double tipRadius; 115 116 120 private double baseRadius; 121 122 123 private double arrowLength; 124 125 126 private double arrowWidth; 127 128 129 private transient Stroke arrowStroke; 130 131 132 private transient Paint arrowPaint; 133 134 135 private double labelOffset; 136 137 145 public CategoryPointerAnnotation(String label, Comparable key, double value, 146 double angle) { 147 148 super(label, key, value); 149 this.angle = angle; 150 this.tipRadius = DEFAULT_TIP_RADIUS; 151 this.baseRadius = DEFAULT_BASE_RADIUS; 152 this.arrowLength = DEFAULT_ARROW_LENGTH; 153 this.arrowWidth = DEFAULT_ARROW_WIDTH; 154 this.labelOffset = DEFAULT_LABEL_OFFSET; 155 this.arrowStroke = new BasicStroke (1.0f); 156 this.arrowPaint = Color.black; 157 158 } 159 160 165 public double getAngle() { 166 return this.angle; 167 } 168 169 174 public void setAngle(double angle) { 175 this.angle = angle; 176 } 177 178 183 public double getTipRadius() { 184 return this.tipRadius; 185 } 186 187 192 public void setTipRadius(double radius) { 193 this.tipRadius = radius; 194 } 195 196 201 public double getBaseRadius() { 202 return this.baseRadius; 203 } 204 205 210 public void setBaseRadius(double radius) { 211 this.baseRadius = radius; 212 } 213 214 219 public double getLabelOffset() { 220 return this.labelOffset; 221 } 222 223 229 public void setLabelOffset(double offset) { 230 this.labelOffset = offset; 231 } 232 233 238 public double getArrowLength() { 239 return this.arrowLength; 240 } 241 242 247 public void setArrowLength(double length) { 248 this.arrowLength = length; 249 } 250 251 256 public double getArrowWidth() { 257 return this.arrowWidth; 258 } 259 260 265 public void setArrowWidth(double width) { 266 this.arrowWidth = width; 267 } 268 269 274 public Stroke getArrowStroke() { 275 return this.arrowStroke; 276 } 277 278 283 public void setArrowStroke(Stroke stroke) { 284 if (stroke == null) { 285 throw new IllegalArgumentException ("Null 'stroke' not permitted."); 286 } 287 this.arrowStroke = stroke; 288 } 289 290 295 public Paint getArrowPaint() { 296 return this.arrowPaint; 297 } 298 299 304 public void setArrowPaint(Paint paint) { 305 if (paint == null) { 306 throw new IllegalArgumentException ("Null 'paint' argument."); 307 } 308 this.arrowPaint = paint; 309 } 310 311 320 public void draw(Graphics2D g2, CategoryPlot plot, Rectangle2D dataArea, 321 CategoryAxis domainAxis, ValueAxis rangeAxis) { 322 323 PlotOrientation orientation = plot.getOrientation(); 324 RectangleEdge domainEdge = Plot.resolveDomainAxisLocation( 325 plot.getDomainAxisLocation(), orientation); 326 RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation( 327 plot.getRangeAxisLocation(), orientation); 328 CategoryDataset dataset = plot.getDataset(); 329 int catIndex = dataset.getColumnIndex(getCategory()); 330 int catCount = dataset.getColumnCount(); 331 double j2DX = domainAxis.getCategoryMiddle(catIndex, catCount, 332 dataArea, domainEdge); 333 double j2DY = rangeAxis.valueToJava2D(getValue(), dataArea, rangeEdge); 334 if (orientation == PlotOrientation.HORIZONTAL) { 335 double temp = j2DX; 336 j2DX = j2DY; 337 j2DY = temp; 338 } 339 double startX = j2DX + Math.cos(this.angle) * this.baseRadius; 340 double startY = j2DY + Math.sin(this.angle) * this.baseRadius; 341 342 double endX = j2DX + Math.cos(this.angle) * this.tipRadius; 343 double endY = j2DY + Math.sin(this.angle) * this.tipRadius; 344 345 double arrowBaseX = endX + Math.cos(this.angle) * this.arrowLength; 346 double arrowBaseY = endY + Math.sin(this.angle) * this.arrowLength; 347 348 double arrowLeftX = arrowBaseX 349 + Math.cos(this.angle + Math.PI / 2.0) * this.arrowWidth; 350 double arrowLeftY = arrowBaseY 351 + Math.sin(this.angle + Math.PI / 2.0) * this.arrowWidth; 352 353 double arrowRightX = arrowBaseX 354 - Math.cos(this.angle + Math.PI / 2.0) * this.arrowWidth; 355 double arrowRightY = arrowBaseY 356 - Math.sin(this.angle + Math.PI / 2.0) * this.arrowWidth; 357 358 GeneralPath arrow = new GeneralPath (); 359 arrow.moveTo((float) endX, (float) endY); 360 arrow.lineTo((float) arrowLeftX, (float) arrowLeftY); 361 arrow.lineTo((float) arrowRightX, (float) arrowRightY); 362 arrow.closePath(); 363 364 g2.setStroke(this.arrowStroke); 365 g2.setPaint(this.arrowPaint); 366 Line2D line = new Line2D.Double (startX, startY, endX, endY); 367 g2.draw(line); 368 g2.fill(arrow); 369 370 g2.setFont(getFont()); 372 g2.setPaint(getPaint()); 373 double labelX = j2DX 374 + Math.cos(this.angle) * (this.baseRadius + this.labelOffset); 375 double labelY = j2DY 376 + Math.sin(this.angle) * (this.baseRadius + this.labelOffset); 377 TextUtilities.drawAlignedString(getText(), 378 g2, (float) labelX, (float) labelY, getTextAnchor()); 379 381 } 382 383 390 public boolean equals(Object obj) { 391 392 if (obj == null) { 393 return false; 394 } 395 if (obj == this) { 396 return true; 397 } 398 if (!(obj instanceof CategoryPointerAnnotation)) { 399 return false; 400 } 401 if (!super.equals(obj)) { 402 return false; 403 } 404 CategoryPointerAnnotation that = (CategoryPointerAnnotation) obj; 405 if (this.angle != that.angle) { 406 return false; 407 } 408 if (this.tipRadius != that.tipRadius) { 409 return false; 410 } 411 if (this.baseRadius != that.baseRadius) { 412 return false; 413 } 414 if (this.arrowLength != that.arrowLength) { 415 return false; 416 } 417 if (this.arrowWidth != that.arrowWidth) { 418 return false; 419 } 420 if (!this.arrowPaint.equals(that.arrowPaint)) { 421 return false; 422 } 423 if (!ObjectUtilities.equal(this.arrowStroke, that.arrowStroke)) { 424 return false; 425 } 426 if (this.labelOffset != that.labelOffset) { 427 return false; 428 } 429 return true; 430 } 431 432 439 public Object clone() throws CloneNotSupportedException { 440 return super.clone(); 441 } 442 443 450 private void writeObject(ObjectOutputStream stream) throws IOException { 451 stream.defaultWriteObject(); 452 SerialUtilities.writePaint(this.arrowPaint, stream); 453 SerialUtilities.writeStroke(this.arrowStroke, stream); 454 } 455 456 464 private void readObject(ObjectInputStream stream) 465 throws IOException , ClassNotFoundException { 466 stream.defaultReadObject(); 467 this.arrowPaint = SerialUtilities.readPaint(stream); 468 this.arrowStroke = SerialUtilities.readStroke(stream); 469 } 470 471 } 472 | Popular Tags |