1:
53:
54: package ;
55:
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66:
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83: import ;
84:
85:
91: public class WaterfallBarRenderer extends BarRenderer
92: implements Cloneable, PublicCloneable,
93: Serializable {
94:
95:
96: private static final long serialVersionUID = -2482910643727230911L;
97:
98:
99: private transient Paint firstBarPaint;
100:
101:
102: private transient Paint lastBarPaint;
103:
104:
105: private transient Paint positiveBarPaint;
106:
107:
108: private transient Paint negativeBarPaint;
109:
110:
113: public WaterfallBarRenderer() {
114: this(new GradientPaint(0.0f, 0.0f, new Color(0x22, 0x22, 0xFF),
115: 0.0f, 0.0f, new Color(0x66, 0x66, 0xFF)),
116: new GradientPaint(0.0f, 0.0f, new Color(0x22, 0xFF, 0x22),
117: 0.0f, 0.0f, new Color(0x66, 0xFF, 0x66)),
118: new GradientPaint(0.0f, 0.0f, new Color(0xFF, 0x22, 0x22),
119: 0.0f, 0.0f, new Color(0xFF, 0x66, 0x66)),
120: new GradientPaint(0.0f, 0.0f, new Color(0xFF, 0xFF, 0x22),
121: 0.0f, 0.0f, new Color(0xFF, 0xFF, 0x66)));
122: }
123:
124:
136: public WaterfallBarRenderer(Paint firstBarPaint,
137: Paint positiveBarPaint,
138: Paint negativeBarPaint,
139: Paint lastBarPaint) {
140: super();
141: if (firstBarPaint == null) {
142: throw new IllegalArgumentException("Null 'firstBarPaint' argument");
143: }
144: if (positiveBarPaint == null) {
145: throw new IllegalArgumentException(
146: "Null 'positiveBarPaint' argument");
147: }
148: if (negativeBarPaint == null) {
149: throw new IllegalArgumentException(
150: "Null 'negativeBarPaint' argument");
151: }
152: if (lastBarPaint == null) {
153: throw new IllegalArgumentException("Null 'lastBarPaint' argument");
154: }
155: this.firstBarPaint = firstBarPaint;
156: this.lastBarPaint = lastBarPaint;
157: this.positiveBarPaint = positiveBarPaint;
158: this.negativeBarPaint = negativeBarPaint;
159: setGradientPaintTransformer(new StandardGradientPaintTransformer(
160: GradientPaintTransformType.CENTER_VERTICAL));
161: setMinimumBarLength(1.0);
162: }
163:
164:
172: public Range findRangeBounds(CategoryDataset dataset) {
173: return DatasetUtilities.findCumulativeRangeBounds(dataset);
174: }
175:
176:
181: public Paint getFirstBarPaint() {
182: return this.firstBarPaint;
183: }
184:
185:
191: public void setFirstBarPaint(Paint paint) {
192: if (paint == null) {
193: throw new IllegalArgumentException("Null 'paint' argument");
194: }
195: this.firstBarPaint = paint;
196: fireChangeEvent();
197: }
198:
199:
204: public Paint getLastBarPaint() {
205: return this.lastBarPaint;
206: }
207:
208:
214: public void setLastBarPaint(Paint paint) {
215: if (paint == null) {
216: throw new IllegalArgumentException("Null 'paint' argument");
217: }
218: this.lastBarPaint = paint;
219: fireChangeEvent();
220: }
221:
222:
227: public Paint getPositiveBarPaint() {
228: return this.positiveBarPaint;
229: }
230:
231:
236: public void setPositiveBarPaint(Paint paint) {
237: if (paint == null) {
238: throw new IllegalArgumentException("Null 'paint' argument");
239: }
240: this.positiveBarPaint = paint;
241: fireChangeEvent();
242: }
243:
244:
249: public Paint getNegativeBarPaint() {
250: return this.negativeBarPaint;
251: }
252:
253:
259: public void setNegativeBarPaint(Paint paint) {
260: if (paint == null) {
261: throw new IllegalArgumentException("Null 'paint' argument");
262: }
263: this.negativeBarPaint = paint;
264: fireChangeEvent();
265: }
266:
267:
281: public void drawItem(Graphics2D g2,
282: CategoryItemRendererState state,
283: Rectangle2D dataArea,
284: CategoryPlot plot,
285: CategoryAxis domainAxis,
286: ValueAxis rangeAxis,
287: CategoryDataset dataset,
288: int row,
289: int column,
290: int pass) {
291:
292: double previous = state.getSeriesRunningTotal();
293: if (column == dataset.getColumnCount() - 1) {
294: previous = 0.0;
295: }
296: double current = 0.0;
297: Number n = dataset.getValue(row, column);
298: if (n != null) {
299: current = previous + n.doubleValue();
300: }
301: state.setSeriesRunningTotal(current);
302:
303: int seriesCount = getRowCount();
304: int categoryCount = getColumnCount();
305: PlotOrientation orientation = plot.getOrientation();
306:
307: double rectX = 0.0;
308: double rectY = 0.0;
309:
310: RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
311: RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
312:
313:
314: double j2dy0 = rangeAxis.valueToJava2D(previous, dataArea,
315: rangeAxisLocation);
316:
317:
318: double j2dy1 = rangeAxis.valueToJava2D(current, dataArea,
319: rangeAxisLocation);
320:
321: double valDiff = current - previous;
322: if (j2dy1 < j2dy0) {
323: double temp = j2dy1;
324: j2dy1 = j2dy0;
325: j2dy0 = temp;
326: }
327:
328:
329: double rectWidth = state.getBarWidth();
330:
331:
332: double rectHeight = Math.max(getMinimumBarLength(),
333: Math.abs(j2dy1 - j2dy0));
334:
335: if (orientation == PlotOrientation.HORIZONTAL) {
336:
337: rectY = domainAxis.getCategoryStart(column, getColumnCount(),
338: dataArea, domainAxisLocation);
339: if (seriesCount > 1) {
340: double seriesGap = dataArea.getHeight() * getItemMargin()
341: / (categoryCount * (seriesCount - 1));
342: rectY = rectY + row * (state.getBarWidth() + seriesGap);
343: }
344: else {
345: rectY = rectY + row * state.getBarWidth();
346: }
347:
348: rectX = j2dy0;
349: rectHeight = state.getBarWidth();
350: rectWidth = Math.max(getMinimumBarLength(),
351: Math.abs(j2dy1 - j2dy0));
352:
353: }
354: else if (orientation == PlotOrientation.VERTICAL) {
355:
356: rectX = domainAxis.getCategoryStart(column, getColumnCount(),
357: dataArea, domainAxisLocation);
358:
359: if (seriesCount > 1) {
360: double seriesGap = dataArea.getWidth() * getItemMargin()
361: / (categoryCount * (seriesCount - 1));
362: rectX = rectX + row * (state.getBarWidth() + seriesGap);
363: }
364: else {
365: rectX = rectX + row * state.getBarWidth();
366: }
367:
368: rectY = j2dy0;
369: }
370: Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth,
371: rectHeight);
372: Paint seriesPaint = getFirstBarPaint();
373: if (column == 0) {
374: seriesPaint = getFirstBarPaint();
375: }
376: else if (column == categoryCount - 1) {
377: seriesPaint = getLastBarPaint();
378: }
379: else {
380: if (valDiff < 0.0) {
381: seriesPaint = getNegativeBarPaint();
382: }
383: else if (valDiff > 0.0) {
384: seriesPaint = getPositiveBarPaint();
385: }
386: else {
387: seriesPaint = getLastBarPaint();
388: }
389: }
390: if (getGradientPaintTransformer() != null
391: && seriesPaint instanceof GradientPaint) {
392: GradientPaint gp = (GradientPaint) seriesPaint;
393: seriesPaint = getGradientPaintTransformer().transform(gp, bar);
394: }
395: g2.setPaint(seriesPaint);
396: g2.fill(bar);
397:
398:
399: if (isDrawBarOutline()
400: && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
401: Stroke stroke = getItemOutlineStroke(row, column);
402: Paint paint = getItemOutlinePaint(row, column);
403: if (stroke != null && paint != null) {
404: g2.setStroke(stroke);
405: g2.setPaint(paint);
406: g2.draw(bar);
407: }
408: }
409:
410: CategoryItemLabelGenerator generator
411: = getItemLabelGenerator(row, column);
412: if (generator != null && isItemLabelVisible(row, column)) {
413: drawItemLabel(g2, dataset, row, column, plot, generator, bar,
414: (valDiff < 0.0));
415: }
416:
417:
418: EntityCollection entities = state.getEntityCollection();
419: if (entities != null) {
420: addItemEntity(entities, dataset, row, column, bar);
421: }
422:
423: }
424:
425:
432: public boolean equals(Object obj) {
433:
434: if (obj == this) {
435: return true;
436: }
437: if (!super.equals(obj)) {
438: return false;
439: }
440: if (!(obj instanceof WaterfallBarRenderer)) {
441: return false;
442: }
443: WaterfallBarRenderer that = (WaterfallBarRenderer) obj;
444: if (!PaintUtilities.equal(this.firstBarPaint, that.firstBarPaint)) {
445: return false;
446: }
447: if (!PaintUtilities.equal(this.lastBarPaint, that.lastBarPaint)) {
448: return false;
449: }
450: if (!PaintUtilities.equal(this.positiveBarPaint,
451: that.positiveBarPaint)) {
452: return false;
453: }
454: if (!PaintUtilities.equal(this.negativeBarPaint,
455: that.negativeBarPaint)) {
456: return false;
457: }
458: return true;
459:
460: }
461:
462:
469: private void writeObject(ObjectOutputStream stream) throws IOException {
470: stream.defaultWriteObject();
471: SerialUtilities.writePaint(this.firstBarPaint, stream);
472: SerialUtilities.writePaint(this.lastBarPaint, stream);
473: SerialUtilities.writePaint(this.positiveBarPaint, stream);
474: SerialUtilities.writePaint(this.negativeBarPaint, stream);
475: }
476:
477:
485: private void readObject(ObjectInputStream stream)
486: throws IOException, ClassNotFoundException {
487: stream.defaultReadObject();
488: this.firstBarPaint = SerialUtilities.readPaint(stream);
489: this.lastBarPaint = SerialUtilities.readPaint(stream);
490: this.positiveBarPaint = SerialUtilities.readPaint(stream);
491: this.negativeBarPaint = SerialUtilities.readPaint(stream);
492: }
493:
494: }