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