1:
95:
96: package ;
97:
98: import ;
99: import ;
100: import ;
101: import ;
102: import ;
103: import ;
104: import ;
105: import ;
106: import ;
107: import ;
108: import ;
109: import ;
110:
111: import ;
112: import ;
113: import ;
114: import ;
115: import ;
116: import ;
117: import ;
118: import ;
119: import ;
120: import ;
121: import ;
122: import ;
123: import ;
124: import ;
125: import ;
126: import ;
127: import ;
128: import ;
129: import ;
130: import ;
131: import ;
132: import ;
133: import ;
134: import ;
135:
136:
140: public class XYBarRenderer extends AbstractXYItemRenderer
141: implements XYItemRenderer, Cloneable, PublicCloneable, Serializable {
142:
143:
144: private static final long serialVersionUID = 770559577251370036L;
145:
146:
149: protected class XYBarRendererState extends XYItemRendererState {
150:
151:
152: private double g2Base;
153:
154:
159: public XYBarRendererState(PlotRenderingInfo info) {
160: super(info);
161: }
162:
163:
168: public double getG2Base() {
169: return this.g2Base;
170: }
171:
172:
177: public void setG2Base(double value) {
178: this.g2Base = value;
179: }
180: }
181:
182:
183: private double base;
184:
185:
189: private boolean useYInterval;
190:
191:
192: private double margin;
193:
194:
195: private boolean drawBarOutline;
196:
197:
201: private GradientPaintTransformer gradientPaintTransformer;
202:
203:
207: private transient Shape legendBar;
208:
209:
213: private ItemLabelPosition positiveItemLabelPositionFallback;
214:
215:
219: private ItemLabelPosition negativeItemLabelPositionFallback;
220:
221:
224: public XYBarRenderer() {
225: this(0.0);
226: }
227:
228:
233: public XYBarRenderer(double margin) {
234: super();
235: this.margin = margin;
236: this.base = 0.0;
237: this.useYInterval = false;
238: this.gradientPaintTransformer = new StandardGradientPaintTransformer();
239: this.drawBarOutline = false;
240: this.legendBar = new Rectangle2D.Double(-3.0, -5.0, 6.0, 10.0);
241: }
242:
243:
250: public double getBase() {
251: return this.base;
252: }
253:
254:
264: public void setBase(double base) {
265: this.base = base;
266: fireChangeEvent();
267: }
268:
269:
277: public boolean getUseYInterval() {
278: return this.useYInterval;
279: }
280:
281:
290: public void setUseYInterval(boolean use) {
291: if (this.useYInterval != use) {
292: this.useYInterval = use;
293: fireChangeEvent();
294: }
295: }
296:
297:
305: public double getMargin() {
306: return this.margin;
307: }
308:
309:
317: public void setMargin(double margin) {
318: this.margin = margin;
319: fireChangeEvent();
320: }
321:
322:
329: public boolean isDrawBarOutline() {
330: return this.drawBarOutline;
331: }
332:
333:
341: public void setDrawBarOutline(boolean draw) {
342: this.drawBarOutline = draw;
343: fireChangeEvent();
344: }
345:
346:
354: public GradientPaintTransformer getGradientPaintTransformer() {
355: return this.gradientPaintTransformer;
356: }
357:
358:
366: public void setGradientPaintTransformer(
367: GradientPaintTransformer transformer) {
368: this.gradientPaintTransformer = transformer;
369: fireChangeEvent();
370: }
371:
372:
380: public Shape getLegendBar() {
381: return this.legendBar;
382: }
383:
384:
392: public void setLegendBar(Shape bar) {
393: if (bar == null) {
394: throw new IllegalArgumentException("Null 'bar' argument.");
395: }
396: this.legendBar = bar;
397: fireChangeEvent();
398: }
399:
400:
409: public ItemLabelPosition getPositiveItemLabelPositionFallback() {
410: return this.positiveItemLabelPositionFallback;
411: }
412:
413:
423: public void setPositiveItemLabelPositionFallback(
424: ItemLabelPosition position) {
425: this.positiveItemLabelPositionFallback = position;
426: fireChangeEvent();
427: }
428:
429:
438: public ItemLabelPosition getNegativeItemLabelPositionFallback() {
439: return this.negativeItemLabelPositionFallback;
440: }
441:
442:
452: public void setNegativeItemLabelPositionFallback(
453: ItemLabelPosition position) {
454: this.negativeItemLabelPositionFallback = position;
455: fireChangeEvent();
456: }
457:
458:
473: public XYItemRendererState initialise(Graphics2D g2, Rectangle2D dataArea,
474: XYPlot plot, XYDataset dataset, PlotRenderingInfo info) {
475:
476: XYBarRendererState state = new XYBarRendererState(info);
477: ValueAxis rangeAxis = plot.getRangeAxisForDataset(plot.indexOf(
478: dataset));
479: state.setG2Base(rangeAxis.valueToJava2D(this.base, dataArea,
480: plot.getRangeAxisEdge()));
481: return state;
482:
483: }
484:
485:
494: public LegendItem getLegendItem(int datasetIndex, int series) {
495: LegendItem result = null;
496: XYPlot xyplot = getPlot();
497: if (xyplot != null) {
498: XYDataset dataset = xyplot.getDataset(datasetIndex);
499: if (dataset != null) {
500: XYSeriesLabelGenerator lg = getLegendItemLabelGenerator();
501: String label = lg.generateLabel(dataset, series);
502: String description = label;
503: String toolTipText = null;
504: if (getLegendItemToolTipGenerator() != null) {
505: toolTipText = getLegendItemToolTipGenerator().generateLabel(
506: dataset, series);
507: }
508: String urlText = null;
509: if (getLegendItemURLGenerator() != null) {
510: urlText = getLegendItemURLGenerator().generateLabel(
511: dataset, series);
512: }
513: Shape shape = this.legendBar;
514: Paint paint = lookupSeriesPaint(series);
515: Paint outlinePaint = lookupSeriesOutlinePaint(series);
516: Stroke outlineStroke = lookupSeriesOutlineStroke(series);
517: if (this.drawBarOutline) {
518: result = new LegendItem(label, description, toolTipText,
519: urlText, shape, paint, outlineStroke, outlinePaint);
520: }
521: else {
522: result = new LegendItem(label, description, toolTipText,
523: urlText, shape, paint);
524: }
525: result.setDataset(dataset);
526: result.setDatasetIndex(datasetIndex);
527: result.setSeriesKey(dataset.getSeriesKey(series));
528: result.setSeriesIndex(series);
529: if (getGradientPaintTransformer() != null) {
530: result.setFillPaintTransformer(
531: getGradientPaintTransformer());
532: }
533: }
534: }
535: return result;
536: }
537:
538:
556: public void drawItem(Graphics2D g2,
557: XYItemRendererState state,
558: Rectangle2D dataArea,
559: PlotRenderingInfo info,
560: XYPlot plot,
561: ValueAxis domainAxis,
562: ValueAxis rangeAxis,
563: XYDataset dataset,
564: int series,
565: int item,
566: CrosshairState crosshairState,
567: int pass) {
568:
569: if (!getItemVisible(series, item)) {
570: return;
571: }
572: IntervalXYDataset intervalDataset = (IntervalXYDataset) dataset;
573:
574: double value0;
575: double value1;
576: if (this.useYInterval) {
577: value0 = intervalDataset.getStartYValue(series, item);
578: value1 = intervalDataset.getEndYValue(series, item);
579: }
580: else {
581: value0 = this.base;
582: value1 = intervalDataset.getYValue(series, item);
583: }
584: if (Double.isNaN(value0) || Double.isNaN(value1)) {
585: return;
586: }
587: if (value0 <= value1) {
588: if (!rangeAxis.getRange().intersects(value0, value1)) {
589: return;
590: }
591: }
592: else {
593: if (!rangeAxis.getRange().intersects(value1, value0)) {
594: return;
595: }
596: }
597:
598: double translatedValue0 = rangeAxis.valueToJava2D(value0, dataArea,
599: plot.getRangeAxisEdge());
600: double translatedValue1 = rangeAxis.valueToJava2D(value1, dataArea,
601: plot.getRangeAxisEdge());
602: double bottom = Math.min(translatedValue0, translatedValue1);
603: double top = Math.max(translatedValue0, translatedValue1);
604:
605: double startX = intervalDataset.getStartXValue(series, item);
606: if (Double.isNaN(startX)) {
607: return;
608: }
609: double endX = intervalDataset.getEndXValue(series, item);
610: if (Double.isNaN(endX)) {
611: return;
612: }
613: if (startX <= endX) {
614: if (!domainAxis.getRange().intersects(startX, endX)) {
615: return;
616: }
617: }
618: else {
619: if (!domainAxis.getRange().intersects(endX, startX)) {
620: return;
621: }
622: }
623:
624: RectangleEdge location = plot.getDomainAxisEdge();
625: double translatedStartX = domainAxis.valueToJava2D(startX, dataArea,
626: location);
627: double translatedEndX = domainAxis.valueToJava2D(endX, dataArea,
628: location);
629:
630: double translatedWidth = Math.max(1, Math.abs(translatedEndX
631: - translatedStartX));
632:
633: double left = Math.min(translatedStartX, translatedEndX);
634: if (getMargin() > 0.0) {
635: double cut = translatedWidth * getMargin();
636: translatedWidth = translatedWidth - cut;
637: left = left + cut / 2;
638: }
639:
640: Rectangle2D bar = null;
641: PlotOrientation orientation = plot.getOrientation();
642: if (orientation == PlotOrientation.HORIZONTAL) {
643:
644: bottom = Math.max(bottom, dataArea.getMinX());
645: top = Math.min(top, dataArea.getMaxX());
646: bar = new Rectangle2D.Double(
647: bottom, left, top - bottom, translatedWidth);
648: }
649: else if (orientation == PlotOrientation.VERTICAL) {
650:
651: bottom = Math.max(bottom, dataArea.getMinY());
652: top = Math.min(top, dataArea.getMaxY());
653: bar = new Rectangle2D.Double(left, bottom, translatedWidth,
654: top - bottom);
655: }
656:
657: Paint itemPaint = getItemPaint(series, item);
658: if (getGradientPaintTransformer()
659: != null && itemPaint instanceof GradientPaint) {
660: GradientPaint gp = (GradientPaint) itemPaint;
661: itemPaint = getGradientPaintTransformer().transform(gp, bar);
662: }
663: g2.setPaint(itemPaint);
664: g2.fill(bar);
665: if (isDrawBarOutline()
666: && Math.abs(translatedEndX - translatedStartX) > 3) {
667: Stroke stroke = getItemOutlineStroke(series, item);
668: Paint paint = getItemOutlinePaint(series, item);
669: if (stroke != null && paint != null) {
670: g2.setStroke(stroke);
671: g2.setPaint(paint);
672: g2.draw(bar);
673: }
674: }
675:
676: if (isItemLabelVisible(series, item)) {
677: XYItemLabelGenerator generator = getItemLabelGenerator(series,
678: item);
679: drawItemLabel(g2, dataset, series, item, plot, generator, bar,
680: value1 < 0.0);
681: }
682:
683:
684: double x1 = (startX + endX) / 2.0;
685: double y1 = dataset.getYValue(series, item);
686: double transX1 = domainAxis.valueToJava2D(x1, dataArea, location);
687: double transY1 = rangeAxis.valueToJava2D(y1, dataArea,
688: plot.getRangeAxisEdge());
689: int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
690: int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
691: updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex,
692: rangeAxisIndex, transX1, transY1, plot.getOrientation());
693:
694: EntityCollection entities = state.getEntityCollection();
695: if (entities != null) {
696: addEntity(entities, bar, dataset, series, item, 0.0, 0.0);
697: }
698:
699: }
700:
701:
717: protected void drawItemLabel(Graphics2D g2, XYDataset dataset,
718: int series, int item, XYPlot plot, XYItemLabelGenerator generator,
719: Rectangle2D bar, boolean negative) {
720:
721: if (generator == null) {
722: return;
723: }
724: String label = generator.generateLabel(dataset, series, item);
725: if (label == null) {
726: return;
727: }
728:
729: Font labelFont = getItemLabelFont(series, item);
730: g2.setFont(labelFont);
731: Paint paint = getItemLabelPaint(series, item);
732: g2.setPaint(paint);
733:
734:
735: ItemLabelPosition position = null;
736: if (!negative) {
737: position = getPositiveItemLabelPosition(series, item);
738: }
739: else {
740: position = getNegativeItemLabelPosition(series, item);
741: }
742:
743:
744: Point2D anchorPoint = calculateLabelAnchorPoint(
745: position.getItemLabelAnchor(), bar, plot.getOrientation());
746:
747: if (isInternalAnchor(position.getItemLabelAnchor())) {
748: Shape bounds = TextUtilities.calculateRotatedStringBounds(label,
749: g2, (float) anchorPoint.getX(), (float) anchorPoint.getY(),
750: position.getTextAnchor(), position.getAngle(),
751: position.getRotationAnchor());
752:
753: if (bounds != null) {
754: if (!bar.contains(bounds.getBounds2D())) {
755: if (!negative) {
756: position = getPositiveItemLabelPositionFallback();
757: }
758: else {
759: position = getNegativeItemLabelPositionFallback();
760: }
761: if (position != null) {
762: anchorPoint = calculateLabelAnchorPoint(
763: position.getItemLabelAnchor(), bar,
764: plot.getOrientation());
765: }
766: }
767: }
768:
769: }
770:
771: if (position != null) {
772: TextUtilities.drawRotatedString(label, g2,
773: (float) anchorPoint.getX(), (float) anchorPoint.getY(),
774: position.getTextAnchor(), position.getAngle(),
775: position.getRotationAnchor());
776: }
777: }
778:
779:
788: private Point2D calculateLabelAnchorPoint(ItemLabelAnchor anchor,
789: Rectangle2D bar, PlotOrientation orientation) {
790:
791: Point2D result = null;
792: double offset = getItemLabelAnchorOffset();
793: double x0 = bar.getX() - offset;
794: double x1 = bar.getX();
795: double x2 = bar.getX() + offset;
796: double x3 = bar.getCenterX();
797: double x4 = bar.getMaxX() - offset;
798: double x5 = bar.getMaxX();
799: double x6 = bar.getMaxX() + offset;
800:
801: double y0 = bar.getMaxY() + offset;
802: double y1 = bar.getMaxY();
803: double y2 = bar.getMaxY() - offset;
804: double y3 = bar.getCenterY();
805: double y4 = bar.getMinY() + offset;
806: double y5 = bar.getMinY();
807: double y6 = bar.getMinY() - offset;
808:
809: if (anchor == ItemLabelAnchor.CENTER) {
810: result = new Point2D.Double(x3, y3);
811: }
812: else if (anchor == ItemLabelAnchor.INSIDE1) {
813: result = new Point2D.Double(x4, y4);
814: }
815: else if (anchor == ItemLabelAnchor.INSIDE2) {
816: result = new Point2D.Double(x4, y4);
817: }
818: else if (anchor == ItemLabelAnchor.INSIDE3) {
819: result = new Point2D.Double(x4, y3);
820: }
821: else if (anchor == ItemLabelAnchor.INSIDE4) {
822: result = new Point2D.Double(x4, y2);
823: }
824: else if (anchor == ItemLabelAnchor.INSIDE5) {
825: result = new Point2D.Double(x4, y2);
826: }
827: else if (anchor == ItemLabelAnchor.INSIDE6) {
828: result = new Point2D.Double(x3, y2);
829: }
830: else if (anchor == ItemLabelAnchor.INSIDE7) {
831: result = new Point2D.Double(x2, y2);
832: }
833: else if (anchor == ItemLabelAnchor.INSIDE8) {
834: result = new Point2D.Double(x2, y2);
835: }
836: else if (anchor == ItemLabelAnchor.INSIDE9) {
837: result = new Point2D.Double(x2, y3);
838: }
839: else if (anchor == ItemLabelAnchor.INSIDE10) {
840: result = new Point2D.Double(x2, y4);
841: }
842: else if (anchor == ItemLabelAnchor.INSIDE11) {
843: result = new Point2D.Double(x2, y4);
844: }
845: else if (anchor == ItemLabelAnchor.INSIDE12) {
846: result = new Point2D.Double(x3, y4);
847: }
848: else if (anchor == ItemLabelAnchor.OUTSIDE1) {
849: result = new Point2D.Double(x5, y6);
850: }
851: else if (anchor == ItemLabelAnchor.OUTSIDE2) {
852: result = new Point2D.Double(x6, y5);
853: }
854: else if (anchor == ItemLabelAnchor.OUTSIDE3) {
855: result = new Point2D.Double(x6, y3);
856: }
857: else if (anchor == ItemLabelAnchor.OUTSIDE4) {
858: result = new Point2D.Double(x6, y1);
859: }
860: else if (anchor == ItemLabelAnchor.OUTSIDE5) {
861: result = new Point2D.Double(x5, y0);
862: }
863: else if (anchor == ItemLabelAnchor.OUTSIDE6) {
864: result = new Point2D.Double(x3, y0);
865: }
866: else if (anchor == ItemLabelAnchor.OUTSIDE7) {
867: result = new Point2D.Double(x1, y0);
868: }
869: else if (anchor == ItemLabelAnchor.OUTSIDE8) {
870: result = new Point2D.Double(x0, y1);
871: }
872: else if (anchor == ItemLabelAnchor.OUTSIDE9) {
873: result = new Point2D.Double(x0, y3);
874: }
875: else if (anchor == ItemLabelAnchor.OUTSIDE10) {
876: result = new Point2D.Double(x0, y5);
877: }
878: else if (anchor == ItemLabelAnchor.OUTSIDE11) {
879: result = new Point2D.Double(x1, y6);
880: }
881: else if (anchor == ItemLabelAnchor.OUTSIDE12) {
882: result = new Point2D.Double(x3, y6);
883: }
884:
885: return result;
886:
887: }
888:
889:
896: private boolean isInternalAnchor(ItemLabelAnchor anchor) {
897: return anchor == ItemLabelAnchor.CENTER
898: || anchor == ItemLabelAnchor.INSIDE1
899: || anchor == ItemLabelAnchor.INSIDE2
900: || anchor == ItemLabelAnchor.INSIDE3
901: || anchor == ItemLabelAnchor.INSIDE4
902: || anchor == ItemLabelAnchor.INSIDE5
903: || anchor == ItemLabelAnchor.INSIDE6
904: || anchor == ItemLabelAnchor.INSIDE7
905: || anchor == ItemLabelAnchor.INSIDE8
906: || anchor == ItemLabelAnchor.INSIDE9
907: || anchor == ItemLabelAnchor.INSIDE10
908: || anchor == ItemLabelAnchor.INSIDE11
909: || anchor == ItemLabelAnchor.INSIDE12;
910: }
911:
912:
922: public Range findDomainBounds(XYDataset dataset) {
923: if (dataset != null) {
924: return DatasetUtilities.findDomainBounds(dataset, true);
925: }
926: else {
927: return null;
928: }
929: }
930:
931:
938: public Object clone() throws CloneNotSupportedException {
939: XYBarRenderer result = (XYBarRenderer) super.clone();
940: if (this.gradientPaintTransformer != null) {
941: result.gradientPaintTransformer = (GradientPaintTransformer)
942: ObjectUtilities.clone(this.gradientPaintTransformer);
943: }
944: result.legendBar = ShapeUtilities.clone(this.legendBar);
945: return result;
946: }
947:
948:
955: public boolean equals(Object obj) {
956: if (obj == this) {
957: return true;
958: }
959: if (!(obj instanceof XYBarRenderer)) {
960: return false;
961: }
962: if (!super.equals(obj)) {
963: return false;
964: }
965: XYBarRenderer that = (XYBarRenderer) obj;
966: if (this.base != that.base) {
967: return false;
968: }
969: if (this.drawBarOutline != that.drawBarOutline) {
970: return false;
971: }
972: if (this.margin != that.margin) {
973: return false;
974: }
975: if (this.useYInterval != that.useYInterval) {
976: return false;
977: }
978: if (!ObjectUtilities.equal(
979: this.gradientPaintTransformer, that.gradientPaintTransformer)
980: ) {
981: return false;
982: }
983: if (!ShapeUtilities.equal(this.legendBar, that.legendBar)) {
984: return false;
985: }
986: if (!ObjectUtilities.equal(this.positiveItemLabelPositionFallback,
987: that.positiveItemLabelPositionFallback)) {
988: return false;
989: }
990: if (!ObjectUtilities.equal(this.negativeItemLabelPositionFallback,
991: that.negativeItemLabelPositionFallback)) {
992: return false;
993: }
994: return true;
995: }
996:
997:
1005: private void readObject(ObjectInputStream stream)
1006: throws IOException, ClassNotFoundException {
1007: stream.defaultReadObject();
1008: this.legendBar = SerialUtilities.readShape(stream);
1009: }
1010:
1011:
1018: private void writeObject(ObjectOutputStream stream) throws IOException {
1019: stream.defaultWriteObject();
1020: SerialUtilities.writeShape(this.legendBar, stream);
1021: }
1022:
1023: }