1:
55:
56: package ;
57:
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:
82:
88: public class StatisticalBarRenderer extends BarRenderer
89: implements CategoryItemRenderer,
90: Cloneable, PublicCloneable,
91: Serializable {
92:
93:
94: private static final long serialVersionUID = -4986038395414039117L;
95:
96:
97: private transient Paint errorIndicatorPaint;
98:
99:
102: public StatisticalBarRenderer() {
103: super();
104: this.errorIndicatorPaint = Color.gray;
105: }
106:
107:
113: public Paint getErrorIndicatorPaint() {
114: return this.errorIndicatorPaint;
115: }
116:
117:
123: public void setErrorIndicatorPaint(Paint paint) {
124: this.errorIndicatorPaint = paint;
125: notifyListeners(new RendererChangeEvent(this));
126: }
127:
128:
143: public void drawItem(Graphics2D g2,
144: CategoryItemRendererState state,
145: Rectangle2D dataArea,
146: CategoryPlot plot,
147: CategoryAxis domainAxis,
148: ValueAxis rangeAxis,
149: CategoryDataset data,
150: int row,
151: int column,
152: int pass) {
153:
154:
155: if (!(data instanceof StatisticalCategoryDataset)) {
156: throw new IllegalArgumentException(
157: "Requires StatisticalCategoryDataset.");
158: }
159: StatisticalCategoryDataset statData = (StatisticalCategoryDataset) data;
160:
161: PlotOrientation orientation = plot.getOrientation();
162: if (orientation == PlotOrientation.HORIZONTAL) {
163: drawHorizontalItem(g2, state, dataArea, plot, domainAxis,
164: rangeAxis, statData, row, column);
165: }
166: else if (orientation == PlotOrientation.VERTICAL) {
167: drawVerticalItem(g2, state, dataArea, plot, domainAxis, rangeAxis,
168: statData, row, column);
169: }
170: }
171:
172:
185: protected void drawHorizontalItem(Graphics2D g2,
186: CategoryItemRendererState state,
187: Rectangle2D dataArea,
188: CategoryPlot plot,
189: CategoryAxis domainAxis,
190: ValueAxis rangeAxis,
191: StatisticalCategoryDataset dataset,
192: int row,
193: int column) {
194:
195: RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
196:
197:
198: double rectY = domainAxis.getCategoryStart(column, getColumnCount(),
199: dataArea, xAxisLocation);
200:
201: int seriesCount = getRowCount();
202: int categoryCount = getColumnCount();
203: if (seriesCount > 1) {
204: double seriesGap = dataArea.getHeight() * getItemMargin()
205: / (categoryCount * (seriesCount - 1));
206: rectY = rectY + row * (state.getBarWidth() + seriesGap);
207: }
208: else {
209: rectY = rectY + row * state.getBarWidth();
210: }
211:
212:
213: Number meanValue = dataset.getMeanValue(row, column);
214:
215: double value = meanValue.doubleValue();
216: double base = 0.0;
217: double lclip = getLowerClip();
218: double uclip = getUpperClip();
219:
220: if (uclip <= 0.0) {
221: if (value >= uclip) {
222: return;
223: }
224: base = uclip;
225: if (value <= lclip) {
226: value = lclip;
227: }
228: }
229: else if (lclip <= 0.0) {
230: if (value >= uclip) {
231: value = uclip;
232: }
233: else {
234: if (value <= lclip) {
235: value = lclip;
236: }
237: }
238: }
239: else {
240: if (value <= lclip) {
241: return;
242: }
243: base = getLowerClip();
244: if (value >= uclip) {
245: value = uclip;
246: }
247: }
248:
249: RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
250: double transY1 = rangeAxis.valueToJava2D(base, dataArea, yAxisLocation);
251: double transY2 = rangeAxis.valueToJava2D(value, dataArea,
252: yAxisLocation);
253: double rectX = Math.min(transY2, transY1);
254:
255: double rectHeight = state.getBarWidth();
256: double rectWidth = Math.abs(transY2 - transY1);
257:
258: Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth,
259: rectHeight);
260: Paint seriesPaint = getItemPaint(row, column);
261: g2.setPaint(seriesPaint);
262: g2.fill(bar);
263: if (state.getBarWidth() > 3) {
264: g2.setStroke(getItemStroke(row, column));
265: g2.setPaint(getItemOutlinePaint(row, column));
266: g2.draw(bar);
267: }
268:
269:
270: double valueDelta = dataset.getStdDevValue(row, column).doubleValue();
271: double highVal = rangeAxis.valueToJava2D(meanValue.doubleValue()
272: + valueDelta, dataArea, yAxisLocation);
273: double lowVal = rangeAxis.valueToJava2D(meanValue.doubleValue()
274: - valueDelta, dataArea, yAxisLocation);
275:
276: if (this.errorIndicatorPaint != null) {
277: g2.setPaint(this.errorIndicatorPaint);
278: }
279: else {
280: g2.setPaint(getItemOutlinePaint(row, column));
281: }
282: Line2D line = null;
283: line = new Line2D.Double(lowVal, rectY + rectHeight / 2.0d,
284: highVal, rectY + rectHeight / 2.0d);
285: g2.draw(line);
286: line = new Line2D.Double(highVal, rectY + rectHeight * 0.25,
287: highVal, rectY + rectHeight * 0.75);
288: g2.draw(line);
289: line = new Line2D.Double(lowVal, rectY + rectHeight * 0.25,
290: lowVal, rectY + rectHeight * 0.75);
291: g2.draw(line);
292:
293: CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
294: column);
295: if (generator != null && isItemLabelVisible(row, column)) {
296: drawItemLabel(g2, dataset, row, column, plot, generator, bar,
297: (value < 0.0));
298: }
299:
300:
301: EntityCollection entities = state.getEntityCollection();
302: if (entities != null) {
303: addItemEntity(entities, dataset, row, column, bar);
304: }
305:
306: }
307:
308:
321: protected void drawVerticalItem(Graphics2D g2,
322: CategoryItemRendererState state,
323: Rectangle2D dataArea,
324: CategoryPlot plot,
325: CategoryAxis domainAxis,
326: ValueAxis rangeAxis,
327: StatisticalCategoryDataset dataset,
328: int row,
329: int column) {
330:
331: RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
332:
333:
334: double rectX = domainAxis.getCategoryStart(
335: column, getColumnCount(), dataArea, xAxisLocation
336: );
337:
338: int seriesCount = getRowCount();
339: int categoryCount = getColumnCount();
340: if (seriesCount > 1) {
341: double seriesGap = dataArea.getWidth() * getItemMargin()
342: / (categoryCount * (seriesCount - 1));
343: rectX = rectX + row * (state.getBarWidth() + seriesGap);
344: }
345: else {
346: rectX = rectX + row * state.getBarWidth();
347: }
348:
349:
350: Number meanValue = dataset.getMeanValue(row, column);
351:
352: double value = meanValue.doubleValue();
353: double base = 0.0;
354: double lclip = getLowerClip();
355: double uclip = getUpperClip();
356:
357: if (uclip <= 0.0) {
358: if (value >= uclip) {
359: return;
360: }
361: base = uclip;
362: if (value <= lclip) {
363: value = lclip;
364: }
365: }
366: else if (lclip <= 0.0) {
367: if (value >= uclip) {
368: value = uclip;
369: }
370: else {
371: if (value <= lclip) {
372: value = lclip;
373: }
374: }
375: }
376: else {
377: if (value <= lclip) {
378: return;
379: }
380: base = getLowerClip();
381: if (value >= uclip) {
382: value = uclip;
383: }
384: }
385:
386: RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
387: double transY1 = rangeAxis.valueToJava2D(base, dataArea, yAxisLocation);
388: double transY2 = rangeAxis.valueToJava2D(value, dataArea,
389: yAxisLocation);
390: double rectY = Math.min(transY2, transY1);
391:
392: double rectWidth = state.getBarWidth();
393: double rectHeight = Math.abs(transY2 - transY1);
394:
395: Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth,
396: rectHeight);
397: Paint seriesPaint = getItemPaint(row, column);
398: g2.setPaint(seriesPaint);
399: g2.fill(bar);
400: if (state.getBarWidth() > 3) {
401: g2.setStroke(getItemStroke(row, column));
402: g2.setPaint(getItemOutlinePaint(row, column));
403: g2.draw(bar);
404: }
405:
406:
407: double valueDelta = dataset.getStdDevValue(row, column).doubleValue();
408: double highVal = rangeAxis.valueToJava2D(meanValue.doubleValue()
409: + valueDelta, dataArea, yAxisLocation);
410: double lowVal = rangeAxis.valueToJava2D(meanValue.doubleValue()
411: - valueDelta, dataArea, yAxisLocation);
412:
413: if (this.errorIndicatorPaint != null) {
414: g2.setPaint(this.errorIndicatorPaint);
415: }
416: else {
417: g2.setPaint(getItemOutlinePaint(row, column));
418: }
419: Line2D line = null;
420: line = new Line2D.Double(rectX + rectWidth / 2.0d, lowVal,
421: rectX + rectWidth / 2.0d, highVal);
422: g2.draw(line);
423: line = new Line2D.Double(rectX + rectWidth / 2.0d - 5.0d, highVal,
424: rectX + rectWidth / 2.0d + 5.0d, highVal);
425: g2.draw(line);
426: line = new Line2D.Double(rectX + rectWidth / 2.0d - 5.0d, lowVal,
427: rectX + rectWidth / 2.0d + 5.0d, lowVal);
428: g2.draw(line);
429:
430: CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
431: column);
432: if (generator != null && isItemLabelVisible(row, column)) {
433: drawItemLabel(g2, dataset, row, column, plot, generator, bar,
434: (value < 0.0));
435: }
436:
437:
438: EntityCollection entities = state.getEntityCollection();
439: if (entities != null) {
440: addItemEntity(entities, dataset, row, column, bar);
441: }
442: }
443:
444:
451: public boolean equals(Object obj) {
452: if (obj == this) {
453: return true;
454: }
455: if (!(obj instanceof StatisticalBarRenderer)) {
456: return false;
457: }
458: if (!super.equals(obj)) {
459: return false;
460: }
461: StatisticalBarRenderer that = (StatisticalBarRenderer) obj;
462: if (!PaintUtilities.equal(this.errorIndicatorPaint,
463: that.errorIndicatorPaint)) {
464: return false;
465: }
466: return true;
467: }
468:
469:
476: private void writeObject(ObjectOutputStream stream) throws IOException {
477: stream.defaultWriteObject();
478: SerialUtilities.writePaint(this.errorIndicatorPaint, stream);
479: }
480:
481:
489: private void readObject(ObjectInputStream stream)
490: throws IOException, ClassNotFoundException {
491: stream.defaultReadObject();
492: this.errorIndicatorPaint = SerialUtilities.readPaint(stream);
493: }
494:
495: }