1:
173:
174: package ;
175:
176: import ;
177: import ;
178: import ;
179: import ;
180: import ;
181: import ;
182: import ;
183: import ;
184: import ;
185: import ;
186: import ;
187: import ;
188: import ;
189: import ;
190: import ;
191: import ;
192: import ;
193: import ;
194: import ;
195: import ;
196: import ;
197: import ;
198: import ;
199: import ;
200:
201: import ;
202: import ;
203: import ;
204: import ;
205: import ;
206: import ;
207: import ;
208: import ;
209: import ;
210: import ;
211: import ;
212: import ;
213: import ;
214: import ;
215: import ;
216: import ;
217: import ;
218: import ;
219: import ;
220: import ;
221: import ;
222: import ;
223: import ;
224: import ;
225: import ;
226: import ;
227: import ;
228: import ;
229: import ;
230:
231:
242: public class XYPlot extends Plot implements ValueAxisPlot,
243: Zoomable,
244: RendererChangeListener,
245: Cloneable, PublicCloneable,
246: Serializable {
247:
248:
249: private static final long serialVersionUID = 7044148245716569264L;
250:
251:
252: public static final Stroke DEFAULT_GRIDLINE_STROKE = new BasicStroke(
253: 0.5f,
254: BasicStroke.CAP_BUTT,
255: BasicStroke.JOIN_BEVEL,
256: 0.0f,
257: new float[] {2.0f, 2.0f},
258: 0.0f
259: );
260:
261:
262: public static final Paint DEFAULT_GRIDLINE_PAINT = Color.lightGray;
263:
264:
265: public static final boolean DEFAULT_CROSSHAIR_VISIBLE = false;
266:
267:
268: public static final Stroke DEFAULT_CROSSHAIR_STROKE
269: = DEFAULT_GRIDLINE_STROKE;
270:
271:
272: public static final Paint DEFAULT_CROSSHAIR_PAINT = Color.blue;
273:
274:
275: protected static ResourceBundle localizationResources
276: = ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle");
277:
278:
279: private PlotOrientation orientation;
280:
281:
282: private RectangleInsets axisOffset;
283:
284:
285: private ObjectList domainAxes;
286:
287:
288: private ObjectList domainAxisLocations;
289:
290:
291: private ObjectList rangeAxes;
292:
293:
294: private ObjectList rangeAxisLocations;
295:
296:
297: private ObjectList datasets;
298:
299:
300: private ObjectList renderers;
301:
302:
307: private Map datasetToDomainAxisMap;
308:
309:
314: private Map datasetToRangeAxisMap;
315:
316:
317: private transient Point2D quadrantOrigin = new Point2D.Double(0.0, 0.0);
318:
319:
320: private transient Paint[] quadrantPaint
321: = new Paint[] {null, null, null, null};
322:
323:
324: private boolean domainGridlinesVisible;
325:
326:
327: private transient Stroke domainGridlineStroke;
328:
329:
330: private transient Paint domainGridlinePaint;
331:
332:
333: private boolean rangeGridlinesVisible;
334:
335:
336: private transient Stroke rangeGridlineStroke;
337:
338:
339: private transient Paint rangeGridlinePaint;
340:
341:
345: private boolean rangeZeroBaselineVisible;
346:
347:
348: private transient Stroke rangeZeroBaselineStroke;
349:
350:
351: private transient Paint rangeZeroBaselinePaint;
352:
353:
354: private boolean domainCrosshairVisible;
355:
356:
357: private double domainCrosshairValue;
358:
359:
360: private transient Stroke domainCrosshairStroke;
361:
362:
363: private transient Paint domainCrosshairPaint;
364:
365:
369: private boolean domainCrosshairLockedOnData = true;
370:
371:
372: private boolean rangeCrosshairVisible;
373:
374:
375: private double rangeCrosshairValue;
376:
377:
378: private transient Stroke rangeCrosshairStroke;
379:
380:
381: private transient Paint rangeCrosshairPaint;
382:
383:
387: private boolean rangeCrosshairLockedOnData = true;
388:
389:
390: private Map foregroundDomainMarkers;
391:
392:
393: private Map backgroundDomainMarkers;
394:
395:
396: private Map foregroundRangeMarkers;
397:
398:
399: private Map backgroundRangeMarkers;
400:
401:
406: private List annotations;
407:
408:
409: private transient Paint domainTickBandPaint;
410:
411:
412: private transient Paint rangeTickBandPaint;
413:
414:
415: private AxisSpace fixedDomainAxisSpace;
416:
417:
418: private AxisSpace fixedRangeAxisSpace;
419:
420:
424: private DatasetRenderingOrder datasetRenderingOrder
425: = DatasetRenderingOrder.REVERSE;
426:
427:
431: private SeriesRenderingOrder seriesRenderingOrder
432: = SeriesRenderingOrder.REVERSE;
433:
434:
438: private int weight;
439:
440:
444: private LegendItemCollection fixedLegendItems;
445:
446:
449: public XYPlot() {
450: this(null, null, null, null);
451: }
452:
453:
461: public XYPlot(XYDataset dataset,
462: ValueAxis domainAxis,
463: ValueAxis rangeAxis,
464: XYItemRenderer renderer) {
465:
466: super();
467:
468: this.orientation = PlotOrientation.VERTICAL;
469: this.weight = 1;
470: this.axisOffset = RectangleInsets.ZERO_INSETS;
471:
472:
473: this.domainAxes = new ObjectList();
474: this.domainAxisLocations = new ObjectList();
475: this.foregroundDomainMarkers = new HashMap();
476: this.backgroundDomainMarkers = new HashMap();
477:
478: this.rangeAxes = new ObjectList();
479: this.rangeAxisLocations = new ObjectList();
480: this.foregroundRangeMarkers = new HashMap();
481: this.backgroundRangeMarkers = new HashMap();
482:
483: this.datasets = new ObjectList();
484: this.renderers = new ObjectList();
485:
486: this.datasetToDomainAxisMap = new TreeMap();
487: this.datasetToRangeAxisMap = new TreeMap();
488:
489: this.datasets.set(0, dataset);
490: if (dataset != null) {
491: dataset.addChangeListener(this);
492: }
493:
494: this.renderers.set(0, renderer);
495: if (renderer != null) {
496: renderer.setPlot(this);
497: renderer.addChangeListener(this);
498: }
499:
500: this.domainAxes.set(0, domainAxis);
501: this.mapDatasetToDomainAxis(0, 0);
502: if (domainAxis != null) {
503: domainAxis.setPlot(this);
504: domainAxis.addChangeListener(this);
505: }
506: this.domainAxisLocations.set(0, AxisLocation.BOTTOM_OR_LEFT);
507:
508: this.rangeAxes.set(0, rangeAxis);
509: this.mapDatasetToRangeAxis(0, 0);
510: if (rangeAxis != null) {
511: rangeAxis.setPlot(this);
512: rangeAxis.addChangeListener(this);
513: }
514: this.rangeAxisLocations.set(0, AxisLocation.BOTTOM_OR_LEFT);
515:
516: configureDomainAxes();
517: configureRangeAxes();
518:
519: this.domainGridlinesVisible = true;
520: this.domainGridlineStroke = DEFAULT_GRIDLINE_STROKE;
521: this.domainGridlinePaint = DEFAULT_GRIDLINE_PAINT;
522:
523: this.rangeGridlinesVisible = true;
524: this.rangeGridlineStroke = DEFAULT_GRIDLINE_STROKE;
525: this.rangeGridlinePaint = DEFAULT_GRIDLINE_PAINT;
526:
527: this.rangeZeroBaselineVisible = false;
528: this.rangeZeroBaselinePaint = Color.black;
529: this.rangeZeroBaselineStroke = new BasicStroke(0.5f);
530:
531: this.domainCrosshairVisible = false;
532: this.domainCrosshairValue = 0.0;
533: this.domainCrosshairStroke = DEFAULT_CROSSHAIR_STROKE;
534: this.domainCrosshairPaint = DEFAULT_CROSSHAIR_PAINT;
535:
536: this.rangeCrosshairVisible = false;
537: this.rangeCrosshairValue = 0.0;
538: this.rangeCrosshairStroke = DEFAULT_CROSSHAIR_STROKE;
539: this.rangeCrosshairPaint = DEFAULT_CROSSHAIR_PAINT;
540:
541: this.annotations = new java.util.ArrayList();
542:
543: }
544:
545:
550: public String getPlotType() {
551: return localizationResources.getString("XY_Plot");
552: }
553:
554:
559: public PlotOrientation getOrientation() {
560: return this.orientation;
561: }
562:
563:
568: public void setOrientation(PlotOrientation orientation) {
569: if (orientation == null) {
570: throw new IllegalArgumentException("Null 'orientation' argument.");
571: }
572: if (orientation != this.orientation) {
573: this.orientation = orientation;
574: notifyListeners(new PlotChangeEvent(this));
575: }
576: }
577:
578:
583: public RectangleInsets getAxisOffset() {
584: return this.axisOffset;
585: }
586:
587:
592: public void setAxisOffset(RectangleInsets offset) {
593: if (offset == null) {
594: throw new IllegalArgumentException("Null 'offset' argument.");
595: }
596: this.axisOffset = offset;
597: notifyListeners(new PlotChangeEvent(this));
598: }
599:
600:
607: public ValueAxis getDomainAxis() {
608: return getDomainAxis(0);
609: }
610:
611:
618: public ValueAxis getDomainAxis(int index) {
619: ValueAxis result = null;
620: if (index < this.domainAxes.size()) {
621: result = (ValueAxis) this.domainAxes.get(index);
622: }
623: if (result == null) {
624: Plot parent = getParent();
625: if (parent instanceof XYPlot) {
626: XYPlot xy = (XYPlot) parent;
627: result = xy.getDomainAxis(index);
628: }
629: }
630: return result;
631: }
632:
633:
639: public void setDomainAxis(ValueAxis axis) {
640: setDomainAxis(0, axis);
641: }
642:
643:
650: public void setDomainAxis(int index, ValueAxis axis) {
651: setDomainAxis(index, axis, true);
652: }
653:
654:
662: public void setDomainAxis(int index, ValueAxis axis, boolean notify) {
663: ValueAxis existing = getDomainAxis(index);
664: if (existing != null) {
665: existing.removeChangeListener(this);
666: }
667: if (axis != null) {
668: axis.setPlot(this);
669: }
670: this.domainAxes.set(index, axis);
671: if (axis != null) {
672: axis.configure();
673: axis.addChangeListener(this);
674: }
675: if (notify) {
676: notifyListeners(new PlotChangeEvent(this));
677: }
678: }
679:
680:
686: public void setDomainAxes(ValueAxis[] axes) {
687: for (int i = 0; i < axes.length; i++) {
688: setDomainAxis(i, axes[i], false);
689: }
690: notifyListeners(new PlotChangeEvent(this));
691: }
692:
693:
698: public AxisLocation getDomainAxisLocation() {
699: return (AxisLocation) this.domainAxisLocations.get(0);
700: }
701:
702:
708: public void setDomainAxisLocation(AxisLocation location) {
709:
710: setDomainAxisLocation(location, true);
711: }
712:
713:
720: public void setDomainAxisLocation(AxisLocation location, boolean notify) {
721: if (location == null) {
722: throw new IllegalArgumentException("Null 'location' argument.");
723: }
724: this.domainAxisLocations.set(0, location);
725: if (notify) {
726: notifyListeners(new PlotChangeEvent(this));
727: }
728: }
729:
730:
736: public RectangleEdge getDomainAxisEdge() {
737: return Plot.resolveDomainAxisLocation(
738: getDomainAxisLocation(), this.orientation
739: );
740: }
741:
742:
747: public int getDomainAxisCount() {
748: return this.domainAxes.size();
749: }
750:
751:
755: public void clearDomainAxes() {
756: for (int i = 0; i < this.domainAxes.size(); i++) {
757: ValueAxis axis = (ValueAxis) this.domainAxes.get(i);
758: if (axis != null) {
759: axis.removeChangeListener(this);
760: }
761: }
762: this.domainAxes.clear();
763: notifyListeners(new PlotChangeEvent(this));
764: }
765:
766:
769: public void configureDomainAxes() {
770: for (int i = 0; i < this.domainAxes.size(); i++) {
771: ValueAxis axis = (ValueAxis) this.domainAxes.get(i);
772: if (axis != null) {
773: axis.configure();
774: }
775: }
776: }
777:
778:
787: public AxisLocation getDomainAxisLocation(int index) {
788: AxisLocation result = null;
789: if (index < this.domainAxisLocations.size()) {
790: result = (AxisLocation) this.domainAxisLocations.get(index);
791: }
792: if (result == null) {
793: result = AxisLocation.getOpposite(getDomainAxisLocation());
794: }
795: return result;
796: }
797:
798:
805: public void setDomainAxisLocation(int index, AxisLocation location) {
806: this.domainAxisLocations.set(index, location);
807: notifyListeners(new PlotChangeEvent(this));
808: }
809:
810:
817: public RectangleEdge getDomainAxisEdge(int index) {
818: AxisLocation location = getDomainAxisLocation(index);
819: RectangleEdge result = Plot.resolveDomainAxisLocation(
820: location, this.orientation
821: );
822: if (result == null) {
823: result = RectangleEdge.opposite(getDomainAxisEdge());
824: }
825: return result;
826: }
827:
828:
835: public ValueAxis getRangeAxis() {
836: return getRangeAxis(0);
837: }
838:
839:
846: public void setRangeAxis(ValueAxis axis) {
847:
848: if (axis != null) {
849: axis.setPlot(this);
850: }
851:
852:
853: ValueAxis existing = getRangeAxis();
854: if (existing != null) {
855: existing.removeChangeListener(this);
856: }
857:
858: this.rangeAxes.set(0, axis);
859: if (axis != null) {
860: axis.configure();
861: axis.addChangeListener(this);
862: }
863: notifyListeners(new PlotChangeEvent(this));
864:
865: }
866:
867:
872: public AxisLocation getRangeAxisLocation() {
873: return (AxisLocation) this.rangeAxisLocations.get(0);
874: }
875:
876:
882: public void setRangeAxisLocation(AxisLocation location) {
883:
884: setRangeAxisLocation(location, true);
885: }
886:
887:
894: public void setRangeAxisLocation(AxisLocation location, boolean notify) {
895: if (location == null) {
896: throw new IllegalArgumentException("Null 'location' argument.");
897: }
898: this.rangeAxisLocations.set(0, location);
899: if (notify) {
900: notifyListeners(new PlotChangeEvent(this));
901: }
902:
903: }
904:
905:
910: public RectangleEdge getRangeAxisEdge() {
911: return Plot.resolveRangeAxisLocation(
912: getRangeAxisLocation(), this.orientation
913: );
914: }
915:
916:
923: public ValueAxis getRangeAxis(int index) {
924: ValueAxis result = null;
925: if (index < this.rangeAxes.size()) {
926: result = (ValueAxis) this.rangeAxes.get(index);
927: }
928: if (result == null) {
929: Plot parent = getParent();
930: if (parent instanceof XYPlot) {
931: XYPlot xy = (XYPlot) parent;
932: result = xy.getRangeAxis(index);
933: }
934: }
935: return result;
936: }
937:
938:
945: public void setRangeAxis(int index, ValueAxis axis) {
946: setRangeAxis(index, axis, true);
947: }
948:
949:
957: public void setRangeAxis(int index, ValueAxis axis, boolean notify) {
958: ValueAxis existing = getRangeAxis(index);
959: if (existing != null) {
960: existing.removeChangeListener(this);
961: }
962: if (axis != null) {
963: axis.setPlot(this);
964: }
965: this.rangeAxes.set(index, axis);
966: if (axis != null) {
967: axis.configure();
968: axis.addChangeListener(this);
969: }
970: if (notify) {
971: notifyListeners(new PlotChangeEvent(this));
972: }
973: }
974:
975:
981: public void setRangeAxes(ValueAxis[] axes) {
982: for (int i = 0; i < axes.length; i++) {
983: setRangeAxis(i, axes[i], false);
984: }
985: notifyListeners(new PlotChangeEvent(this));
986: }
987:
988:
993: public int getRangeAxisCount() {
994: return this.rangeAxes.size();
995: }
996:
997:
1001: public void clearRangeAxes() {
1002: for (int i = 0; i < this.rangeAxes.size(); i++) {
1003: ValueAxis axis = (ValueAxis) this.rangeAxes.get(i);
1004: if (axis != null) {
1005: axis.removeChangeListener(this);
1006: }
1007: }
1008: this.rangeAxes.clear();
1009: notifyListeners(new PlotChangeEvent(this));
1010: }
1011:
1012:
1015: public void configureRangeAxes() {
1016: for (int i = 0; i < this.rangeAxes.size(); i++) {
1017: ValueAxis axis = (ValueAxis) this.rangeAxes.get(i);
1018: if (axis != null) {
1019: axis.configure();
1020: }
1021: }
1022: }
1023:
1024:
1033: public AxisLocation getRangeAxisLocation(int index) {
1034: AxisLocation result = null;
1035: if (index < this.rangeAxisLocations.size()) {
1036: result = (AxisLocation) this.rangeAxisLocations.get(index);
1037: }
1038: if (result == null) {
1039: result = AxisLocation.getOpposite(getRangeAxisLocation());
1040: }
1041: return result;
1042: }
1043:
1044:
1051: public void setRangeAxisLocation(int index, AxisLocation location) {
1052: this.rangeAxisLocations.set(index, location);
1053: notifyListeners(new PlotChangeEvent(this));
1054: }
1055:
1056:
1063: public RectangleEdge getRangeAxisEdge(int index) {
1064: AxisLocation location = getRangeAxisLocation(index);
1065: RectangleEdge result = Plot.resolveRangeAxisLocation(
1066: location, this.orientation
1067: );
1068: if (result == null) {
1069: result = RectangleEdge.opposite(getRangeAxisEdge());
1070: }
1071: return result;
1072: }
1073:
1074:
1079: public XYDataset getDataset() {
1080: return getDataset(0);
1081: }
1082:
1083:
1090: public XYDataset getDataset(int index) {
1091: XYDataset result = null;
1092: if (this.datasets.size() > index) {
1093: result = (XYDataset) this.datasets.get(index);
1094: }
1095: return result;
1096: }
1097:
1098:
1104: public void setDataset(XYDataset dataset) {
1105: setDataset(0, dataset);
1106: }
1107:
1108:
1114: public void setDataset(int index, XYDataset dataset) {
1115: XYDataset existing = getDataset(index);
1116: if (existing != null) {
1117: existing.removeChangeListener(this);
1118: }
1119: this.datasets.set(index, dataset);
1120: if (dataset != null) {
1121: dataset.addChangeListener(this);
1122: }
1123:
1124:
1125: DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
1126: datasetChanged(event);
1127: }
1128:
1129:
1134: public int getDatasetCount() {
1135: return this.datasets.size();
1136: }
1137:
1138:
1146: public int indexOf(XYDataset dataset) {
1147: int result = -1;
1148: for (int i = 0; i < this.datasets.size(); i++) {
1149: if (dataset == this.datasets.get(i)) {
1150: result = i;
1151: break;
1152: }
1153: }
1154: return result;
1155: }
1156:
1157:
1164: public void mapDatasetToDomainAxis(int index, int axisIndex) {
1165: this.datasetToDomainAxisMap.put(
1166: new Integer(index), new Integer(axisIndex)
1167: );
1168:
1169: datasetChanged(new DatasetChangeEvent(this, getDataset(index)));
1170: }
1171:
1172:
1179: public void mapDatasetToRangeAxis(int index, int axisIndex) {
1180: this.datasetToRangeAxisMap.put(
1181: new Integer(index), new Integer(axisIndex)
1182: );
1183:
1184: datasetChanged(new DatasetChangeEvent(this, getDataset(index)));
1185: }
1186:
1187:
1192: public XYItemRenderer getRenderer() {
1193: return getRenderer(0);
1194: }
1195:
1196:
1203: public XYItemRenderer getRenderer(int index) {
1204: XYItemRenderer result = null;
1205: if (this.renderers.size() > index) {
1206: result = (XYItemRenderer) this.renderers.get(index);
1207: }
1208: return result;
1209:
1210: }
1211:
1212:
1219: public void setRenderer(XYItemRenderer renderer) {
1220: setRenderer(0, renderer);
1221: }
1222:
1223:
1230: public void setRenderer(int index, XYItemRenderer renderer) {
1231: setRenderer(index, renderer, true);
1232: }
1233:
1234:
1242: public void setRenderer(int index, XYItemRenderer renderer,
1243: boolean notify) {
1244: XYItemRenderer existing = getRenderer(index);
1245: if (existing != null) {
1246: existing.removeChangeListener(this);
1247: }
1248: this.renderers.set(index, renderer);
1249: if (renderer != null) {
1250: renderer.setPlot(this);
1251: renderer.addChangeListener(this);
1252: }
1253: configureDomainAxes();
1254: configureRangeAxes();
1255: if (notify) {
1256: notifyListeners(new PlotChangeEvent(this));
1257: }
1258: }
1259:
1260:
1266: public void setRenderers(XYItemRenderer[] renderers) {
1267: for (int i = 0; i < renderers.length; i++) {
1268: setRenderer(i, renderers[i], false);
1269: }
1270: notifyListeners(new PlotChangeEvent(this));
1271: }
1272:
1273:
1278: public DatasetRenderingOrder getDatasetRenderingOrder() {
1279: return this.datasetRenderingOrder;
1280: }
1281:
1282:
1290: public void setDatasetRenderingOrder(DatasetRenderingOrder order) {
1291: if (order == null) {
1292: throw new IllegalArgumentException("Null 'order' argument.");
1293: }
1294: this.datasetRenderingOrder = order;
1295: notifyListeners(new PlotChangeEvent(this));
1296: }
1297:
1298:
1303: public SeriesRenderingOrder getSeriesRenderingOrder() {
1304: return this.seriesRenderingOrder;
1305: }
1306:
1307:
1315: public void setSeriesRenderingOrder(SeriesRenderingOrder order) {
1316: if (order == null) {
1317: throw new IllegalArgumentException("Null 'order' argument.");
1318: }
1319: this.seriesRenderingOrder = order;
1320: notifyListeners(new PlotChangeEvent(this));
1321: }
1322:
1323:
1331: public int getIndexOf(XYItemRenderer renderer) {
1332: return this.renderers.indexOf(renderer);
1333: }
1334:
1335:
1344: public XYItemRenderer getRendererForDataset(XYDataset dataset) {
1345: XYItemRenderer result = null;
1346: for (int i = 0; i < this.datasets.size(); i++) {
1347: if (this.datasets.get(i) == dataset) {
1348: result = (XYItemRenderer) this.renderers.get(i);
1349: if (result == null) {
1350: result = getRenderer();
1351: }
1352: break;
1353: }
1354: }
1355: return result;
1356: }
1357:
1358:
1364: public int getWeight() {
1365: return this.weight;
1366: }
1367:
1368:
1373: public void setWeight(int weight) {
1374: this.weight = weight;
1375: }
1376:
1377:
1383: public boolean isDomainGridlinesVisible() {
1384: return this.domainGridlinesVisible;
1385: }
1386:
1387:
1396: public void setDomainGridlinesVisible(boolean visible) {
1397: if (this.domainGridlinesVisible != visible) {
1398: this.domainGridlinesVisible = visible;
1399: notifyListeners(new PlotChangeEvent(this));
1400: }
1401: }
1402:
1403:
1409: public Stroke getDomainGridlineStroke() {
1410: return this.domainGridlineStroke;
1411: }
1412:
1413:
1420: public void setDomainGridlineStroke(Stroke stroke) {
1421: this.domainGridlineStroke = stroke;
1422: notifyListeners(new PlotChangeEvent(this));
1423: }
1424:
1425:
1431: public Paint getDomainGridlinePaint() {
1432: return this.domainGridlinePaint;
1433: }
1434:
1435:
1442: public void setDomainGridlinePaint(Paint paint) {
1443: this.domainGridlinePaint = paint;
1444: notifyListeners(new PlotChangeEvent(this));
1445: }
1446:
1447:
1453: public boolean isRangeGridlinesVisible() {
1454: return this.rangeGridlinesVisible;
1455: }
1456:
1457:
1466: public void setRangeGridlinesVisible(boolean visible) {
1467: if (this.rangeGridlinesVisible != visible) {
1468: this.rangeGridlinesVisible = visible;
1469: notifyListeners(new PlotChangeEvent(this));
1470: }
1471: }
1472:
1473:
1479: public Stroke getRangeGridlineStroke() {
1480: return this.rangeGridlineStroke;
1481: }
1482:
1483:
1489: public void setRangeGridlineStroke(Stroke stroke) {
1490: if (stroke == null) {
1491: throw new IllegalArgumentException("Null 'stroke' argument.");
1492: }
1493: this.rangeGridlineStroke = stroke;
1494: notifyListeners(new PlotChangeEvent(this));
1495: }
1496:
1497:
1503: public Paint getRangeGridlinePaint() {
1504: return this.rangeGridlinePaint;
1505: }
1506:
1507:
1513: public void setRangeGridlinePaint(Paint paint) {
1514: this.rangeGridlinePaint = paint;
1515: notifyListeners(new PlotChangeEvent(this));
1516: }
1517:
1518:
1524: public boolean isRangeZeroBaselineVisible() {
1525: return this.rangeZeroBaselineVisible;
1526: }
1527:
1528:
1535: public void setRangeZeroBaselineVisible(boolean visible) {
1536: this.rangeZeroBaselineVisible = visible;
1537: notifyListeners(new PlotChangeEvent(this));
1538: }
1539:
1540:
1545: public Stroke getRangeZeroBaselineStroke() {
1546: return this.rangeZeroBaselineStroke;
1547: }
1548:
1549:
1555: public void setRangeZeroBaselineStroke(Stroke stroke) {
1556: if (stroke == null) {
1557: throw new IllegalArgumentException("Null 'stroke' argument.");
1558: }
1559: this.rangeZeroBaselineStroke = stroke;
1560: notifyListeners(new PlotChangeEvent(this));
1561: }
1562:
1563:
1569: public Paint getRangeZeroBaselinePaint() {
1570: return this.rangeZeroBaselinePaint;
1571: }
1572:
1573:
1579: public void setRangeZeroBaselinePaint(Paint paint) {
1580: this.rangeZeroBaselinePaint = paint;
1581: notifyListeners(new PlotChangeEvent(this));
1582: }
1583:
1584:
1590: public Paint getDomainTickBandPaint() {
1591: return this.domainTickBandPaint;
1592: }
1593:
1594:
1599: public void setDomainTickBandPaint(Paint paint) {
1600: this.domainTickBandPaint = paint;
1601: notifyListeners(new PlotChangeEvent(this));
1602: }
1603:
1604:
1610: public Paint getRangeTickBandPaint() {
1611: return this.rangeTickBandPaint;
1612: }
1613:
1614:
1619: public void setRangeTickBandPaint(Paint paint) {
1620: this.rangeTickBandPaint = paint;
1621: notifyListeners(new PlotChangeEvent(this));
1622: }
1623:
1624:
1630: public Point2D getQuadrantOrigin() {
1631: return this.quadrantOrigin;
1632: }
1633:
1634:
1640: public void setQuadrantOrigin(Point2D origin) {
1641: if (origin == null) {
1642: throw new IllegalArgumentException("Null 'origin' argument.");
1643: }
1644: this.quadrantOrigin = origin;
1645: notifyListeners(new PlotChangeEvent(this));
1646: }
1647:
1648:
1655: public Paint getQuadrantPaint(int index) {
1656: if (index < 0 || index > 3) {
1657: throw new IllegalArgumentException(
1658: "The index should be in the range 0 to 3."
1659: );
1660: }
1661: return this.quadrantPaint[index];
1662: }
1663:
1664:
1671: public void setQuadrantPaint(int index, Paint paint) {
1672: if (index < 0 || index > 3) {
1673: throw new IllegalArgumentException(
1674: "The index should be in the range 0 to 3."
1675: );
1676: }
1677: this.quadrantPaint[index] = paint;
1678: notifyListeners(new PlotChangeEvent(this));
1679: }
1680:
1681:
1690: public void addDomainMarker(Marker marker) {
1691:
1692: addDomainMarker(marker, Layer.FOREGROUND);
1693: }
1694:
1695:
1705: public void addDomainMarker(Marker marker, Layer layer) {
1706: addDomainMarker(0, marker, layer);
1707: }
1708:
1709:
1713: public void clearDomainMarkers() {
1714: if (this.foregroundDomainMarkers != null) {
1715: this.foregroundDomainMarkers.clear();
1716: }
1717: if (this.backgroundDomainMarkers != null) {
1718: this.backgroundDomainMarkers.clear();
1719: }
1720: notifyListeners(new PlotChangeEvent(this));
1721: }
1722:
1723:
1729: public void clearDomainMarkers(int index) {
1730: Integer key = new Integer(index);
1731: if (this.backgroundDomainMarkers != null) {
1732: Collection markers
1733: = (Collection) this.backgroundDomainMarkers.get(key);
1734: if (markers != null) {
1735: markers.clear();
1736: }
1737: }
1738: if (this.foregroundRangeMarkers != null) {
1739: Collection markers
1740: = (Collection) this.foregroundDomainMarkers.get(key);
1741: if (markers != null) {
1742: markers.clear();
1743: }
1744: }
1745: notifyListeners(new PlotChangeEvent(this));
1746: }
1747:
1748:
1760: public void addDomainMarker(int index, Marker marker, Layer layer) {
1761: Collection markers;
1762: if (layer == Layer.FOREGROUND) {
1763: markers = (Collection) this.foregroundDomainMarkers.get(
1764: new Integer(index)
1765: );
1766: if (markers == null) {
1767: markers = new java.util.ArrayList();
1768: this.foregroundDomainMarkers.put(new Integer(index), markers);
1769: }
1770: markers.add(marker);
1771: }
1772: else if (layer == Layer.BACKGROUND) {
1773: markers = (Collection) this.backgroundDomainMarkers.get(
1774: new Integer(index)
1775: );
1776: if (markers == null) {
1777: markers = new java.util.ArrayList();
1778: this.backgroundDomainMarkers.put(new Integer(index), markers);
1779: }
1780: markers.add(marker);
1781: }
1782: notifyListeners(new PlotChangeEvent(this));
1783: }
1784:
1785:
1794: public void addRangeMarker(Marker marker) {
1795: addRangeMarker(marker, Layer.FOREGROUND);
1796: }
1797:
1798:
1808: public void addRangeMarker(Marker marker, Layer layer) {
1809: addRangeMarker(0, marker, layer);
1810: }
1811:
1812:
1816: public void clearRangeMarkers() {
1817: if (this.foregroundRangeMarkers != null) {
1818: this.foregroundRangeMarkers.clear();
1819: }
1820: if (this.backgroundRangeMarkers != null) {
1821: this.backgroundRangeMarkers.clear();
1822: }
1823: notifyListeners(new PlotChangeEvent(this));
1824: }
1825:
1826:
1837: public void addRangeMarker(int index, Marker marker, Layer layer) {
1838: Collection markers;
1839: if (layer == Layer.FOREGROUND) {
1840: markers = (Collection) this.foregroundRangeMarkers.get(
1841: new Integer(index)
1842: );
1843: if (markers == null) {
1844: markers = new java.util.ArrayList();
1845: this.foregroundRangeMarkers.put(new Integer(index), markers);
1846: }
1847: markers.add(marker);
1848: }
1849: else if (layer == Layer.BACKGROUND) {
1850: markers = (Collection) this.backgroundRangeMarkers.get(
1851: new Integer(index)
1852: );
1853: if (markers == null) {
1854: markers = new java.util.ArrayList();
1855: this.backgroundRangeMarkers.put(new Integer(index), markers);
1856: }
1857: markers.add(marker);
1858: }
1859: notifyListeners(new PlotChangeEvent(this));
1860: }
1861:
1862:
1868: public void clearRangeMarkers(int index) {
1869: Integer key = new Integer(index);
1870: if (this.backgroundRangeMarkers != null) {
1871: Collection markers
1872: = (Collection) this.backgroundRangeMarkers.get(key);
1873: if (markers != null) {
1874: markers.clear();
1875: }
1876: }
1877: if (this.foregroundRangeMarkers != null) {
1878: Collection markers
1879: = (Collection) this.foregroundRangeMarkers.get(key);
1880: if (markers != null) {
1881: markers.clear();
1882: }
1883: }
1884: notifyListeners(new PlotChangeEvent(this));
1885: }
1886:
1887:
1893: public void addAnnotation(XYAnnotation annotation) {
1894: if (annotation == null) {
1895: throw new IllegalArgumentException("Null 'annotation' argument.");
1896: }
1897: this.annotations.add(annotation);
1898: notifyListeners(new PlotChangeEvent(this));
1899: }
1900:
1901:
1909: public boolean removeAnnotation(XYAnnotation annotation) {
1910: if (annotation == null) {
1911: throw new IllegalArgumentException("Null 'annotation' argument.");
1912: }
1913: boolean removed = this.annotations.remove(annotation);
1914: if (removed) {
1915: notifyListeners(new PlotChangeEvent(this));
1916: }
1917: return removed;
1918: }
1919:
1920:
1927: public List getAnnotations() {
1928: return new ArrayList(this.annotations);
1929: }
1930:
1931:
1935: public void clearAnnotations() {
1936: this.annotations.clear();
1937: notifyListeners(new PlotChangeEvent(this));
1938: }
1939:
1940:
1948: protected AxisSpace calculateAxisSpace(Graphics2D g2,
1949: Rectangle2D plotArea) {
1950: AxisSpace space = new AxisSpace();
1951: space = calculateDomainAxisSpace(g2, plotArea, space);
1952: space = calculateRangeAxisSpace(g2, plotArea, space);
1953: return space;
1954: }
1955:
1956:
1965: protected AxisSpace calculateDomainAxisSpace(Graphics2D g2,
1966: Rectangle2D plotArea,
1967: AxisSpace space) {
1968:
1969: if (space == null) {
1970: space = new AxisSpace();
1971: }
1972:
1973:
1974: if (this.fixedDomainAxisSpace != null) {
1975: if (this.orientation == PlotOrientation.HORIZONTAL) {
1976: space.ensureAtLeast(
1977: this.fixedDomainAxisSpace.getLeft(), RectangleEdge.LEFT
1978: );
1979: space.ensureAtLeast(
1980: this.fixedDomainAxisSpace.getRight(), RectangleEdge.RIGHT
1981: );
1982: }
1983: else if (this.orientation == PlotOrientation.VERTICAL) {
1984: space.ensureAtLeast(
1985: this.fixedDomainAxisSpace.getTop(), RectangleEdge.TOP
1986: );
1987: space.ensureAtLeast(
1988: this.fixedDomainAxisSpace.getBottom(), RectangleEdge.BOTTOM
1989: );
1990: }
1991: }
1992: else {
1993:
1994: for (int i = 0; i < this.domainAxes.size(); i++) {
1995: Axis axis = (Axis) this.domainAxes.get(i);
1996: if (axis != null) {
1997: RectangleEdge edge = getDomainAxisEdge(i);
1998: space = axis.reserveSpace(g2, this, plotArea, edge, space);
1999: }
2000: }
2001: }
2002:
2003: return space;
2004:
2005: }
2006:
2007:
2016: protected AxisSpace calculateRangeAxisSpace(Graphics2D g2,
2017: Rectangle2D plotArea,
2018: AxisSpace space) {
2019:
2020: if (space == null) {
2021: space = new AxisSpace();
2022: }
2023:
2024:
2025: if (this.fixedRangeAxisSpace != null) {
2026: if (this.orientation == PlotOrientation.HORIZONTAL) {
2027: space.ensureAtLeast(
2028: this.fixedRangeAxisSpace.getTop(), RectangleEdge.TOP
2029: );
2030: space.ensureAtLeast(
2031: this.fixedRangeAxisSpace.getBottom(), RectangleEdge.BOTTOM
2032: );
2033: }
2034: else if (this.orientation == PlotOrientation.VERTICAL) {
2035: space.ensureAtLeast(
2036: this.fixedRangeAxisSpace.getLeft(), RectangleEdge.LEFT
2037: );
2038: space.ensureAtLeast(
2039: this.fixedRangeAxisSpace.getRight(), RectangleEdge.RIGHT
2040: );
2041: }
2042: }
2043: else {
2044:
2045: for (int i = 0; i < this.rangeAxes.size(); i++) {
2046: Axis axis = (Axis) this.rangeAxes.get(i);
2047: if (axis != null) {
2048: RectangleEdge edge = getRangeAxisEdge(i);
2049: space = axis.reserveSpace(g2, this, plotArea, edge, space);
2050: }
2051: }
2052: }
2053: return space;
2054:
2055: }
2056:
2057:
2069: public void draw(Graphics2D g2,
2070: Rectangle2D area,
2071: Point2D anchor,
2072: PlotState parentState,
2073: PlotRenderingInfo info) {
2074:
2075:
2076: boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW);
2077: boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW);
2078: if (b1 || b2) {
2079: return;
2080: }
2081:
2082:
2083: if (info != null) {
2084: info.setPlotArea(area);
2085: }
2086:
2087:
2088: RectangleInsets insets = getInsets();
2089: insets.trim(area);
2090:
2091: AxisSpace space = calculateAxisSpace(g2, area);
2092: Rectangle2D dataArea = space.shrink(area, null);
2093: this.axisOffset.trim(dataArea);
2094:
2095: if (info != null) {
2096: info.setDataArea(dataArea);
2097: }
2098:
2099:
2100: drawBackground(g2, dataArea);
2101: Map axisStateMap = drawAxes(g2, area, dataArea, info);
2102:
2103: if (anchor != null && !dataArea.contains(anchor)) {
2104: anchor = null;
2105: }
2106: CrosshairState crosshairState = new CrosshairState();
2107: crosshairState.setCrosshairDistance(Double.POSITIVE_INFINITY);
2108: crosshairState.setAnchor(anchor);
2109: crosshairState.setCrosshairX(getDomainCrosshairValue());
2110: crosshairState.setCrosshairY(getRangeCrosshairValue());
2111: Shape originalClip = g2.getClip();
2112: Composite originalComposite = g2.getComposite();
2113:
2114: g2.clip(dataArea);
2115: g2.setComposite(
2116: AlphaComposite.getInstance(
2117: AlphaComposite.SRC_OVER, getForegroundAlpha()
2118: )
2119: );
2120:
2121: AxisState domainAxisState
2122: = (AxisState) axisStateMap.get(getDomainAxis());
2123: if (domainAxisState == null) {
2124: if (parentState != null) {
2125: domainAxisState
2126: = (AxisState) parentState.getSharedAxisStates().get(
2127: getDomainAxis()
2128: );
2129: }
2130: }
2131:
2132: AxisState rangeAxisState = (AxisState) axisStateMap.get(getRangeAxis());
2133: if (rangeAxisState == null) {
2134: if (parentState != null) {
2135: rangeAxisState
2136: = (AxisState) parentState.getSharedAxisStates().get(
2137: getRangeAxis()
2138: );
2139: }
2140: }
2141: if (domainAxisState != null) {
2142: drawDomainTickBands(g2, dataArea, domainAxisState.getTicks());
2143: }
2144: if (rangeAxisState != null) {
2145: drawRangeTickBands(g2, dataArea, rangeAxisState.getTicks());
2146: }
2147: if (domainAxisState != null) {
2148: drawDomainGridlines(g2, dataArea, domainAxisState.getTicks());
2149: }
2150: if (rangeAxisState != null) {
2151: drawRangeGridlines(g2, dataArea, rangeAxisState.getTicks());
2152: drawZeroRangeBaseline(g2, dataArea);
2153: }
2154:
2155:
2156: for (int i = 0; i < this.renderers.size(); i++) {
2157: drawDomainMarkers(g2, dataArea, i, Layer.BACKGROUND);
2158: }
2159: for (int i = 0; i < this.renderers.size(); i++) {
2160: drawRangeMarkers(g2, dataArea, i, Layer.BACKGROUND);
2161: }
2162:
2163:
2164: boolean foundData = false;
2165: DatasetRenderingOrder order = getDatasetRenderingOrder();
2166: if (order == DatasetRenderingOrder.FORWARD) {
2167:
2168:
2169: int rendererCount = this.renderers.size();
2170: for (int i = 0; i < rendererCount; i++) {
2171: XYItemRenderer r = getRenderer(i);
2172: if (r != null) {
2173: ValueAxis domainAxis = getDomainAxisForDataset(i);
2174: ValueAxis rangeAxis = getRangeAxisForDataset(i);
2175: r.drawAnnotations(
2176: g2, dataArea, domainAxis, rangeAxis,
2177: Layer.BACKGROUND, info
2178: );
2179: }
2180: }
2181:
2182:
2183: for (int i = 0; i < getDatasetCount(); i++) {
2184: foundData = render(g2, dataArea, i, info, crosshairState)
2185: || foundData;
2186: }
2187:
2188:
2189: for (int i = 0; i < rendererCount; i++) {
2190: XYItemRenderer r = getRenderer(i);
2191: if (r != null) {
2192: ValueAxis domainAxis = getDomainAxisForDataset(i);
2193: ValueAxis rangeAxis = getRangeAxisForDataset(i);
2194: r.drawAnnotations(
2195: g2, dataArea, domainAxis, rangeAxis,
2196: Layer.FOREGROUND, info
2197: );
2198: }
2199: }
2200:
2201: }
2202: else if (order == DatasetRenderingOrder.REVERSE) {
2203:
2204:
2205: int rendererCount = this.renderers.size();
2206: for (int i = rendererCount - 1; i >= 0; i--) {
2207: XYItemRenderer r = getRenderer(i);
2208: if (r != null) {
2209: ValueAxis domainAxis = getDomainAxisForDataset(i);
2210: ValueAxis rangeAxis = getRangeAxisForDataset(i);
2211: r.drawAnnotations(
2212: g2, dataArea, domainAxis, rangeAxis,
2213: Layer.BACKGROUND, info
2214: );
2215: }
2216: }
2217:
2218: for (int i = getDatasetCount() - 1; i >= 0; i--) {
2219: foundData = render(g2, dataArea, i, info, crosshairState)
2220: || foundData;
2221: }
2222:
2223:
2224: for (int i = rendererCount - 1; i >= 0; i--) {
2225: XYItemRenderer r = getRenderer(i);
2226: if (r != null) {
2227: ValueAxis domainAxis = getDomainAxisForDataset(i);
2228: ValueAxis rangeAxis = getRangeAxisForDataset(i);
2229: r.drawAnnotations(
2230: g2, dataArea, domainAxis, rangeAxis,
2231: Layer.FOREGROUND, info
2232: );
2233: }
2234: }
2235:
2236: }
2237:
2238: PlotOrientation orient = getOrientation();
2239:
2240:
2241: if (!this.domainCrosshairLockedOnData && anchor != null) {
2242: double xx = getDomainAxis().java2DToValue(
2243: anchor.getX(), dataArea, getDomainAxisEdge()
2244: );
2245: crosshairState.setCrosshairX(xx);
2246: }
2247: setDomainCrosshairValue(crosshairState.getCrosshairX(), false);
2248: if (isDomainCrosshairVisible()) {
2249: double x = getDomainCrosshairValue();
2250: Paint paint = getDomainCrosshairPaint();
2251: Stroke stroke = getDomainCrosshairStroke();
2252: if (orient == PlotOrientation.HORIZONTAL) {
2253: drawHorizontalLine(g2, dataArea, x, stroke, paint);
2254: }
2255: else if (orient == PlotOrientation.VERTICAL) {
2256: drawVerticalLine(g2, dataArea, x, stroke, paint);
2257: }
2258: }
2259:
2260:
2261: if (!this.rangeCrosshairLockedOnData && anchor != null) {
2262: double yy = getRangeAxis().java2DToValue(
2263: anchor.getY(), dataArea, getRangeAxisEdge()
2264: );
2265: crosshairState.setCrosshairY(yy);
2266: }
2267: setRangeCrosshairValue(crosshairState.getCrosshairY(), false);
2268: if (isRangeCrosshairVisible()
2269: && getRangeAxis().getRange().contains(getRangeCrosshairValue())) {
2270: double y = getRangeCrosshairValue();
2271: Paint paint = getRangeCrosshairPaint();
2272: Stroke stroke = getRangeCrosshairStroke();
2273: if (orient == PlotOrientation.HORIZONTAL) {
2274: drawVerticalLine(g2, dataArea, y, stroke, paint);
2275: }
2276: else if (orient == PlotOrientation.VERTICAL) {
2277: drawHorizontalLine(g2, dataArea, y, stroke, paint);
2278: }
2279: }
2280:
2281: if (!foundData) {
2282: drawNoDataMessage(g2, dataArea);
2283: }
2284:
2285: for (int i = 0; i < this.renderers.size(); i++) {
2286: drawDomainMarkers(g2, dataArea, i, Layer.FOREGROUND);
2287: }
2288: for (int i = 0; i < this.renderers.size(); i++) {
2289: drawRangeMarkers(g2, dataArea, i, Layer.FOREGROUND);
2290: }
2291:
2292: drawAnnotations(g2, dataArea, info);
2293: g2.setClip(originalClip);
2294: g2.setComposite(originalComposite);
2295:
2296: drawOutline(g2, dataArea);
2297:
2298: }
2299:
2300:
2306: public void drawBackground(Graphics2D g2, Rectangle2D area) {
2307: fillBackground(g2, area);
2308: drawQuadrants(g2, area);
2309: drawBackgroundImage(g2, area);
2310: }
2311:
2312:
2318: protected void drawQuadrants(Graphics2D g2, Rectangle2D area) {
2319:
2320:
2321:
2322: boolean somethingToDraw = false;
2323:
2324: ValueAxis xAxis = getDomainAxis();
2325: double x = this.quadrantOrigin.getX();
2326: double xx = xAxis.valueToJava2D(x, area, getDomainAxisEdge());
2327:
2328: ValueAxis yAxis = getRangeAxis();
2329: double y = this.quadrantOrigin.getY();
2330: double yy = yAxis.valueToJava2D(y, area, getRangeAxisEdge());
2331:
2332: double xmin = xAxis.getLowerBound();
2333: double xxmin = xAxis.valueToJava2D(xmin, area, getDomainAxisEdge());
2334:
2335: double xmax = xAxis.getUpperBound();
2336: double xxmax = xAxis.valueToJava2D(xmax, area, getDomainAxisEdge());
2337:
2338: double ymin = yAxis.getLowerBound();
2339: double yymin = yAxis.valueToJava2D(ymin, area, getRangeAxisEdge());
2340:
2341: double ymax = yAxis.getUpperBound();
2342: double yymax = yAxis.valueToJava2D(ymax, area, getRangeAxisEdge());
2343:
2344: Rectangle2D[] r = new Rectangle2D[] {null, null, null, null};
2345: if (this.quadrantPaint[0] != null) {
2346: if (x > xmin && y < ymax) {
2347: if (this.orientation == PlotOrientation.HORIZONTAL) {
2348: r[0] = new Rectangle2D.Double(
2349: Math.min(yymax, yy), Math.min(xxmin, xx),
2350: Math.abs(yy - yymax), Math.abs(xx - xxmin)
2351: );
2352: }
2353: else {
2354: r[0] = new Rectangle2D.Double(
2355: Math.min(xxmin, xx), Math.min(yymax, yy),
2356: Math.abs(xx - xxmin), Math.abs(yy - yymax)
2357: );
2358: }
2359: somethingToDraw = true;
2360: }
2361: }
2362: if (this.quadrantPaint[1] != null) {
2363: if (x < xmax && y < ymax) {
2364: if (this.orientation == PlotOrientation.HORIZONTAL) {
2365: r[1] = new Rectangle2D.Double(
2366: Math.min(yymax, yy), Math.min(xxmax, xx),
2367: Math.abs(yy - yymax), Math.abs(xx - xxmax)
2368: );
2369: }
2370: else {
2371: r[1] = new Rectangle2D.Double(
2372: Math.min(xx, xxmax), Math.min(yymax, yy),
2373: Math.abs(xx - xxmax), Math.abs(yy - yymax)
2374: );
2375: }
2376: somethingToDraw = true;
2377: }
2378: }
2379: if (this.quadrantPaint[2] != null) {
2380: if (x > xmin && y > ymin) {
2381: if (this.orientation == PlotOrientation.HORIZONTAL) {
2382: r[2] = new Rectangle2D.Double(
2383: Math.min(yymin, yy), Math.min(xxmin, xx),
2384: Math.abs(yy - yymin), Math.abs(xx - xxmin)
2385: );
2386: }
2387: else {
2388: r[2] = new Rectangle2D.Double(
2389: Math.min(xxmin, xx), Math.min(yymin, yy),
2390: Math.abs(xx - xxmin), Math.abs(yy - yymin)
2391: );
2392: }
2393: somethingToDraw = true;
2394: }
2395: }
2396: if (this.quadrantPaint[3] != null) {
2397: if (x < xmax && y > ymin) {
2398: if (this.orientation == PlotOrientation.HORIZONTAL) {
2399: r[3] = new Rectangle2D.Double(
2400: Math.min(yymin, yy), Math.min(xxmax, xx),
2401: Math.abs(yy - yymin), Math.abs(xx - xxmax)
2402: );
2403: }
2404: else {
2405: r[3] = new Rectangle2D.Double(
2406: Math.min(xx, xxmax), Math.min(yymin, yy),
2407: Math.abs(xx - xxmax), Math.abs(yy - yymin)
2408: );
2409: }
2410: somethingToDraw = true;
2411: }
2412: }
2413: if (somethingToDraw) {
2414: Composite originalComposite = g2.getComposite();
2415: g2.setComposite(
2416: AlphaComposite.getInstance(
2417: AlphaComposite.SRC_OVER, getBackgroundAlpha()
2418: )
2419: );
2420: for (int i = 0; i < 4; i++) {
2421: if (this.quadrantPaint[i] != null && r[i] != null) {
2422: g2.setPaint(this.quadrantPaint[i]);
2423: g2.fill(r[i]);
2424: }
2425: }
2426: g2.setComposite(originalComposite);
2427: }
2428: }
2429:
2430:
2437: public void drawDomainTickBands(Graphics2D g2, Rectangle2D dataArea,
2438: List ticks) {
2439:
2440: Paint bandPaint = getDomainTickBandPaint();
2441: if (bandPaint != null) {
2442: boolean fillBand = false;
2443: ValueAxis xAxis = getDomainAxis();
2444: double previous = xAxis.getLowerBound();
2445: Iterator iterator = ticks.iterator();
2446: while (iterator.hasNext()) {
2447: ValueTick tick = (ValueTick) iterator.next();
2448: double current = tick.getValue();
2449: if (fillBand) {
2450: getRenderer().fillDomainGridBand(
2451: g2, this, xAxis, dataArea, previous, current
2452: );
2453: }
2454: previous = current;
2455: fillBand = !fillBand;
2456: }
2457: double end = xAxis.getUpperBound();
2458: if (fillBand) {
2459: getRenderer().fillDomainGridBand(
2460: g2, this, xAxis, dataArea, previous, end
2461: );
2462: }
2463: }
2464: }
2465:
2466:
2473: public void drawRangeTickBands(Graphics2D g2, Rectangle2D dataArea,
2474: List ticks) {
2475:
2476:
2477: Paint bandPaint = getRangeTickBandPaint();
2478: if (bandPaint != null) {
2479: boolean fillBand = false;
2480: ValueAxis axis = getRangeAxis();
2481: double previous = axis.getLowerBound();
2482: Iterator iterator = ticks.iterator();
2483: while (iterator.hasNext()) {
2484: ValueTick tick = (ValueTick) iterator.next();
2485: double current = tick.getValue();
2486: if (fillBand) {
2487: getRenderer().fillRangeGridBand(
2488: g2, this, axis, dataArea, previous, current
2489: );
2490: }
2491: previous = current;
2492: fillBand = !fillBand;
2493: }
2494: double end = axis.getUpperBound();
2495: if (fillBand) {
2496: getRenderer().fillRangeGridBand(
2497: g2, this, axis, dataArea, previous, end
2498: );
2499: }
2500: }
2501: }
2502:
2503:
2514: protected Map drawAxes(Graphics2D g2,
2515: Rectangle2D plotArea,
2516: Rectangle2D dataArea,
2517: PlotRenderingInfo plotState) {
2518:
2519: AxisCollection axisCollection = new AxisCollection();
2520:
2521:
2522: for (int index = 0; index < this.domainAxes.size(); index++) {
2523: ValueAxis axis = (ValueAxis) this.domainAxes.get(index);
2524: if (axis != null) {
2525: axisCollection.add(axis, getDomainAxisEdge(index));
2526: }
2527: }
2528:
2529:
2530: for (int index = 0; index < this.rangeAxes.size(); index++) {
2531: ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(index);
2532: if (yAxis != null) {
2533: axisCollection.add(yAxis, getRangeAxisEdge(index));
2534: }
2535: }
2536:
2537: Map axisStateMap = new HashMap();
2538:
2539:
2540: double cursor = dataArea.getMinY() - this.axisOffset.calculateTopOutset(
2541: dataArea.getHeight()
2542: );
2543: Iterator iterator = axisCollection.getAxesAtTop().iterator();
2544: while (iterator.hasNext()) {
2545: ValueAxis axis = (ValueAxis) iterator.next();
2546: AxisState info = axis.draw(
2547: g2, cursor, plotArea, dataArea, RectangleEdge.TOP, plotState
2548: );
2549: cursor = info.getCursor();
2550: axisStateMap.put(axis, info);
2551: }
2552:
2553:
2554: cursor = dataArea.getMaxY()
2555: + this.axisOffset.calculateBottomOutset(dataArea.getHeight());
2556: iterator = axisCollection.getAxesAtBottom().iterator();
2557: while (iterator.hasNext()) {
2558: ValueAxis axis = (ValueAxis) iterator.next();
2559: AxisState info = axis.draw(
2560: g2, cursor, plotArea, dataArea, RectangleEdge.BOTTOM, plotState
2561: );
2562: cursor = info.getCursor();
2563: axisStateMap.put(axis, info);
2564: }
2565:
2566:
2567: cursor = dataArea.getMinX()
2568: - this.axisOffset.calculateLeftOutset(dataArea.getWidth());
2569: iterator = axisCollection.getAxesAtLeft().iterator();
2570: while (iterator.hasNext()) {
2571: ValueAxis axis = (ValueAxis) iterator.next();
2572: AxisState info = axis.draw(
2573: g2, cursor, plotArea, dataArea, RectangleEdge.LEFT, plotState
2574: );
2575: cursor = info.getCursor();
2576: axisStateMap.put(axis, info);
2577: }
2578:
2579:
2580: cursor = dataArea.getMaxX()
2581: + this.axisOffset.calculateRightOutset(dataArea.getWidth());
2582: iterator = axisCollection.getAxesAtRight().iterator();
2583: while (iterator.hasNext()) {
2584: ValueAxis axis = (ValueAxis) iterator.next();
2585: AxisState info = axis.draw(
2586: g2, cursor, plotArea, dataArea, RectangleEdge.RIGHT, plotState
2587: );
2588: cursor = info.getCursor();
2589: axisStateMap.put(axis, info);
2590: }
2591:
2592: return axisStateMap;
2593: }
2594:
2595:
2611: public boolean render(Graphics2D g2,
2612: Rectangle2D dataArea,
2613: int index,
2614: PlotRenderingInfo info,
2615: CrosshairState crosshairState) {
2616:
2617: boolean foundData = false;
2618: XYDataset dataset = getDataset(index);
2619: if (!DatasetUtilities.isEmptyOrNull(dataset)) {
2620: foundData = true;
2621: ValueAxis xAxis = getDomainAxisForDataset(index);
2622: ValueAxis yAxis = getRangeAxisForDataset(index);
2623: XYItemRenderer renderer = getRenderer(index);
2624: if (renderer == null) {
2625: renderer = getRenderer();
2626: }
2627:
2628: XYItemRendererState state = renderer.initialise(
2629: g2, dataArea, this, dataset, info
2630: );
2631: int passCount = renderer.getPassCount();
2632:
2633: SeriesRenderingOrder seriesOrder = getSeriesRenderingOrder();
2634: if (seriesOrder == SeriesRenderingOrder.REVERSE) {
2635:
2636: for (int pass = 0; pass < passCount; pass++) {
2637: int seriesCount = dataset.getSeriesCount();
2638: for (int series = seriesCount-1; series >= 0 ; series--) {
2639: int itemCount = dataset.getItemCount(series);
2640: for (int item = 0; item < itemCount; item++) {
2641: renderer.drawItem(
2642: g2, state, dataArea, info,
2643: this, xAxis, yAxis, dataset, series, item,
2644: crosshairState, pass
2645: );
2646: }
2647: }
2648: }
2649: }
2650: else {
2651:
2652: for (int pass = 0; pass < passCount; pass++) {
2653: int seriesCount = dataset.getSeriesCount();
2654: for (int series = 0; series < seriesCount; series++) {
2655: int itemCount = dataset.getItemCount(series);
2656: for (int item = 0; item < itemCount; item++) {
2657: renderer.drawItem(
2658: g2, state, dataArea, info,
2659: this, xAxis, yAxis, dataset, series, item,
2660: crosshairState, pass
2661: );
2662: }
2663: }
2664: }
2665: }
2666: }
2667: return foundData;
2668: }
2669:
2670:
2677: public ValueAxis getDomainAxisForDataset(int index) {
2678:
2679: if (index < 0 || index >= getDatasetCount()) {
2680: throw new IllegalArgumentException("Index 'index' out of bounds.");
2681: }
2682:
2683: ValueAxis valueAxis = null;
2684: Integer axisIndex = (Integer) this.datasetToDomainAxisMap.get(
2685: new Integer(index)
2686: );
2687: if (axisIndex != null) {
2688: valueAxis = getDomainAxis(axisIndex.intValue());
2689: }
2690: else {
2691: valueAxis = getDomainAxis(0);
2692: }
2693: return valueAxis;
2694:
2695: }
2696:
2697:
2704: public ValueAxis getRangeAxisForDataset(int index) {
2705:
2706: if (index < 0 || index >= getDatasetCount()) {
2707: throw new IllegalArgumentException("Index 'index' out of bounds.");
2708: }
2709:
2710: ValueAxis valueAxis = null;
2711: Integer axisIndex
2712: = (Integer) this.datasetToRangeAxisMap.get(new Integer(index));
2713: if (axisIndex != null) {
2714: valueAxis = getRangeAxis(axisIndex.intValue());
2715: }
2716: else {
2717: valueAxis = getRangeAxis(0);
2718: }
2719: return valueAxis;
2720:
2721: }
2722:
2723:
2730: protected void drawDomainGridlines(Graphics2D g2, Rectangle2D dataArea,
2731: List ticks) {
2732:
2733:
2734: if (getRenderer() == null) {
2735: return;
2736: }
2737:
2738:
2739: if (isDomainGridlinesVisible()) {
2740: Stroke gridStroke = getDomainGridlineStroke();
2741: Paint gridPaint = getDomainGridlinePaint();
2742: if ((gridStroke != null) && (gridPaint != null)) {
2743: Iterator iterator = ticks.iterator();
2744: while (iterator.hasNext()) {
2745: ValueTick tick = (ValueTick) iterator.next();
2746: getRenderer().drawDomainGridLine(
2747: g2, this, getDomainAxis(), dataArea, tick.getValue()
2748: );
2749: }
2750: }
2751: }
2752: }
2753:
2754:
2762: protected void drawRangeGridlines(Graphics2D g2, Rectangle2D area,
2763: List ticks) {
2764:
2765:
2766: if (isRangeGridlinesVisible()) {
2767: Stroke gridStroke = getRangeGridlineStroke();
2768: Paint gridPaint = getRangeGridlinePaint();
2769: ValueAxis axis = getRangeAxis();
2770: if (axis != null) {
2771: Iterator iterator = ticks.iterator();
2772: while (iterator.hasNext()) {
2773: ValueTick tick = (ValueTick) iterator.next();
2774: if (tick.getValue() != 0.0
2775: || !isRangeZeroBaselineVisible()) {
2776: getRenderer().drawRangeLine(
2777: g2, this, getRangeAxis(), area,
2778: tick.getValue(), gridPaint, gridStroke
2779: );
2780: }
2781: }
2782: }
2783: }
2784: }
2785:
2786:
2792: protected void drawZeroRangeBaseline(Graphics2D g2, Rectangle2D area) {
2793: if (isRangeZeroBaselineVisible()) {
2794: getRenderer().drawRangeLine(
2795: g2, this, getRangeAxis(), area,
2796: 0.0, this.rangeZeroBaselinePaint, this.rangeZeroBaselineStroke
2797: );
2798: }
2799: }
2800:
2801:
2808: public void drawAnnotations(Graphics2D g2,
2809: Rectangle2D dataArea,
2810: PlotRenderingInfo info) {
2811:
2812: Iterator iterator = this.annotations.iterator();
2813: while (iterator.hasNext()) {
2814: XYAnnotation annotation = (XYAnnotation) iterator.next();
2815: ValueAxis xAxis = getDomainAxis();
2816: ValueAxis yAxis = getRangeAxis();
2817: annotation.draw(g2, this, dataArea, xAxis, yAxis, 0, info);
2818: }
2819:
2820: }
2821:
2822:
2831: protected void drawDomainMarkers(Graphics2D g2, Rectangle2D dataArea,
2832: int index, Layer layer) {
2833:
2834: XYItemRenderer r = getRenderer(index);
2835: if (r == null) {
2836: return;
2837: }
2838:
2839: Collection markers = getDomainMarkers(index, layer);
2840: ValueAxis axis = getDomainAxisForDataset(index);
2841: if (markers != null && axis != null) {
2842: Iterator iterator = markers.iterator();
2843: while (iterator.hasNext()) {
2844: Marker marker = (Marker) iterator.next();
2845: r.drawDomainMarker(g2, this, axis, marker, dataArea);
2846: }
2847: }
2848:
2849: }
2850:
2851:
2860: protected void drawRangeMarkers(Graphics2D g2, Rectangle2D dataArea,
2861: int index, Layer layer) {
2862:
2863: XYItemRenderer r = getRenderer(index);
2864: if (r == null) {
2865: return;
2866: }
2867:
2868: Collection markers = getRangeMarkers(index, layer);
2869: ValueAxis axis = getRangeAxis(index);
2870:
2871: if (markers != null && axis != null) {
2872: Iterator iterator = markers.iterator();
2873: while (iterator.hasNext()) {
2874: Marker marker = (Marker) iterator.next();
2875: r.drawRangeMarker(g2, this, axis, marker, dataArea);
2876: }
2877: }
2878:
2879: }
2880:
2881:
2888: public Collection getDomainMarkers(Layer layer) {
2889: return getDomainMarkers(0, layer);
2890: }
2891:
2892:
2899: public Collection getRangeMarkers(Layer layer) {
2900: return getRangeMarkers(0, layer);
2901: }
2902:
2903:
2912: public Collection getDomainMarkers(int index, Layer layer) {
2913: Collection result = null;
2914: Integer key = new Integer(index);
2915: if (layer == Layer.FOREGROUND) {
2916: result = (Collection) this.foregroundDomainMarkers.get(key);
2917: }
2918: else if (layer == Layer.BACKGROUND) {
2919: result = (Collection) this.backgroundDomainMarkers.get(key);
2920: }
2921: if (result != null) {
2922: result = Collections.unmodifiableCollection(result);
2923: }
2924: return result;
2925: }
2926:
2927:
2936: public Collection getRangeMarkers(int index, Layer layer) {
2937: Collection result = null;
2938: Integer key = new Integer(index);
2939: if (layer == Layer.FOREGROUND) {
2940: result = (Collection) this.foregroundRangeMarkers.get(key);
2941: }
2942: else if (layer == Layer.BACKGROUND) {
2943: result = (Collection) this.backgroundRangeMarkers.get(key);
2944: }
2945: if (result != null) {
2946: result = Collections.unmodifiableCollection(result);
2947: }
2948: return result;
2949: }
2950:
2951:
2961: protected void drawHorizontalLine(Graphics2D g2, Rectangle2D dataArea,
2962: double value, Stroke stroke,
2963: Paint paint) {
2964:
2965: ValueAxis axis = getRangeAxis();
2966: if (getOrientation() == PlotOrientation.HORIZONTAL) {
2967: axis = getDomainAxis();
2968: }
2969: if (axis.getRange().contains(value)) {
2970: double yy = axis.valueToJava2D(value, dataArea, RectangleEdge.LEFT);
2971: Line2D line = new Line2D.Double(
2972: dataArea.getMinX(), yy, dataArea.getMaxX(), yy
2973: );
2974: g2.setStroke(stroke);
2975: g2.setPaint(paint);
2976: g2.draw(line);
2977: }
2978:
2979: }
2980:
2981:
2990: protected void drawVerticalLine(Graphics2D g2, Rectangle2D dataArea,
2991: double value, Stroke stroke, Paint paint) {
2992:
2993: ValueAxis axis = getDomainAxis();
2994: if (getOrientation() == PlotOrientation.HORIZONTAL) {
2995: axis = getRangeAxis();
2996: }
2997: if (axis.getRange().contains(value)) {
2998: double xx = axis.valueToJava2D(
2999: value, dataArea, RectangleEdge.BOTTOM
3000: );
3001: Line2D line = new Line2D.Double(
3002: xx, dataArea.getMinY(), xx, dataArea.getMaxY()
3003: );
3004: g2.setStroke(stroke);
3005: g2.setPaint(paint);
3006: g2.draw(line);
3007: }
3008:
3009: }
3010:
3011:
3018: public void handleClick(int x, int y, PlotRenderingInfo info) {
3019:
3020: Rectangle2D dataArea = info.getDataArea();
3021: if (dataArea.contains(x, y)) {
3022:
3023: ValueAxis da = getDomainAxis();
3024: if (da != null) {
3025: double hvalue = da.java2DToValue(
3026: x, info.getDataArea(), getDomainAxisEdge()
3027: );
3028:
3029: setDomainCrosshairValue(hvalue);
3030: }
3031:
3032:
3033: ValueAxis ra = getRangeAxis();
3034: if (ra != null) {
3035: double vvalue = ra.java2DToValue(
3036: y, info.getDataArea(), getRangeAxisEdge()
3037: );
3038: setRangeCrosshairValue(vvalue);
3039: }
3040: }
3041: }
3042:
3043:
3051: private List getDatasetsMappedToDomainAxis(Integer axisIndex) {
3052: if (axisIndex == null) {
3053: throw new IllegalArgumentException("Null 'axisIndex' argument.");
3054: }
3055: List result = new ArrayList();
3056: for (int i = 0; i < this.datasets.size(); i++) {
3057: Integer mappedAxis = (Integer) this.datasetToDomainAxisMap.get(
3058: new Integer(i)
3059: );
3060: if (mappedAxis == null) {
3061: if (axisIndex.equals(ZERO)) {
3062: result.add(this.datasets.get(i));
3063: }
3064: }
3065: else {
3066: if (mappedAxis.equals(axisIndex)) {
3067: result.add(this.datasets.get(i));
3068: }
3069: }
3070: }
3071: return result;
3072: }
3073:
3074:
3082: private List getDatasetsMappedToRangeAxis(Integer axisIndex) {
3083: if (axisIndex == null) {
3084: throw new IllegalArgumentException("Null 'axisIndex' argument.");
3085: }
3086: List result = new ArrayList();
3087: for (int i = 0; i < this.datasets.size(); i++) {
3088: Integer mappedAxis = (Integer) this.datasetToRangeAxisMap.get(
3089: new Integer(i)
3090: );
3091: if (mappedAxis == null) {
3092: if (axisIndex.equals(ZERO)) {
3093: result.add(this.datasets.get(i));
3094: }
3095: }
3096: else {
3097: if (mappedAxis.equals(axisIndex)) {
3098: result.add(this.datasets.get(i));
3099: }
3100: }
3101: }
3102: return result;
3103: }
3104:
3105:
3112: protected int getDomainAxisIndex(ValueAxis axis) {
3113: int result = this.domainAxes.indexOf(axis);
3114: if (result < 0) {
3115:
3116: Plot parent = getParent();
3117: if (parent instanceof XYPlot) {
3118: XYPlot p = (XYPlot) parent;
3119: result = p.getDomainAxisIndex(axis);
3120: }
3121: }
3122: return result;
3123: }
3124:
3125:
3132: protected int getRangeAxisIndex(ValueAxis axis) {
3133: int result = this.rangeAxes.indexOf(axis);
3134: if (result < 0) {
3135:
3136: Plot parent = getParent();
3137: if (parent instanceof XYPlot) {
3138: XYPlot p = (XYPlot) parent;
3139: result = p.getRangeAxisIndex(axis);
3140: }
3141: }
3142: return result;
3143: }
3144:
3145:
3152: public Range getDataRange(ValueAxis axis) {
3153:
3154: Range result = null;
3155: List mappedDatasets = new ArrayList();
3156: boolean isDomainAxis = true;
3157:
3158:
3159: int domainIndex = getDomainAxisIndex(axis);
3160: if (domainIndex >= 0) {
3161: isDomainAxis = true;
3162: mappedDatasets.addAll(
3163: getDatasetsMappedToDomainAxis(new Integer(domainIndex))
3164: );
3165: }
3166:
3167:
3168: int rangeIndex = getRangeAxisIndex(axis);
3169: if (rangeIndex >= 0) {
3170: isDomainAxis = false;
3171: mappedDatasets.addAll(
3172: getDatasetsMappedToRangeAxis(new Integer(rangeIndex))
3173: );
3174: }
3175:
3176:
3177:
3178: Iterator iterator = mappedDatasets.iterator();
3179: while (iterator.hasNext()) {
3180: XYDataset d = (XYDataset) iterator.next();
3181: if (d != null) {
3182: XYItemRenderer r = getRendererForDataset(d);
3183: if (isDomainAxis) {
3184: if (r != null) {
3185: result = Range.combine(result, r.findDomainBounds(d));
3186: }
3187: else {
3188: result = Range.combine(
3189: result, DatasetUtilities.findDomainBounds(d)
3190: );
3191: }
3192: }
3193: else {
3194: if (r != null) {
3195: result = Range.combine(result, r.findRangeBounds(d));
3196: }
3197: else {
3198: result = Range.combine(
3199: result, DatasetUtilities.findRangeBounds(d)
3200: );
3201: }
3202: }
3203: }
3204: }
3205: return result;
3206:
3207: }
3208:
3209:
3216: public void datasetChanged(DatasetChangeEvent event) {
3217: configureDomainAxes();
3218: configureRangeAxes();
3219: if (getParent() != null) {
3220: getParent().datasetChanged(event);
3221: }
3222: else {
3223: PlotChangeEvent e = new PlotChangeEvent(this);
3224: e.setType(ChartChangeEventType.DATASET_UPDATED);
3225: notifyListeners(e);
3226: }
3227: }
3228:
3229:
3234: public void rendererChanged(RendererChangeEvent event) {
3235: notifyListeners(new PlotChangeEvent(this));
3236: }
3237:
3238:
3243: public boolean isDomainCrosshairVisible() {
3244: return this.domainCrosshairVisible;
3245: }
3246:
3247:
3252: public void setDomainCrosshairVisible(boolean flag) {
3253:
3254: if (this.domainCrosshairVisible != flag) {
3255: this.domainCrosshairVisible = flag;
3256: notifyListeners(new PlotChangeEvent(this));
3257: }
3258:
3259: }
3260:
3261:
3267: public boolean isDomainCrosshairLockedOnData() {
3268: return this.domainCrosshairLockedOnData;
3269: }
3270:
3271:
3277: public void setDomainCrosshairLockedOnData(boolean flag) {
3278:
3279: if (this.domainCrosshairLockedOnData != flag) {
3280: this.domainCrosshairLockedOnData = flag;
3281: notifyListeners(new PlotChangeEvent(this));
3282: }
3283:
3284: }
3285:
3286:
3291: public double getDomainCrosshairValue() {
3292: return this.domainCrosshairValue;
3293: }
3294:
3295:
3301: public void setDomainCrosshairValue(double value) {
3302: setDomainCrosshairValue(value, true);
3303: }
3304:
3305:
3313: public void setDomainCrosshairValue(double value, boolean notify) {
3314: this.domainCrosshairValue = value;
3315: if (isDomainCrosshairVisible() && notify) {
3316: notifyListeners(new PlotChangeEvent(this));
3317: }
3318: }
3319:
3320:
3325: public Stroke getDomainCrosshairStroke() {
3326: return this.domainCrosshairStroke;
3327: }
3328:
3329:
3335: public void setDomainCrosshairStroke(Stroke stroke) {
3336: this.domainCrosshairStroke = stroke;
3337: notifyListeners(new PlotChangeEvent(this));
3338: }
3339:
3340:
3345: public Paint getDomainCrosshairPaint() {
3346: return this.domainCrosshairPaint;
3347: }
3348:
3349:
3355: public void setDomainCrosshairPaint(Paint paint) {
3356: this.domainCrosshairPaint = paint;
3357: notifyListeners(new PlotChangeEvent(this));
3358: }
3359:
3360:
3365: public boolean isRangeCrosshairVisible() {
3366: return this.rangeCrosshairVisible;
3367: }
3368:
3369:
3374: public void setRangeCrosshairVisible(boolean flag) {
3375:
3376: if (this.rangeCrosshairVisible != flag) {
3377: this.rangeCrosshairVisible = flag;
3378: notifyListeners(new PlotChangeEvent(this));
3379: }
3380:
3381: }
3382:
3383:
3389: public boolean isRangeCrosshairLockedOnData() {
3390: return this.rangeCrosshairLockedOnData;
3391: }
3392:
3393:
3399: public void setRangeCrosshairLockedOnData(boolean flag) {
3400:
3401: if (this.rangeCrosshairLockedOnData != flag) {
3402: this.rangeCrosshairLockedOnData = flag;
3403: notifyListeners(new PlotChangeEvent(this));
3404: }
3405:
3406: }
3407:
3408:
3413: public double getRangeCrosshairValue() {
3414: return this.rangeCrosshairValue;
3415: }
3416:
3417:
3425: public void setRangeCrosshairValue(double value) {
3426: setRangeCrosshairValue(value, true);
3427: }
3428:
3429:
3439: public void setRangeCrosshairValue(double value, boolean notify) {
3440: this.rangeCrosshairValue = value;
3441: if (isRangeCrosshairVisible() && notify) {
3442: notifyListeners(new PlotChangeEvent(this));
3443: }
3444: }
3445:
3446:
3451: public Stroke getRangeCrosshairStroke() {
3452: return this.rangeCrosshairStroke;
3453: }
3454:
3455:
3461: public void setRangeCrosshairStroke(Stroke stroke) {
3462: this.rangeCrosshairStroke = stroke;
3463: notifyListeners(new PlotChangeEvent(this));
3464: }
3465:
3466:
3471: public Paint getRangeCrosshairPaint() {
3472: return this.rangeCrosshairPaint;
3473: }
3474:
3475:
3481: public void setRangeCrosshairPaint(Paint paint) {
3482: this.rangeCrosshairPaint = paint;
3483: notifyListeners(new PlotChangeEvent(this));
3484: }
3485:
3486:
3491: public AxisSpace getFixedDomainAxisSpace() {
3492: return this.fixedDomainAxisSpace;
3493: }
3494:
3495:
3500: public void setFixedDomainAxisSpace(AxisSpace space) {
3501: this.fixedDomainAxisSpace = space;
3502: }
3503:
3504:
3509: public AxisSpace getFixedRangeAxisSpace() {
3510: return this.fixedRangeAxisSpace;
3511: }
3512:
3513:
3518: public void setFixedRangeAxisSpace(AxisSpace space) {
3519: this.fixedRangeAxisSpace = space;
3520: }
3521:
3522:
3529: public void zoomDomainAxes(double factor, PlotRenderingInfo info,
3530: Point2D source) {
3531: for (int i = 0; i < this.domainAxes.size(); i++) {
3532: ValueAxis domainAxis = (ValueAxis) this.domainAxes.get(i);
3533: if (domainAxis != null) {
3534: domainAxis.resizeRange(factor);
3535: }
3536: }
3537: }
3538:
3539:
3551: public void zoomDomainAxes(double lowerPercent, double upperPercent,
3552: PlotRenderingInfo info, Point2D source) {
3553: for (int i = 0; i < this.domainAxes.size(); i++) {
3554: ValueAxis domainAxis = (ValueAxis) this.domainAxes.get(i);
3555: if (domainAxis != null) {
3556: domainAxis.zoomRange(lowerPercent, upperPercent);
3557: }
3558: }
3559: }
3560:
3561:
3568: public void zoomRangeAxes(double factor, PlotRenderingInfo info,
3569: Point2D source) {
3570: for (int i = 0; i < this.rangeAxes.size(); i++) {
3571: ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i);
3572: if (rangeAxis != null) {
3573: rangeAxis.resizeRange(factor);
3574: }
3575: }
3576: }
3577:
3578:
3586: public void zoomRangeAxes(double lowerPercent, double upperPercent,
3587: PlotRenderingInfo info, Point2D source) {
3588: for (int i = 0; i < this.rangeAxes.size(); i++) {
3589: ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i);
3590: if (rangeAxis != null) {
3591: rangeAxis.zoomRange(lowerPercent, upperPercent);
3592: }
3593: }
3594: }
3595:
3596:
3601: public boolean isDomainZoomable() {
3602: return true;
3603: }
3604:
3605:
3610: public boolean isRangeZoomable() {
3611: return true;
3612: }
3613:
3614:
3620: public int getSeriesCount() {
3621: int result = 0;
3622: XYDataset dataset = getDataset();
3623: if (dataset != null) {
3624: result = dataset.getSeriesCount();
3625: }
3626: return result;
3627: }
3628:
3629:
3634: public LegendItemCollection getFixedLegendItems() {
3635: return this.fixedLegendItems;
3636: }
3637:
3638:
3645: public void setFixedLegendItems(LegendItemCollection items) {
3646: this.fixedLegendItems = items;
3647: notifyListeners(new PlotChangeEvent(this));
3648: }
3649:
3650:
3657: public LegendItemCollection getLegendItems() {
3658: if (this.fixedLegendItems != null) {
3659: return this.fixedLegendItems;
3660: }
3661: LegendItemCollection result = new LegendItemCollection();
3662: int count = this.datasets.size();
3663: for (int datasetIndex = 0; datasetIndex < count; datasetIndex++) {
3664: XYDataset dataset = getDataset(datasetIndex);
3665: if (dataset != null) {
3666: XYItemRenderer renderer = getRenderer(datasetIndex);
3667: if (renderer == null) {
3668: renderer = getRenderer(0);
3669: }
3670: if (renderer != null) {
3671: int seriesCount = dataset.getSeriesCount();
3672: for (int i = 0; i < seriesCount; i++) {
3673: if (renderer.isSeriesVisible(i)
3674: && renderer.isSeriesVisibleInLegend(i)) {
3675: LegendItem item = renderer.getLegendItem(
3676: datasetIndex, i
3677: );
3678: if (item != null) {
3679: result.add(item);
3680: }
3681: }
3682: }
3683: }
3684: }
3685: }
3686: return result;
3687: }
3688:
3689:
3696: public boolean equals(Object obj) {
3697:
3698: if (obj == this) {
3699: return true;
3700: }
3701: if (!(obj instanceof XYPlot)) {
3702: return false;
3703: }
3704: if (!super.equals(obj)) {
3705: return false;
3706: }
3707:
3708: XYPlot that = (XYPlot) obj;
3709: if (this.weight != that.weight) {
3710: return false;
3711: }
3712: if (this.orientation != that.orientation) {
3713: return false;
3714: }
3715: if (!this.domainAxes.equals(that.domainAxes)) {
3716: return false;
3717: }
3718: if (!this.domainAxisLocations.equals(that.domainAxisLocations)) {
3719: return false;
3720: }
3721: if (this.rangeCrosshairLockedOnData
3722: != that.rangeCrosshairLockedOnData) {
3723: return false;
3724: }
3725: if (this.domainGridlinesVisible != that.domainGridlinesVisible) {
3726: return false;
3727: }
3728: if (this.rangeGridlinesVisible != that.rangeGridlinesVisible) {
3729: return false;
3730: }
3731: if (this.rangeZeroBaselineVisible != that.rangeZeroBaselineVisible) {
3732: return false;
3733: }
3734: if (this.domainCrosshairVisible != that.domainCrosshairVisible) {
3735: return false;
3736: }
3737: if (this.domainCrosshairValue != that.domainCrosshairValue) {
3738: return false;
3739: }
3740: if (this.domainCrosshairLockedOnData
3741: != that.domainCrosshairLockedOnData) {
3742: return false;
3743: }
3744: if (this.rangeCrosshairVisible != that.rangeCrosshairVisible) {
3745: return false;
3746: }
3747: if (this.rangeCrosshairValue != that.rangeCrosshairValue) {
3748: return false;
3749: }
3750: if (!ObjectUtilities.equal(this.axisOffset, that.axisOffset)) {
3751: return false;
3752: }
3753: if (!ObjectUtilities.equal(this.renderers, that.renderers)) {
3754: return false;
3755: }
3756: if (!ObjectUtilities.equal(this.rangeAxes, that.rangeAxes)) {
3757: return false;
3758: }
3759: if (!this.rangeAxisLocations.equals(that.rangeAxisLocations)) {
3760: return false;
3761: }
3762: if (!ObjectUtilities.equal(
3763: this.datasetToDomainAxisMap, that.datasetToDomainAxisMap
3764: )) {
3765: return false;
3766: }
3767: if (!ObjectUtilities.equal(
3768: this.datasetToRangeAxisMap, that.datasetToRangeAxisMap
3769: )) {
3770: return false;
3771: }
3772: if (!ObjectUtilities.equal(
3773: this.domainGridlineStroke, that.domainGridlineStroke)) {
3774: return false;
3775: }
3776: if (!PaintUtilities.equal(
3777: this.domainGridlinePaint, that.domainGridlinePaint)) {
3778: return false;
3779: }
3780: if (!ObjectUtilities.equal(
3781: this.rangeGridlineStroke, that.rangeGridlineStroke)) {
3782: return false;
3783: }
3784: if (!PaintUtilities.equal(
3785: this.rangeGridlinePaint, that.rangeGridlinePaint)) {
3786: return false;
3787: }
3788: if (!PaintUtilities.equal(
3789: this.rangeZeroBaselinePaint, that.rangeZeroBaselinePaint
3790: )) {
3791: return false;
3792: }
3793: if (!ObjectUtilities.equal(
3794: this.rangeZeroBaselineStroke, that.rangeZeroBaselineStroke
3795: )) {
3796: return false;
3797: }
3798: if (!ObjectUtilities.equal(
3799: this.domainCrosshairStroke, that.domainCrosshairStroke
3800: )) {
3801: return false;
3802: }
3803: if (!PaintUtilities.equal(
3804: this.domainCrosshairPaint, that.domainCrosshairPaint
3805: )) {
3806: return false;
3807: }
3808: if (!ObjectUtilities.equal(
3809: this.rangeCrosshairStroke, that.rangeCrosshairStroke
3810: )) {
3811: return false;
3812: }
3813: if (!PaintUtilities.equal(
3814: this.rangeCrosshairPaint, that.rangeCrosshairPaint
3815: )) {
3816: return false;
3817: }
3818: if (!ObjectUtilities.equal(
3819: this.foregroundDomainMarkers, that.foregroundDomainMarkers
3820: )) {
3821: return false;
3822: }
3823: if (!ObjectUtilities.equal(
3824: this.backgroundDomainMarkers, that.backgroundDomainMarkers
3825: )) {
3826: return false;
3827: }
3828: if (!ObjectUtilities.equal(
3829: this.foregroundRangeMarkers, that.foregroundRangeMarkers
3830: )) {
3831: return false;
3832: }
3833: if (!ObjectUtilities.equal(
3834: this.backgroundRangeMarkers, that.backgroundRangeMarkers
3835: )) {
3836: return false;
3837: }
3838: if (!ObjectUtilities.equal(
3839: this.foregroundDomainMarkers, that.foregroundDomainMarkers
3840: )) {
3841: return false;
3842: }
3843: if (!ObjectUtilities.equal(
3844: this.backgroundDomainMarkers, that.backgroundDomainMarkers
3845: )) {
3846: return false;
3847: }
3848: if (!ObjectUtilities.equal(
3849: this.foregroundRangeMarkers, that.foregroundRangeMarkers
3850: )) {
3851: return false;
3852: }
3853: if (!ObjectUtilities.equal(
3854: this.backgroundRangeMarkers, that.backgroundRangeMarkers
3855: )) {
3856: return false;
3857: }
3858: if (!ObjectUtilities.equal(
3859: this.annotations, that.annotations
3860: )) {
3861: return false;
3862: }
3863: return true;
3864:
3865: }
3866:
3867:
3875: public Object clone() throws CloneNotSupportedException {
3876:
3877: XYPlot clone = (XYPlot) super.clone();
3878: clone.domainAxes = (ObjectList) ObjectUtilities.clone(this.domainAxes);
3879: for (int i = 0; i < this.domainAxes.size(); i++) {
3880: ValueAxis axis = (ValueAxis) this.domainAxes.get(i);
3881: if (axis != null) {
3882: ValueAxis clonedAxis = (ValueAxis) axis.clone();
3883: clone.domainAxes.set(i, clonedAxis);
3884: clonedAxis.setPlot(clone);
3885: clonedAxis.addChangeListener(clone);
3886: }
3887: }
3888: clone.domainAxisLocations
3889: = (ObjectList) this.domainAxisLocations.clone();
3890:
3891: clone.rangeAxes = (ObjectList) ObjectUtilities.clone(this.rangeAxes);
3892: for (int i = 0; i < this.rangeAxes.size(); i++) {
3893: ValueAxis axis = (ValueAxis) this.rangeAxes.get(i);
3894: if (axis != null) {
3895: ValueAxis clonedAxis = (ValueAxis) axis.clone();
3896: clone.rangeAxes.set(i, clonedAxis);
3897: clonedAxis.setPlot(clone);
3898: clonedAxis.addChangeListener(clone);
3899: }
3900: }
3901: clone.rangeAxisLocations
3902: = (ObjectList) ObjectUtilities.clone(this.rangeAxisLocations);
3903:
3904:
3905: clone.datasets = (ObjectList) ObjectUtilities.clone(this.datasets);
3906: for (int i = 0; i < clone.datasets.size(); ++i) {
3907: XYDataset d = getDataset(i);
3908: if (d != null) {
3909: d.addChangeListener(clone);
3910: }
3911: }
3912:
3913: clone.datasetToDomainAxisMap = new TreeMap();
3914: clone.datasetToDomainAxisMap.putAll(this.datasetToDomainAxisMap);
3915: clone.datasetToRangeAxisMap = new TreeMap();
3916: clone.datasetToRangeAxisMap.putAll(this.datasetToRangeAxisMap);
3917:
3918: clone.renderers = (ObjectList) ObjectUtilities.clone(this.renderers);
3919: for (int i = 0; i < this.renderers.size(); i++) {
3920: XYItemRenderer renderer2 = (XYItemRenderer) this.renderers.get(i);
3921: if (renderer2 instanceof PublicCloneable) {
3922: PublicCloneable pc = (PublicCloneable) renderer2;
3923: clone.renderers.set(i, pc.clone());
3924: }
3925: }
3926: clone.foregroundDomainMarkers = (Map) ObjectUtilities.clone(
3927: this.foregroundDomainMarkers
3928: );
3929: clone.backgroundDomainMarkers = (Map) ObjectUtilities.clone(
3930: this.backgroundDomainMarkers
3931: );
3932: clone.foregroundRangeMarkers = (Map) ObjectUtilities.clone(
3933: this.foregroundRangeMarkers
3934: );
3935: clone.backgroundRangeMarkers = (Map) ObjectUtilities.clone(
3936: this.backgroundRangeMarkers
3937: );
3938: clone.annotations = (List) ObjectUtilities.deepClone(this.annotations);
3939: if (this.fixedDomainAxisSpace != null) {
3940: clone.fixedDomainAxisSpace = (AxisSpace) ObjectUtilities.clone(
3941: this.fixedDomainAxisSpace
3942: );
3943: }
3944: if (this.fixedRangeAxisSpace != null) {
3945: clone.fixedRangeAxisSpace = (AxisSpace) ObjectUtilities.clone(
3946: this.fixedRangeAxisSpace
3947: );
3948: }
3949: return clone;
3950:
3951: }
3952:
3953:
3960: private void writeObject(ObjectOutputStream stream) throws IOException {
3961: stream.defaultWriteObject();
3962: SerialUtilities.writeStroke(this.domainGridlineStroke, stream);
3963: SerialUtilities.writePaint(this.domainGridlinePaint, stream);
3964: SerialUtilities.writeStroke(this.rangeGridlineStroke, stream);
3965: SerialUtilities.writePaint(this.rangeGridlinePaint, stream);
3966: SerialUtilities.writeStroke(this.rangeZeroBaselineStroke, stream);
3967: SerialUtilities.writePaint(this.rangeZeroBaselinePaint, stream);
3968: SerialUtilities.writeStroke(this.domainCrosshairStroke, stream);
3969: SerialUtilities.writePaint(this.domainCrosshairPaint, stream);
3970: SerialUtilities.writeStroke(this.rangeCrosshairStroke, stream);
3971: SerialUtilities.writePaint(this.rangeCrosshairPaint, stream);
3972: SerialUtilities.writePaint(this.domainTickBandPaint, stream);
3973: SerialUtilities.writePaint(this.rangeTickBandPaint, stream);
3974: SerialUtilities.writePoint2D(this.quadrantOrigin, stream);
3975: for (int i = 0; i < 4; i++) {
3976: SerialUtilities.writePaint(this.quadrantPaint[i], stream);
3977: }
3978: }
3979:
3980:
3988: private void readObject(ObjectInputStream stream)
3989: throws IOException, ClassNotFoundException {
3990:
3991: stream.defaultReadObject();
3992: this.domainGridlineStroke = SerialUtilities.readStroke(stream);
3993: this.domainGridlinePaint = SerialUtilities.readPaint(stream);
3994: this.rangeGridlineStroke = SerialUtilities.readStroke(stream);
3995: this.rangeGridlinePaint = SerialUtilities.readPaint(stream);
3996: this.rangeZeroBaselineStroke = SerialUtilities.readStroke(stream);
3997: this.rangeZeroBaselinePaint = SerialUtilities.readPaint(stream);
3998: this.domainCrosshairStroke = SerialUtilities.readStroke(stream);
3999: this.domainCrosshairPaint = SerialUtilities.readPaint(stream);
4000: this.rangeCrosshairStroke = SerialUtilities.readStroke(stream);
4001: this.rangeCrosshairPaint = SerialUtilities.readPaint(stream);
4002: this.domainTickBandPaint = SerialUtilities.readPaint(stream);
4003: this.rangeTickBandPaint = SerialUtilities.readPaint(stream);
4004: this.quadrantOrigin = SerialUtilities.readPoint2D(stream);
4005: this.quadrantPaint = new Paint[4];
4006: for (int i = 0; i < 4; i++) {
4007: this.quadrantPaint[i] = SerialUtilities.readPaint(stream);
4008: }
4009:
4010:
4011:
4012: int domainAxisCount = this.domainAxes.size();
4013: for (int i = 0; i < domainAxisCount; i++) {
4014: Axis axis = (Axis) this.domainAxes.get(i);
4015: if (axis != null) {
4016: axis.setPlot(this);
4017: axis.addChangeListener(this);
4018: }
4019: }
4020: int rangeAxisCount = this.rangeAxes.size();
4021: for (int i = 0; i < rangeAxisCount; i++) {
4022: Axis axis = (Axis) this.rangeAxes.get(i);
4023: if (axis != null) {
4024: axis.setPlot(this);
4025: axis.addChangeListener(this);
4026: }
4027: }
4028: int datasetCount = this.datasets.size();
4029: for (int i = 0; i < datasetCount; i++) {
4030: Dataset dataset = (Dataset) this.datasets.get(i);
4031: if (dataset != null) {
4032: dataset.addChangeListener(this);
4033: }
4034: }
4035: int rendererCount = this.renderers.size();
4036: for (int i = 0; i < rendererCount; i++) {
4037: XYItemRenderer renderer = (XYItemRenderer) this.renderers.get(i);
4038: if (renderer != null) {
4039: renderer.addChangeListener(this);
4040: }
4041: }
4042:
4043: }
4044:
4045: }