1:
54:
55: package ;
56:
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67:
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: import ;
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:
328: double j2dy0 = rangeAxis.valueToJava2D(
329: previous, dataArea, rangeAxisLocation
330: );
331:
332:
333: 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:
345: double rectWidth = state.getBarWidth();
346:
347:
348: double rectHeight = Math.max(
349: getMinimumBarLength(), Math.abs(j2dy1 - j2dy0)
350: );
351:
352: if (orientation == PlotOrientation.HORIZONTAL) {
353:
354: 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:
375: 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:
420: 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:
440: 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: }