1:
164:
165: package ;
166:
167: import ;
168: import ;
169: import ;
170: import ;
171: import ;
172: import ;
173: import ;
174: import ;
175: import ;
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:
193: import ;
194: import ;
195: import ;
196: import ;
197: import ;
198: import ;
199: import ;
200: import ;
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:
226:
230: public class CategoryPlot extends Plot implements ValueAxisPlot,
231: Zoomable, RendererChangeListener, Cloneable, PublicCloneable,
232: Serializable {
233:
234:
235: private static final long serialVersionUID = -3537691700434728188L;
236:
237:
241: public static final boolean DEFAULT_DOMAIN_GRIDLINES_VISIBLE = false;
242:
243:
247: public static final boolean DEFAULT_RANGE_GRIDLINES_VISIBLE = true;
248:
249:
250: public static final Stroke DEFAULT_GRIDLINE_STROKE = new BasicStroke(0.5f,
251: BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0.0f, new float[]
252: {2.0f, 2.0f}, 0.0f);
253:
254:
255: public static final Paint DEFAULT_GRIDLINE_PAINT = Color.lightGray;
256:
257:
258: public static final Font DEFAULT_VALUE_LABEL_FONT = new Font("SansSerif",
259: Font.PLAIN, 10);
260:
261:
266: public static final boolean DEFAULT_CROSSHAIR_VISIBLE = false;
267:
268:
273: public static final Stroke DEFAULT_CROSSHAIR_STROKE
274: = DEFAULT_GRIDLINE_STROKE;
275:
276:
281: public static final Paint DEFAULT_CROSSHAIR_PAINT = Color.blue;
282:
283:
284: protected static ResourceBundle localizationResources
285: = ResourceBundle.getBundle(
286: "org.jfree.chart.plot.LocalizationBundle");
287:
288:
289: private PlotOrientation orientation;
290:
291:
292: private RectangleInsets axisOffset;
293:
294:
295: private ObjectList domainAxes;
296:
297:
298: private ObjectList domainAxisLocations;
299:
300:
304: private boolean drawSharedDomainAxis;
305:
306:
307: private ObjectList rangeAxes;
308:
309:
310: private ObjectList rangeAxisLocations;
311:
312:
313: private ObjectList datasets;
314:
315:
316: private ObjectList datasetToDomainAxisMap;
317:
318:
319: private ObjectList datasetToRangeAxisMap;
320:
321:
322: private ObjectList renderers;
323:
324:
325: private DatasetRenderingOrder renderingOrder
326: = DatasetRenderingOrder.REVERSE;
327:
328:
332: private SortOrder columnRenderingOrder = SortOrder.ASCENDING;
333:
334:
338: private SortOrder rowRenderingOrder = SortOrder.ASCENDING;
339:
340:
344: private boolean domainGridlinesVisible;
345:
346:
347: private CategoryAnchor domainGridlinePosition;
348:
349:
350: private transient Stroke domainGridlineStroke;
351:
352:
353: private transient Paint domainGridlinePaint;
354:
355:
359: private boolean rangeGridlinesVisible;
360:
361:
362: private transient Stroke rangeGridlineStroke;
363:
364:
365: private transient Paint rangeGridlinePaint;
366:
367:
368: private double anchorValue;
369:
370:
371: private boolean rangeCrosshairVisible;
372:
373:
374: private double rangeCrosshairValue;
375:
376:
377: private transient Stroke rangeCrosshairStroke;
378:
379:
380: private transient Paint rangeCrosshairPaint;
381:
382:
386: private boolean rangeCrosshairLockedOnData = true;
387:
388:
389: private Map foregroundDomainMarkers;
390:
391:
392: private Map backgroundDomainMarkers;
393:
394:
395: private Map foregroundRangeMarkers;
396:
397:
398: private Map backgroundRangeMarkers;
399:
400:
405: private List annotations;
406:
407:
411: private int weight;
412:
413:
414: private AxisSpace fixedDomainAxisSpace;
415:
416:
417: private AxisSpace fixedRangeAxisSpace;
418:
419:
423: private LegendItemCollection fixedLegendItems;
424:
425:
428: public CategoryPlot() {
429: this(null, null, null, null);
430: }
431:
432:
441: public CategoryPlot(CategoryDataset dataset,
442: CategoryAxis domainAxis,
443: ValueAxis rangeAxis,
444: CategoryItemRenderer renderer) {
445:
446: super();
447:
448: this.orientation = PlotOrientation.VERTICAL;
449:
450:
451: this.domainAxes = new ObjectList();
452: this.domainAxisLocations = new ObjectList();
453: this.rangeAxes = new ObjectList();
454: this.rangeAxisLocations = new ObjectList();
455:
456: this.datasetToDomainAxisMap = new ObjectList();
457: this.datasetToRangeAxisMap = new ObjectList();
458:
459: this.renderers = new ObjectList();
460:
461: this.datasets = new ObjectList();
462: this.datasets.set(0, dataset);
463: if (dataset != null) {
464: dataset.addChangeListener(this);
465: }
466:
467: this.axisOffset = RectangleInsets.ZERO_INSETS;
468:
469: setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT, false);
470: setRangeAxisLocation(AxisLocation.TOP_OR_LEFT, false);
471:
472: this.renderers.set(0, renderer);
473: if (renderer != null) {
474: renderer.setPlot(this);
475: renderer.addChangeListener(this);
476: }
477:
478: this.domainAxes.set(0, domainAxis);
479: this.mapDatasetToDomainAxis(0, 0);
480: if (domainAxis != null) {
481: domainAxis.setPlot(this);
482: domainAxis.addChangeListener(this);
483: }
484: this.drawSharedDomainAxis = false;
485:
486: this.rangeAxes.set(0, rangeAxis);
487: this.mapDatasetToRangeAxis(0, 0);
488: if (rangeAxis != null) {
489: rangeAxis.setPlot(this);
490: rangeAxis.addChangeListener(this);
491: }
492:
493: configureDomainAxes();
494: configureRangeAxes();
495:
496: this.domainGridlinesVisible = DEFAULT_DOMAIN_GRIDLINES_VISIBLE;
497: this.domainGridlinePosition = CategoryAnchor.MIDDLE;
498: this.domainGridlineStroke = DEFAULT_GRIDLINE_STROKE;
499: this.domainGridlinePaint = DEFAULT_GRIDLINE_PAINT;
500:
501: this.rangeGridlinesVisible = DEFAULT_RANGE_GRIDLINES_VISIBLE;
502: this.rangeGridlineStroke = DEFAULT_GRIDLINE_STROKE;
503: this.rangeGridlinePaint = DEFAULT_GRIDLINE_PAINT;
504:
505: this.foregroundDomainMarkers = new HashMap();
506: this.backgroundDomainMarkers = new HashMap();
507: this.foregroundRangeMarkers = new HashMap();
508: this.backgroundRangeMarkers = new HashMap();
509:
510: Marker baseline = new ValueMarker(0.0, new Color(0.8f, 0.8f, 0.8f,
511: 0.5f), new BasicStroke(1.0f), new Color(0.85f, 0.85f, 0.95f,
512: 0.5f), new BasicStroke(1.0f), 0.6f);
513: addRangeMarker(baseline, Layer.BACKGROUND);
514:
515: this.anchorValue = 0.0;
516:
517: this.rangeCrosshairVisible = DEFAULT_CROSSHAIR_VISIBLE;
518: this.rangeCrosshairValue = 0.0;
519: this.rangeCrosshairStroke = DEFAULT_CROSSHAIR_STROKE;
520: this.rangeCrosshairPaint = DEFAULT_CROSSHAIR_PAINT;
521:
522: this.annotations = new java.util.ArrayList();
523:
524: }
525:
526:
531: public String getPlotType() {
532: return localizationResources.getString("Category_Plot");
533: }
534:
535:
542: public PlotOrientation getOrientation() {
543: return this.orientation;
544: }
545:
546:
554: public void setOrientation(PlotOrientation orientation) {
555: if (orientation == null) {
556: throw new IllegalArgumentException("Null 'orientation' argument.");
557: }
558: this.orientation = orientation;
559: fireChangeEvent();
560: }
561:
562:
569: public RectangleInsets getAxisOffset() {
570: return this.axisOffset;
571: }
572:
573:
581: public void setAxisOffset(RectangleInsets offset) {
582: if (offset == null) {
583: throw new IllegalArgumentException("Null 'offset' argument.");
584: }
585: this.axisOffset = offset;
586: fireChangeEvent();
587: }
588:
589:
598: public CategoryAxis getDomainAxis() {
599: return getDomainAxis(0);
600: }
601:
602:
611: public CategoryAxis getDomainAxis(int index) {
612: CategoryAxis result = null;
613: if (index < this.domainAxes.size()) {
614: result = (CategoryAxis) this.domainAxes.get(index);
615: }
616: if (result == null) {
617: Plot parent = getParent();
618: if (parent instanceof CategoryPlot) {
619: CategoryPlot cp = (CategoryPlot) parent;
620: result = cp.getDomainAxis(index);
621: }
622: }
623: return result;
624: }
625:
626:
634: public void setDomainAxis(CategoryAxis axis) {
635: setDomainAxis(0, axis);
636: }
637:
638:
647: public void setDomainAxis(int index, CategoryAxis axis) {
648: setDomainAxis(index, axis, true);
649: }
650:
651:
659: public void setDomainAxis(int index, CategoryAxis axis, boolean notify) {
660: CategoryAxis existing = (CategoryAxis) this.domainAxes.get(index);
661: if (existing != null) {
662: existing.removeChangeListener(this);
663: }
664: if (axis != null) {
665: axis.setPlot(this);
666: }
667: this.domainAxes.set(index, axis);
668: if (axis != null) {
669: axis.configure();
670: axis.addChangeListener(this);
671: }
672: if (notify) {
673: fireChangeEvent();
674: }
675: }
676:
677:
685: public void setDomainAxes(CategoryAxis[] axes) {
686: for (int i = 0; i < axes.length; i++) {
687: setDomainAxis(i, axes[i], false);
688: }
689: fireChangeEvent();
690: }
691:
692:
705: public int getDomainAxisIndex(CategoryAxis axis) {
706: if (axis == null) {
707: throw new IllegalArgumentException("Null 'axis' argument.");
708: }
709: return this.domainAxes.indexOf(axis);
710: }
711:
712:
719: public AxisLocation getDomainAxisLocation() {
720: return getDomainAxisLocation(0);
721: }
722:
723:
732: public AxisLocation getDomainAxisLocation(int index) {
733: AxisLocation result = null;
734: if (index < this.domainAxisLocations.size()) {
735: result = (AxisLocation) this.domainAxisLocations.get(index);
736: }
737: if (result == null) {
738: result = AxisLocation.getOpposite(getDomainAxisLocation(0));
739: }
740: return result;
741: }
742:
743:
752: public void setDomainAxisLocation(AxisLocation location) {
753:
754: setDomainAxisLocation(0, location, true);
755: }
756:
757:
764: public void setDomainAxisLocation(AxisLocation location, boolean notify) {
765:
766: setDomainAxisLocation(0, location, notify);
767: }
768:
769:
779: public void setDomainAxisLocation(int index, AxisLocation location) {
780:
781: setDomainAxisLocation(index, location, true);
782: }
783:
784:
797: public void setDomainAxisLocation(int index, AxisLocation location,
798: boolean notify) {
799: if (index == 0 && location == null) {
800: throw new IllegalArgumentException(
801: "Null 'location' for index 0 not permitted.");
802: }
803: this.domainAxisLocations.set(index, location);
804: if (notify) {
805: fireChangeEvent();
806: }
807: }
808:
809:
815: public RectangleEdge getDomainAxisEdge() {
816: return getDomainAxisEdge(0);
817: }
818:
819:
826: public RectangleEdge getDomainAxisEdge(int index) {
827: RectangleEdge result = null;
828: AxisLocation location = getDomainAxisLocation(index);
829: if (location != null) {
830: result = Plot.resolveDomainAxisLocation(location, this.orientation);
831: }
832: else {
833: result = RectangleEdge.opposite(getDomainAxisEdge(0));
834: }
835: return result;
836: }
837:
838:
843: public int getDomainAxisCount() {
844: return this.domainAxes.size();
845: }
846:
847:
851: public void clearDomainAxes() {
852: for (int i = 0; i < this.domainAxes.size(); i++) {
853: CategoryAxis axis = (CategoryAxis) this.domainAxes.get(i);
854: if (axis != null) {
855: axis.removeChangeListener(this);
856: }
857: }
858: this.domainAxes.clear();
859: fireChangeEvent();
860: }
861:
862:
865: public void configureDomainAxes() {
866: for (int i = 0; i < this.domainAxes.size(); i++) {
867: CategoryAxis axis = (CategoryAxis) this.domainAxes.get(i);
868: if (axis != null) {
869: axis.configure();
870: }
871: }
872: }
873:
874:
881: public ValueAxis getRangeAxis() {
882: return getRangeAxis(0);
883: }
884:
885:
892: public ValueAxis getRangeAxis(int index) {
893: ValueAxis result = null;
894: if (index < this.rangeAxes.size()) {
895: result = (ValueAxis) this.rangeAxes.get(index);
896: }
897: if (result == null) {
898: Plot parent = getParent();
899: if (parent instanceof CategoryPlot) {
900: CategoryPlot cp = (CategoryPlot) parent;
901: result = cp.getRangeAxis(index);
902: }
903: }
904: return result;
905: }
906:
907:
913: public void setRangeAxis(ValueAxis axis) {
914: setRangeAxis(0, axis);
915: }
916:
917:
924: public void setRangeAxis(int index, ValueAxis axis) {
925: setRangeAxis(index, axis, true);
926: }
927:
928:
936: public void setRangeAxis(int index, ValueAxis axis, boolean notify) {
937: ValueAxis existing = (ValueAxis) this.rangeAxes.get(index);
938: if (existing != null) {
939: existing.removeChangeListener(this);
940: }
941: if (axis != null) {
942: axis.setPlot(this);
943: }
944: this.rangeAxes.set(index, axis);
945: if (axis != null) {
946: axis.configure();
947: axis.addChangeListener(this);
948: }
949: if (notify) {
950: fireChangeEvent();
951: }
952: }
953:
954:
962: public void setRangeAxes(ValueAxis[] axes) {
963: for (int i = 0; i < axes.length; i++) {
964: setRangeAxis(i, axes[i], false);
965: }
966: fireChangeEvent();
967: }
968:
969:
982: public int getRangeAxisIndex(ValueAxis axis) {
983: if (axis == null) {
984: throw new IllegalArgumentException("Null 'axis' argument.");
985: }
986: int result = this.rangeAxes.indexOf(axis);
987: if (result < 0) {
988: Plot parent = getParent();
989: if (parent instanceof CategoryPlot) {
990: CategoryPlot p = (CategoryPlot) parent;
991: result = p.getRangeAxisIndex(axis);
992: }
993: }
994: return result;
995: }
996:
997:
1002: public AxisLocation getRangeAxisLocation() {
1003: return getRangeAxisLocation(0);
1004: }
1005:
1006:
1015: public AxisLocation getRangeAxisLocation(int index) {
1016: AxisLocation result = null;
1017: if (index < this.rangeAxisLocations.size()) {
1018: result = (AxisLocation) this.rangeAxisLocations.get(index);
1019: }
1020: if (result == null) {
1021: result = AxisLocation.getOpposite(getRangeAxisLocation(0));
1022: }
1023: return result;
1024: }
1025:
1026:
1035: public void setRangeAxisLocation(AxisLocation location) {
1036:
1037: setRangeAxisLocation(location, true);
1038: }
1039:
1040:
1049: public void setRangeAxisLocation(AxisLocation location, boolean notify) {
1050: setRangeAxisLocation(0, location, notify);
1051: }
1052:
1053:
1063: public void setRangeAxisLocation(int index, AxisLocation location) {
1064: setRangeAxisLocation(index, location, true);
1065: }
1066:
1067:
1078: public void setRangeAxisLocation(int index, AxisLocation location,
1079: boolean notify) {
1080: if (index == 0 && location == null) {
1081: throw new IllegalArgumentException(
1082: "Null 'location' for index 0 not permitted.");
1083: }
1084: this.rangeAxisLocations.set(index, location);
1085: if (notify) {
1086: fireChangeEvent();
1087: }
1088: }
1089:
1090:
1095: public RectangleEdge getRangeAxisEdge() {
1096: return getRangeAxisEdge(0);
1097: }
1098:
1099:
1106: public RectangleEdge getRangeAxisEdge(int index) {
1107: AxisLocation location = getRangeAxisLocation(index);
1108: RectangleEdge result = Plot.resolveRangeAxisLocation(location,
1109: this.orientation);
1110: if (result == null) {
1111: result = RectangleEdge.opposite(getRangeAxisEdge(0));
1112: }
1113: return result;
1114: }
1115:
1116:
1121: public int getRangeAxisCount() {
1122: return this.rangeAxes.size();
1123: }
1124:
1125:
1129: public void clearRangeAxes() {
1130: for (int i = 0; i < this.rangeAxes.size(); i++) {
1131: ValueAxis axis = (ValueAxis) this.rangeAxes.get(i);
1132: if (axis != null) {
1133: axis.removeChangeListener(this);
1134: }
1135: }
1136: this.rangeAxes.clear();
1137: fireChangeEvent();
1138: }
1139:
1140:
1143: public void configureRangeAxes() {
1144: for (int i = 0; i < this.rangeAxes.size(); i++) {
1145: ValueAxis axis = (ValueAxis) this.rangeAxes.get(i);
1146: if (axis != null) {
1147: axis.configure();
1148: }
1149: }
1150: }
1151:
1152:
1159: public CategoryDataset getDataset() {
1160: return getDataset(0);
1161: }
1162:
1163:
1172: public CategoryDataset getDataset(int index) {
1173: CategoryDataset result = null;
1174: if (this.datasets.size() > index) {
1175: result = (CategoryDataset) this.datasets.get(index);
1176: }
1177: return result;
1178: }
1179:
1180:
1191: public void setDataset(CategoryDataset dataset) {
1192: setDataset(0, dataset);
1193: }
1194:
1195:
1203: public void setDataset(int index, CategoryDataset dataset) {
1204:
1205: CategoryDataset existing = (CategoryDataset) this.datasets.get(index);
1206: if (existing != null) {
1207: existing.removeChangeListener(this);
1208: }
1209: this.datasets.set(index, dataset);
1210: if (dataset != null) {
1211: dataset.addChangeListener(this);
1212: }
1213:
1214:
1215: DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
1216: datasetChanged(event);
1217:
1218: }
1219:
1220:
1227: public int getDatasetCount() {
1228: return this.datasets.size();
1229: }
1230:
1231:
1239: public void mapDatasetToDomainAxis(int index, int axisIndex) {
1240: this.datasetToDomainAxisMap.set(index, new Integer(axisIndex));
1241:
1242: datasetChanged(new DatasetChangeEvent(this, getDataset(index)));
1243: }
1244:
1245:
1255: public CategoryAxis getDomainAxisForDataset(int index) {
1256: CategoryAxis result = getDomainAxis();
1257: Integer axisIndex = (Integer) this.datasetToDomainAxisMap.get(index);
1258: if (axisIndex != null) {
1259: result = getDomainAxis(axisIndex.intValue());
1260: }
1261: return result;
1262: }
1263:
1264:
1272: public void mapDatasetToRangeAxis(int index, int axisIndex) {
1273: this.datasetToRangeAxisMap.set(index, new Integer(axisIndex));
1274:
1275: datasetChanged(new DatasetChangeEvent(this, getDataset(index)));
1276: }
1277:
1278:
1288: public ValueAxis getRangeAxisForDataset(int index) {
1289: ValueAxis result = getRangeAxis();
1290: Integer axisIndex = (Integer) this.datasetToRangeAxisMap.get(index);
1291: if (axisIndex != null) {
1292: result = getRangeAxis(axisIndex.intValue());
1293: }
1294: return result;
1295: }
1296:
1297:
1304: public CategoryItemRenderer getRenderer() {
1305: return getRenderer(0);
1306: }
1307:
1308:
1317: public CategoryItemRenderer getRenderer(int index) {
1318: CategoryItemRenderer result = null;
1319: if (this.renderers.size() > index) {
1320: result = (CategoryItemRenderer) this.renderers.get(index);
1321: }
1322: return result;
1323: }
1324:
1325:
1334: public void setRenderer(CategoryItemRenderer renderer) {
1335: setRenderer(0, renderer, true);
1336: }
1337:
1338:
1355: public void setRenderer(CategoryItemRenderer renderer, boolean notify) {
1356: setRenderer(0, renderer, notify);
1357: }
1358:
1359:
1369: public void setRenderer(int index, CategoryItemRenderer renderer) {
1370: setRenderer(index, renderer, true);
1371: }
1372:
1373:
1383: public void setRenderer(int index, CategoryItemRenderer renderer,
1384: boolean notify) {
1385:
1386:
1387: CategoryItemRenderer existing
1388: = (CategoryItemRenderer) this.renderers.get(index);
1389: if (existing != null) {
1390: existing.removeChangeListener(this);
1391: }
1392:
1393:
1394: this.renderers.set(index, renderer);
1395: if (renderer != null) {
1396: renderer.setPlot(this);
1397: renderer.addChangeListener(this);
1398: }
1399:
1400: configureDomainAxes();
1401: configureRangeAxes();
1402:
1403: if (notify) {
1404: fireChangeEvent();
1405: }
1406: }
1407:
1408:
1414: public void setRenderers(CategoryItemRenderer[] renderers) {
1415: for (int i = 0; i < renderers.length; i++) {
1416: setRenderer(i, renderers[i], false);
1417: }
1418: fireChangeEvent();
1419: }
1420:
1421:
1429: public CategoryItemRenderer getRendererForDataset(CategoryDataset dataset) {
1430: CategoryItemRenderer result = null;
1431: for (int i = 0; i < this.datasets.size(); i++) {
1432: if (this.datasets.get(i) == dataset) {
1433: result = (CategoryItemRenderer) this.renderers.get(i);
1434: break;
1435: }
1436: }
1437: return result;
1438: }
1439:
1440:
1448: public int getIndexOf(CategoryItemRenderer renderer) {
1449: return this.renderers.indexOf(renderer);
1450: }
1451:
1452:
1459: public DatasetRenderingOrder getDatasetRenderingOrder() {
1460: return this.renderingOrder;
1461: }
1462:
1463:
1473: public void setDatasetRenderingOrder(DatasetRenderingOrder order) {
1474: if (order == null) {
1475: throw new IllegalArgumentException("Null 'order' argument.");
1476: }
1477: this.renderingOrder = order;
1478: fireChangeEvent();
1479: }
1480:
1481:
1489: public SortOrder getColumnRenderingOrder() {
1490: return this.columnRenderingOrder;
1491: }
1492:
1493:
1504: public void setColumnRenderingOrder(SortOrder order) {
1505: if (order == null) {
1506: throw new IllegalArgumentException("Null 'order' argument.");
1507: }
1508: this.columnRenderingOrder = order;
1509: fireChangeEvent();
1510: }
1511:
1512:
1520: public SortOrder getRowRenderingOrder() {
1521: return this.rowRenderingOrder;
1522: }
1523:
1524:
1535: public void setRowRenderingOrder(SortOrder order) {
1536: if (order == null) {
1537: throw new IllegalArgumentException("Null 'order' argument.");
1538: }
1539: this.rowRenderingOrder = order;
1540: fireChangeEvent();
1541: }
1542:
1543:
1550: public boolean isDomainGridlinesVisible() {
1551: return this.domainGridlinesVisible;
1552: }
1553:
1554:
1565: public void setDomainGridlinesVisible(boolean visible) {
1566: if (this.domainGridlinesVisible != visible) {
1567: this.domainGridlinesVisible = visible;
1568: fireChangeEvent();
1569: }
1570: }
1571:
1572:
1579: public CategoryAnchor getDomainGridlinePosition() {
1580: return this.domainGridlinePosition;
1581: }
1582:
1583:
1591: public void setDomainGridlinePosition(CategoryAnchor position) {
1592: if (position == null) {
1593: throw new IllegalArgumentException("Null 'position' argument.");
1594: }
1595: this.domainGridlinePosition = position;
1596: fireChangeEvent();
1597: }
1598:
1599:
1606: public Stroke getDomainGridlineStroke() {
1607: return this.domainGridlineStroke;
1608: }
1609:
1610:
1618: public void setDomainGridlineStroke(Stroke stroke) {
1619: if (stroke == null) {
1620: throw new IllegalArgumentException("Null 'stroke' not permitted.");
1621: }
1622: this.domainGridlineStroke = stroke;
1623: fireChangeEvent();
1624: }
1625:
1626:
1633: public Paint getDomainGridlinePaint() {
1634: return this.domainGridlinePaint;
1635: }
1636:
1637:
1645: public void setDomainGridlinePaint(Paint paint) {
1646: if (paint == null) {
1647: throw new IllegalArgumentException("Null 'paint' argument.");
1648: }
1649: this.domainGridlinePaint = paint;
1650: fireChangeEvent();
1651: }
1652:
1653:
1660: public boolean isRangeGridlinesVisible() {
1661: return this.rangeGridlinesVisible;
1662: }
1663:
1664:
1673: public void setRangeGridlinesVisible(boolean visible) {
1674: if (this.rangeGridlinesVisible != visible) {
1675: this.rangeGridlinesVisible = visible;
1676: fireChangeEvent();
1677: }
1678: }
1679:
1680:
1687: public Stroke getRangeGridlineStroke() {
1688: return this.rangeGridlineStroke;
1689: }
1690:
1691:
1699: public void setRangeGridlineStroke(Stroke stroke) {
1700: if (stroke == null) {
1701: throw new IllegalArgumentException("Null 'stroke' argument.");
1702: }
1703: this.rangeGridlineStroke = stroke;
1704: fireChangeEvent();
1705: }
1706:
1707:
1714: public Paint getRangeGridlinePaint() {
1715: return this.rangeGridlinePaint;
1716: }
1717:
1718:
1726: public void setRangeGridlinePaint(Paint paint) {
1727: if (paint == null) {
1728: throw new IllegalArgumentException("Null 'paint' argument.");
1729: }
1730: this.rangeGridlinePaint = paint;
1731: fireChangeEvent();
1732: }
1733:
1734:
1741: public LegendItemCollection getFixedLegendItems() {
1742: return this.fixedLegendItems;
1743: }
1744:
1745:
1754: public void setFixedLegendItems(LegendItemCollection items) {
1755: this.fixedLegendItems = items;
1756: fireChangeEvent();
1757: }
1758:
1759:
1766: public LegendItemCollection getLegendItems() {
1767: LegendItemCollection result = this.fixedLegendItems;
1768: if (result == null) {
1769: result = new LegendItemCollection();
1770:
1771: int count = this.datasets.size();
1772: for (int datasetIndex = 0; datasetIndex < count; datasetIndex++) {
1773: CategoryDataset dataset = getDataset(datasetIndex);
1774: if (dataset != null) {
1775: CategoryItemRenderer renderer = getRenderer(datasetIndex);
1776: if (renderer != null) {
1777: int seriesCount = dataset.getRowCount();
1778: for (int i = 0; i < seriesCount; i++) {
1779: LegendItem item = renderer.getLegendItem(
1780: datasetIndex, i);
1781: if (item != null) {
1782: result.add(item);
1783: }
1784: }
1785: }
1786: }
1787: }
1788: }
1789: return result;
1790: }
1791:
1792:
1800: public void handleClick(int x, int y, PlotRenderingInfo info) {
1801:
1802: Rectangle2D dataArea = info.getDataArea();
1803: if (dataArea.contains(x, y)) {
1804:
1805: double java2D = 0.0;
1806: if (this.orientation == PlotOrientation.HORIZONTAL) {
1807: java2D = x;
1808: }
1809: else if (this.orientation == PlotOrientation.VERTICAL) {
1810: java2D = y;
1811: }
1812: RectangleEdge edge = Plot.resolveRangeAxisLocation(
1813: getRangeAxisLocation(), this.orientation);
1814: double value = getRangeAxis().java2DToValue(
1815: java2D, info.getDataArea(), edge);
1816: setAnchorValue(value);
1817: setRangeCrosshairValue(value);
1818: }
1819:
1820: }
1821:
1822:
1831: public void zoom(double percent) {
1832:
1833: if (percent > 0.0) {
1834: double range = getRangeAxis().getRange().getLength();
1835: double scaledRange = range * percent;
1836: getRangeAxis().setRange(this.anchorValue - scaledRange / 2.0,
1837: this.anchorValue + scaledRange / 2.0);
1838: }
1839: else {
1840: getRangeAxis().setAutoRange(true);
1841: }
1842:
1843: }
1844:
1845:
1852: public void datasetChanged(DatasetChangeEvent event) {
1853:
1854: int count = this.rangeAxes.size();
1855: for (int axisIndex = 0; axisIndex < count; axisIndex++) {
1856: ValueAxis yAxis = getRangeAxis(axisIndex);
1857: if (yAxis != null) {
1858: yAxis.configure();
1859: }
1860: }
1861: if (getParent() != null) {
1862: getParent().datasetChanged(event);
1863: }
1864: else {
1865: PlotChangeEvent e = new PlotChangeEvent(this);
1866: e.setType(ChartChangeEventType.DATASET_UPDATED);
1867: notifyListeners(e);
1868: }
1869:
1870: }
1871:
1872:
1877: public void rendererChanged(RendererChangeEvent event) {
1878: Plot parent = getParent();
1879: if (parent != null) {
1880: if (parent instanceof RendererChangeListener) {
1881: RendererChangeListener rcl = (RendererChangeListener) parent;
1882: rcl.rendererChanged(event);
1883: }
1884: else {
1885:
1886:
1887: throw new RuntimeException(
1888: "The renderer has changed and I don't know what to do!");
1889: }
1890: }
1891: else {
1892: configureRangeAxes();
1893: PlotChangeEvent e = new PlotChangeEvent(this);
1894: notifyListeners(e);
1895: }
1896: }
1897:
1898:
1908: public void addDomainMarker(CategoryMarker marker) {
1909: addDomainMarker(marker, Layer.FOREGROUND);
1910: }
1911:
1912:
1924: public void addDomainMarker(CategoryMarker marker, Layer layer) {
1925: addDomainMarker(0, marker, layer);
1926: }
1927:
1928:
1941: public void addDomainMarker(int index, CategoryMarker marker, Layer layer) {
1942: addDomainMarker(index, marker, layer, true);
1943: }
1944:
1945:
1961: public void addDomainMarker(int index, CategoryMarker marker, Layer layer,
1962: boolean notify) {
1963: if (marker == null) {
1964: throw new IllegalArgumentException("Null 'marker' not permitted.");
1965: }
1966: if (layer == null) {
1967: throw new IllegalArgumentException("Null 'layer' not permitted.");
1968: }
1969: Collection markers;
1970: if (layer == Layer.FOREGROUND) {
1971: markers = (Collection) this.foregroundDomainMarkers.get(
1972: new Integer(index));
1973: if (markers == null) {
1974: markers = new java.util.ArrayList();
1975: this.foregroundDomainMarkers.put(new Integer(index), markers);
1976: }
1977: markers.add(marker);
1978: }
1979: else if (layer == Layer.BACKGROUND) {
1980: markers = (Collection) this.backgroundDomainMarkers.get(
1981: new Integer(index));
1982: if (markers == null) {
1983: markers = new java.util.ArrayList();
1984: this.backgroundDomainMarkers.put(new Integer(index), markers);
1985: }
1986: markers.add(marker);
1987: }
1988: marker.addChangeListener(this);
1989: if (notify) {
1990: fireChangeEvent();
1991: }
1992: }
1993:
1994:
2000: public void clearDomainMarkers() {
2001: if (this.backgroundDomainMarkers != null) {
2002: Set keys = this.backgroundDomainMarkers.keySet();
2003: Iterator iterator = keys.iterator();
2004: while (iterator.hasNext()) {
2005: Integer key = (Integer) iterator.next();
2006: clearDomainMarkers(key.intValue());
2007: }
2008: this.backgroundDomainMarkers.clear();
2009: }
2010: if (this.foregroundDomainMarkers != null) {
2011: Set keys = this.foregroundDomainMarkers.keySet();
2012: Iterator iterator = keys.iterator();
2013: while (iterator.hasNext()) {
2014: Integer key = (Integer) iterator.next();
2015: clearDomainMarkers(key.intValue());
2016: }
2017: this.foregroundDomainMarkers.clear();
2018: }
2019: fireChangeEvent();
2020: }
2021:
2022:
2029: public Collection getDomainMarkers(Layer layer) {
2030: return getDomainMarkers(0, layer);
2031: }
2032:
2033:
2042: public Collection getDomainMarkers(int index, Layer layer) {
2043: Collection result = null;
2044: Integer key = new Integer(index);
2045: if (layer == Layer.FOREGROUND) {
2046: result = (Collection) this.foregroundDomainMarkers.get(key);
2047: }
2048: else if (layer == Layer.BACKGROUND) {
2049: result = (Collection) this.backgroundDomainMarkers.get(key);
2050: }
2051: if (result != null) {
2052: result = Collections.unmodifiableCollection(result);
2053: }
2054: return result;
2055: }
2056:
2057:
2064: public void clearDomainMarkers(int index) {
2065: Integer key = new Integer(index);
2066: if (this.backgroundDomainMarkers != null) {
2067: Collection markers
2068: = (Collection) this.backgroundDomainMarkers.get(key);
2069: if (markers != null) {
2070: Iterator iterator = markers.iterator();
2071: while (iterator.hasNext()) {
2072: Marker m = (Marker) iterator.next();
2073: m.removeChangeListener(this);
2074: }
2075: markers.clear();
2076: }
2077: }
2078: if (this.foregroundDomainMarkers != null) {
2079: Collection markers
2080: = (Collection) this.foregroundDomainMarkers.get(key);
2081: if (markers != null) {
2082: Iterator iterator = markers.iterator();
2083: while (iterator.hasNext()) {
2084: Marker m = (Marker) iterator.next();
2085: m.removeChangeListener(this);
2086: }
2087: markers.clear();
2088: }
2089: }
2090: fireChangeEvent();
2091: }
2092:
2093:
2104: public boolean removeDomainMarker(Marker marker) {
2105: return removeDomainMarker(marker, Layer.FOREGROUND);
2106: }
2107:
2108:
2120: public boolean removeDomainMarker(Marker marker, Layer layer) {
2121: return removeDomainMarker(0, marker, layer);
2122: }
2123:
2124:
2137: public boolean removeDomainMarker(int index, Marker marker, Layer layer) {
2138: return removeDomainMarker(index, marker, layer, true);
2139: }
2140:
2141:
2154: public boolean removeDomainMarker(int index, Marker marker, Layer layer,
2155: boolean notify) {
2156: ArrayList markers;
2157: if (layer == Layer.FOREGROUND) {
2158: markers = (ArrayList) this.foregroundDomainMarkers.get(new Integer(
2159: index));
2160: }
2161: else {
2162: markers = (ArrayList) this.backgroundDomainMarkers.get(new Integer(
2163: index));
2164: }
2165: if (markers == null) {
2166: return false;
2167: }
2168: boolean removed = markers.remove(marker);
2169: if (removed && notify) {
2170: fireChangeEvent();
2171: }
2172: return removed;
2173: }
2174:
2175:
2185: public void addRangeMarker(Marker marker) {
2186: addRangeMarker(marker, Layer.FOREGROUND);
2187: }
2188:
2189:
2201: public void addRangeMarker(Marker marker, Layer layer) {
2202: addRangeMarker(0, marker, layer);
2203: }
2204:
2205:
2218: public void addRangeMarker(int index, Marker marker, Layer layer) {
2219: addRangeMarker(index, marker, layer, true);
2220: }
2221:
2222:
2238: public void addRangeMarker(int index, Marker marker, Layer layer,
2239: boolean notify) {
2240: Collection markers;
2241: if (layer == Layer.FOREGROUND) {
2242: markers = (Collection) this.foregroundRangeMarkers.get(
2243: new Integer(index));
2244: if (markers == null) {
2245: markers = new java.util.ArrayList();
2246: this.foregroundRangeMarkers.put(new Integer(index), markers);
2247: }
2248: markers.add(marker);
2249: }
2250: else if (layer == Layer.BACKGROUND) {
2251: markers = (Collection) this.backgroundRangeMarkers.get(
2252: new Integer(index));
2253: if (markers == null) {
2254: markers = new java.util.ArrayList();
2255: this.backgroundRangeMarkers.put(new Integer(index), markers);
2256: }
2257: markers.add(marker);
2258: }
2259: marker.addChangeListener(this);
2260: if (notify) {
2261: fireChangeEvent();
2262: }
2263: }
2264:
2265:
2271: public void clearRangeMarkers() {
2272: if (this.backgroundRangeMarkers != null) {
2273: Set keys = this.backgroundRangeMarkers.keySet();
2274: Iterator iterator = keys.iterator();
2275: while (iterator.hasNext()) {
2276: Integer key = (Integer) iterator.next();
2277: clearRangeMarkers(key.intValue());
2278: }
2279: this.backgroundRangeMarkers.clear();
2280: }
2281: if (this.foregroundRangeMarkers != null) {
2282: Set keys = this.foregroundRangeMarkers.keySet();
2283: Iterator iterator = keys.iterator();
2284: while (iterator.hasNext()) {
2285: Integer key = (Integer) iterator.next();
2286: clearRangeMarkers(key.intValue());
2287: }
2288: this.foregroundRangeMarkers.clear();
2289: }
2290: fireChangeEvent();
2291: }
2292:
2293:
2302: public Collection getRangeMarkers(Layer layer) {
2303: return getRangeMarkers(0, layer);
2304: }
2305:
2306:
2315: public Collection getRangeMarkers(int index, Layer layer) {
2316: Collection result = null;
2317: Integer key = new Integer(index);
2318: if (layer == Layer.FOREGROUND) {
2319: result = (Collection) this.foregroundRangeMarkers.get(key);
2320: }
2321: else if (layer == Layer.BACKGROUND) {
2322: result = (Collection) this.backgroundRangeMarkers.get(key);
2323: }
2324: if (result != null) {
2325: result = Collections.unmodifiableCollection(result);
2326: }
2327: return result;
2328: }
2329:
2330:
2337: public void clearRangeMarkers(int index) {
2338: Integer key = new Integer(index);
2339: if (this.backgroundRangeMarkers != null) {
2340: Collection markers
2341: = (Collection) this.backgroundRangeMarkers.get(key);
2342: if (markers != null) {
2343: Iterator iterator = markers.iterator();
2344: while (iterator.hasNext()) {
2345: Marker m = (Marker) iterator.next();
2346: m.removeChangeListener(this);
2347: }
2348: markers.clear();
2349: }
2350: }
2351: if (this.foregroundRangeMarkers != null) {
2352: Collection markers
2353: = (Collection) this.foregroundRangeMarkers.get(key);
2354: if (markers != null) {
2355: Iterator iterator = markers.iterator();
2356: while (iterator.hasNext()) {
2357: Marker m = (Marker) iterator.next();
2358: m.removeChangeListener(this);
2359: }
2360: markers.clear();
2361: }
2362: }
2363: fireChangeEvent();
2364: }
2365:
2366:
2379: public boolean removeRangeMarker(Marker marker) {
2380: return removeRangeMarker(marker, Layer.FOREGROUND);
2381: }
2382:
2383:
2397: public boolean removeRangeMarker(Marker marker, Layer layer) {
2398: return removeRangeMarker(0, marker, layer);
2399: }
2400:
2401:
2416: public boolean removeRangeMarker(int index, Marker marker, Layer layer) {
2417: return removeRangeMarker(index, marker, layer, true);
2418: }
2419:
2420:
2436: public boolean removeRangeMarker(int index, Marker marker, Layer layer,
2437: boolean notify) {
2438: if (marker == null) {
2439: throw new IllegalArgumentException("Null 'marker' argument.");
2440: }
2441: ArrayList markers;
2442: if (layer == Layer.FOREGROUND) {
2443: markers = (ArrayList) this.foregroundRangeMarkers.get(new Integer(
2444: index));
2445: }
2446: else {
2447: markers = (ArrayList) this.backgroundRangeMarkers.get(new Integer(
2448: index));
2449: }
2450: if (markers == null) {
2451: return false;
2452: }
2453: boolean removed = markers.remove(marker);
2454: if (removed && notify) {
2455: fireChangeEvent();
2456: }
2457: return removed;
2458: }
2459:
2460:
2467: public boolean isRangeCrosshairVisible() {
2468: return this.rangeCrosshairVisible;
2469: }
2470:
2471:
2478: public void setRangeCrosshairVisible(boolean flag) {
2479: if (this.rangeCrosshairVisible != flag) {
2480: this.rangeCrosshairVisible = flag;
2481: fireChangeEvent();
2482: }
2483: }
2484:
2485:
2493: public boolean isRangeCrosshairLockedOnData() {
2494: return this.rangeCrosshairLockedOnData;
2495: }
2496:
2497:
2506: public void setRangeCrosshairLockedOnData(boolean flag) {
2507: if (this.rangeCrosshairLockedOnData != flag) {
2508: this.rangeCrosshairLockedOnData = flag;
2509: fireChangeEvent();
2510: }
2511: }
2512:
2513:
2520: public double getRangeCrosshairValue() {
2521: return this.rangeCrosshairValue;
2522: }
2523:
2524:
2532: public void setRangeCrosshairValue(double value) {
2533: setRangeCrosshairValue(value, true);
2534: }
2535:
2536:
2547: public void setRangeCrosshairValue(double value, boolean notify) {
2548: this.rangeCrosshairValue = value;
2549: if (isRangeCrosshairVisible() && notify) {
2550: fireChangeEvent();
2551: }
2552: }
2553:
2554:
2564: public Stroke getRangeCrosshairStroke() {
2565: return this.rangeCrosshairStroke;
2566: }
2567:
2568:
2578: public void setRangeCrosshairStroke(Stroke stroke) {
2579: if (stroke == null) {
2580: throw new IllegalArgumentException("Null 'stroke' argument.");
2581: }
2582: this.rangeCrosshairStroke = stroke;
2583: fireChangeEvent();
2584: }
2585:
2586:
2595: public Paint getRangeCrosshairPaint() {
2596: return this.rangeCrosshairPaint;
2597: }
2598:
2599:
2607: public void setRangeCrosshairPaint(Paint paint) {
2608: if (paint == null) {
2609: throw new IllegalArgumentException("Null 'paint' argument.");
2610: }
2611: this.rangeCrosshairPaint = paint;
2612: fireChangeEvent();
2613: }
2614:
2615:
2623: public List getAnnotations() {
2624: return this.annotations;
2625: }
2626:
2627:
2635: public void addAnnotation(CategoryAnnotation annotation) {
2636: addAnnotation(annotation, true);
2637: }
2638:
2639:
2648: public void addAnnotation(CategoryAnnotation annotation, boolean notify) {
2649: if (annotation == null) {
2650: throw new IllegalArgumentException("Null 'annotation' argument.");
2651: }
2652: this.annotations.add(annotation);
2653: if (notify) {
2654: fireChangeEvent();
2655: }
2656: }
2657:
2658:
2668: public boolean removeAnnotation(CategoryAnnotation annotation) {
2669: return removeAnnotation(annotation, true);
2670: }
2671:
2672:
2683: public boolean removeAnnotation(CategoryAnnotation annotation,
2684: boolean notify) {
2685: if (annotation == null) {
2686: throw new IllegalArgumentException("Null 'annotation' argument.");
2687: }
2688: boolean removed = this.annotations.remove(annotation);
2689: if (removed && notify) {
2690: fireChangeEvent();
2691: }
2692: return removed;
2693: }
2694:
2695:
2699: public void clearAnnotations() {
2700: this.annotations.clear();
2701: fireChangeEvent();
2702: }
2703:
2704:
2713: protected AxisSpace calculateDomainAxisSpace(Graphics2D g2,
2714: Rectangle2D plotArea,
2715: AxisSpace space) {
2716:
2717: if (space == null) {
2718: space = new AxisSpace();
2719: }
2720:
2721:
2722: if (this.fixedDomainAxisSpace != null) {
2723: if (this.orientation == PlotOrientation.HORIZONTAL) {
2724: space.ensureAtLeast(
2725: this.fixedDomainAxisSpace.getLeft(), RectangleEdge.LEFT);
2726: space.ensureAtLeast(this.fixedDomainAxisSpace.getRight(),
2727: RectangleEdge.RIGHT);
2728: }
2729: else if (this.orientation == PlotOrientation.VERTICAL) {
2730: space.ensureAtLeast(this.fixedDomainAxisSpace.getTop(),
2731: RectangleEdge.TOP);
2732: space.ensureAtLeast(this.fixedDomainAxisSpace.getBottom(),
2733: RectangleEdge.BOTTOM);
2734: }
2735: }
2736: else {
2737:
2738: RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
2739: getDomainAxisLocation(), this.orientation);
2740: if (this.drawSharedDomainAxis) {
2741: space = getDomainAxis().reserveSpace(g2, this, plotArea,
2742: domainEdge, space);
2743: }
2744:
2745:
2746: for (int i = 0; i < this.domainAxes.size(); i++) {
2747: Axis xAxis = (Axis) this.domainAxes.get(i);
2748: if (xAxis != null) {
2749: RectangleEdge edge = getDomainAxisEdge(i);
2750: space = xAxis.reserveSpace(g2, this, plotArea, edge, space);
2751: }
2752: }
2753: }
2754:
2755: return space;
2756:
2757: }
2758:
2759:
2768: protected AxisSpace calculateRangeAxisSpace(Graphics2D g2,
2769: Rectangle2D plotArea,
2770: AxisSpace space) {
2771:
2772: if (space == null) {
2773: space = new AxisSpace();
2774: }
2775:
2776:
2777: if (this.fixedRangeAxisSpace != null) {
2778: if (this.orientation == PlotOrientation.HORIZONTAL) {
2779: space.ensureAtLeast(this.fixedRangeAxisSpace.getTop(),
2780: RectangleEdge.TOP);
2781: space.ensureAtLeast(this.fixedRangeAxisSpace.getBottom(),
2782: RectangleEdge.BOTTOM);
2783: }
2784: else if (this.orientation == PlotOrientation.VERTICAL) {
2785: space.ensureAtLeast(this.fixedRangeAxisSpace.getLeft(),
2786: RectangleEdge.LEFT);
2787: space.ensureAtLeast(this.fixedRangeAxisSpace.getRight(),
2788: RectangleEdge.RIGHT);
2789: }
2790: }
2791: else {
2792:
2793: for (int i = 0; i < this.rangeAxes.size(); i++) {
2794: Axis yAxis = (Axis) this.rangeAxes.get(i);
2795: if (yAxis != null) {
2796: RectangleEdge edge = getRangeAxisEdge(i);
2797: space = yAxis.reserveSpace(g2, this, plotArea, edge, space);
2798: }
2799: }
2800: }
2801: return space;
2802:
2803: }
2804:
2805:
2813: protected AxisSpace calculateAxisSpace(Graphics2D g2,
2814: Rectangle2D plotArea) {
2815: AxisSpace space = new AxisSpace();
2816: space = calculateRangeAxisSpace(g2, plotArea, space);
2817: space = calculateDomainAxisSpace(g2, plotArea, space);
2818: return space;
2819: }
2820:
2821:
2837: public void draw(Graphics2D g2, Rectangle2D area,
2838: Point2D anchor,
2839: PlotState parentState,
2840: PlotRenderingInfo state) {
2841:
2842:
2843: boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW);
2844: boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW);
2845: if (b1 || b2) {
2846: return;
2847: }
2848:
2849:
2850: if (state == null) {
2851:
2852:
2853:
2854: state = new PlotRenderingInfo(null);
2855: }
2856: state.setPlotArea(area);
2857:
2858:
2859: RectangleInsets insets = getInsets();
2860: insets.trim(area);
2861:
2862:
2863: AxisSpace space = calculateAxisSpace(g2, area);
2864: Rectangle2D dataArea = space.shrink(area, null);
2865: this.axisOffset.trim(dataArea);
2866:
2867: state.setDataArea(dataArea);
2868:
2869:
2870:
2871: if (getRenderer() != null) {
2872: getRenderer().drawBackground(g2, this, dataArea);
2873: }
2874: else {
2875: drawBackground(g2, dataArea);
2876: }
2877:
2878: Map axisStateMap = drawAxes(g2, area, dataArea, state);
2879:
2880:
2881: Shape savedClip = g2.getClip();
2882: g2.clip(dataArea);
2883:
2884: drawDomainGridlines(g2, dataArea);
2885:
2886: AxisState rangeAxisState = (AxisState) axisStateMap.get(getRangeAxis());
2887: if (rangeAxisState == null) {
2888: if (parentState != null) {
2889: rangeAxisState = (AxisState) parentState.getSharedAxisStates()
2890: .get(getRangeAxis());
2891: }
2892: }
2893: if (rangeAxisState != null) {
2894: drawRangeGridlines(g2, dataArea, rangeAxisState.getTicks());
2895: }
2896:
2897:
2898: for (int i = 0; i < this.renderers.size(); i++) {
2899: drawDomainMarkers(g2, dataArea, i, Layer.BACKGROUND);
2900: }
2901: for (int i = 0; i < this.renderers.size(); i++) {
2902: drawRangeMarkers(g2, dataArea, i, Layer.BACKGROUND);
2903: }
2904:
2905:
2906: boolean foundData = false;
2907:
2908:
2909: Composite originalComposite = g2.getComposite();
2910: g2.setComposite(AlphaComposite.getInstance(
2911: AlphaComposite.SRC_OVER, getForegroundAlpha()));
2912:
2913: DatasetRenderingOrder order = getDatasetRenderingOrder();
2914: if (order == DatasetRenderingOrder.FORWARD) {
2915: for (int i = 0; i < this.datasets.size(); i++) {
2916: foundData = render(g2, dataArea, i, state) || foundData;
2917: }
2918: }
2919: else {
2920: for (int i = this.datasets.size() - 1; i >= 0; i--) {
2921: foundData = render(g2, dataArea, i, state) || foundData;
2922: }
2923: }
2924:
2925: for (int i = 0; i < this.renderers.size(); i++) {
2926: drawDomainMarkers(g2, dataArea, i, Layer.FOREGROUND);
2927: }
2928: for (int i = 0; i < this.renderers.size(); i++) {
2929: drawRangeMarkers(g2, dataArea, i, Layer.FOREGROUND);
2930: }
2931:
2932:
2933: drawAnnotations(g2, dataArea);
2934:
2935: g2.setClip(savedClip);
2936: g2.setComposite(originalComposite);
2937:
2938: if (!foundData) {
2939: drawNoDataMessage(g2, dataArea);
2940: }
2941:
2942:
2943: if (isRangeCrosshairVisible()) {
2944:
2945: drawRangeCrosshair(g2, dataArea, getOrientation(),
2946: getRangeCrosshairValue(), getRangeAxis(),
2947: getRangeCrosshairStroke(), getRangeCrosshairPaint());
2948: }
2949:
2950:
2951: if (getRenderer() != null) {
2952: getRenderer().drawOutline(g2, this, dataArea);
2953: }
2954: else {
2955: drawOutline(g2, dataArea);
2956: }
2957:
2958: }
2959:
2960:
2970: public void drawBackground(Graphics2D g2, Rectangle2D area) {
2971: fillBackground(g2, area, this.orientation);
2972: drawBackgroundImage(g2, area);
2973: }
2974:
2975:
2986: protected Map drawAxes(Graphics2D g2,
2987: Rectangle2D plotArea,
2988: Rectangle2D dataArea,
2989: PlotRenderingInfo plotState) {
2990:
2991: AxisCollection axisCollection = new AxisCollection();
2992:
2993:
2994: for (int index = 0; index < this.domainAxes.size(); index++) {
2995: CategoryAxis xAxis = (CategoryAxis) this.domainAxes.get(index);
2996: if (xAxis != null) {
2997: axisCollection.add(xAxis, getDomainAxisEdge(index));
2998: }
2999: }
3000:
3001:
3002: for (int index = 0; index < this.rangeAxes.size(); index++) {
3003: ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(index);
3004: if (yAxis != null) {
3005: axisCollection.add(yAxis, getRangeAxisEdge(index));
3006: }
3007: }
3008:
3009: Map axisStateMap = new HashMap();
3010:
3011:
3012: double cursor = dataArea.getMinY() - this.axisOffset.calculateTopOutset(
3013: dataArea.getHeight());
3014: Iterator iterator = axisCollection.getAxesAtTop().iterator();
3015: while (iterator.hasNext()) {
3016: Axis axis = (Axis) iterator.next();
3017: if (axis != null) {
3018: AxisState axisState = axis.draw(g2, cursor, plotArea, dataArea,
3019: RectangleEdge.TOP, plotState);
3020: cursor = axisState.getCursor();
3021: axisStateMap.put(axis, axisState);
3022: }
3023: }
3024:
3025:
3026: cursor = dataArea.getMaxY()
3027: + this.axisOffset.calculateBottomOutset(dataArea.getHeight());
3028: iterator = axisCollection.getAxesAtBottom().iterator();
3029: while (iterator.hasNext()) {
3030: Axis axis = (Axis) iterator.next();
3031: if (axis != null) {
3032: AxisState axisState = axis.draw(g2, cursor, plotArea, dataArea,
3033: RectangleEdge.BOTTOM, plotState);
3034: cursor = axisState.getCursor();
3035: axisStateMap.put(axis, axisState);
3036: }
3037: }
3038:
3039:
3040: cursor = dataArea.getMinX()
3041: - this.axisOffset.calculateLeftOutset(dataArea.getWidth());
3042: iterator = axisCollection.getAxesAtLeft().iterator();
3043: while (iterator.hasNext()) {
3044: Axis axis = (Axis) iterator.next();
3045: if (axis != null) {
3046: AxisState axisState = axis.draw(g2, cursor, plotArea, dataArea,
3047: RectangleEdge.LEFT, plotState);
3048: cursor = axisState.getCursor();
3049: axisStateMap.put(axis, axisState);
3050: }
3051: }
3052:
3053:
3054: cursor = dataArea.getMaxX()
3055: + this.axisOffset.calculateRightOutset(dataArea.getWidth());
3056: iterator = axisCollection.getAxesAtRight().iterator();
3057: while (iterator.hasNext()) {
3058: Axis axis = (Axis) iterator.next();
3059: if (axis != null) {
3060: AxisState axisState = axis.draw(g2, cursor, plotArea, dataArea,
3061: RectangleEdge.RIGHT, plotState);
3062: cursor = axisState.getCursor();
3063: axisStateMap.put(axis, axisState);
3064: }
3065: }
3066:
3067: return axisStateMap;
3068:
3069: }
3070:
3071:
3082: public boolean render(Graphics2D g2, Rectangle2D dataArea, int index,
3083: PlotRenderingInfo info) {
3084:
3085: boolean foundData = false;
3086: CategoryDataset currentDataset = getDataset(index);
3087: CategoryItemRenderer renderer = getRenderer(index);
3088: CategoryAxis domainAxis = getDomainAxisForDataset(index);
3089: ValueAxis rangeAxis = getRangeAxisForDataset(index);
3090: boolean hasData = !DatasetUtilities.isEmptyOrNull(currentDataset);
3091: if (hasData && renderer != null) {
3092:
3093: foundData = true;
3094: CategoryItemRendererState state = renderer.initialise(g2, dataArea,
3095: this, index, info);
3096: int columnCount = currentDataset.getColumnCount();
3097: int rowCount = currentDataset.getRowCount();
3098: int passCount = renderer.getPassCount();
3099: for (int pass = 0; pass < passCount; pass++) {
3100: if (this.columnRenderingOrder == SortOrder.ASCENDING) {
3101: for (int column = 0; column < columnCount; column++) {
3102: if (this.rowRenderingOrder == SortOrder.ASCENDING) {
3103: for (int row = 0; row < rowCount; row++) {
3104: renderer.drawItem(g2, state, dataArea, this,
3105: domainAxis, rangeAxis, currentDataset,
3106: row, column, pass);
3107: }
3108: }
3109: else {
3110: for (int row = rowCount - 1; row >= 0; row--) {
3111: renderer.drawItem(g2, state, dataArea, this,
3112: domainAxis, rangeAxis, currentDataset,
3113: row, column, pass);
3114: }
3115: }
3116: }
3117: }
3118: else {
3119: for (int column = columnCount - 1; column >= 0; column--) {
3120: if (this.rowRenderingOrder == SortOrder.ASCENDING) {
3121: for (int row = 0; row < rowCount; row++) {
3122: renderer.drawItem(g2, state, dataArea, this,
3123: domainAxis, rangeAxis, currentDataset,
3124: row, column, pass);
3125: }
3126: }
3127: else {
3128: for (int row = rowCount - 1; row >= 0; row--) {
3129: renderer.drawItem(g2, state, dataArea, this,
3130: domainAxis, rangeAxis, currentDataset,
3131: row, column, pass);
3132: }
3133: }
3134: }
3135: }
3136: }
3137: }
3138: return foundData;
3139:
3140: }
3141:
3142:
3150: protected void drawDomainGridlines(Graphics2D g2, Rectangle2D dataArea) {
3151:
3152:
3153: if (isDomainGridlinesVisible()) {
3154: CategoryAnchor anchor = getDomainGridlinePosition();
3155: RectangleEdge domainAxisEdge = getDomainAxisEdge();
3156: Stroke gridStroke = getDomainGridlineStroke();
3157: Paint gridPaint = getDomainGridlinePaint();
3158: if ((gridStroke != null) && (gridPaint != null)) {
3159:
3160: CategoryDataset data = getDataset();
3161: if (data != null) {
3162: CategoryAxis axis = getDomainAxis();
3163: if (axis != null) {
3164: int columnCount = data.getColumnCount();
3165: for (int c = 0; c < columnCount; c++) {
3166: double xx = axis.getCategoryJava2DCoordinate(
3167: anchor, c, columnCount, dataArea,
3168: domainAxisEdge);
3169: CategoryItemRenderer renderer1 = getRenderer();
3170: if (renderer1 != null) {
3171: renderer1.drawDomainGridline(g2, this,
3172: dataArea, xx);
3173: }
3174: }
3175: }
3176: }
3177: }
3178: }
3179: }
3180:
3181:
3190: protected void drawRangeGridlines(Graphics2D g2, Rectangle2D dataArea,
3191: List ticks) {
3192:
3193: if (isRangeGridlinesVisible()) {
3194: Stroke gridStroke = getRangeGridlineStroke();
3195: Paint gridPaint = getRangeGridlinePaint();
3196: if ((gridStroke != null) && (gridPaint != null)) {
3197: ValueAxis axis = getRangeAxis();
3198: if (axis != null) {
3199: Iterator iterator = ticks.iterator();
3200: while (iterator.hasNext()) {
3201: ValueTick tick = (ValueTick) iterator.next();
3202: CategoryItemRenderer renderer1 = getRenderer();
3203: if (renderer1 != null) {
3204: renderer1.drawRangeGridline(g2, this,
3205: getRangeAxis(), dataArea, tick.getValue());
3206: }
3207: }
3208: }
3209: }
3210: }
3211: }
3212:
3213:
3219: protected void drawAnnotations(Graphics2D g2, Rectangle2D dataArea) {
3220:
3221: if (getAnnotations() != null) {
3222: Iterator iterator = getAnnotations().iterator();
3223: while (iterator.hasNext()) {
3224: CategoryAnnotation annotation
3225: = (CategoryAnnotation) iterator.next();
3226: annotation.draw(g2, this, dataArea, getDomainAxis(),
3227: getRangeAxis());
3228: }
3229: }
3230:
3231: }
3232:
3233:
3244: protected void drawDomainMarkers(Graphics2D g2, Rectangle2D dataArea,
3245: int index, Layer layer) {
3246:
3247: CategoryItemRenderer r = getRenderer(index);
3248: if (r == null) {
3249: return;
3250: }
3251:
3252: Collection markers = getDomainMarkers(index, layer);
3253: CategoryAxis axis = getDomainAxisForDataset(index);
3254: if (markers != null && axis != null) {
3255: Iterator iterator = markers.iterator();
3256: while (iterator.hasNext()) {
3257: CategoryMarker marker = (CategoryMarker) iterator.next();
3258: r.drawDomainMarker(g2, this, axis, marker, dataArea);
3259: }
3260: }
3261:
3262: }
3263:
3264:
3275: protected void drawRangeMarkers(Graphics2D g2, Rectangle2D dataArea,
3276: int index, Layer layer) {
3277:
3278: CategoryItemRenderer r = getRenderer(index);
3279: if (r == null) {
3280: return;
3281: }
3282:
3283: Collection markers = getRangeMarkers(index, layer);
3284: ValueAxis axis = getRangeAxisForDataset(index);
3285: if (markers != null && axis != null) {
3286: Iterator iterator = markers.iterator();
3287: while (iterator.hasNext()) {
3288: Marker marker = (Marker) iterator.next();
3289: r.drawRangeMarker(g2, this, axis, marker, dataArea);
3290: }
3291: }
3292:
3293: }
3294:
3295:
3305: protected void drawRangeLine(Graphics2D g2, Rectangle2D dataArea,
3306: double value, Stroke stroke, Paint paint) {
3307:
3308: double java2D = getRangeAxis().valueToJava2D(value, dataArea,
3309: getRangeAxisEdge());
3310: Line2D line = null;
3311: if (this.orientation == PlotOrientation.HORIZONTAL) {
3312: line = new Line2D.Double(java2D, dataArea.getMinY(), java2D,
3313: dataArea.getMaxY());
3314: }
3315: else if (this.orientation == PlotOrientation.VERTICAL) {
3316: line = new Line2D.Double(dataArea.getMinX(), java2D,
3317: dataArea.getMaxX(), java2D);
3318: }
3319: g2.setStroke(stroke);
3320: g2.setPaint(paint);
3321: g2.draw(line);
3322:
3323: }
3324:
3325:
3338: protected void drawRangeCrosshair(Graphics2D g2, Rectangle2D dataArea,
3339: PlotOrientation orientation, double value, ValueAxis axis,
3340: Stroke stroke, Paint paint) {
3341:
3342: if (!axis.getRange().contains(value)) {
3343: return;
3344: }
3345: Line2D line = null;
3346: if (orientation == PlotOrientation.HORIZONTAL) {
3347: double xx = axis.valueToJava2D(value, dataArea,
3348: RectangleEdge.BOTTOM);
3349: line = new Line2D.Double(xx, dataArea.getMinY(), xx,
3350: dataArea.getMaxY());
3351: }
3352: else {
3353: double yy = axis.valueToJava2D(value, dataArea,
3354: RectangleEdge.LEFT);
3355: line = new Line2D.Double(dataArea.getMinX(), yy,
3356: dataArea.getMaxX(), yy);
3357: }
3358: g2.setStroke(stroke);
3359: g2.setPaint(paint);
3360: g2.draw(line);
3361:
3362: }
3363:
3364:
3373: public Range getDataRange(ValueAxis axis) {
3374:
3375: Range result = null;
3376: List mappedDatasets = new ArrayList();
3377:
3378: int rangeIndex = this.rangeAxes.indexOf(axis);
3379: if (rangeIndex >= 0) {
3380: mappedDatasets.addAll(datasetsMappedToRangeAxis(rangeIndex));
3381: }
3382: else if (axis == getRangeAxis()) {
3383: mappedDatasets.addAll(datasetsMappedToRangeAxis(0));
3384: }
3385:
3386:
3387:
3388: Iterator iterator = mappedDatasets.iterator();
3389: while (iterator.hasNext()) {
3390: CategoryDataset d = (CategoryDataset) iterator.next();
3391: CategoryItemRenderer r = getRendererForDataset(d);
3392: if (r != null) {
3393: result = Range.combine(result, r.findRangeBounds(d));
3394: }
3395: }
3396: return result;
3397:
3398: }
3399:
3400:
3410: private List datasetsMappedToDomainAxis(int axisIndex) {
3411: List result = new ArrayList();
3412: for (int datasetIndex = 0; datasetIndex < this.datasets.size();
3413: datasetIndex++) {
3414: Object dataset = this.datasets.get(datasetIndex);
3415: if (dataset != null) {
3416: Integer m = (Integer) this.datasetToDomainAxisMap.get(
3417: datasetIndex);
3418: if (m == null) {
3419:
3420: if (axisIndex == 0) {
3421: result.add(dataset);
3422: }
3423: }
3424: else {
3425: if (m.intValue() == axisIndex) {
3426: result.add(dataset);
3427: }
3428: }
3429: }
3430: }
3431: return result;
3432: }
3433:
3434:
3442: private List datasetsMappedToRangeAxis(int index) {
3443: List result = new ArrayList();
3444: for (int i = 0; i < this.datasets.size(); i++) {
3445: Object dataset = this.datasets.get(i);
3446: if (dataset != null) {
3447: Integer m = (Integer) this.datasetToRangeAxisMap.get(i);
3448: if (m == null) {
3449:
3450: if (index == 0) {
3451: result.add(dataset);
3452: }
3453: }
3454: else {
3455: if (m.intValue() == index) {
3456: result.add(dataset);
3457: }
3458: }
3459: }
3460: }
3461: return result;
3462: }
3463:
3464:
3472: public int getWeight() {
3473: return this.weight;
3474: }
3475:
3476:
3484: public void setWeight(int weight) {
3485: this.weight = weight;
3486: fireChangeEvent();
3487: }
3488:
3489:
3496: public AxisSpace getFixedDomainAxisSpace() {
3497: return this.fixedDomainAxisSpace;
3498: }
3499:
3500:
3508: public void setFixedDomainAxisSpace(AxisSpace space) {
3509: setFixedDomainAxisSpace(space, true);
3510: }
3511:
3512:
3523: public void setFixedDomainAxisSpace(AxisSpace space, boolean notify) {
3524: this.fixedDomainAxisSpace = space;
3525: if (notify) {
3526: fireChangeEvent();
3527: }
3528: }
3529:
3530:
3537: public AxisSpace getFixedRangeAxisSpace() {
3538: return this.fixedRangeAxisSpace;
3539: }
3540:
3541:
3549: public void setFixedRangeAxisSpace(AxisSpace space) {
3550: setFixedRangeAxisSpace(space, true);
3551: }
3552:
3553:
3564: public void setFixedRangeAxisSpace(AxisSpace space, boolean notify) {
3565: this.fixedRangeAxisSpace = space;
3566: if (notify) {
3567: fireChangeEvent();
3568: }
3569: }
3570:
3571:
3578: public List getCategories() {
3579: List result = null;
3580: if (getDataset() != null) {
3581: result = Collections.unmodifiableList(getDataset().getColumnKeys());
3582: }
3583: return result;
3584: }
3585:
3586:
3596: public List getCategoriesForAxis(CategoryAxis axis) {
3597: List result = new ArrayList();
3598: int axisIndex = this.domainAxes.indexOf(axis);
3599: List datasets = datasetsMappedToDomainAxis(axisIndex);
3600: Iterator iterator = datasets.iterator();
3601: while (iterator.hasNext()) {
3602: CategoryDataset dataset = (CategoryDataset) iterator.next();
3603:
3604: for (int i = 0; i < dataset.getColumnCount(); i++) {
3605: Comparable category = dataset.getColumnKey(i);
3606: if (!result.contains(category)) {
3607: result.add(category);
3608: }
3609: }
3610: }
3611: return result;
3612: }
3613:
3614:
3622: public boolean getDrawSharedDomainAxis() {
3623: return this.drawSharedDomainAxis;
3624: }
3625:
3626:
3634: public void setDrawSharedDomainAxis(boolean draw) {
3635: this.drawSharedDomainAxis = draw;
3636: fireChangeEvent();
3637: }
3638:
3639:
3647: public boolean isDomainZoomable() {
3648: return false;
3649: }
3650:
3651:
3658: public boolean isRangeZoomable() {
3659: return true;
3660: }
3661:
3662:
3670: public void zoomDomainAxes(double factor, PlotRenderingInfo state,
3671: Point2D source) {
3672:
3673: }
3674:
3675:
3684: public void zoomDomainAxes(double lowerPercent, double upperPercent,
3685: PlotRenderingInfo state, Point2D source) {
3686:
3687: }
3688:
3689:
3702: public void zoomDomainAxes(double factor, PlotRenderingInfo info,
3703: Point2D source, boolean useAnchor) {
3704:
3705: }
3706:
3707:
3714: public void zoomRangeAxes(double factor, PlotRenderingInfo state,
3715: Point2D source) {
3716:
3717: zoomRangeAxes(factor, state, source, false);
3718: }
3719:
3720:
3733: public void zoomRangeAxes(double factor, PlotRenderingInfo info,
3734: Point2D source, boolean useAnchor) {
3735:
3736:
3737: for (int i = 0; i < this.rangeAxes.size(); i++) {
3738: ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i);
3739: if (rangeAxis != null) {
3740: if (useAnchor) {
3741:
3742:
3743: double sourceY = source.getY();
3744: if (this.orientation == PlotOrientation.HORIZONTAL) {
3745: sourceY = source.getX();
3746: }
3747: double anchorY = rangeAxis.java2DToValue(sourceY,
3748: info.getDataArea(), getRangeAxisEdge());
3749: rangeAxis.resizeRange(factor, anchorY);
3750: }
3751: else {
3752: rangeAxis.resizeRange(factor);
3753: }
3754: }
3755: }
3756: }
3757:
3758:
3766: public void zoomRangeAxes(double lowerPercent, double upperPercent,
3767: PlotRenderingInfo state, Point2D source) {
3768: for (int i = 0; i < this.rangeAxes.size(); i++) {
3769: ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i);
3770: if (rangeAxis != null) {
3771: rangeAxis.zoomRange(lowerPercent, upperPercent);
3772: }
3773: }
3774: }
3775:
3776:
3783: public double getAnchorValue() {
3784: return this.anchorValue;
3785: }
3786:
3787:
3795: public void setAnchorValue(double value) {
3796: setAnchorValue(value, true);
3797: }
3798:
3799:
3808: public void setAnchorValue(double value, boolean notify) {
3809: this.anchorValue = value;
3810: if (notify) {
3811: fireChangeEvent();
3812: }
3813: }
3814:
3815:
3822: public boolean equals(Object obj) {
3823:
3824: if (obj == this) {
3825: return true;
3826: }
3827: if (!(obj instanceof CategoryPlot)) {
3828: return false;
3829: }
3830: CategoryPlot that = (CategoryPlot) obj;
3831: if (this.orientation != that.orientation) {
3832: return false;
3833: }
3834: if (!ObjectUtilities.equal(this.axisOffset, that.axisOffset)) {
3835: return false;
3836: }
3837: if (!this.domainAxes.equals(that.domainAxes)) {
3838: return false;
3839: }
3840: if (!this.domainAxisLocations.equals(that.domainAxisLocations)) {
3841: return false;
3842: }
3843: if (this.drawSharedDomainAxis != that.drawSharedDomainAxis) {
3844: return false;
3845: }
3846: if (!this.rangeAxes.equals(that.rangeAxes)) {
3847: return false;
3848: }
3849: if (!this.rangeAxisLocations.equals(that.rangeAxisLocations)) {
3850: return false;
3851: }
3852: if (!ObjectUtilities.equal(this.datasetToDomainAxisMap,
3853: that.datasetToDomainAxisMap)) {
3854: return false;
3855: }
3856: if (!ObjectUtilities.equal(this.datasetToRangeAxisMap,
3857: that.datasetToRangeAxisMap)) {
3858: return false;
3859: }
3860: if (!ObjectUtilities.equal(this.renderers, that.renderers)) {
3861: return false;
3862: }
3863: if (this.renderingOrder != that.renderingOrder) {
3864: return false;
3865: }
3866: if (this.columnRenderingOrder != that.columnRenderingOrder) {
3867: return false;
3868: }
3869: if (this.rowRenderingOrder != that.rowRenderingOrder) {
3870: return false;
3871: }
3872: if (this.domainGridlinesVisible != that.domainGridlinesVisible) {
3873: return false;
3874: }
3875: if (this.domainGridlinePosition != that.domainGridlinePosition) {
3876: return false;
3877: }
3878: if (!ObjectUtilities.equal(this.domainGridlineStroke,
3879: that.domainGridlineStroke)) {
3880: return false;
3881: }
3882: if (!PaintUtilities.equal(this.domainGridlinePaint,
3883: that.domainGridlinePaint)) {
3884: return false;
3885: }
3886: if (this.rangeGridlinesVisible != that.rangeGridlinesVisible) {
3887: return false;
3888: }
3889: if (!ObjectUtilities.equal(this.rangeGridlineStroke,
3890: that.rangeGridlineStroke)) {
3891: return false;
3892: }
3893: if (!PaintUtilities.equal(this.rangeGridlinePaint,
3894: that.rangeGridlinePaint)) {
3895: return false;
3896: }
3897: if (this.anchorValue != that.anchorValue) {
3898: return false;
3899: }
3900: if (this.rangeCrosshairVisible != that.rangeCrosshairVisible) {
3901: return false;
3902: }
3903: if (this.rangeCrosshairValue != that.rangeCrosshairValue) {
3904: return false;
3905: }
3906: if (!ObjectUtilities.equal(this.rangeCrosshairStroke,
3907: that.rangeCrosshairStroke)) {
3908: return false;
3909: }
3910: if (!PaintUtilities.equal(this.rangeCrosshairPaint,
3911: that.rangeCrosshairPaint)) {
3912: return false;
3913: }
3914: if (this.rangeCrosshairLockedOnData
3915: != that.rangeCrosshairLockedOnData) {
3916: return false;
3917: }
3918: if (!ObjectUtilities.equal(this.foregroundDomainMarkers,
3919: that.foregroundDomainMarkers)) {
3920: return false;
3921: }
3922: if (!ObjectUtilities.equal(this.backgroundDomainMarkers,
3923: that.backgroundDomainMarkers)) {
3924: return false;
3925: }
3926: if (!ObjectUtilities.equal(this.foregroundRangeMarkers,
3927: that.foregroundRangeMarkers)) {
3928: return false;
3929: }
3930: if (!ObjectUtilities.equal(this.backgroundRangeMarkers,
3931: that.backgroundRangeMarkers)) {
3932: return false;
3933: }
3934: if (!ObjectUtilities.equal(this.annotations, that.annotations)) {
3935: return false;
3936: }
3937: if (this.weight != that.weight) {
3938: return false;
3939: }
3940: if (!ObjectUtilities.equal(this.fixedDomainAxisSpace,
3941: that.fixedDomainAxisSpace)) {
3942: return false;
3943: }
3944: if (!ObjectUtilities.equal(this.fixedRangeAxisSpace,
3945: that.fixedRangeAxisSpace)) {
3946: return false;
3947: }
3948: if (!ObjectUtilities.equal(this.fixedLegendItems,
3949: that.fixedLegendItems)) {
3950: return false;
3951: }
3952:
3953: return super.equals(obj);
3954:
3955: }
3956:
3957:
3964: public Object clone() throws CloneNotSupportedException {
3965:
3966: CategoryPlot clone = (CategoryPlot) super.clone();
3967:
3968: clone.domainAxes = new ObjectList();
3969: for (int i = 0; i < this.domainAxes.size(); i++) {
3970: CategoryAxis xAxis = (CategoryAxis) this.domainAxes.get(i);
3971: if (xAxis != null) {
3972: CategoryAxis clonedAxis = (CategoryAxis) xAxis.clone();
3973: clone.setDomainAxis(i, clonedAxis);
3974: }
3975: }
3976: clone.domainAxisLocations
3977: = (ObjectList) this.domainAxisLocations.clone();
3978:
3979: clone.rangeAxes = new ObjectList();
3980: for (int i = 0; i < this.rangeAxes.size(); i++) {
3981: ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(i);
3982: if (yAxis != null) {
3983: ValueAxis clonedAxis = (ValueAxis) yAxis.clone();
3984: clone.setRangeAxis(i, clonedAxis);
3985: }
3986: }
3987: clone.rangeAxisLocations = (ObjectList) this.rangeAxisLocations.clone();
3988:
3989: clone.datasets = (ObjectList) this.datasets.clone();
3990: for (int i = 0; i < clone.datasets.size(); i++) {
3991: CategoryDataset dataset = clone.getDataset(i);
3992: if (dataset != null) {
3993: dataset.addChangeListener(clone);
3994: }
3995: }
3996: clone.datasetToDomainAxisMap
3997: = (ObjectList) this.datasetToDomainAxisMap.clone();
3998: clone.datasetToRangeAxisMap
3999: = (ObjectList) this.datasetToRangeAxisMap.clone();
4000: clone.renderers = (ObjectList) this.renderers.clone();
4001: if (this.fixedDomainAxisSpace != null) {
4002: clone.fixedDomainAxisSpace = (AxisSpace) ObjectUtilities.clone(
4003: this.fixedDomainAxisSpace);
4004: }
4005: if (this.fixedRangeAxisSpace != null) {
4006: clone.fixedRangeAxisSpace = (AxisSpace) ObjectUtilities.clone(
4007: this.fixedRangeAxisSpace);
4008: }
4009:
4010: clone.annotations = (List) ObjectUtilities.deepClone(this.annotations);
4011: clone.foregroundDomainMarkers = cloneMarkerMap(
4012: this.foregroundDomainMarkers);
4013: clone.backgroundDomainMarkers = cloneMarkerMap(
4014: this.backgroundDomainMarkers);
4015: clone.foregroundRangeMarkers = cloneMarkerMap(
4016: this.foregroundRangeMarkers);
4017: clone.backgroundRangeMarkers = cloneMarkerMap(
4018: this.backgroundRangeMarkers);
4019: if (this.fixedLegendItems != null) {
4020: clone.fixedLegendItems
4021: = (LegendItemCollection) this.fixedLegendItems.clone();
4022: }
4023: return clone;
4024:
4025: }
4026:
4027:
4037: private Map cloneMarkerMap(Map map) throws CloneNotSupportedException {
4038: Map clone = new HashMap();
4039: Set keys = map.keySet();
4040: Iterator iterator = keys.iterator();
4041: while (iterator.hasNext()) {
4042: Object key = iterator.next();
4043: List entry = (List) map.get(key);
4044: Object toAdd = ObjectUtilities.deepClone(entry);
4045: clone.put(key, toAdd);
4046: }
4047: return clone;
4048: }
4049:
4050:
4057: private void writeObject(ObjectOutputStream stream) throws IOException {
4058: stream.defaultWriteObject();
4059: SerialUtilities.writeStroke(this.domainGridlineStroke, stream);
4060: SerialUtilities.writePaint(this.domainGridlinePaint, stream);
4061: SerialUtilities.writeStroke(this.rangeGridlineStroke, stream);
4062: SerialUtilities.writePaint(this.rangeGridlinePaint, stream);
4063: SerialUtilities.writeStroke(this.rangeCrosshairStroke, stream);
4064: SerialUtilities.writePaint(this.rangeCrosshairPaint, stream);
4065: }
4066:
4067:
4075: private void readObject(ObjectInputStream stream)
4076: throws IOException, ClassNotFoundException {
4077:
4078: stream.defaultReadObject();
4079: this.domainGridlineStroke = SerialUtilities.readStroke(stream);
4080: this.domainGridlinePaint = SerialUtilities.readPaint(stream);
4081: this.rangeGridlineStroke = SerialUtilities.readStroke(stream);
4082: this.rangeGridlinePaint = SerialUtilities.readPaint(stream);
4083: this.rangeCrosshairStroke = SerialUtilities.readStroke(stream);
4084: this.rangeCrosshairPaint = SerialUtilities.readPaint(stream);
4085:
4086: for (int i = 0; i < this.domainAxes.size(); i++) {
4087: CategoryAxis xAxis = (CategoryAxis) this.domainAxes.get(i);
4088: if (xAxis != null) {
4089: xAxis.setPlot(this);
4090: xAxis.addChangeListener(this);
4091: }
4092: }
4093: for (int i = 0; i < this.rangeAxes.size(); i++) {
4094: ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(i);
4095: if (yAxis != null) {
4096: yAxis.setPlot(this);
4097: yAxis.addChangeListener(this);
4098: }
4099: }
4100: int datasetCount = this.datasets.size();
4101: for (int i = 0; i < datasetCount; i++) {
4102: Dataset dataset = (Dataset) this.datasets.get(i);
4103: if (dataset != null) {
4104: dataset.addChangeListener(this);
4105: }
4106: }
4107: int rendererCount = this.renderers.size();
4108: for (int i = 0; i < rendererCount; i++) {
4109: CategoryItemRenderer renderer
4110: = (CategoryItemRenderer) this.renderers.get(i);
4111: if (renderer != null) {
4112: renderer.addChangeListener(this);
4113: }
4114: }
4115:
4116: }
4117:
4118: }