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: notifyListeners(new RendererChangeEvent(this));
197: }
198:
199:
204: public Paint getLastBarPaint() {
205: return this.lastBarPaint;
206: }
207:
208:
213: public void setLastBarPaint(Paint paint) {
214: if (paint == null) {
215: throw new IllegalArgumentException("Null 'paint' argument");
216: }
217: this.lastBarPaint = paint;
218: notifyListeners(new RendererChangeEvent(this));
219: }
220:
221:
226: public Paint getPositiveBarPaint() {
227: return this.positiveBarPaint;
228: }
229:
230:
235: public void setPositiveBarPaint(Paint paint) {
236: if (paint == null) {
237: throw new IllegalArgumentException("Null 'paint' argument");
238: }
239: this.positiveBarPaint = paint;
240: notifyListeners(new RendererChangeEvent(this));
241: }
242:
243:
248: public Paint getNegativeBarPaint() {
249: return this.negativeBarPaint;
250: }
251:
252:
257: public void setNegativeBarPaint(Paint paint) {
258: if (paint == null) {
259: throw new IllegalArgumentException("Null 'paint' argument");
260: }
261: this.negativeBarPaint = paint;
262: notifyListeners(new RendererChangeEvent(this));
263: }
264:
265:
279: public void drawItem(Graphics2D g2,
280: CategoryItemRendererState state,
281: Rectangle2D dataArea,
282: CategoryPlot plot,
283: CategoryAxis domainAxis,
284: ValueAxis rangeAxis,
285: CategoryDataset dataset,
286: int row,
287: int column,
288: int pass) {
289:
290: double previous = state.getSeriesRunningTotal();
291: if (column == dataset.getColumnCount() - 1) {
292: previous = 0.0;
293: }
294: double current = 0.0;
295: Number n = dataset.getValue(row, column);
296: if (n != null) {
297: current = previous + n.doubleValue();
298: }
299: state.setSeriesRunningTotal(current);
300:
301: int seriesCount = getRowCount();
302: int categoryCount = getColumnCount();
303: PlotOrientation orientation = plot.getOrientation();
304:
305: double rectX = 0.0;
306: double rectY = 0.0;
307:
308: RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
309: RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
310:
311:
312: double j2dy0 = rangeAxis.valueToJava2D(previous, dataArea,
313: rangeAxisLocation);
314:
315:
316: double j2dy1 = rangeAxis.valueToJava2D(current, dataArea,
317: rangeAxisLocation);
318:
319: double valDiff = current - previous;
320: if (j2dy1 < j2dy0) {
321: double temp = j2dy1;
322: j2dy1 = j2dy0;
323: j2dy0 = temp;
324: }
325:
326:
327: double rectWidth = state.getBarWidth();
328:
329:
330: double rectHeight = Math.max(getMinimumBarLength(),
331: Math.abs(j2dy1 - j2dy0));
332:
333: if (orientation == PlotOrientation.HORIZONTAL) {
334:
335: rectY = domainAxis.getCategoryStart(column, getColumnCount(),
336: dataArea, domainAxisLocation);
337: if (seriesCount > 1) {
338: double seriesGap = dataArea.getHeight() * getItemMargin()
339: / (categoryCount * (seriesCount - 1));
340: rectY = rectY + row * (state.getBarWidth() + seriesGap);
341: }
342: else {
343: rectY = rectY + row * state.getBarWidth();
344: }
345:
346: rectX = j2dy0;
347: rectHeight = state.getBarWidth();
348: rectWidth = Math.max(getMinimumBarLength(),
349: Math.abs(j2dy1 - j2dy0));
350:
351: }
352: else if (orientation == PlotOrientation.VERTICAL) {
353:
354: rectX = domainAxis.getCategoryStart(column, getColumnCount(),
355: dataArea, domainAxisLocation);
356:
357: if (seriesCount > 1) {
358: double seriesGap = dataArea.getWidth() * getItemMargin()
359: / (categoryCount * (seriesCount - 1));
360: rectX = rectX + row * (state.getBarWidth() + seriesGap);
361: }
362: else {
363: rectX = rectX + row * state.getBarWidth();
364: }
365:
366: rectY = j2dy0;
367: }
368: Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth,
369: rectHeight);
370: Paint seriesPaint = getFirstBarPaint();
371: if (column == 0) {
372: seriesPaint = getFirstBarPaint();
373: }
374: else if (column == categoryCount - 1) {
375: seriesPaint = getLastBarPaint();
376: }
377: else {
378: if (valDiff < 0.0) {
379: seriesPaint = getNegativeBarPaint();
380: }
381: else if (valDiff > 0.0) {
382: seriesPaint = getPositiveBarPaint();
383: }
384: else {
385: seriesPaint = getLastBarPaint();
386: }
387: }
388: if (getGradientPaintTransformer() != null
389: && seriesPaint instanceof GradientPaint) {
390: GradientPaint gp = (GradientPaint) seriesPaint;
391: seriesPaint = getGradientPaintTransformer().transform(gp, bar);
392: }
393: g2.setPaint(seriesPaint);
394: g2.fill(bar);
395:
396:
397: if (isDrawBarOutline()
398: && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
399: Stroke stroke = getItemOutlineStroke(row, column);
400: Paint paint = getItemOutlinePaint(row, column);
401: if (stroke != null && paint != null) {
402: g2.setStroke(stroke);
403: g2.setPaint(paint);
404: g2.draw(bar);
405: }
406: }
407:
408: CategoryItemLabelGenerator generator
409: = getItemLabelGenerator(row, column);
410: if (generator != null && isItemLabelVisible(row, column)) {
411: drawItemLabel(g2, dataset, row, column, plot, generator, bar,
412: (valDiff < 0.0));
413: }
414:
415:
416: EntityCollection entities = state.getEntityCollection();
417: if (entities != null) {
418: addItemEntity(entities, dataset, row, column, bar);
419: }
420:
421: }
422:
423:
430: public boolean equals(Object obj) {
431:
432: if (obj == this) {
433: return true;
434: }
435: if (!super.equals(obj)) {
436: return false;
437: }
438: if (!(obj instanceof WaterfallBarRenderer)) {
439: return false;
440: }
441: WaterfallBarRenderer that = (WaterfallBarRenderer) obj;
442: if (!PaintUtilities.equal(this.firstBarPaint, that.firstBarPaint)) {
443: return false;
444: }
445: if (!PaintUtilities.equal(this.lastBarPaint, that.lastBarPaint)) {
446: return false;
447: }
448: if (!PaintUtilities.equal(this.positiveBarPaint,
449: that.positiveBarPaint)) {
450: return false;
451: }
452: if (!PaintUtilities.equal(this.negativeBarPaint,
453: that.negativeBarPaint)) {
454: return false;
455: }
456: return true;
457:
458: }
459:
460:
467: private void writeObject(ObjectOutputStream stream) throws IOException {
468: stream.defaultWriteObject();
469: SerialUtilities.writePaint(this.firstBarPaint, stream);
470: SerialUtilities.writePaint(this.lastBarPaint, stream);
471: SerialUtilities.writePaint(this.positiveBarPaint, stream);
472: SerialUtilities.writePaint(this.negativeBarPaint, stream);
473: }
474:
475:
483: private void readObject(ObjectInputStream stream)
484: throws IOException, ClassNotFoundException {
485: stream.defaultReadObject();
486: this.firstBarPaint = SerialUtilities.readPaint(stream);
487: this.lastBarPaint = SerialUtilities.readPaint(stream);
488: this.positiveBarPaint = SerialUtilities.readPaint(stream);
489: this.negativeBarPaint = SerialUtilities.readPaint(stream);
490: }
491:
492: }