1:
109:
110: package ;
111:
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:
128: import ;
129: import ;
130: import ;
131: import ;
132: import ;
133: import ;
134: import ;
135: import ;
136: import ;
137: import ;
138: import ;
139: import ;
140: import ;
141: import ;
142: import ;
143: import ;
144: import ;
145: import ;
146: import ;
147: import ;
148: import ;
149: import ;
150: import ;
151: import ;
152: import ;
153: import ;
154: import ;
155: import ;
156: import ;
157: import ;
158: import ;
159: import ;
160: import ;
161: import ;
162: import ;
163:
164:
168: public abstract class AbstractXYItemRenderer extends AbstractRenderer
169: implements XYItemRenderer, Cloneable, Serializable {
170:
171:
172: private static final long serialVersionUID = 8019124836026607990L;
173:
174:
175: private XYPlot plot;
176:
177:
183: private XYItemLabelGenerator itemLabelGenerator;
184:
185:
186: private ObjectList itemLabelGeneratorList;
187:
188:
189: private XYItemLabelGenerator baseItemLabelGenerator;
190:
191:
197: private XYToolTipGenerator toolTipGenerator;
198:
199:
200: private ObjectList toolTipGeneratorList;
201:
202:
203: private XYToolTipGenerator baseToolTipGenerator;
204:
205:
206: private XYURLGenerator urlGenerator;
207:
208:
212: private List backgroundAnnotations;
213:
214:
218: private List foregroundAnnotations;
219:
220:
221: private int defaultEntityRadius;
222:
223:
224: private XYSeriesLabelGenerator legendItemLabelGenerator;
225:
226:
227: private XYSeriesLabelGenerator legendItemToolTipGenerator;
228:
229:
230: private XYSeriesLabelGenerator legendItemURLGenerator;
231:
232:
236: protected AbstractXYItemRenderer() {
237: super();
238: this.itemLabelGenerator = null;
239: this.itemLabelGeneratorList = new ObjectList();
240: this.toolTipGenerator = null;
241: this.toolTipGeneratorList = new ObjectList();
242: this.urlGenerator = null;
243: this.backgroundAnnotations = new java.util.ArrayList();
244: this.foregroundAnnotations = new java.util.ArrayList();
245: this.defaultEntityRadius = 3;
246: this.legendItemLabelGenerator = new StandardXYSeriesLabelGenerator(
247: "{0}");
248: }
249:
250:
257: public int getPassCount() {
258: return 1;
259: }
260:
261:
266: public XYPlot getPlot() {
267: return this.plot;
268: }
269:
270:
275: public void setPlot(XYPlot plot) {
276: this.plot = plot;
277: }
278:
279:
296: public XYItemRendererState initialise(Graphics2D g2,
297: Rectangle2D dataArea,
298: XYPlot plot,
299: XYDataset data,
300: PlotRenderingInfo info) {
301:
302: XYItemRendererState state = new XYItemRendererState(info);
303: return state;
304:
305: }
306:
307:
308:
309:
320: public XYItemLabelGenerator getItemLabelGenerator(int series, int item) {
321:
322: if (this.itemLabelGenerator != null) {
323: return this.itemLabelGenerator;
324: }
325:
326:
327: XYItemLabelGenerator generator
328: = (XYItemLabelGenerator) this.itemLabelGeneratorList.get(series);
329: if (generator == null) {
330: generator = this.baseItemLabelGenerator;
331: }
332: return generator;
333: }
334:
335:
342: public XYItemLabelGenerator getSeriesItemLabelGenerator(int series) {
343: return (XYItemLabelGenerator) this.itemLabelGeneratorList.get(series);
344: }
345:
346:
359: public XYItemLabelGenerator getItemLabelGenerator() {
360: return this.itemLabelGenerator;
361: }
362:
363:
375: public void setItemLabelGenerator(XYItemLabelGenerator generator) {
376: this.itemLabelGenerator = generator;
377: fireChangeEvent();
378: }
379:
380:
387: public void setSeriesItemLabelGenerator(int series,
388: XYItemLabelGenerator generator) {
389: this.itemLabelGeneratorList.set(series, generator);
390: fireChangeEvent();
391: }
392:
393:
398: public XYItemLabelGenerator getBaseItemLabelGenerator() {
399: return this.baseItemLabelGenerator;
400: }
401:
402:
408: public void setBaseItemLabelGenerator(XYItemLabelGenerator generator) {
409: this.baseItemLabelGenerator = generator;
410: fireChangeEvent();
411: }
412:
413:
414:
415:
425: public XYToolTipGenerator getToolTipGenerator(int series, int item) {
426:
427: if (this.toolTipGenerator != null) {
428: return this.toolTipGenerator;
429: }
430:
431:
432: XYToolTipGenerator generator
433: = (XYToolTipGenerator) this.toolTipGeneratorList.get(series);
434: if (generator == null) {
435: generator = this.baseToolTipGenerator;
436: }
437: return generator;
438: }
439:
440:
453: public XYToolTipGenerator getToolTipGenerator() {
454: return this.toolTipGenerator;
455: }
456:
457:
469: public void setToolTipGenerator(XYToolTipGenerator generator) {
470: this.toolTipGenerator = generator;
471: fireChangeEvent();
472: }
473:
474:
481: public XYToolTipGenerator getSeriesToolTipGenerator(int series) {
482: return (XYToolTipGenerator) this.toolTipGeneratorList.get(series);
483: }
484:
485:
492: public void setSeriesToolTipGenerator(int series,
493: XYToolTipGenerator generator) {
494: this.toolTipGeneratorList.set(series, generator);
495: fireChangeEvent();
496: }
497:
498:
505: public XYToolTipGenerator getBaseToolTipGenerator() {
506: return this.baseToolTipGenerator;
507: }
508:
509:
517: public void setBaseToolTipGenerator(XYToolTipGenerator generator) {
518: this.baseToolTipGenerator = generator;
519: fireChangeEvent();
520: }
521:
522:
523:
524:
529: public XYURLGenerator getURLGenerator() {
530: return this.urlGenerator;
531: }
532:
533:
539: public void setURLGenerator(XYURLGenerator urlGenerator) {
540: this.urlGenerator = urlGenerator;
541: fireChangeEvent();
542: }
543:
544:
551: public void addAnnotation(XYAnnotation annotation) {
552:
553: addAnnotation(annotation, Layer.FOREGROUND);
554: }
555:
556:
563: public void addAnnotation(XYAnnotation annotation, Layer layer) {
564: if (annotation == null) {
565: throw new IllegalArgumentException("Null 'annotation' argument.");
566: }
567: if (layer.equals(Layer.FOREGROUND)) {
568: this.foregroundAnnotations.add(annotation);
569: fireChangeEvent();
570: }
571: else if (layer.equals(Layer.BACKGROUND)) {
572: this.backgroundAnnotations.add(annotation);
573: fireChangeEvent();
574: }
575: else {
576:
577: throw new RuntimeException("Unknown layer.");
578: }
579: }
580:
590: public boolean removeAnnotation(XYAnnotation annotation) {
591: boolean removed = this.foregroundAnnotations.remove(annotation);
592: removed = removed & this.backgroundAnnotations.remove(annotation);
593: fireChangeEvent();
594: return removed;
595: }
596:
597:
601: public void removeAnnotations() {
602: this.foregroundAnnotations.clear();
603: this.backgroundAnnotations.clear();
604: fireChangeEvent();
605: }
606:
607:
613: public int getDefaultEntityRadius() {
614: return this.defaultEntityRadius;
615: }
616:
617:
623: public void setDefaultEntityRadius(int radius) {
624: this.defaultEntityRadius = radius;
625: }
626:
627:
634: public XYSeriesLabelGenerator getLegendItemLabelGenerator() {
635: return this.legendItemLabelGenerator;
636: }
637:
638:
646: public void setLegendItemLabelGenerator(XYSeriesLabelGenerator generator) {
647: if (generator == null) {
648: throw new IllegalArgumentException("Null 'generator' argument.");
649: }
650: this.legendItemLabelGenerator = generator;
651: fireChangeEvent();
652: }
653:
654:
661: public XYSeriesLabelGenerator getLegendItemToolTipGenerator() {
662: return this.legendItemToolTipGenerator;
663: }
664:
665:
673: public void setLegendItemToolTipGenerator(
674: XYSeriesLabelGenerator generator) {
675: this.legendItemToolTipGenerator = generator;
676: fireChangeEvent();
677: }
678:
679:
686: public XYSeriesLabelGenerator getLegendItemURLGenerator() {
687: return this.legendItemURLGenerator;
688: }
689:
690:
698: public void setLegendItemURLGenerator(XYSeriesLabelGenerator generator) {
699: this.legendItemURLGenerator = generator;
700: fireChangeEvent();
701: }
702:
703:
712: public Range findDomainBounds(XYDataset dataset) {
713: if (dataset != null) {
714: return DatasetUtilities.findDomainBounds(dataset, false);
715: }
716: else {
717: return null;
718: }
719: }
720:
721:
730: public Range findRangeBounds(XYDataset dataset) {
731: if (dataset != null) {
732: return DatasetUtilities.findRangeBounds(dataset, false);
733: }
734: else {
735: return null;
736: }
737: }
738:
739:
745: public LegendItemCollection getLegendItems() {
746: if (this.plot == null) {
747: return new LegendItemCollection();
748: }
749: LegendItemCollection result = new LegendItemCollection();
750: int index = this.plot.getIndexOf(this);
751: XYDataset dataset = this.plot.getDataset(index);
752: if (dataset != null) {
753: int seriesCount = dataset.getSeriesCount();
754: for (int i = 0; i < seriesCount; i++) {
755: if (isSeriesVisibleInLegend(i)) {
756: LegendItem item = getLegendItem(index, i);
757: if (item != null) {
758: result.add(item);
759: }
760: }
761: }
762:
763: }
764: return result;
765: }
766:
767:
776: public LegendItem getLegendItem(int datasetIndex, int series) {
777: LegendItem result = null;
778: XYPlot xyplot = getPlot();
779: if (xyplot != null) {
780: XYDataset dataset = xyplot.getDataset(datasetIndex);
781: if (dataset != null) {
782: String label = this.legendItemLabelGenerator.generateLabel(
783: dataset, series);
784: String description = label;
785: String toolTipText = null;
786: if (getLegendItemToolTipGenerator() != null) {
787: toolTipText = getLegendItemToolTipGenerator().generateLabel(
788: dataset, series);
789: }
790: String urlText = null;
791: if (getLegendItemURLGenerator() != null) {
792: urlText = getLegendItemURLGenerator().generateLabel(
793: dataset, series);
794: }
795: Shape shape = lookupSeriesShape(series);
796: Paint paint = lookupSeriesPaint(series);
797: Paint outlinePaint = lookupSeriesOutlinePaint(series);
798: Stroke outlineStroke = lookupSeriesOutlineStroke(series);
799: result = new LegendItem(label, description, toolTipText,
800: urlText, shape, paint, outlineStroke, outlinePaint);
801: result.setSeriesKey(dataset.getSeriesKey(series));
802: result.setSeriesIndex(series);
803: result.setDataset(dataset);
804: result.setDatasetIndex(datasetIndex);
805: }
806: }
807: return result;
808: }
809:
810:
821: public void fillDomainGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis,
822: Rectangle2D dataArea, double start, double end) {
823:
824: double x1 = axis.valueToJava2D(start, dataArea,
825: plot.getDomainAxisEdge());
826: double x2 = axis.valueToJava2D(end, dataArea,
827: plot.getDomainAxisEdge());
828: Rectangle2D band;
829: if (plot.getOrientation() == PlotOrientation.VERTICAL) {
830: band = new Rectangle2D.Double(Math.min(x1, x2), dataArea.getMinY(),
831: Math.abs(x2 - x1), dataArea.getWidth());
832: }
833: else {
834: band = new Rectangle2D.Double(dataArea.getMinX(), Math.min(x1, x2),
835: dataArea.getWidth(), Math.abs(x2 - x1));
836: }
837: Paint paint = plot.getDomainTickBandPaint();
838:
839: if (paint != null) {
840: g2.setPaint(paint);
841: g2.fill(band);
842: }
843:
844: }
845:
846:
857: public void fillRangeGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis,
858: Rectangle2D dataArea, double start, double end) {
859:
860: double y1 = axis.valueToJava2D(start, dataArea,
861: plot.getRangeAxisEdge());
862: double y2 = axis.valueToJava2D(end, dataArea, plot.getRangeAxisEdge());
863: Rectangle2D band;
864: if (plot.getOrientation() == PlotOrientation.VERTICAL) {
865: band = new Rectangle2D.Double(dataArea.getMinX(), Math.min(y1, y2),
866: dataArea.getWidth(), Math.abs(y2 - y1));
867: }
868: else {
869: band = new Rectangle2D.Double(Math.min(y1, y2), dataArea.getMinY(),
870: Math.abs(y2 - y1), dataArea.getHeight());
871: }
872: Paint paint = plot.getRangeTickBandPaint();
873:
874: if (paint != null) {
875: g2.setPaint(paint);
876: g2.fill(band);
877: }
878:
879: }
880:
881:
891: public void drawDomainGridLine(Graphics2D g2,
892: XYPlot plot,
893: ValueAxis axis,
894: Rectangle2D dataArea,
895: double value) {
896:
897: Range range = axis.getRange();
898: if (!range.contains(value)) {
899: return;
900: }
901:
902: PlotOrientation orientation = plot.getOrientation();
903: double v = axis.valueToJava2D(value, dataArea,
904: plot.getDomainAxisEdge());
905: Line2D line = null;
906: if (orientation == PlotOrientation.HORIZONTAL) {
907: line = new Line2D.Double(dataArea.getMinX(), v,
908: dataArea.getMaxX(), v);
909: }
910: else if (orientation == PlotOrientation.VERTICAL) {
911: line = new Line2D.Double(v, dataArea.getMinY(), v,
912: dataArea.getMaxY());
913: }
914:
915: Paint paint = plot.getDomainGridlinePaint();
916: Stroke stroke = plot.getDomainGridlineStroke();
917: g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
918: g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
919: g2.draw(line);
920:
921: }
922:
923:
937: public void drawDomainLine(Graphics2D g2, XYPlot plot, ValueAxis axis,
938: Rectangle2D dataArea, double value, Paint paint, Stroke stroke) {
939:
940: Range range = axis.getRange();
941: if (!range.contains(value)) {
942: return;
943: }
944:
945: PlotOrientation orientation = plot.getOrientation();
946: Line2D line = null;
947: double v = axis.valueToJava2D(value, dataArea,
948: plot.getDomainAxisEdge());
949: if (orientation == PlotOrientation.HORIZONTAL) {
950: line = new Line2D.Double(dataArea.getMinX(), v, dataArea.getMaxX(),
951: v);
952: }
953: else if (orientation == PlotOrientation.VERTICAL) {
954: line = new Line2D.Double(v, dataArea.getMinY(), v,
955: dataArea.getMaxY());
956: }
957:
958: g2.setPaint(paint);
959: g2.setStroke(stroke);
960: g2.draw(line);
961:
962: }
963:
964:
976: public void drawRangeLine(Graphics2D g2,
977: XYPlot plot,
978: ValueAxis axis,
979: Rectangle2D dataArea,
980: double value,
981: Paint paint,
982: Stroke stroke) {
983:
984: Range range = axis.getRange();
985: if (!range.contains(value)) {
986: return;
987: }
988:
989: PlotOrientation orientation = plot.getOrientation();
990: Line2D line = null;
991: double v = axis.valueToJava2D(value, dataArea, plot.getRangeAxisEdge());
992: if (orientation == PlotOrientation.HORIZONTAL) {
993: line = new Line2D.Double(v, dataArea.getMinY(), v,
994: dataArea.getMaxY());
995: }
996: else if (orientation == PlotOrientation.VERTICAL) {
997: line = new Line2D.Double(dataArea.getMinX(), v,
998: dataArea.getMaxX(), v);
999: }
1000:
1001: g2.setPaint(paint);
1002: g2.setStroke(stroke);
1003: g2.draw(line);
1004:
1005: }
1006:
1007:
1016: public void drawDomainMarker(Graphics2D g2,
1017: XYPlot plot,
1018: ValueAxis domainAxis,
1019: Marker marker,
1020: Rectangle2D dataArea) {
1021:
1022: if (marker instanceof ValueMarker) {
1023: ValueMarker vm = (ValueMarker) marker;
1024: double value = vm.getValue();
1025: Range range = domainAxis.getRange();
1026: if (!range.contains(value)) {
1027: return;
1028: }
1029:
1030: double v = domainAxis.valueToJava2D(value, dataArea,
1031: plot.getDomainAxisEdge());
1032:
1033: PlotOrientation orientation = plot.getOrientation();
1034: Line2D line = null;
1035: if (orientation == PlotOrientation.HORIZONTAL) {
1036: line = new Line2D.Double(dataArea.getMinX(), v,
1037: dataArea.getMaxX(), v);
1038: }
1039: else if (orientation == PlotOrientation.VERTICAL) {
1040: line = new Line2D.Double(v, dataArea.getMinY(), v,
1041: dataArea.getMaxY());
1042: }
1043:
1044: final Composite originalComposite = g2.getComposite();
1045: g2.setComposite(AlphaComposite.getInstance(
1046: AlphaComposite.SRC_OVER, marker.getAlpha()));
1047: g2.setPaint(marker.getPaint());
1048: g2.setStroke(marker.getStroke());
1049: g2.draw(line);
1050:
1051: String label = marker.getLabel();
1052: RectangleAnchor anchor = marker.getLabelAnchor();
1053: if (label != null) {
1054: Font labelFont = marker.getLabelFont();
1055: g2.setFont(labelFont);
1056: g2.setPaint(marker.getLabelPaint());
1057: Point2D coordinates = calculateDomainMarkerTextAnchorPoint(
1058: g2, orientation, dataArea, line.getBounds2D(),
1059: marker.getLabelOffset(),
1060: LengthAdjustmentType.EXPAND, anchor);
1061: TextUtilities.drawAlignedString(label, g2,
1062: (float) coordinates.getX(), (float) coordinates.getY(),
1063: marker.getLabelTextAnchor());
1064: }
1065: g2.setComposite(originalComposite);
1066: }
1067: else if (marker instanceof IntervalMarker) {
1068: IntervalMarker im = (IntervalMarker) marker;
1069: double start = im.getStartValue();
1070: double end = im.getEndValue();
1071: Range range = domainAxis.getRange();
1072: if (!(range.intersects(start, end))) {
1073: return;
1074: }
1075:
1076: double start2d = domainAxis.valueToJava2D(start, dataArea,
1077: plot.getDomainAxisEdge());
1078: double end2d = domainAxis.valueToJava2D(end, dataArea,
1079: plot.getDomainAxisEdge());
1080: double low = Math.min(start2d, end2d);
1081: double high = Math.max(start2d, end2d);
1082:
1083: PlotOrientation orientation = plot.getOrientation();
1084: Rectangle2D rect = null;
1085: if (orientation == PlotOrientation.HORIZONTAL) {
1086:
1087: low = Math.max(low, dataArea.getMinY());
1088: high = Math.min(high, dataArea.getMaxY());
1089: rect = new Rectangle2D.Double(dataArea.getMinX(),
1090: low, dataArea.getWidth(),
1091: high - low);
1092: }
1093: else if (orientation == PlotOrientation.VERTICAL) {
1094:
1095: low = Math.max(low, dataArea.getMinX());
1096: high = Math.min(high, dataArea.getMaxX());
1097: rect = new Rectangle2D.Double(low,
1098: dataArea.getMinY(), high - low,
1099: dataArea.getHeight());
1100: }
1101:
1102: final Composite originalComposite = g2.getComposite();
1103: g2.setComposite(AlphaComposite.getInstance(
1104: AlphaComposite.SRC_OVER, marker.getAlpha()));
1105: Paint p = marker.getPaint();
1106: if (p instanceof GradientPaint) {
1107: GradientPaint gp = (GradientPaint) p;
1108: GradientPaintTransformer t = im.getGradientPaintTransformer();
1109: if (t != null) {
1110: gp = t.transform(gp, rect);
1111: }
1112: g2.setPaint(gp);
1113: }
1114: else {
1115: g2.setPaint(p);
1116: }
1117: g2.fill(rect);
1118:
1119:
1120: if (im.getOutlinePaint() != null && im.getOutlineStroke() != null) {
1121: if (orientation == PlotOrientation.VERTICAL) {
1122: Line2D line = new Line2D.Double();
1123: double y0 = dataArea.getMinY();
1124: double y1 = dataArea.getMaxY();
1125: g2.setPaint(im.getOutlinePaint());
1126: g2.setStroke(im.getOutlineStroke());
1127: if (range.contains(start)) {
1128: line.setLine(start2d, y0, start2d, y1);
1129: g2.draw(line);
1130: }
1131: if (range.contains(end)) {
1132: line.setLine(end2d, y0, end2d, y1);
1133: g2.draw(line);
1134: }
1135: }
1136: else {
1137: Line2D line = new Line2D.Double();
1138: double x0 = dataArea.getMinX();
1139: double x1 = dataArea.getMaxX();
1140: g2.setPaint(im.getOutlinePaint());
1141: g2.setStroke(im.getOutlineStroke());
1142: if (range.contains(start)) {
1143: line.setLine(x0, start2d, x1, start2d);
1144: g2.draw(line);
1145: }
1146: if (range.contains(end)) {
1147: line.setLine(x0, end2d, x1, end2d);
1148: g2.draw(line);
1149: }
1150: }
1151: }
1152:
1153: String label = marker.getLabel();
1154: RectangleAnchor anchor = marker.getLabelAnchor();
1155: if (label != null) {
1156: Font labelFont = marker.getLabelFont();
1157: g2.setFont(labelFont);
1158: g2.setPaint(marker.getLabelPaint());
1159: Point2D coordinates = calculateDomainMarkerTextAnchorPoint(
1160: g2, orientation, dataArea, rect,
1161: marker.getLabelOffset(), marker.getLabelOffsetType(),
1162: anchor);
1163: TextUtilities.drawAlignedString(label, g2,
1164: (float) coordinates.getX(), (float) coordinates.getY(),
1165: marker.getLabelTextAnchor());
1166: }
1167: g2.setComposite(originalComposite);
1168:
1169: }
1170:
1171: }
1172:
1173:
1186: protected Point2D calculateDomainMarkerTextAnchorPoint(Graphics2D g2,
1187: PlotOrientation orientation,
1188: Rectangle2D dataArea,
1189: Rectangle2D markerArea,
1190: RectangleInsets markerOffset,
1191: LengthAdjustmentType labelOffsetType,
1192: RectangleAnchor anchor) {
1193:
1194: Rectangle2D anchorRect = null;
1195: if (orientation == PlotOrientation.HORIZONTAL) {
1196: anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1197: LengthAdjustmentType.CONTRACT, labelOffsetType);
1198: }
1199: else if (orientation == PlotOrientation.VERTICAL) {
1200: anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1201: labelOffsetType, LengthAdjustmentType.CONTRACT);
1202: }
1203: return RectangleAnchor.coordinates(anchorRect, anchor);
1204:
1205: }
1206:
1207:
1216: public void drawRangeMarker(Graphics2D g2,
1217: XYPlot plot,
1218: ValueAxis rangeAxis,
1219: Marker marker,
1220: Rectangle2D dataArea) {
1221:
1222: if (marker instanceof ValueMarker) {
1223: ValueMarker vm = (ValueMarker) marker;
1224: double value = vm.getValue();
1225: Range range = rangeAxis.getRange();
1226: if (!range.contains(value)) {
1227: return;
1228: }
1229:
1230: double v = rangeAxis.valueToJava2D(value, dataArea,
1231: plot.getRangeAxisEdge());
1232: PlotOrientation orientation = plot.getOrientation();
1233: Line2D line = null;
1234: if (orientation == PlotOrientation.HORIZONTAL) {
1235: line = new Line2D.Double(v, dataArea.getMinY(), v,
1236: dataArea.getMaxY());
1237: }
1238: else if (orientation == PlotOrientation.VERTICAL) {
1239: line = new Line2D.Double(dataArea.getMinX(), v,
1240: dataArea.getMaxX(), v);
1241: }
1242:
1243: final Composite originalComposite = g2.getComposite();
1244: g2.setComposite(AlphaComposite.getInstance(
1245: AlphaComposite.SRC_OVER, marker.getAlpha()));
1246: g2.setPaint(marker.getPaint());
1247: g2.setStroke(marker.getStroke());
1248: g2.draw(line);
1249:
1250: String label = marker.getLabel();
1251: RectangleAnchor anchor = marker.getLabelAnchor();
1252: if (label != null) {
1253: Font labelFont = marker.getLabelFont();
1254: g2.setFont(labelFont);
1255: g2.setPaint(marker.getLabelPaint());
1256: Point2D coordinates = calculateRangeMarkerTextAnchorPoint(
1257: g2, orientation, dataArea, line.getBounds2D(),
1258: marker.getLabelOffset(),
1259: LengthAdjustmentType.EXPAND, anchor);
1260: TextUtilities.drawAlignedString(label, g2,
1261: (float) coordinates.getX(), (float) coordinates.getY(),
1262: marker.getLabelTextAnchor());
1263: }
1264: g2.setComposite(originalComposite);
1265: }
1266: else if (marker instanceof IntervalMarker) {
1267: IntervalMarker im = (IntervalMarker) marker;
1268: double start = im.getStartValue();
1269: double end = im.getEndValue();
1270: Range range = rangeAxis.getRange();
1271: if (!(range.intersects(start, end))) {
1272: return;
1273: }
1274:
1275: double start2d = rangeAxis.valueToJava2D(start, dataArea,
1276: plot.getRangeAxisEdge());
1277: double end2d = rangeAxis.valueToJava2D(end, dataArea,
1278: plot.getRangeAxisEdge());
1279: double low = Math.min(start2d, end2d);
1280: double high = Math.max(start2d, end2d);
1281:
1282: PlotOrientation orientation = plot.getOrientation();
1283: Rectangle2D rect = null;
1284: if (orientation == PlotOrientation.HORIZONTAL) {
1285:
1286: low = Math.max(low, dataArea.getMinX());
1287: high = Math.min(high, dataArea.getMaxX());
1288: rect = new Rectangle2D.Double(low,
1289: dataArea.getMinY(), high - low,
1290: dataArea.getHeight());
1291: }
1292: else if (orientation == PlotOrientation.VERTICAL) {
1293:
1294: low = Math.max(low, dataArea.getMinY());
1295: high = Math.min(high, dataArea.getMaxY());
1296: rect = new Rectangle2D.Double(dataArea.getMinX(),
1297: low, dataArea.getWidth(),
1298: high - low);
1299: }
1300:
1301: final Composite originalComposite = g2.getComposite();
1302: g2.setComposite(AlphaComposite.getInstance(
1303: AlphaComposite.SRC_OVER, marker.getAlpha()));
1304: Paint p = marker.getPaint();
1305: if (p instanceof GradientPaint) {
1306: GradientPaint gp = (GradientPaint) p;
1307: GradientPaintTransformer t = im.getGradientPaintTransformer();
1308: if (t != null) {
1309: gp = t.transform(gp, rect);
1310: }
1311: g2.setPaint(gp);
1312: }
1313: else {
1314: g2.setPaint(p);
1315: }
1316: g2.fill(rect);
1317:
1318:
1319: if (im.getOutlinePaint() != null && im.getOutlineStroke() != null) {
1320: if (orientation == PlotOrientation.VERTICAL) {
1321: Line2D line = new Line2D.Double();
1322: double x0 = dataArea.getMinX();
1323: double x1 = dataArea.getMaxX();
1324: g2.setPaint(im.getOutlinePaint());
1325: g2.setStroke(im.getOutlineStroke());
1326: if (range.contains(start)) {
1327: line.setLine(x0, start2d, x1, start2d);
1328: g2.draw(line);
1329: }
1330: if (range.contains(end)) {
1331: line.setLine(x0, end2d, x1, end2d);
1332: g2.draw(line);
1333: }
1334: }
1335: else {
1336: Line2D line = new Line2D.Double();
1337: double y0 = dataArea.getMinY();
1338: double y1 = dataArea.getMaxY();
1339: g2.setPaint(im.getOutlinePaint());
1340: g2.setStroke(im.getOutlineStroke());
1341: if (range.contains(start)) {
1342: line.setLine(start2d, y0, start2d, y1);
1343: g2.draw(line);
1344: }
1345: if (range.contains(end)) {
1346: line.setLine(end2d, y0, end2d, y1);
1347: g2.draw(line);
1348: }
1349: }
1350: }
1351:
1352: String label = marker.getLabel();
1353: RectangleAnchor anchor = marker.getLabelAnchor();
1354: if (label != null) {
1355: Font labelFont = marker.getLabelFont();
1356: g2.setFont(labelFont);
1357: g2.setPaint(marker.getLabelPaint());
1358: Point2D coordinates = calculateRangeMarkerTextAnchorPoint(
1359: g2, orientation, dataArea, rect,
1360: marker.getLabelOffset(), marker.getLabelOffsetType(),
1361: anchor);
1362: TextUtilities.drawAlignedString(label, g2,
1363: (float) coordinates.getX(), (float) coordinates.getY(),
1364: marker.getLabelTextAnchor());
1365: }
1366: g2.setComposite(originalComposite);
1367: }
1368: }
1369:
1370:
1383: private Point2D calculateRangeMarkerTextAnchorPoint(Graphics2D g2,
1384: PlotOrientation orientation,
1385: Rectangle2D dataArea,
1386: Rectangle2D markerArea,
1387: RectangleInsets markerOffset,
1388: LengthAdjustmentType labelOffsetForRange,
1389: RectangleAnchor anchor) {
1390:
1391: Rectangle2D anchorRect = null;
1392: if (orientation == PlotOrientation.HORIZONTAL) {
1393: anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1394: labelOffsetForRange, LengthAdjustmentType.CONTRACT);
1395: }
1396: else if (orientation == PlotOrientation.VERTICAL) {
1397: anchorRect = markerOffset.createAdjustedRectangle(markerArea,
1398: LengthAdjustmentType.CONTRACT, labelOffsetForRange);
1399: }
1400: return RectangleAnchor.coordinates(anchorRect, anchor);
1401:
1402: }
1403:
1404:
1412: protected Object clone() throws CloneNotSupportedException {
1413: AbstractXYItemRenderer clone = (AbstractXYItemRenderer) super.clone();
1414:
1415:
1416: if (this.itemLabelGenerator != null
1417: && this.itemLabelGenerator instanceof PublicCloneable) {
1418: PublicCloneable pc = (PublicCloneable) this.itemLabelGenerator;
1419: clone.itemLabelGenerator = (XYItemLabelGenerator) pc.clone();
1420: }
1421: clone.itemLabelGeneratorList
1422: = (ObjectList) this.itemLabelGeneratorList.clone();
1423: if (this.baseItemLabelGenerator != null
1424: && this.baseItemLabelGenerator instanceof PublicCloneable) {
1425: PublicCloneable pc = (PublicCloneable) this.baseItemLabelGenerator;
1426: clone.baseItemLabelGenerator = (XYItemLabelGenerator) pc.clone();
1427: }
1428:
1429: if (this.toolTipGenerator != null
1430: && this.toolTipGenerator instanceof PublicCloneable) {
1431: PublicCloneable pc = (PublicCloneable) this.toolTipGenerator;
1432: clone.toolTipGenerator = (XYToolTipGenerator) pc.clone();
1433: }
1434: clone.toolTipGeneratorList
1435: = (ObjectList) this.toolTipGeneratorList.clone();
1436: if (this.baseToolTipGenerator != null
1437: && this.baseToolTipGenerator instanceof PublicCloneable) {
1438: PublicCloneable pc = (PublicCloneable) this.baseToolTipGenerator;
1439: clone.baseToolTipGenerator = (XYToolTipGenerator) pc.clone();
1440: }
1441:
1442: if (clone.legendItemLabelGenerator instanceof PublicCloneable) {
1443: clone.legendItemLabelGenerator = (XYSeriesLabelGenerator)
1444: ObjectUtilities.clone(this.legendItemLabelGenerator);
1445: }
1446: if (clone.legendItemToolTipGenerator instanceof PublicCloneable) {
1447: clone.legendItemToolTipGenerator = (XYSeriesLabelGenerator)
1448: ObjectUtilities.clone(this.legendItemToolTipGenerator);
1449: }
1450: if (clone.legendItemURLGenerator instanceof PublicCloneable) {
1451: clone.legendItemURLGenerator = (XYSeriesLabelGenerator)
1452: ObjectUtilities.clone(this.legendItemURLGenerator);
1453: }
1454:
1455: clone.foregroundAnnotations = (List) ObjectUtilities.deepClone(
1456: this.foregroundAnnotations);
1457: clone.backgroundAnnotations = (List) ObjectUtilities.deepClone(
1458: this.backgroundAnnotations);
1459:
1460: if (clone.legendItemLabelGenerator instanceof PublicCloneable) {
1461: clone.legendItemLabelGenerator = (XYSeriesLabelGenerator)
1462: ObjectUtilities.clone(this.legendItemLabelGenerator);
1463: }
1464: if (clone.legendItemToolTipGenerator instanceof PublicCloneable) {
1465: clone.legendItemToolTipGenerator = (XYSeriesLabelGenerator)
1466: ObjectUtilities.clone(this.legendItemToolTipGenerator);
1467: }
1468: if (clone.legendItemURLGenerator instanceof PublicCloneable) {
1469: clone.legendItemURLGenerator = (XYSeriesLabelGenerator)
1470: ObjectUtilities.clone(this.legendItemURLGenerator);
1471: }
1472:
1473: return clone;
1474: }
1475:
1476:
1483: public boolean equals(Object obj) {
1484: if (obj == this) {
1485: return true;
1486: }
1487: if (!(obj instanceof AbstractXYItemRenderer)) {
1488: return false;
1489: }
1490: AbstractXYItemRenderer that = (AbstractXYItemRenderer) obj;
1491: if (!ObjectUtilities.equal(this.itemLabelGenerator,
1492: that.itemLabelGenerator)) {
1493: return false;
1494: }
1495: if (!this.itemLabelGeneratorList.equals(that.itemLabelGeneratorList)) {
1496: return false;
1497: }
1498: if (!ObjectUtilities.equal(this.baseItemLabelGenerator,
1499: that.baseItemLabelGenerator)) {
1500: return false;
1501: }
1502: if (!ObjectUtilities.equal(this.toolTipGenerator,
1503: that.toolTipGenerator)) {
1504: return false;
1505: }
1506: if (!this.toolTipGeneratorList.equals(that.toolTipGeneratorList)) {
1507: return false;
1508: }
1509: if (!ObjectUtilities.equal(this.baseToolTipGenerator,
1510: that.baseToolTipGenerator)) {
1511: return false;
1512: }
1513: if (!ObjectUtilities.equal(this.urlGenerator, that.urlGenerator)) {
1514: return false;
1515: }
1516: if (!this.foregroundAnnotations.equals(that.foregroundAnnotations)) {
1517: return false;
1518: }
1519: if (!this.backgroundAnnotations.equals(that.backgroundAnnotations)) {
1520: return false;
1521: }
1522: if (this.defaultEntityRadius != that.defaultEntityRadius) {
1523: return false;
1524: }
1525: if (!ObjectUtilities.equal(this.legendItemLabelGenerator,
1526: that.legendItemLabelGenerator)) {
1527: return false;
1528: }
1529: if (!ObjectUtilities.equal(this.legendItemToolTipGenerator,
1530: that.legendItemToolTipGenerator)) {
1531: return false;
1532: }
1533: if (!ObjectUtilities.equal(this.legendItemURLGenerator,
1534: that.legendItemURLGenerator)) {
1535: return false;
1536: }
1537: return super.equals(obj);
1538: }
1539:
1540:
1545: public DrawingSupplier getDrawingSupplier() {
1546: DrawingSupplier result = null;
1547: XYPlot p = getPlot();
1548: if (p != null) {
1549: result = p.getDrawingSupplier();
1550: }
1551: return result;
1552: }
1553:
1554:
1572: protected void updateCrosshairValues(CrosshairState crosshairState,
1573: double x, double y, double transX, double transY,
1574: PlotOrientation orientation) {
1575: updateCrosshairValues(crosshairState, x, y, 0, 0, transX, transY,
1576: orientation);
1577: }
1578:
1579:
1597: protected void updateCrosshairValues(CrosshairState crosshairState,
1598: double x, double y, int domainAxisIndex, int rangeAxisIndex,
1599: double transX, double transY, PlotOrientation orientation) {
1600:
1601: if (orientation == null) {
1602: throw new IllegalArgumentException("Null 'orientation' argument.");
1603: }
1604:
1605: if (crosshairState != null) {
1606:
1607: if (this.plot.isDomainCrosshairLockedOnData()) {
1608: if (this.plot.isRangeCrosshairLockedOnData()) {
1609:
1610: crosshairState.updateCrosshairPoint(x, y, domainAxisIndex,
1611: rangeAxisIndex, transX, transY, orientation);
1612: }
1613: else {
1614:
1615: crosshairState.updateCrosshairX(x, domainAxisIndex);
1616: }
1617: }
1618: else {
1619: if (this.plot.isRangeCrosshairLockedOnData()) {
1620:
1621: crosshairState.updateCrosshairY(y, rangeAxisIndex);
1622: }
1623: }
1624: }
1625:
1626: }
1627:
1628:
1641: protected void drawItemLabel(Graphics2D g2, PlotOrientation orientation,
1642: XYDataset dataset, int series, int item, double x, double y,
1643: boolean negative) {
1644:
1645: XYItemLabelGenerator generator = getItemLabelGenerator(series, item);
1646: if (generator != null) {
1647: Font labelFont = getItemLabelFont(series, item);
1648: Paint paint = getItemLabelPaint(series, item);
1649: g2.setFont(labelFont);
1650: g2.setPaint(paint);
1651: String label = generator.generateLabel(dataset, series, item);
1652:
1653:
1654: ItemLabelPosition position = null;
1655: if (!negative) {
1656: position = getPositiveItemLabelPosition(series, item);
1657: }
1658: else {
1659: position = getNegativeItemLabelPosition(series, item);
1660: }
1661:
1662:
1663: Point2D anchorPoint = calculateLabelAnchorPoint(
1664: position.getItemLabelAnchor(), x, y, orientation);
1665: TextUtilities.drawRotatedString(label, g2,
1666: (float) anchorPoint.getX(), (float) anchorPoint.getY(),
1667: position.getTextAnchor(), position.getAngle(),
1668: position.getRotationAnchor());
1669: }
1670:
1671: }
1672:
1673:
1683: public void drawAnnotations(Graphics2D g2,
1684: Rectangle2D dataArea,
1685: ValueAxis domainAxis,
1686: ValueAxis rangeAxis,
1687: Layer layer,
1688: PlotRenderingInfo info) {
1689:
1690: Iterator iterator = null;
1691: if (layer.equals(Layer.FOREGROUND)) {
1692: iterator = this.foregroundAnnotations.iterator();
1693: }
1694: else if (layer.equals(Layer.BACKGROUND)) {
1695: iterator = this.backgroundAnnotations.iterator();
1696: }
1697: else {
1698:
1699: throw new RuntimeException("Unknown layer.");
1700: }
1701: while (iterator.hasNext()) {
1702: XYAnnotation annotation = (XYAnnotation) iterator.next();
1703: annotation.draw(g2, this.plot, dataArea, domainAxis, rangeAxis,
1704: 0, info);
1705: }
1706:
1707: }
1708:
1709:
1723: protected void addEntity(EntityCollection entities, Shape area,
1724: XYDataset dataset, int series, int item,
1725: double entityX, double entityY) {
1726: if (!getItemCreateEntity(series, item)) {
1727: return;
1728: }
1729: Shape hotspot = area;
1730: if (hotspot == null) {
1731: double w = this.defaultEntityRadius * 2;
1732: if (getPlot().getOrientation() == PlotOrientation.VERTICAL) {
1733: hotspot = new Ellipse2D.Double(
1734: entityX - this.defaultEntityRadius,
1735: entityY - this.defaultEntityRadius, w, w);
1736: }
1737: else {
1738: hotspot = new Ellipse2D.Double(
1739: entityY - this.defaultEntityRadius,
1740: entityX - this.defaultEntityRadius, w, w);
1741: }
1742: }
1743: String tip = null;
1744: XYToolTipGenerator generator = getToolTipGenerator(series, item);
1745: if (generator != null) {
1746: tip = generator.generateToolTip(dataset, series, item);
1747: }
1748: String url = null;
1749: if (getURLGenerator() != null) {
1750: url = getURLGenerator().generateURL(dataset, series, item);
1751: }
1752: XYItemEntity entity = new XYItemEntity(hotspot, dataset, series, item,
1753: tip, url);
1754: entities.add(entity);
1755: }
1756:
1757:
1769: public static boolean isPointInRect(Rectangle2D rect, double x, double y) {
1770:
1771:
1772: return (x >= rect.getMinX() && x <= rect.getMaxX()
1773: && y >= rect.getMinY() && y <= rect.getMaxY());
1774: }
1775:
1776: }