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