1 54 55 package org.jfree.chart.renderer.category; 56 57 import java.awt.Color ; 58 import java.awt.GradientPaint ; 59 import java.awt.Graphics2D ; 60 import java.awt.Paint ; 61 import java.awt.Stroke ; 62 import java.awt.geom.Rectangle2D ; 63 import java.io.IOException ; 64 import java.io.ObjectInputStream ; 65 import java.io.ObjectOutputStream ; 66 import java.io.Serializable ; 67 68 import org.jfree.chart.axis.CategoryAxis; 69 import org.jfree.chart.axis.ValueAxis; 70 import org.jfree.chart.entity.EntityCollection; 71 import org.jfree.chart.event.RendererChangeEvent; 72 import org.jfree.chart.labels.CategoryItemLabelGenerator; 73 import org.jfree.chart.plot.CategoryPlot; 74 import org.jfree.chart.plot.PlotOrientation; 75 import org.jfree.chart.renderer.AbstractRenderer; 76 import org.jfree.data.Range; 77 import org.jfree.data.category.CategoryDataset; 78 import org.jfree.data.general.DatasetUtilities; 79 import org.jfree.io.SerialUtilities; 80 import org.jfree.ui.GradientPaintTransformType; 81 import org.jfree.ui.RectangleEdge; 82 import org.jfree.ui.StandardGradientPaintTransformer; 83 import org.jfree.util.PaintUtilities; 84 import org.jfree.util.PublicCloneable; 85 86 92 public class WaterfallBarRenderer extends BarRenderer 93 implements Cloneable , PublicCloneable, 94 Serializable { 95 96 97 private static final long serialVersionUID = -2482910643727230911L; 98 99 100 private transient Paint firstBarPaint; 101 102 103 private transient Paint lastBarPaint; 104 105 106 private transient Paint positiveBarPaint; 107 108 109 private transient Paint negativeBarPaint; 110 111 114 public WaterfallBarRenderer() { 115 this( 116 new GradientPaint ( 117 0.0f, 0.0f, new Color (0x22, 0x22, 0xFF), 118 0.0f, 0.0f, new Color (0x66, 0x66, 0xFF) 119 ), 120 new GradientPaint ( 121 0.0f, 0.0f, new Color (0x22, 0xFF, 0x22), 122 0.0f, 0.0f, new Color (0x66, 0xFF, 0x66) 123 ), 124 new GradientPaint ( 125 0.0f, 0.0f, new Color (0xFF, 0x22, 0x22), 126 0.0f, 0.0f, new Color (0xFF, 0x66, 0x66) 127 ), 128 new GradientPaint ( 129 0.0f, 0.0f, new Color (0xFF, 0xFF, 0x22), 130 0.0f, 0.0f, new Color (0xFF, 0xFF, 0x66) 131 ) 132 ); 133 } 134 135 147 public WaterfallBarRenderer(Paint firstBarPaint, 148 Paint positiveBarPaint, 149 Paint negativeBarPaint, 150 Paint lastBarPaint) { 151 super(); 152 if (firstBarPaint == null) { 153 throw new IllegalArgumentException ("Null 'firstBarPaint' argument"); 154 } 155 if (positiveBarPaint == null) { 156 throw new IllegalArgumentException ( 157 "Null 'positiveBarPaint' argument" 158 ); 159 } 160 if (negativeBarPaint == null) { 161 throw new IllegalArgumentException ( 162 "Null 'negativeBarPaint' argument" 163 ); 164 } 165 if (lastBarPaint == null) { 166 throw new IllegalArgumentException ("Null 'lastBarPaint' argument"); 167 } 168 this.firstBarPaint = firstBarPaint; 169 this.lastBarPaint = lastBarPaint; 170 this.positiveBarPaint = positiveBarPaint; 171 this.negativeBarPaint = negativeBarPaint; 172 setGradientPaintTransformer( 173 new StandardGradientPaintTransformer( 174 GradientPaintTransformType.CENTER_VERTICAL 175 ) 176 ); 177 setMinimumBarLength(1.0); 178 } 179 180 188 public Range findRangeBounds(CategoryDataset dataset) { 189 return DatasetUtilities.findCumulativeRangeBounds(dataset); 190 } 191 192 197 public Paint getFirstBarPaint() { 198 return this.firstBarPaint; 199 } 200 201 207 public void setFirstBarPaint(Paint paint) { 208 if (paint == null) { 209 throw new IllegalArgumentException ("Null 'paint' argument"); 210 } 211 this.firstBarPaint = paint; 212 notifyListeners(new RendererChangeEvent(this)); 213 } 214 215 220 public Paint getLastBarPaint() { 221 return this.lastBarPaint; 222 } 223 224 229 public void setLastBarPaint(Paint paint) { 230 if (paint == null) { 231 throw new IllegalArgumentException ("Null 'paint' argument"); 232 } 233 this.lastBarPaint = paint; 234 notifyListeners(new RendererChangeEvent(this)); 235 } 236 237 242 public Paint getPositiveBarPaint() { 243 return this.positiveBarPaint; 244 } 245 246 251 public void setPositiveBarPaint(Paint paint) { 252 if (paint == null) { 253 throw new IllegalArgumentException ("Null 'paint' argument"); 254 } 255 this.positiveBarPaint = paint; 256 notifyListeners(new RendererChangeEvent(this)); 257 } 258 259 264 public Paint getNegativeBarPaint() { 265 return this.negativeBarPaint; 266 } 267 268 273 public void setNegativeBarPaint(Paint paint) { 274 if (paint == null) { 275 throw new IllegalArgumentException ("Null 'paint' argument"); 276 } 277 this.negativeBarPaint = paint; 278 notifyListeners(new RendererChangeEvent(this)); 279 } 280 281 295 public void drawItem(Graphics2D g2, 296 CategoryItemRendererState state, 297 Rectangle2D dataArea, 298 CategoryPlot plot, 299 CategoryAxis domainAxis, 300 ValueAxis rangeAxis, 301 CategoryDataset dataset, 302 int row, 303 int column, 304 int pass) { 305 306 double previous = state.getSeriesRunningTotal(); 307 if (column == dataset.getColumnCount() - 1) { 308 previous = 0.0; 309 } 310 double current = 0.0; 311 Number n = dataset.getValue(row, column); 312 if (n != null) { 313 current = previous + n.doubleValue(); 314 } 315 state.setSeriesRunningTotal(current); 316 317 int seriesCount = getRowCount(); 318 int categoryCount = getColumnCount(); 319 PlotOrientation orientation = plot.getOrientation(); 320 321 double rectX = 0.0; 322 double rectY = 0.0; 323 324 RectangleEdge domainAxisLocation = plot.getDomainAxisEdge(); 325 RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); 326 327 double j2dy0 = rangeAxis.valueToJava2D( 329 previous, dataArea, rangeAxisLocation 330 ); 331 332 double j2dy1 = rangeAxis.valueToJava2D( 334 current, dataArea, rangeAxisLocation 335 ); 336 337 double valDiff = current - previous; 338 if (j2dy1 < j2dy0) { 339 double temp = j2dy1; 340 j2dy1 = j2dy0; 341 j2dy0 = temp; 342 } 343 344 double rectWidth = state.getBarWidth(); 346 347 double rectHeight = Math.max( 349 getMinimumBarLength(), Math.abs(j2dy1 - j2dy0) 350 ); 351 352 if (orientation == PlotOrientation.HORIZONTAL) { 353 rectY = domainAxis.getCategoryStart( 355 column, getColumnCount(), dataArea, domainAxisLocation 356 ); 357 if (seriesCount > 1) { 358 double seriesGap = dataArea.getHeight() * getItemMargin() 359 / (categoryCount * (seriesCount - 1)); 360 rectY = rectY + row * (state.getBarWidth() + seriesGap); 361 } 362 else { 363 rectY = rectY + row * state.getBarWidth(); 364 } 365 366 rectX = j2dy0; 367 rectHeight = state.getBarWidth(); 368 rectWidth = Math.max( 369 getMinimumBarLength(), Math.abs(j2dy1 - j2dy0) 370 ); 371 372 } 373 else if (orientation == PlotOrientation.VERTICAL) { 374 rectX = domainAxis.getCategoryStart( 376 column, getColumnCount(), dataArea, domainAxisLocation 377 ); 378 379 if (seriesCount > 1) { 380 double seriesGap = dataArea.getWidth() * getItemMargin() 381 / (categoryCount * (seriesCount - 1)); 382 rectX = rectX + row * (state.getBarWidth() + seriesGap); 383 } 384 else { 385 rectX = rectX + row * state.getBarWidth(); 386 } 387 388 rectY = j2dy0; 389 } 390 Rectangle2D bar = new Rectangle2D.Double ( 391 rectX, rectY, rectWidth, rectHeight 392 ); 393 Paint seriesPaint = getFirstBarPaint(); 394 if (column == 0) { 395 seriesPaint = getFirstBarPaint(); 396 } 397 else if (column == categoryCount - 1) { 398 seriesPaint = getLastBarPaint(); 399 } 400 else { 401 if (valDiff < 0.0) { 402 seriesPaint = getNegativeBarPaint(); 403 } 404 else if (valDiff > 0.0) { 405 seriesPaint = getPositiveBarPaint(); 406 } 407 else { 408 seriesPaint = getLastBarPaint(); 409 } 410 } 411 if (getGradientPaintTransformer() != null 412 && seriesPaint instanceof GradientPaint ) { 413 GradientPaint gp = (GradientPaint ) seriesPaint; 414 seriesPaint = getGradientPaintTransformer().transform(gp, bar); 415 } 416 g2.setPaint(seriesPaint); 417 g2.fill(bar); 418 419 if (isDrawBarOutline() 421 && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { 422 Stroke stroke = getItemOutlineStroke(row, column); 423 Paint paint = getItemOutlinePaint(row, column); 424 if (stroke != null && paint != null) { 425 g2.setStroke(stroke); 426 g2.setPaint(paint); 427 g2.draw(bar); 428 } 429 } 430 431 CategoryItemLabelGenerator generator 432 = getItemLabelGenerator(row, column); 433 if (generator != null && isItemLabelVisible(row, column)) { 434 drawItemLabel( 435 g2, dataset, row, column, plot, generator, bar, (valDiff < 0.0) 436 ); 437 } 438 439 EntityCollection entities = state.getEntityCollection(); 441 if (entities != null) { 442 addItemEntity(entities, dataset, row, column, bar); 443 } 444 445 } 446 447 454 public boolean equals(Object obj) { 455 456 if (obj == this) { 457 return true; 458 } 459 if (!super.equals(obj)) { 460 return false; 461 } 462 if (!(obj instanceof WaterfallBarRenderer)) { 463 return false; 464 } 465 WaterfallBarRenderer that = (WaterfallBarRenderer) obj; 466 if (!PaintUtilities.equal(this.firstBarPaint, that.firstBarPaint)) { 467 return false; 468 } 469 if (!PaintUtilities.equal(this.lastBarPaint, that.lastBarPaint)) { 470 return false; 471 } 472 if (!PaintUtilities.equal(this.positiveBarPaint, 473 that.positiveBarPaint)) { 474 return false; 475 } 476 if (!PaintUtilities.equal(this.negativeBarPaint, 477 that.negativeBarPaint)) { 478 return false; 479 } 480 return true; 481 482 } 483 484 491 private void writeObject(ObjectOutputStream stream) throws IOException { 492 stream.defaultWriteObject(); 493 SerialUtilities.writePaint(this.firstBarPaint, stream); 494 SerialUtilities.writePaint(this.lastBarPaint, stream); 495 SerialUtilities.writePaint(this.positiveBarPaint, stream); 496 SerialUtilities.writePaint(this.negativeBarPaint, stream); 497 } 498 499 507 private void readObject(ObjectInputStream stream) 508 throws IOException , ClassNotFoundException { 509 stream.defaultReadObject(); 510 this.firstBarPaint = SerialUtilities.readPaint(stream); 511 this.lastBarPaint = SerialUtilities.readPaint(stream); 512 this.positiveBarPaint = SerialUtilities.readPaint(stream); 513 this.negativeBarPaint = SerialUtilities.readPaint(stream); 514 } 515 516 } 517 | Popular Tags |