1 70 71 package org.jfree.chart.renderer; 72 73 import java.awt.Graphics2D ; 74 import java.awt.Image ; 75 import java.awt.Paint ; 76 import java.awt.Point ; 77 import java.awt.Shape ; 78 import java.awt.Stroke ; 79 import java.awt.geom.Line2D ; 80 import java.awt.geom.Rectangle2D ; 81 import java.io.IOException ; 82 import java.io.ObjectInputStream ; 83 import java.io.Serializable ; 84 85 import org.jfree.chart.CrosshairInfo; 86 import org.jfree.chart.axis.ValueAxis; 87 import org.jfree.chart.entity.EntityCollection; 88 import org.jfree.chart.entity.XYItemEntity; 89 import org.jfree.chart.labels.StandardXYToolTipGenerator; 90 import org.jfree.chart.labels.XYToolTipGenerator; 91 import org.jfree.chart.plot.Plot; 92 import org.jfree.chart.plot.PlotOrientation; 93 import org.jfree.chart.plot.PlotRenderingInfo; 94 import org.jfree.chart.plot.XYPlot; 95 import org.jfree.chart.urls.XYURLGenerator; 96 import org.jfree.data.XYDataset; 97 import org.jfree.ui.RectangleEdge; 98 import org.jfree.util.BooleanList; 99 import org.jfree.util.PublicCloneable; 100 101 107 public class StandardXYItemRenderer extends AbstractXYItemRenderer implements XYItemRenderer, 108 Cloneable , 109 PublicCloneable, 110 Serializable { 111 112 113 public static final int SHAPES = 1; 114 115 116 public static final int LINES = 2; 117 118 119 public static final int SHAPES_AND_LINES = SHAPES | LINES; 120 121 122 public static final int IMAGES = 4; 123 124 125 public static final int DISCONTINUOUS = 8; 126 127 128 public static final int DISCONTINUOUS_LINES = LINES | DISCONTINUOUS; 129 130 131 private boolean plotShapes; 132 133 134 private boolean plotLines; 135 136 137 private boolean plotImages; 138 139 140 private boolean plotDiscontinuous; 141 142 143 private double gapThreshold = 1.0; 144 145 146 private Boolean shapesFilled; 147 148 149 private BooleanList seriesShapesFilled; 150 151 152 private Boolean defaultShapesFilled; 153 154 155 private transient Line2D line; 156 157 160 public StandardXYItemRenderer() { 161 162 this(LINES, new StandardXYToolTipGenerator()); 163 164 } 165 166 174 public StandardXYItemRenderer(int type) { 175 this(type, new StandardXYToolTipGenerator()); 176 } 177 178 187 public StandardXYItemRenderer(int type, XYToolTipGenerator toolTipGenerator) { 188 189 this(type, toolTipGenerator, null); 190 191 } 192 193 202 public StandardXYItemRenderer(int type, 203 XYToolTipGenerator toolTipGenerator, 204 XYURLGenerator urlGenerator) { 205 206 super(); 207 setToolTipGenerator(toolTipGenerator); 208 setURLGenerator(urlGenerator); 209 if ((type & SHAPES) != 0) { 210 this.plotShapes = true; 211 } 212 if ((type & LINES) != 0) { 213 this.plotLines = true; 214 } 215 if ((type & IMAGES) != 0) { 216 this.plotImages = true; 217 } 218 if ((type & DISCONTINUOUS) != 0) { 219 this.plotDiscontinuous = true; 220 } 221 this.line = new Line2D.Double (0.0, 0.0, 0.0, 0.0); 222 223 this.shapesFilled = null; 224 this.seriesShapesFilled = new BooleanList(); 225 this.defaultShapesFilled = Boolean.TRUE; 226 227 } 228 229 234 public boolean getPlotShapes() { 235 return this.plotShapes; 236 } 237 238 243 public void setPlotShapes(boolean flag) { 244 if (this.plotShapes != flag) { 245 Object oldValue = new Boolean (this.plotShapes); 246 this.plotShapes = flag; 247 firePropertyChanged("renderer.PlotShapes", oldValue, new Boolean (flag)); 248 } 249 } 250 251 253 264 public boolean getItemShapeFilled(int series, int item) { 265 return getSeriesShapesFilled(series); 266 } 267 268 275 public boolean getSeriesShapesFilled(int series) { 276 277 if (this.shapesFilled != null) { 279 return this.shapesFilled.booleanValue(); 280 } 281 282 Boolean flag = this.seriesShapesFilled.getBoolean(series); 284 if (flag != null) { 285 return flag.booleanValue(); 286 } 287 else { 288 return this.defaultShapesFilled.booleanValue(); 289 } 290 291 } 292 293 298 public void setShapesFilled(boolean filled) { 299 if (filled) { 300 setShapesFilled(Boolean.TRUE); 301 } 302 else { 303 setShapesFilled(Boolean.FALSE); 304 } 305 } 307 308 313 public void setShapesFilled(Boolean filled) { 314 this.shapesFilled = filled; 315 } 316 317 323 public void setSeriesShapesFilled(int series, Boolean flag) { 324 this.seriesShapesFilled.setBoolean(series, flag); 325 } 326 327 332 public Boolean getDefaultShapesFilled() { 333 return this.defaultShapesFilled; 334 } 335 336 341 public void setDefaultShapesFilled(Boolean flag) { 342 this.defaultShapesFilled = flag; 343 } 344 345 350 public boolean getPlotLines() { 351 return this.plotLines; 352 } 353 354 359 public void setPlotLines(boolean flag) { 360 if (this.plotLines != flag) { 361 Object oldValue = new Boolean (this.plotLines); 362 this.plotLines = flag; 363 firePropertyChanged("renderer.PlotLines", oldValue, new Boolean (flag)); 364 } 365 } 366 367 372 public double getGapThreshold() { 373 return this.gapThreshold; 374 } 375 376 381 public void setGapThreshold(double t) { 382 Object oldValue = new Double (this.gapThreshold); 383 this.gapThreshold = t; 384 firePropertyChanged("renderer.GapThreshold", oldValue, new Double (t)); 385 } 386 387 392 public boolean getPlotImages() { 393 return this.plotImages; 394 } 395 396 401 public void setPlotImages(boolean flag) { 402 if (this.plotImages != flag) { 403 Object oldValue = new Boolean (this.plotImages); 404 this.plotImages = flag; 405 firePropertyChanged("renderer.PlotImages", oldValue, new Boolean (flag)); 406 } 407 } 408 409 414 public boolean getPlotDiscontinuous() { 415 return this.plotDiscontinuous; 416 } 417 418 434 public void drawItem(Graphics2D g2, 435 XYItemRendererState state, 436 Rectangle2D dataArea, 437 PlotRenderingInfo info, 438 XYPlot plot, 439 ValueAxis domainAxis, 440 ValueAxis rangeAxis, 441 XYDataset dataset, 442 int series, 443 int item, 444 CrosshairInfo crosshairInfo, 445 int pass) { 446 447 Shape entityArea = null; 449 EntityCollection entities = null; 450 if (info != null) { 451 entities = info.getOwner().getEntityCollection(); 452 } 453 454 Paint paint = getItemPaint(series, item); 455 Stroke seriesStroke = getItemStroke(series, item); 456 g2.setPaint(paint); 457 g2.setStroke(seriesStroke); 458 459 Number x1n = dataset.getXValue(series, item); 461 Number y1n = dataset.getYValue(series, item); 462 if (y1n == null || x1n == null) { 463 return; 464 } 465 466 double x1 = x1n.doubleValue(); 467 double y1 = y1n.doubleValue(); 468 final RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); 469 final RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); 470 double transX1 = domainAxis.translateValueToJava2D(x1, dataArea, xAxisLocation); 471 double transY1 = rangeAxis.translateValueToJava2D(y1, dataArea, yAxisLocation); 472 473 if (this.plotLines) { 474 475 if (item > 0) { 476 Number x0n = dataset.getXValue(series, item - 1); 478 Number y0n = dataset.getYValue(series, item - 1); 479 if (y0n != null && x0n != null) { 480 double x0 = x0n.doubleValue(); 481 double y0 = y0n.doubleValue(); 482 boolean drawLine = true; 483 if (this.plotDiscontinuous) { 484 int numX = dataset.getItemCount(series); 487 double minX = dataset.getXValue(series, 0).doubleValue(); 488 double maxX = dataset.getXValue(series, numX - 1).doubleValue(); 489 drawLine = (x1 - x0) <= ((maxX - minX) / numX * this.gapThreshold); 490 } 491 if (drawLine) { 492 double transX0 493 = domainAxis.translateValueToJava2D(x0, dataArea, xAxisLocation); 494 double transY0 495 = rangeAxis.translateValueToJava2D(y0, dataArea, yAxisLocation); 496 497 if (Double.isNaN(transX0) || Double.isNaN(transY0) 499 || Double.isNaN(transX1) || Double.isNaN(transY1)) { 500 return; 501 } 502 503 PlotOrientation orientation = plot.getOrientation(); 504 if (orientation == PlotOrientation.HORIZONTAL) { 505 line.setLine(transY0, transX0, transY1, transX1); 506 } 507 else if (orientation == PlotOrientation.VERTICAL) { 508 line.setLine(transX0, transY0, transX1, transY1); 509 } 510 511 if (line.intersects(dataArea)) { 512 g2.draw(line); 513 } 514 } 515 } 516 } 517 } 518 519 if (this.plotShapes) { 520 521 Shape shape = getItemShape(series, item); 522 PlotOrientation orientation = plot.getOrientation(); 523 if (orientation == PlotOrientation.HORIZONTAL) { 524 shape = createTransformedShape(shape, transY1, transX1); 525 } 526 else if (orientation == PlotOrientation.VERTICAL) { 527 shape = createTransformedShape(shape, transX1, transY1); 528 } 529 if (shape.intersects(dataArea)) { 530 if (getItemShapeFilled(series, item)) { 531 g2.fill(shape); 532 } 533 else { 534 g2.draw(shape); 535 } 536 } 537 entityArea = shape; 538 539 } 540 541 if (this.plotImages) { 542 Image image = getImage(plot, series, item, transX1, transY1); 545 if (image != null) { 546 Point hotspot = getImageHotspot(plot, series, item, transX1, transY1, image); 547 g2.drawImage(image, 548 (int) (transX1 - hotspot.getX()), 549 (int) (transY1 - hotspot.getY()), null); 550 entityArea = new Rectangle2D.Double (transX1 - hotspot.getX(), 551 transY1 - hotspot.getY(), 552 image.getWidth(null), 553 image.getHeight(null)); 554 } 555 556 } 557 558 if (entities != null) { 560 if (entityArea == null) { 561 entityArea = new Rectangle2D.Double (transX1 - 2, transY1 - 2, 4, 4); 562 } 563 String tip = null; 564 if (getToolTipGenerator() != null) { 565 tip = getToolTipGenerator().generateToolTip(dataset, series, item); 566 } 567 String url = null; 568 if (getURLGenerator() != null) { 569 url = getURLGenerator().generateURL(dataset, series, item); 570 } 571 XYItemEntity entity = new XYItemEntity(entityArea, dataset, series, item, tip, url); 572 entities.addEntity(entity); 573 } 574 575 if (plot.isDomainCrosshairLockedOnData()) { 577 if (plot.isRangeCrosshairLockedOnData()) { 578 crosshairInfo.updateCrosshairPoint(x1, y1, transX1, transY1); 580 } 581 else { 582 crosshairInfo.updateCrosshairX(x1); 584 } 585 } 586 else { 587 if (plot.isRangeCrosshairLockedOnData()) { 588 crosshairInfo.updateCrosshairY(y1); 590 } 591 } 592 593 } 594 595 602 public boolean equals(Object obj) { 603 604 if (obj == null) { 605 return false; 606 } 607 608 if (obj == this) { 609 return true; 610 } 611 612 if (obj instanceof StandardXYItemRenderer) { 613 StandardXYItemRenderer r = (StandardXYItemRenderer) obj; 614 if (super.equals(obj)) { 615 boolean b0 = (this.plotShapes == r.plotShapes); 616 boolean b1 = (this.plotLines == r.plotLines); 617 boolean b2 = (this.plotImages == r.plotImages); 618 boolean b3 = (this.plotDiscontinuous == r.plotDiscontinuous); 619 boolean b4 = (this.gapThreshold == r.gapThreshold); 620 return b0 && b1 && b2 && b3 && b4; 622 } 623 } 624 625 return false; 626 627 } 628 629 634 645 protected Image getImage(Plot plot, int series, int item, double x, double y) { 646 return null; 650 } 651 652 667 protected Point getImageHotspot(Plot plot, int series, int item, 668 double x, double y, Image image) { 669 670 int height = image.getHeight(null); 671 int width = image.getWidth(null); 672 return new Point (width / 2, height / 2); 673 674 } 675 676 683 public Object clone() throws CloneNotSupportedException { 684 return super.clone(); 685 } 686 687 695 private void readObject(ObjectInputStream stream) throws IOException , ClassNotFoundException { 696 stream.defaultReadObject(); 697 this.line = new Line2D.Double (0.0, 0.0, 0.0, 0.0); 698 } 699 700 } 701 | Popular Tags |