1:
52:
53: package ;
54:
55: import ;
56: import ;
57: import ;
58: import ;
59:
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77:
78:
86: public class StackedXYBarRenderer extends XYBarRenderer {
87:
88:
89: private static final long serialVersionUID = -7049101055533436444L;
90:
91:
92: private boolean renderAsPercentages;
93:
94:
97: public StackedXYBarRenderer() {
98: this(0.0);
99: }
100:
101:
106: public StackedXYBarRenderer(double margin) {
107: super(margin);
108: this.renderAsPercentages = false;
109:
110:
111:
112: ItemLabelPosition p = new ItemLabelPosition(ItemLabelAnchor.CENTER,
113: TextAnchor.CENTER);
114: setBasePositiveItemLabelPosition(p);
115: setBaseNegativeItemLabelPosition(p);
116: setPositiveItemLabelPositionFallback(null);
117: setNegativeItemLabelPositionFallback(null);
118: }
119:
120:
131: public boolean getRenderAsPercentages() {
132: return this.renderAsPercentages;
133: }
134:
135:
146: public void setRenderAsPercentages(boolean asPercentages) {
147: this.renderAsPercentages = asPercentages;
148: fireChangeEvent();
149: }
150:
151:
158: public int getPassCount() {
159: return 2;
160: }
161:
162:
176: public XYItemRendererState initialise(Graphics2D g2,
177: Rectangle2D dataArea,
178: XYPlot plot,
179: XYDataset data,
180: PlotRenderingInfo info) {
181: return new XYBarRendererState(info);
182: }
183:
184:
193: public Range findRangeBounds(XYDataset dataset) {
194: if (dataset != null) {
195: if (this.renderAsPercentages) {
196: return new Range(0.0, 1.0);
197: }
198: else {
199: return DatasetUtilities.findStackedRangeBounds(
200: (TableXYDataset) dataset);
201: }
202: }
203: else {
204: return null;
205: }
206: }
207:
208:
226: public void drawItem(Graphics2D g2,
227: XYItemRendererState state,
228: Rectangle2D dataArea,
229: PlotRenderingInfo info,
230: XYPlot plot,
231: ValueAxis domainAxis,
232: ValueAxis rangeAxis,
233: XYDataset dataset,
234: int series,
235: int item,
236: CrosshairState crosshairState,
237: int pass) {
238:
239: if (!(dataset instanceof IntervalXYDataset
240: && dataset instanceof TableXYDataset)) {
241: String message = "dataset (type " + dataset.getClass().getName()
242: + ") has wrong type:";
243: boolean and = false;
244: if (!IntervalXYDataset.class.isAssignableFrom(dataset.getClass())) {
245: message += " it is no IntervalXYDataset";
246: and = true;
247: }
248: if (!TableXYDataset.class.isAssignableFrom(dataset.getClass())) {
249: if (and) {
250: message += " and";
251: }
252: message += " it is no TableXYDataset";
253: }
254:
255: throw new IllegalArgumentException(message);
256: }
257:
258: IntervalXYDataset intervalDataset = (IntervalXYDataset) dataset;
259: double value = intervalDataset.getYValue(series, item);
260: if (Double.isNaN(value)) {
261: return;
262: }
263:
264:
265:
266:
267:
268:
269:
270:
271: double total = 0.0;
272: if (this.renderAsPercentages) {
273: total = DatasetUtilities.calculateStackTotal(
274: (TableXYDataset) dataset, item);
275: value = value / total;
276: }
277:
278: double positiveBase = 0.0;
279: double negativeBase = 0.0;
280:
281: for (int i = 0; i < series; i++) {
282: double v = dataset.getYValue(i, item);
283: if (!Double.isNaN(v)) {
284: if (this.renderAsPercentages) {
285: v = v / total;
286: }
287: if (v > 0) {
288: positiveBase = positiveBase + v;
289: }
290: else {
291: negativeBase = negativeBase + v;
292: }
293: }
294: }
295:
296: double translatedBase;
297: double translatedValue;
298: RectangleEdge edgeR = plot.getRangeAxisEdge();
299: if (value > 0.0) {
300: translatedBase = rangeAxis.valueToJava2D(positiveBase, dataArea,
301: edgeR);
302: translatedValue = rangeAxis.valueToJava2D(positiveBase + value,
303: dataArea, edgeR);
304: }
305: else {
306: translatedBase = rangeAxis.valueToJava2D(negativeBase, dataArea,
307: edgeR);
308: translatedValue = rangeAxis.valueToJava2D(negativeBase + value,
309: dataArea, edgeR);
310: }
311:
312: RectangleEdge edgeD = plot.getDomainAxisEdge();
313: double startX = intervalDataset.getStartXValue(series, item);
314: if (Double.isNaN(startX)) {
315: return;
316: }
317: double translatedStartX = domainAxis.valueToJava2D(startX, dataArea,
318: edgeD);
319:
320: double endX = intervalDataset.getEndXValue(series, item);
321: if (Double.isNaN(endX)) {
322: return;
323: }
324: double translatedEndX = domainAxis.valueToJava2D(endX, dataArea, edgeD);
325:
326: double translatedWidth = Math.max(1, Math.abs(translatedEndX
327: - translatedStartX));
328: double translatedHeight = Math.abs(translatedValue - translatedBase);
329: if (getMargin() > 0.0) {
330: double cut = translatedWidth * getMargin();
331: translatedWidth = translatedWidth - cut;
332: translatedStartX = translatedStartX + cut / 2;
333: }
334:
335: Rectangle2D bar = null;
336: PlotOrientation orientation = plot.getOrientation();
337: if (orientation == PlotOrientation.HORIZONTAL) {
338: bar = new Rectangle2D.Double(Math.min(translatedBase,
339: translatedValue), translatedEndX, translatedHeight,
340: translatedWidth);
341: }
342: else if (orientation == PlotOrientation.VERTICAL) {
343: bar = new Rectangle2D.Double(translatedStartX,
344: Math.min(translatedBase, translatedValue),
345: translatedWidth, translatedHeight);
346: }
347:
348: if (pass == 0) {
349: Paint itemPaint = getItemPaint(series, item);
350: if (getGradientPaintTransformer()
351: != null && itemPaint instanceof GradientPaint) {
352: GradientPaint gp = (GradientPaint) itemPaint;
353: itemPaint = getGradientPaintTransformer().transform(gp, bar);
354: }
355: g2.setPaint(itemPaint);
356: g2.fill(bar);
357: if (isDrawBarOutline()
358: && Math.abs(translatedEndX - translatedStartX) > 3) {
359: g2.setStroke(getItemStroke(series, item));
360: g2.setPaint(getItemOutlinePaint(series, item));
361: g2.draw(bar);
362: }
363:
364:
365: if (info != null) {
366: EntityCollection entities = info.getOwner()
367: .getEntityCollection();
368: if (entities != null) {
369: addEntity(entities, bar, dataset, series, item,
370: bar.getCenterX(), bar.getCenterY());
371: }
372: }
373: }
374: else if (pass == 1) {
375:
376:
377: if (isItemLabelVisible(series, item)) {
378: XYItemLabelGenerator generator = getItemLabelGenerator(series,
379: item);
380: drawItemLabel(g2, dataset, series, item, plot, generator, bar,
381: value < 0.0);
382: }
383: }
384:
385: }
386:
387:
394: public boolean equals(Object obj) {
395: if (obj == this) {
396: return true;
397: }
398: if (!(obj instanceof StackedXYBarRenderer)) {
399: return false;
400: }
401: StackedXYBarRenderer that = (StackedXYBarRenderer) obj;
402: if (this.renderAsPercentages != that.renderAsPercentages) {
403: return false;
404: }
405: return super.equals(obj);
406: }
407:
408:
413: public int hashCode() {
414: int result = super.hashCode();
415: result = result * 37 + (this.renderAsPercentages ? 1 : 0);
416: return result;
417: }
418:
419: }