1 65 66 package org.jfree.chart.renderer.xy; 67 68 import java.awt.Graphics2D ; 69 import java.awt.Paint ; 70 import java.awt.Point ; 71 import java.awt.Polygon ; 72 import java.awt.Shape ; 73 import java.awt.Stroke ; 74 import java.awt.geom.Line2D ; 75 import java.awt.geom.Rectangle2D ; 76 import java.io.IOException ; 77 import java.io.ObjectInputStream ; 78 import java.io.ObjectOutputStream ; 79 import java.io.Serializable ; 80 import java.util.Stack ; 81 82 import org.jfree.chart.axis.ValueAxis; 83 import org.jfree.chart.entity.EntityCollection; 84 import org.jfree.chart.entity.XYItemEntity; 85 import org.jfree.chart.labels.XYToolTipGenerator; 86 import org.jfree.chart.plot.CrosshairState; 87 import org.jfree.chart.plot.PlotOrientation; 88 import org.jfree.chart.plot.PlotRenderingInfo; 89 import org.jfree.chart.plot.XYPlot; 90 import org.jfree.chart.urls.XYURLGenerator; 91 import org.jfree.data.Range; 92 import org.jfree.data.general.DatasetUtilities; 93 import org.jfree.data.xy.TableXYDataset; 94 import org.jfree.data.xy.XYDataset; 95 import org.jfree.io.SerialUtilities; 96 import org.jfree.util.ObjectUtilities; 97 import org.jfree.util.PaintUtilities; 98 import org.jfree.util.PublicCloneable; 99 import org.jfree.util.ShapeUtilities; 100 101 108 public class StackedXYAreaRenderer extends XYAreaRenderer 109 implements Cloneable , 110 PublicCloneable, 111 Serializable { 112 113 114 private static final long serialVersionUID = 5217394318178570889L; 115 116 119 static class StackedXYAreaRendererState extends XYItemRendererState { 120 121 122 private Polygon seriesArea; 123 124 125 private Line2D line; 126 127 128 private Stack lastSeriesPoints; 129 130 131 private Stack currentSeriesPoints; 132 133 138 public StackedXYAreaRendererState(PlotRenderingInfo info) { 139 super(info); 140 this.seriesArea = null; 141 this.line = new Line2D.Double (); 142 this.lastSeriesPoints = new Stack (); 143 this.currentSeriesPoints = new Stack (); 144 } 145 146 151 public Polygon getSeriesArea() { 152 return this.seriesArea; 153 } 154 155 160 public void setSeriesArea(Polygon area) { 161 this.seriesArea = area; 162 } 163 164 169 public Line2D getLine() { 170 return this.line; 171 } 172 173 178 public Stack getCurrentSeriesPoints() { 179 return this.currentSeriesPoints; 180 } 181 182 187 public void setCurrentSeriesPoints(Stack points) { 188 this.currentSeriesPoints = points; 189 } 190 191 196 public Stack getLastSeriesPoints() { 197 return this.lastSeriesPoints; 198 } 199 200 205 public void setLastSeriesPoints(Stack points) { 206 this.lastSeriesPoints = points; 207 } 208 209 } 210 211 214 private transient Paint shapePaint = null; 215 216 220 private transient Stroke shapeStroke = null; 221 222 225 public StackedXYAreaRenderer() { 226 this(AREA); 227 } 228 233 public StackedXYAreaRenderer(int type) { 234 this(type, null, null); 235 } 236 237 248 public StackedXYAreaRenderer(int type, 249 XYToolTipGenerator labelGenerator, 250 XYURLGenerator urlGenerator) { 251 252 super(type, labelGenerator, urlGenerator); 253 } 254 255 261 public Paint getShapePaint() { 262 return this.shapePaint; 263 } 264 265 271 public Stroke getShapeStroke() { 272 return this.shapeStroke; 273 } 274 275 280 public void setShapePaint(Paint shapePaint) { 281 this.shapePaint = shapePaint; 282 } 283 284 289 public void setShapeStroke(Stroke shapeStroke) { 290 this.shapeStroke = shapeStroke; 291 } 292 293 308 public XYItemRendererState initialise(Graphics2D g2, 309 Rectangle2D dataArea, 310 XYPlot plot, 311 XYDataset data, 312 PlotRenderingInfo info) { 313 314 return new StackedXYAreaRendererState(info); 315 316 } 317 318 323 public int getPassCount() { 324 return 2; 325 } 326 327 339 public Range findRangeBounds(XYDataset dataset) { 340 if (dataset != null) { 341 return DatasetUtilities.findStackedRangeBounds( 342 (TableXYDataset) dataset); 343 } 344 else { 345 return null; 346 } 347 } 348 349 370 public void drawItem(Graphics2D g2, 371 XYItemRendererState state, 372 Rectangle2D dataArea, 373 PlotRenderingInfo info, 374 XYPlot plot, 375 ValueAxis domainAxis, 376 ValueAxis rangeAxis, 377 XYDataset dataset, 378 int series, 379 int item, 380 CrosshairState crosshairState, 381 int pass) { 382 383 PlotOrientation orientation = plot.getOrientation(); 384 StackedXYAreaRendererState areaState 385 = (StackedXYAreaRendererState) state; 386 TableXYDataset tdataset = (TableXYDataset) dataset; 389 int itemCount = tdataset.getItemCount(); 390 391 double x1 = dataset.getXValue(series, item); 393 double y1 = dataset.getYValue(series, item); 394 boolean nullPoint = false; 395 if (Double.isNaN(y1)) { 396 y1 = 0.0; 397 nullPoint = true; 398 } 399 400 double ph1 = getPreviousHeight(tdataset, series, item); 402 double transX1 = domainAxis.valueToJava2D(x1, dataArea, 403 plot.getDomainAxisEdge()); 404 double transY1 = rangeAxis.valueToJava2D(y1 + ph1, dataArea, 405 plot.getRangeAxisEdge()); 406 407 Paint seriesPaint = getItemPaint(series, item); 409 Stroke seriesStroke = getItemStroke(series, item); 410 411 if (pass == 0) { 412 414 if (item == 0) { 415 areaState.setSeriesArea(new Polygon ()); 417 areaState.setLastSeriesPoints( 418 areaState.getCurrentSeriesPoints()); 419 areaState.setCurrentSeriesPoints(new Stack ()); 420 421 double transY2 = rangeAxis.valueToJava2D(ph1, dataArea, 423 plot.getRangeAxisEdge()); 424 425 if (orientation == PlotOrientation.VERTICAL) { 427 areaState.getSeriesArea().addPoint((int) transX1, 428 (int) transY2); 429 } 430 else if (orientation == PlotOrientation.HORIZONTAL) { 431 areaState.getSeriesArea().addPoint((int) transY2, 432 (int) transX1); 433 } 434 } 435 436 if (orientation == PlotOrientation.VERTICAL) { 438 Point point = new Point ((int) transX1, (int) transY1); 439 areaState.getSeriesArea().addPoint((int) point.getX(), 440 (int) point.getY()); 441 areaState.getCurrentSeriesPoints().push(point); 442 } 443 else if (orientation == PlotOrientation.HORIZONTAL) { 444 areaState.getSeriesArea().addPoint((int) transY1, 445 (int) transX1); 446 } 447 448 if (getPlotLines()) { 449 if (item > 0) { 450 double x0 = dataset.getXValue(series, item - 1); 452 double y0 = dataset.getYValue(series, item - 1); 453 double ph0 = getPreviousHeight(tdataset, series, item - 1); 454 double transX0 = domainAxis.valueToJava2D(x0, dataArea, 455 plot.getDomainAxisEdge()); 456 double transY0 = rangeAxis.valueToJava2D(y0 + ph0, 457 dataArea, plot.getRangeAxisEdge()); 458 459 if (orientation == PlotOrientation.VERTICAL) { 460 areaState.getLine().setLine(transX0, transY0, transX1, 461 transY1); 462 } 463 else if (orientation == PlotOrientation.HORIZONTAL) { 464 areaState.getLine().setLine(transY0, transX0, transY1, 465 transX1); 466 } 467 g2.draw(areaState.getLine()); 468 } 469 } 470 471 if (getPlotArea() && item > 0 && item == (itemCount - 1)) { 474 475 double transY2 = rangeAxis.valueToJava2D(ph1, dataArea, 476 plot.getRangeAxisEdge()); 477 478 if (orientation == PlotOrientation.VERTICAL) { 479 areaState.getSeriesArea().addPoint((int) transX1, 481 (int) transY2); 482 } 483 else if (orientation == PlotOrientation.HORIZONTAL) { 484 areaState.getSeriesArea().addPoint((int) transY2, 486 (int) transX1); 487 } 488 489 if (series != 0) { 492 Stack points = areaState.getLastSeriesPoints(); 493 while (!points.empty()) { 494 Point point = (Point ) points.pop(); 495 areaState.getSeriesArea().addPoint((int) point.getX(), 496 (int) point.getY()); 497 } 498 } 499 500 g2.setPaint(seriesPaint); 502 g2.setStroke(seriesStroke); 503 g2.fill(areaState.getSeriesArea()); 504 505 if (isOutline()) { 507 g2.setStroke(getSeriesOutlineStroke(series)); 508 g2.setPaint(getSeriesOutlinePaint(series)); 509 g2.draw(areaState.getSeriesArea()); 510 } 511 } 512 513 updateCrosshairValues(crosshairState, x1, y1, transX1, transY1, 514 orientation); 515 516 } 517 else if (pass == 1) { 518 521 Shape shape = null; 522 if (getPlotShapes()) { 523 shape = getItemShape(series, item); 524 if (plot.getOrientation() == PlotOrientation.VERTICAL) { 525 shape = ShapeUtilities.createTranslatedShape(shape, 526 transX1, transY1); 527 } 528 else if (plot.getOrientation() == PlotOrientation.HORIZONTAL) { 529 shape = ShapeUtilities.createTranslatedShape(shape, 530 transY1, transX1); 531 } 532 if (!nullPoint) { 533 if (getShapePaint() != null) { 534 g2.setPaint(getShapePaint()); 535 } 536 else { 537 g2.setPaint(seriesPaint); 538 } 539 if (getShapeStroke() != null) { 540 g2.setStroke(getShapeStroke()); 541 } 542 else { 543 g2.setStroke(seriesStroke); 544 } 545 g2.draw(shape); 546 } 547 } 548 else { 549 if (plot.getOrientation() == PlotOrientation.VERTICAL) { 550 shape = new Rectangle2D.Double (transX1 - 3, transY1 - 3, 551 6.0, 6.0); 552 } 553 else if (plot.getOrientation() == PlotOrientation.HORIZONTAL) { 554 shape = new Rectangle2D.Double (transY1 - 3, transX1 - 3, 555 6.0, 6.0); 556 } 557 } 558 559 if (state.getInfo() != null) { 561 EntityCollection entities = state.getEntityCollection(); 562 if (entities != null && shape != null && !nullPoint) { 563 String tip = null; 564 XYToolTipGenerator generator 565 = getToolTipGenerator(series, item); 566 if (generator != null) { 567 tip = generator.generateToolTip(dataset, series, item); 568 } 569 String url = null; 570 if (getURLGenerator() != null) { 571 url = getURLGenerator().generateURL(dataset, series, 572 item); 573 } 574 XYItemEntity entity = new XYItemEntity(shape, dataset, 575 series, item, tip, url); 576 entities.add(entity); 577 } 578 } 579 580 } 581 } 582 583 595 protected double getPreviousHeight(TableXYDataset dataset, 596 int series, int index) { 597 double result = 0.0; 598 for (int i = 0; i < series; i++) { 599 double value = dataset.getYValue(i, index); 600 if (!Double.isNaN(value)) { 601 result += value; 602 } 603 } 604 return result; 605 } 606 607 614 public boolean equals(Object obj) { 615 if (obj == this) { 616 return true; 617 } 618 if (!(obj instanceof StackedXYAreaRenderer) || !super.equals(obj)) { 619 return false; 620 } 621 StackedXYAreaRenderer that = (StackedXYAreaRenderer) obj; 622 if (!PaintUtilities.equal(this.shapePaint, that.shapePaint)) { 623 return false; 624 } 625 if (!ObjectUtilities.equal(this.shapeStroke, that.shapeStroke)) { 626 return false; 627 } 628 return true; 629 } 630 631 638 public Object clone() throws CloneNotSupportedException { 639 return super.clone(); 640 } 641 642 650 private void readObject(ObjectInputStream stream) 651 throws IOException , ClassNotFoundException { 652 stream.defaultReadObject(); 653 this.shapePaint = SerialUtilities.readPaint(stream); 654 this.shapeStroke = SerialUtilities.readStroke(stream); 655 } 656 657 664 private void writeObject(ObjectOutputStream stream) throws IOException { 665 stream.defaultWriteObject(); 666 SerialUtilities.writePaint(this.shapePaint, stream); 667 SerialUtilities.writeStroke(this.shapeStroke, stream); 668 } 669 670 } 671 | Popular Tags |