1 76 77 package org.jfree.chart.renderer; 78 79 import java.awt.AlphaComposite ; 80 import java.awt.Color ; 81 import java.awt.Composite ; 82 import java.awt.Graphics2D ; 83 import java.awt.Image ; 84 import java.awt.Paint ; 85 import java.awt.Stroke ; 86 import java.awt.geom.GeneralPath ; 87 import java.awt.geom.Line2D ; 88 import java.awt.geom.Rectangle2D ; 89 import java.io.IOException ; 90 import java.io.ObjectInputStream ; 91 import java.io.ObjectOutputStream ; 92 import java.io.Serializable ; 93 94 import org.jfree.chart.Effect3D; 95 import org.jfree.chart.Marker; 96 import org.jfree.chart.axis.CategoryAxis; 97 import org.jfree.chart.axis.ValueAxis; 98 import org.jfree.chart.entity.CategoryItemEntity; 99 import org.jfree.chart.entity.EntityCollection; 100 import org.jfree.chart.labels.CategoryItemLabelGenerator; 101 import org.jfree.chart.plot.CategoryPlot; 102 import org.jfree.chart.plot.Plot; 103 import org.jfree.chart.plot.PlotOrientation; 104 import org.jfree.data.CategoryDataset; 105 import org.jfree.data.Range; 106 import org.jfree.io.SerialUtilities; 107 import org.jfree.ui.RectangleEdge; 108 import org.jfree.ui.TextAnchor; 109 import org.jfree.util.PublicCloneable; 110 111 117 public class BarRenderer3D extends BarRenderer 118 implements Effect3D, Cloneable , PublicCloneable, Serializable { 119 120 121 public static final double DEFAULT_X_OFFSET = 12.0; 122 123 124 public static final double DEFAULT_Y_OFFSET = 8.0; 125 126 127 public static final Paint DEFAULT_WALL_PAINT = new Color (0xDD, 0xDD, 0xDD); 128 129 130 private double xOffset; 131 132 133 private double yOffset; 134 135 136 private transient Paint wallPaint; 137 138 141 public BarRenderer3D() { 142 this(DEFAULT_X_OFFSET, DEFAULT_Y_OFFSET); 143 } 144 145 151 public BarRenderer3D(double xOffset, double yOffset) { 152 153 super(); 154 this.xOffset = xOffset; 155 this.yOffset = yOffset; 156 this.wallPaint = DEFAULT_WALL_PAINT; 157 ItemLabelPosition p1 = new ItemLabelPosition( 159 ItemLabelAnchor.INSIDE12, TextAnchor.TOP_CENTER, TextAnchor.TOP_CENTER, 0.0 160 ); 161 setPositiveItemLabelPosition(p1); 162 ItemLabelPosition p2 = new ItemLabelPosition( 163 ItemLabelAnchor.INSIDE12, TextAnchor.TOP_CENTER, TextAnchor.TOP_CENTER, 0.0 164 ); 165 setNegativeItemLabelPosition(p2); 166 167 } 168 169 174 public double getXOffset() { 175 return this.xOffset; 176 } 177 178 183 public double getYOffset() { 184 return this.yOffset; 185 } 186 187 192 public Paint getWallPaint() { 193 return this.wallPaint; 194 } 195 196 201 public void setWallPaint(Paint paint) { 202 this.wallPaint = paint; 203 } 204 205 212 public void drawBackground(Graphics2D g2, CategoryPlot plot, Rectangle2D dataArea) { 213 214 float x0 = (float) dataArea.getX(); 215 float x1 = x0 + (float) Math.abs(this.xOffset); 216 float x3 = (float) dataArea.getMaxX(); 217 float x2 = x3 - (float) Math.abs(this.xOffset); 218 219 float y0 = (float) dataArea.getMaxY(); 220 float y1 = y0 - (float) Math.abs(this.yOffset); 221 float y3 = (float) dataArea.getMinY(); 222 float y2 = y3 + (float) Math.abs(this.yOffset); 223 224 GeneralPath clip = new GeneralPath (); 225 clip.moveTo(x0, y0); 226 clip.lineTo(x0, y2); 227 clip.lineTo(x1, y3); 228 clip.lineTo(x3, y3); 229 clip.lineTo(x3, y1); 230 clip.lineTo(x2, y0); 231 clip.closePath(); 232 233 Paint backgroundPaint = plot.getBackgroundPaint(); 235 if (backgroundPaint != null) { 236 g2.setPaint(backgroundPaint); 237 g2.fill(clip); 238 } 239 240 GeneralPath leftWall = new GeneralPath (); 241 leftWall.moveTo(x0, y0); 242 leftWall.lineTo(x0, y2); 243 leftWall.lineTo(x1, y3); 244 leftWall.lineTo(x1, y1); 245 leftWall.closePath(); 246 g2.setPaint(getWallPaint()); 247 g2.fill(leftWall); 248 249 GeneralPath bottomWall = new GeneralPath (); 250 bottomWall.moveTo(x0, y0); 251 bottomWall.lineTo(x1, y1); 252 bottomWall.lineTo(x3, y1); 253 bottomWall.lineTo(x2, y0); 254 bottomWall.closePath(); 255 g2.setPaint(getWallPaint()); 256 g2.fill(bottomWall); 257 258 g2.setPaint(Color.lightGray); 260 Line2D corner = new Line2D.Double (x0, y0, x1, y1); 261 g2.draw(corner); 262 corner.setLine(x1, y1, x1, y3); 263 g2.draw(corner); 264 corner.setLine(x1, y1, x3, y1); 265 g2.draw(corner); 266 267 Image backgroundImage = plot.getBackgroundImage(); 269 if (backgroundImage != null) { 270 Composite originalComposite = g2.getComposite(); 271 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 272 plot.getBackgroundAlpha())); 273 g2.drawImage(backgroundImage, 274 (int) x1, (int) y3, 275 (int) (x3 - x1 + 1), (int) (y1 - y3 + 1), 276 null); 277 g2.setComposite(originalComposite); 278 } 279 280 } 281 282 289 public void drawOutline(Graphics2D g2, CategoryPlot plot, Rectangle2D dataArea) { 290 291 float x0 = (float) dataArea.getX(); 292 float x1 = x0 + (float) Math.abs(this.xOffset); 293 float x3 = (float) dataArea.getMaxX(); 294 float x2 = x3 - (float) Math.abs(this.xOffset); 295 296 float y0 = (float) dataArea.getMaxY(); 297 float y1 = y0 - (float) Math.abs(this.yOffset); 298 float y3 = (float) dataArea.getMinY(); 299 float y2 = y3 + (float) Math.abs(this.yOffset); 300 301 GeneralPath clip = new GeneralPath (); 302 clip.moveTo(x0, y0); 303 clip.lineTo(x0, y2); 304 clip.lineTo(x1, y3); 305 clip.lineTo(x3, y3); 306 clip.lineTo(x3, y1); 307 clip.lineTo(x2, y0); 308 clip.closePath(); 309 310 Stroke outlineStroke = plot.getOutlineStroke(); 312 Paint outlinePaint = plot.getOutlinePaint(); 313 if ((outlineStroke != null) && (outlinePaint != null)) { 314 g2.setStroke(outlineStroke); 315 g2.setPaint(outlinePaint); 316 g2.draw(clip); 317 } 318 319 } 320 321 330 public void drawDomainGridline(Graphics2D g2, 331 CategoryPlot plot, 332 Rectangle2D dataArea, 333 double value) { 334 335 Line2D line1 = null; 336 Line2D line2 = null; 337 PlotOrientation orientation = plot.getOrientation(); 338 if (orientation == PlotOrientation.HORIZONTAL) { 339 double y0 = value; 340 double y1 = value - getYOffset(); 341 double x0 = dataArea.getMinX(); 342 double x1 = x0 + getXOffset(); 343 double x2 = dataArea.getMaxY(); 344 line1 = new Line2D.Double (x0, y0, x1, y1); 345 line2 = new Line2D.Double (x1, y1, x2, y1); 346 } 347 else if (orientation == PlotOrientation.VERTICAL) { 348 double x0 = value; 349 double x1 = value + getXOffset(); 350 double y0 = dataArea.getMaxY(); 351 double y1 = y0 - getYOffset(); 352 double y2 = dataArea.getMinY(); 353 line1 = new Line2D.Double (x0, y0, x1, y1); 354 line2 = new Line2D.Double (x1, y1, x1, y2); 355 } 356 Paint paint = plot.getDomainGridlinePaint(); 357 Stroke stroke = plot.getDomainGridlineStroke(); 358 g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT); 359 g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE); 360 g2.draw(line1); 361 g2.draw(line2); 362 363 } 364 365 375 public void drawRangeGridline(Graphics2D g2, 376 CategoryPlot plot, 377 ValueAxis axis, 378 Rectangle2D dataArea, 379 double value) { 380 381 Range range = axis.getRange(); 382 383 if (!range.contains(value)) { 384 return; 385 } 386 387 Rectangle2D adjusted = new Rectangle2D.Double (dataArea.getX(), 388 dataArea.getY() + getYOffset(), 389 dataArea.getWidth() - getXOffset(), 390 dataArea.getHeight() - getYOffset()); 391 392 Line2D line1 = null; 393 Line2D line2 = null; 394 PlotOrientation orientation = plot.getOrientation(); 395 if (orientation == PlotOrientation.HORIZONTAL) { 396 double x0 = axis.translateValueToJava2D(value, adjusted, plot.getRangeAxisEdge()); 397 double x1 = x0 + getXOffset(); 398 double y0 = dataArea.getMaxY(); 399 double y1 = y0 - getYOffset(); 400 double y2 = dataArea.getMinY(); 401 line1 = new Line2D.Double (x0, y0, x1, y1); 402 line2 = new Line2D.Double (x1, y1, x1, y2); 403 } 404 else if (orientation == PlotOrientation.VERTICAL) { 405 double y0 = axis.translateValueToJava2D(value, adjusted, plot.getRangeAxisEdge()); 406 double y1 = y0 - getYOffset(); 407 double x0 = dataArea.getMinX(); 408 double x1 = x0 + getXOffset(); 409 double x2 = dataArea.getMaxX(); 410 line1 = new Line2D.Double (x0, y0, x1, y1); 411 line2 = new Line2D.Double (x1, y1, x2, y1); 412 } 413 Paint paint = plot.getRangeGridlinePaint(); 414 Stroke stroke = plot.getRangeGridlineStroke(); 415 g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT); 416 g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE); 417 g2.draw(line1); 418 g2.draw(line2); 419 420 } 421 422 431 public void drawRangeMarker(Graphics2D g2, 432 CategoryPlot plot, 433 ValueAxis axis, 434 Marker marker, 435 Rectangle2D dataArea) { 436 437 double value = marker.getValue(); 438 Range range = axis.getRange(); 439 if (!range.contains(value)) { 440 return; 441 } 442 443 Rectangle2D adjusted = new Rectangle2D.Double (dataArea.getX(), 444 dataArea.getY() + getYOffset(), 445 dataArea.getWidth() - getXOffset(), 446 dataArea.getHeight() - getYOffset()); 447 448 449 GeneralPath path = null; 450 PlotOrientation orientation = plot.getOrientation(); 451 if (orientation == PlotOrientation.HORIZONTAL) { 452 float x = (float) axis.translateValueToJava2D(marker.getValue(), adjusted, 453 plot.getRangeAxisEdge()); 454 float y = (float) adjusted.getMaxY(); 455 path = new GeneralPath (); 456 path.moveTo(x, y); 457 path.lineTo((float) (x + getXOffset()), y - (float) getYOffset()); 458 path.lineTo((float) (x + getXOffset()), (float) (adjusted.getMinY() - getYOffset())); 459 path.lineTo(x, (float) adjusted.getMinY()); 460 path.closePath(); 461 } 462 else if (orientation == PlotOrientation.VERTICAL) { 463 float y = (float) axis.translateValueToJava2D(marker.getValue(), adjusted, 464 plot.getRangeAxisEdge()); 465 float x = (float) dataArea.getX(); 466 path = new GeneralPath (); 467 path.moveTo(x, y); 468 path.lineTo(x + (float) this.xOffset, y - (float) this.yOffset); 469 path.lineTo((float) (adjusted.getMaxX() + this.xOffset), y - (float) this.yOffset); 470 path.lineTo((float) (adjusted.getMaxX()), y); 471 path.closePath(); 472 } 473 g2.setPaint(marker.getPaint()); 474 g2.fill(path); 475 g2.setPaint(marker.getOutlinePaint()); 476 g2.draw(path); 477 478 } 479 480 493 public void drawItem(Graphics2D g2, 494 CategoryItemRendererState state, 495 Rectangle2D dataArea, 496 CategoryPlot plot, 497 CategoryAxis domainAxis, 498 ValueAxis rangeAxis, 499 CategoryDataset dataset, 500 int row, 501 int column) { 502 503 Number dataValue = dataset.getValue(row, column); 505 if (dataValue == null) { 506 return; 507 } 508 509 double value = dataValue.doubleValue(); 510 511 Rectangle2D adjusted = new Rectangle2D.Double (dataArea.getX(), 512 dataArea.getY() + getYOffset(), 513 dataArea.getWidth() - getXOffset(), 514 dataArea.getHeight() - getYOffset()); 515 516 PlotOrientation orientation = plot.getOrientation(); 517 518 double barW0 = calculateBarW0(plot, orientation, adjusted, domainAxis, state, row, column); 519 double[] barL0L1 = calculateBarL0L1(value); 520 if (barL0L1 == null) { 521 return; } 523 524 RectangleEdge edge = plot.getRangeAxisEdge(); 525 double transL0 = rangeAxis.translateValueToJava2D(barL0L1[0], adjusted, edge); 526 double transL1 = rangeAxis.translateValueToJava2D(barL0L1[1], adjusted, edge); 527 double barL0 = Math.min(transL0, transL1); 528 double barLength = Math.abs(transL1 - transL0); 529 530 Rectangle2D bar = null; 532 if (orientation == PlotOrientation.HORIZONTAL) { 533 bar = new Rectangle2D.Double (barL0, barW0, barLength, state.getBarWidth()); 534 } 535 else { 536 bar = new Rectangle2D.Double (barW0, barL0, state.getBarWidth(), barLength); 537 } 538 Paint itemPaint = getItemPaint(row, column); 539 g2.setPaint(itemPaint); 540 g2.fill(bar); 541 542 double x0 = bar.getMinX(); 543 double x1 = x0 + this.xOffset; 544 double x2 = bar.getMaxX(); 545 double x3 = x2 + this.xOffset; 546 547 double y0 = bar.getMinY() - this.yOffset; 548 double y1 = bar.getMinY(); 549 double y2 = bar.getMaxY() - this.yOffset; 550 double y3 = bar.getMaxY(); 551 552 GeneralPath bar3dRight = null; 553 GeneralPath bar3dTop = null; 554 if (barLength > 0.0) { 555 bar3dRight = new GeneralPath (); 556 bar3dRight.moveTo((float) x2, (float) y3); 557 bar3dRight.lineTo((float) x2, (float) y1); 558 bar3dRight.lineTo((float) x3, (float) y0); 559 bar3dRight.lineTo((float) x3, (float) y2); 560 bar3dRight.closePath(); 561 562 if (itemPaint instanceof Color ) { 563 g2.setPaint(((Color ) itemPaint).darker()); 564 } 565 g2.fill(bar3dRight); 566 } 567 568 bar3dTop = new GeneralPath (); 569 bar3dTop.moveTo((float) x0, (float) y1); 570 bar3dTop.lineTo((float) x1, (float) y0); 571 bar3dTop.lineTo((float) x3, (float) y0); 572 bar3dTop.lineTo((float) x2, (float) y1); 573 bar3dTop.closePath(); 574 g2.fill(bar3dTop); 575 576 if (state.getBarWidth() > 3) { 577 g2.setStroke(getItemOutlineStroke(row, column)); 578 g2.setPaint(getItemOutlinePaint(row, column)); 579 g2.draw(bar); 580 if (bar3dRight != null) { 581 g2.draw(bar3dRight); 582 } 583 if (bar3dTop != null) { 584 g2.draw(bar3dTop); 585 } 586 } 587 588 CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column); 589 if (generator != null && isItemLabelVisible(row, column)) { 590 drawItemLabel(g2, dataset, row, column, plot, generator, bar, (transL0 < transL1)); 591 } 592 593 if (state.getInfo() != null) { 595 EntityCollection entities = state.getInfo().getOwner().getEntityCollection(); 596 if (entities != null) { 597 GeneralPath barOutline = new GeneralPath (); 598 barOutline.moveTo((float) x0, (float) y3); 599 barOutline.lineTo((float) x0, (float) y1); 600 barOutline.lineTo((float) x1, (float) y0); 601 barOutline.lineTo((float) x3, (float) y0); 602 barOutline.lineTo((float) x3, (float) y2); 603 barOutline.lineTo((float) x2, (float) y3); 604 barOutline.closePath(); 605 606 String tip = null; 607 generator = getItemLabelGenerator(row, column); 608 if (generator != null) { 609 tip = generator.generateToolTip(dataset, row, column); 610 } 611 String url = null; 612 if (getItemURLGenerator(row, column) != null) { 613 url = getItemURLGenerator(row, column).generateURL(dataset, row, column); 614 } 615 CategoryItemEntity entity = new CategoryItemEntity( 616 barOutline, tip, url, dataset, row, dataset.getColumnKey(column), column 617 ); 618 entities.addEntity(entity); 619 } 620 } 621 622 } 623 624 631 private void writeObject(ObjectOutputStream stream) throws IOException { 632 stream.defaultWriteObject(); 633 SerialUtilities.writePaint(this.wallPaint, stream); 634 } 635 636 644 private void readObject(ObjectInputStream stream) throws IOException , ClassNotFoundException { 645 stream.defaultReadObject(); 646 this.wallPaint = SerialUtilities.readPaint(stream); 647 } 648 649 } 650 | Popular Tags |