1 92 93 package org.jfree.chart.renderer.category; 94 95 import java.awt.AlphaComposite ; 96 import java.awt.Color ; 97 import java.awt.Composite ; 98 import java.awt.Font ; 99 import java.awt.Graphics2D ; 100 import java.awt.Image ; 101 import java.awt.Paint ; 102 import java.awt.Stroke ; 103 import java.awt.geom.GeneralPath ; 104 import java.awt.geom.Line2D ; 105 import java.awt.geom.Point2D ; 106 import java.awt.geom.Rectangle2D ; 107 import java.io.IOException ; 108 import java.io.ObjectInputStream ; 109 import java.io.ObjectOutputStream ; 110 import java.io.Serializable ; 111 112 import org.jfree.chart.Effect3D; 113 import org.jfree.chart.axis.CategoryAxis; 114 import org.jfree.chart.axis.ValueAxis; 115 import org.jfree.chart.entity.EntityCollection; 116 import org.jfree.chart.labels.CategoryItemLabelGenerator; 117 import org.jfree.chart.labels.ItemLabelAnchor; 118 import org.jfree.chart.labels.ItemLabelPosition; 119 import org.jfree.chart.plot.CategoryPlot; 120 import org.jfree.chart.plot.Marker; 121 import org.jfree.chart.plot.Plot; 122 import org.jfree.chart.plot.PlotOrientation; 123 import org.jfree.chart.plot.PlotRenderingInfo; 124 import org.jfree.chart.plot.ValueMarker; 125 import org.jfree.data.Range; 126 import org.jfree.data.category.CategoryDataset; 127 import org.jfree.io.SerialUtilities; 128 import org.jfree.text.TextUtilities; 129 import org.jfree.ui.LengthAdjustmentType; 130 import org.jfree.ui.RectangleAnchor; 131 import org.jfree.ui.RectangleEdge; 132 import org.jfree.ui.TextAnchor; 133 import org.jfree.util.PublicCloneable; 134 135 141 public class BarRenderer3D extends BarRenderer 142 implements Effect3D, Cloneable , PublicCloneable, 143 Serializable { 144 145 146 private static final long serialVersionUID = 7686976503536003636L; 147 148 149 public static final double DEFAULT_X_OFFSET = 12.0; 150 151 152 public static final double DEFAULT_Y_OFFSET = 8.0; 153 154 155 public static final Paint DEFAULT_WALL_PAINT = new Color (0xDD, 0xDD, 0xDD); 156 157 158 private double xOffset; 159 160 161 private double yOffset; 162 163 164 private transient Paint wallPaint; 165 166 169 public BarRenderer3D() { 170 this(DEFAULT_X_OFFSET, DEFAULT_Y_OFFSET); 171 } 172 173 179 public BarRenderer3D(double xOffset, double yOffset) { 180 181 super(); 182 this.xOffset = xOffset; 183 this.yOffset = yOffset; 184 this.wallPaint = DEFAULT_WALL_PAINT; 185 ItemLabelPosition p1 = new ItemLabelPosition(ItemLabelAnchor.INSIDE12, 187 TextAnchor.TOP_CENTER); 188 setPositiveItemLabelPosition(p1); 189 ItemLabelPosition p2 = new ItemLabelPosition(ItemLabelAnchor.INSIDE12, 190 TextAnchor.TOP_CENTER); 191 setNegativeItemLabelPosition(p2); 192 193 } 194 195 200 public double getXOffset() { 201 return this.xOffset; 202 } 203 204 209 public double getYOffset() { 210 return this.yOffset; 211 } 212 213 219 public Paint getWallPaint() { 220 return this.wallPaint; 221 } 222 223 229 public void setWallPaint(Paint paint) { 230 this.wallPaint = paint; 231 } 232 233 234 247 public CategoryItemRendererState initialise(Graphics2D g2, 248 Rectangle2D dataArea, 249 CategoryPlot plot, 250 int rendererIndex, 251 PlotRenderingInfo info) { 252 253 Rectangle2D adjusted = new Rectangle2D.Double (dataArea.getX(), 254 dataArea.getY() + getYOffset(), dataArea.getWidth() 255 - getXOffset(), dataArea.getHeight() - getYOffset()); 256 CategoryItemRendererState state = super.initialise(g2, adjusted, plot, 257 rendererIndex, info); 258 return state; 259 260 } 261 262 269 public void drawBackground(Graphics2D g2, CategoryPlot plot, 270 Rectangle2D dataArea) { 271 272 float x0 = (float) dataArea.getX(); 273 float x1 = x0 + (float) Math.abs(this.xOffset); 274 float x3 = (float) dataArea.getMaxX(); 275 float x2 = x3 - (float) Math.abs(this.xOffset); 276 277 float y0 = (float) dataArea.getMaxY(); 278 float y1 = y0 - (float) Math.abs(this.yOffset); 279 float y3 = (float) dataArea.getMinY(); 280 float y2 = y3 + (float) Math.abs(this.yOffset); 281 282 GeneralPath clip = new GeneralPath (); 283 clip.moveTo(x0, y0); 284 clip.lineTo(x0, y2); 285 clip.lineTo(x1, y3); 286 clip.lineTo(x3, y3); 287 clip.lineTo(x3, y1); 288 clip.lineTo(x2, y0); 289 clip.closePath(); 290 291 Paint backgroundPaint = plot.getBackgroundPaint(); 293 if (backgroundPaint != null) { 294 g2.setPaint(backgroundPaint); 295 g2.fill(clip); 296 } 297 298 GeneralPath leftWall = new GeneralPath (); 299 leftWall.moveTo(x0, y0); 300 leftWall.lineTo(x0, y2); 301 leftWall.lineTo(x1, y3); 302 leftWall.lineTo(x1, y1); 303 leftWall.closePath(); 304 g2.setPaint(getWallPaint()); 305 g2.fill(leftWall); 306 307 GeneralPath bottomWall = new GeneralPath (); 308 bottomWall.moveTo(x0, y0); 309 bottomWall.lineTo(x1, y1); 310 bottomWall.lineTo(x3, y1); 311 bottomWall.lineTo(x2, y0); 312 bottomWall.closePath(); 313 g2.setPaint(getWallPaint()); 314 g2.fill(bottomWall); 315 316 g2.setPaint(Color.lightGray); 318 Line2D corner = new Line2D.Double (x0, y0, x1, y1); 319 g2.draw(corner); 320 corner.setLine(x1, y1, x1, y3); 321 g2.draw(corner); 322 corner.setLine(x1, y1, x3, y1); 323 g2.draw(corner); 324 325 Image backgroundImage = plot.getBackgroundImage(); 327 if (backgroundImage != null) { 328 Composite originalComposite = g2.getComposite(); 329 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 330 plot.getBackgroundAlpha())); 331 g2.drawImage(backgroundImage, (int) x1, (int) y3, 332 (int) (x3 - x1 + 1), (int) (y1 - y3 + 1), null); 333 g2.setComposite(originalComposite); 334 } 335 336 } 337 338 345 public void drawOutline(Graphics2D g2, CategoryPlot plot, 346 Rectangle2D dataArea) { 347 348 float x0 = (float) dataArea.getX(); 349 float x1 = x0 + (float) Math.abs(this.xOffset); 350 float x3 = (float) dataArea.getMaxX(); 351 float x2 = x3 - (float) Math.abs(this.xOffset); 352 353 float y0 = (float) dataArea.getMaxY(); 354 float y1 = y0 - (float) Math.abs(this.yOffset); 355 float y3 = (float) dataArea.getMinY(); 356 float y2 = y3 + (float) Math.abs(this.yOffset); 357 358 GeneralPath clip = new GeneralPath (); 359 clip.moveTo(x0, y0); 360 clip.lineTo(x0, y2); 361 clip.lineTo(x1, y3); 362 clip.lineTo(x3, y3); 363 clip.lineTo(x3, y1); 364 clip.lineTo(x2, y0); 365 clip.closePath(); 366 367 Stroke outlineStroke = plot.getOutlineStroke(); 369 Paint outlinePaint = plot.getOutlinePaint(); 370 if ((outlineStroke != null) && (outlinePaint != null)) { 371 g2.setStroke(outlineStroke); 372 g2.setPaint(outlinePaint); 373 g2.draw(clip); 374 } 375 376 } 377 378 388 public void drawDomainGridline(Graphics2D g2, 389 CategoryPlot plot, 390 Rectangle2D dataArea, 391 double value) { 392 393 Line2D line1 = null; 394 Line2D line2 = null; 395 PlotOrientation orientation = plot.getOrientation(); 396 if (orientation == PlotOrientation.HORIZONTAL) { 397 double y0 = value; 398 double y1 = value - getYOffset(); 399 double x0 = dataArea.getMinX(); 400 double x1 = x0 + getXOffset(); 401 double x2 = dataArea.getMaxY(); 402 line1 = new Line2D.Double (x0, y0, x1, y1); 403 line2 = new Line2D.Double (x1, y1, x2, y1); 404 } 405 else if (orientation == PlotOrientation.VERTICAL) { 406 double x0 = value; 407 double x1 = value + getXOffset(); 408 double y0 = dataArea.getMaxY(); 409 double y1 = y0 - getYOffset(); 410 double y2 = dataArea.getMinY(); 411 line1 = new Line2D.Double (x0, y0, x1, y1); 412 line2 = new Line2D.Double (x1, y1, x1, y2); 413 } 414 Paint paint = plot.getDomainGridlinePaint(); 415 Stroke stroke = plot.getDomainGridlineStroke(); 416 g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT); 417 g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE); 418 g2.draw(line1); 419 g2.draw(line2); 420 421 } 422 423 434 public void drawRangeGridline(Graphics2D g2, 435 CategoryPlot plot, 436 ValueAxis axis, 437 Rectangle2D dataArea, 438 double value) { 439 440 Range range = axis.getRange(); 441 442 if (!range.contains(value)) { 443 return; 444 } 445 446 Rectangle2D adjusted = new Rectangle2D.Double (dataArea.getX(), 447 dataArea.getY() + getYOffset(), dataArea.getWidth() 448 - getXOffset(), dataArea.getHeight() - getYOffset()); 449 450 Line2D line1 = null; 451 Line2D line2 = null; 452 PlotOrientation orientation = plot.getOrientation(); 453 if (orientation == PlotOrientation.HORIZONTAL) { 454 double x0 = axis.valueToJava2D(value, adjusted, 455 plot.getRangeAxisEdge()); 456 double x1 = x0 + getXOffset(); 457 double y0 = dataArea.getMaxY(); 458 double y1 = y0 - getYOffset(); 459 double y2 = dataArea.getMinY(); 460 line1 = new Line2D.Double (x0, y0, x1, y1); 461 line2 = new Line2D.Double (x1, y1, x1, y2); 462 } 463 else if (orientation == PlotOrientation.VERTICAL) { 464 double y0 = axis.valueToJava2D(value, adjusted, 465 plot.getRangeAxisEdge()); 466 double y1 = y0 - getYOffset(); 467 double x0 = dataArea.getMinX(); 468 double x1 = x0 + getXOffset(); 469 double x2 = dataArea.getMaxX(); 470 line1 = new Line2D.Double (x0, y0, x1, y1); 471 line2 = new Line2D.Double (x1, y1, x2, y1); 472 } 473 Paint paint = plot.getRangeGridlinePaint(); 474 Stroke stroke = plot.getRangeGridlineStroke(); 475 g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT); 476 g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE); 477 g2.draw(line1); 478 g2.draw(line2); 479 480 } 481 482 491 public void drawRangeMarker(Graphics2D g2, 492 CategoryPlot plot, 493 ValueAxis axis, 494 Marker marker, 495 Rectangle2D dataArea) { 496 497 if (marker instanceof ValueMarker) { 498 ValueMarker vm = (ValueMarker) marker; 499 double value = vm.getValue(); 500 Range range = axis.getRange(); 501 if (!range.contains(value)) { 502 return; 503 } 504 505 Rectangle2D adjusted = new Rectangle2D.Double (dataArea.getX(), 506 dataArea.getY() + getYOffset(), dataArea.getWidth() 507 - getXOffset(), dataArea.getHeight() - getYOffset()); 508 509 GeneralPath path = null; 510 PlotOrientation orientation = plot.getOrientation(); 511 if (orientation == PlotOrientation.HORIZONTAL) { 512 float x = (float) axis.valueToJava2D(value, adjusted, 513 plot.getRangeAxisEdge()); 514 float y = (float) adjusted.getMaxY(); 515 path = new GeneralPath (); 516 path.moveTo(x, y); 517 path.lineTo((float) (x + getXOffset()), 518 y - (float) getYOffset()); 519 path.lineTo((float) (x + getXOffset()), 520 (float) (adjusted.getMinY() - getYOffset())); 521 path.lineTo(x, (float) adjusted.getMinY()); 522 path.closePath(); 523 } 524 else if (orientation == PlotOrientation.VERTICAL) { 525 float y = (float) axis.valueToJava2D(value, adjusted, 526 plot.getRangeAxisEdge()); 527 float x = (float) dataArea.getX(); 528 path = new GeneralPath (); 529 path.moveTo(x, y); 530 path.lineTo(x + (float) this.xOffset, y - (float) this.yOffset); 531 path.lineTo((float) (adjusted.getMaxX() + this.xOffset), 532 y - (float) this.yOffset); 533 path.lineTo((float) (adjusted.getMaxX()), y); 534 path.closePath(); 535 } 536 g2.setPaint(marker.getPaint()); 537 g2.fill(path); 538 g2.setPaint(marker.getOutlinePaint()); 539 g2.draw(path); 540 541 String label = marker.getLabel(); 542 RectangleAnchor anchor = marker.getLabelAnchor(); 543 if (label != null) { 544 Font labelFont = marker.getLabelFont(); 545 g2.setFont(labelFont); 546 g2.setPaint(marker.getLabelPaint()); 547 Point2D coordinates = calculateRangeMarkerTextAnchorPoint( 548 g2, orientation, dataArea, path.getBounds2D(), 549 marker.getLabelOffset(), LengthAdjustmentType.EXPAND, 550 anchor); 551 TextUtilities.drawAlignedString(label, g2, 552 (float) coordinates.getX(), (float) coordinates.getY(), 553 marker.getLabelTextAnchor()); 554 } 555 556 } 557 else { 558 super.drawRangeMarker(g2, plot, axis, marker, dataArea); 559 } 561 } 562 563 577 public void drawItem(Graphics2D g2, 578 CategoryItemRendererState state, 579 Rectangle2D dataArea, 580 CategoryPlot plot, 581 CategoryAxis domainAxis, 582 ValueAxis rangeAxis, 583 CategoryDataset dataset, 584 int row, 585 int column, 586 int pass) { 587 588 Number dataValue = dataset.getValue(row, column); 590 if (dataValue == null) { 591 return; 592 } 593 594 double value = dataValue.doubleValue(); 595 596 Rectangle2D adjusted = new Rectangle2D.Double (dataArea.getX(), 597 dataArea.getY() + getYOffset(), 598 dataArea.getWidth() - getXOffset(), 599 dataArea.getHeight() - getYOffset()); 600 601 PlotOrientation orientation = plot.getOrientation(); 602 603 double barW0 = calculateBarW0(plot, orientation, adjusted, domainAxis, 604 state, row, column); 605 double[] barL0L1 = calculateBarL0L1(value); 606 if (barL0L1 == null) { 607 return; } 609 610 RectangleEdge edge = plot.getRangeAxisEdge(); 611 double transL0 = rangeAxis.valueToJava2D(barL0L1[0], adjusted, edge); 612 double transL1 = rangeAxis.valueToJava2D(barL0L1[1], adjusted, edge); 613 double barL0 = Math.min(transL0, transL1); 614 double barLength = Math.abs(transL1 - transL0); 615 616 Rectangle2D bar = null; 618 if (orientation == PlotOrientation.HORIZONTAL) { 619 bar = new Rectangle2D.Double (barL0, barW0, barLength, 620 state.getBarWidth()); 621 } 622 else { 623 bar = new Rectangle2D.Double (barW0, barL0, state.getBarWidth(), 624 barLength); 625 } 626 Paint itemPaint = getItemPaint(row, column); 627 g2.setPaint(itemPaint); 628 g2.fill(bar); 629 630 double x0 = bar.getMinX(); 631 double x1 = x0 + getXOffset(); 632 double x2 = bar.getMaxX(); 633 double x3 = x2 + getXOffset(); 634 635 double y0 = bar.getMinY() - getYOffset(); 636 double y1 = bar.getMinY(); 637 double y2 = bar.getMaxY() - getYOffset(); 638 double y3 = bar.getMaxY(); 639 640 GeneralPath bar3dRight = null; 641 GeneralPath bar3dTop = null; 642 if (barLength > 0.0) { 643 bar3dRight = new GeneralPath (); 644 bar3dRight.moveTo((float) x2, (float) y3); 645 bar3dRight.lineTo((float) x2, (float) y1); 646 bar3dRight.lineTo((float) x3, (float) y0); 647 bar3dRight.lineTo((float) x3, (float) y2); 648 bar3dRight.closePath(); 649 650 if (itemPaint instanceof Color ) { 651 g2.setPaint(((Color ) itemPaint).darker()); 652 } 653 g2.fill(bar3dRight); 654 } 655 656 bar3dTop = new GeneralPath (); 657 bar3dTop.moveTo((float) x0, (float) y1); 658 bar3dTop.lineTo((float) x1, (float) y0); 659 bar3dTop.lineTo((float) x3, (float) y0); 660 bar3dTop.lineTo((float) x2, (float) y1); 661 bar3dTop.closePath(); 662 g2.fill(bar3dTop); 663 664 if (isDrawBarOutline() 665 && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { 666 g2.setStroke(getItemOutlineStroke(row, column)); 667 g2.setPaint(getItemOutlinePaint(row, column)); 668 g2.draw(bar); 669 if (bar3dRight != null) { 670 g2.draw(bar3dRight); 671 } 672 if (bar3dTop != null) { 673 g2.draw(bar3dTop); 674 } 675 } 676 677 CategoryItemLabelGenerator generator 678 = getItemLabelGenerator(row, column); 679 if (generator != null && isItemLabelVisible(row, column)) { 680 drawItemLabel(g2, dataset, row, column, plot, generator, bar, 681 (value < 0.0)); 682 } 683 684 EntityCollection entities = state.getEntityCollection(); 686 if (entities != null) { 687 GeneralPath barOutline = new GeneralPath (); 688 barOutline.moveTo((float) x0, (float) y3); 689 barOutline.lineTo((float) x0, (float) y1); 690 barOutline.lineTo((float) x1, (float) y0); 691 barOutline.lineTo((float) x3, (float) y0); 692 barOutline.lineTo((float) x3, (float) y2); 693 barOutline.lineTo((float) x2, (float) y3); 694 barOutline.closePath(); 695 addItemEntity(entities, dataset, row, column, barOutline); 696 } 697 698 } 699 700 707 private void writeObject(ObjectOutputStream stream) throws IOException { 708 stream.defaultWriteObject(); 709 SerialUtilities.writePaint(this.wallPaint, stream); 710 } 711 712 720 private void readObject(ObjectInputStream stream) 721 throws IOException , ClassNotFoundException { 722 stream.defaultReadObject(); 723 this.wallPaint = SerialUtilities.readPaint(stream); 724 } 725 726 } 727 | Popular Tags |