1:
140:
141: package ;
142:
143:
144: import ;
145: import ;
146: import ;
147: import ;
148: import ;
149: import ;
150: import ;
151: import ;
152: import ;
153: import ;
154: import ;
155: import ;
156: import ;
157: import ;
158: import ;
159: import ;
160: import ;
161: import ;
162: import ;
163: import ;
164: import ;
165: import ;
166: import ;
167: import ;
168:
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: import ;
193: import ;
194: import ;
195: import ;
196: import ;
197: import ;
198: import ;
199: import ;
200: import ;
201:
202:
206: public class CategoryPlot extends Plot
207: implements ValueAxisPlot,
208: Zoomable,
209: RendererChangeListener,
210: Cloneable, PublicCloneable, Serializable {
211:
212:
213: private static final long serialVersionUID = -3537691700434728188L;
214:
215:
219: public static final boolean DEFAULT_DOMAIN_GRIDLINES_VISIBLE = false;
220:
221:
225: public static final boolean DEFAULT_RANGE_GRIDLINES_VISIBLE = true;
226:
227:
228: public static final Stroke DEFAULT_GRIDLINE_STROKE = new BasicStroke(0.5f,
229: BasicStroke.CAP_BUTT,
230: BasicStroke.JOIN_BEVEL,
231: 0.0f,
232: new float[] {2.0f, 2.0f},
233: 0.0f);
234:
235:
236: public static final Paint DEFAULT_GRIDLINE_PAINT = Color.lightGray;
237:
238:
239: public static final Font DEFAULT_VALUE_LABEL_FONT
240: = new Font("SansSerif", Font.PLAIN, 10);
241:
242:
243: protected static ResourceBundle localizationResources
244: = ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle");
245:
246:
247: private PlotOrientation orientation;
248:
249:
250: private RectangleInsets axisOffset;
251:
252:
253: private ObjectList domainAxes;
254:
255:
256: private ObjectList domainAxisLocations;
257:
258:
262: private boolean drawSharedDomainAxis;
263:
264:
265: private ObjectList rangeAxes;
266:
267:
268: private ObjectList rangeAxisLocations;
269:
270:
271: private ObjectList datasets;
272:
273:
274: private ObjectList datasetToDomainAxisMap;
275:
276:
277: private ObjectList datasetToRangeAxisMap;
278:
279:
280: private ObjectList renderers;
281:
282:
283: private DatasetRenderingOrder renderingOrder
284: = DatasetRenderingOrder.REVERSE;
285:
286:
290: private SortOrder columnRenderingOrder = SortOrder.ASCENDING;
291:
292:
296: private SortOrder rowRenderingOrder = SortOrder.ASCENDING;
297:
298:
302: private boolean domainGridlinesVisible;
303:
304:
305: private CategoryAnchor domainGridlinePosition;
306:
307:
308: private transient Stroke domainGridlineStroke;
309:
310:
311: private transient Paint domainGridlinePaint;
312:
313:
317: private boolean rangeGridlinesVisible;
318:
319:
320: private transient Stroke rangeGridlineStroke;
321:
322:
323: private transient Paint rangeGridlinePaint;
324:
325:
326: private double anchorValue;
327:
328:
329: private boolean rangeCrosshairVisible;
330:
331:
332: private double rangeCrosshairValue;
333:
334:
335: private transient Stroke rangeCrosshairStroke;
336:
337:
338: private transient Paint rangeCrosshairPaint;
339:
340:
344: private boolean rangeCrosshairLockedOnData = true;
345:
346:
347: private Map foregroundDomainMarkers;
348:
349:
350: private Map backgroundDomainMarkers;
351:
352:
353: private Map foregroundRangeMarkers;
354:
355:
356: private Map backgroundRangeMarkers;
357:
358:
363: private List annotations;
364:
365:
369: private int weight;
370:
371:
372: private AxisSpace fixedDomainAxisSpace;
373:
374:
375: private AxisSpace fixedRangeAxisSpace;
376:
377:
381: private LegendItemCollection fixedLegendItems;
382:
383:
386: public CategoryPlot() {
387: this(null, null, null, null);
388: }
389:
390:
399: public CategoryPlot(CategoryDataset dataset,
400: CategoryAxis domainAxis,
401: ValueAxis rangeAxis,
402: CategoryItemRenderer renderer) {
403:
404: super();
405:
406: this.orientation = PlotOrientation.VERTICAL;
407:
408:
409: this.domainAxes = new ObjectList();
410: this.domainAxisLocations = new ObjectList();
411: this.rangeAxes = new ObjectList();
412: this.rangeAxisLocations = new ObjectList();
413:
414: this.datasetToDomainAxisMap = new ObjectList();
415: this.datasetToRangeAxisMap = new ObjectList();
416:
417: this.renderers = new ObjectList();
418:
419: this.datasets = new ObjectList();
420: this.datasets.set(0, dataset);
421: if (dataset != null) {
422: dataset.addChangeListener(this);
423: }
424:
425: this.axisOffset = RectangleInsets.ZERO_INSETS;
426:
427: setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT, false);
428: setRangeAxisLocation(AxisLocation.TOP_OR_LEFT, false);
429:
430: this.renderers.set(0, renderer);
431: if (renderer != null) {
432: renderer.setPlot(this);
433: renderer.addChangeListener(this);
434: }
435:
436: this.domainAxes.set(0, domainAxis);
437: this.mapDatasetToDomainAxis(0, 0);
438: if (domainAxis != null) {
439: domainAxis.setPlot(this);
440: domainAxis.addChangeListener(this);
441: }
442: this.drawSharedDomainAxis = false;
443:
444: this.rangeAxes.set(0, rangeAxis);
445: this.mapDatasetToRangeAxis(0, 0);
446: if (rangeAxis != null) {
447: rangeAxis.setPlot(this);
448: rangeAxis.addChangeListener(this);
449: }
450:
451: configureDomainAxes();
452: configureRangeAxes();
453:
454: this.domainGridlinesVisible = DEFAULT_DOMAIN_GRIDLINES_VISIBLE;
455: this.domainGridlinePosition = CategoryAnchor.MIDDLE;
456: this.domainGridlineStroke = DEFAULT_GRIDLINE_STROKE;
457: this.domainGridlinePaint = DEFAULT_GRIDLINE_PAINT;
458:
459: this.rangeGridlinesVisible = DEFAULT_RANGE_GRIDLINES_VISIBLE;
460: this.rangeGridlineStroke = DEFAULT_GRIDLINE_STROKE;
461: this.rangeGridlinePaint = DEFAULT_GRIDLINE_PAINT;
462:
463: this.foregroundDomainMarkers = new HashMap();
464: this.backgroundDomainMarkers = new HashMap();
465: this.foregroundRangeMarkers = new HashMap();
466: this.backgroundRangeMarkers = new HashMap();
467:
468: Marker baseline = new ValueMarker(
469: 0.0, new Color(0.8f, 0.8f, 0.8f, 0.5f), new BasicStroke(1.0f),
470: new Color(0.85f, 0.85f, 0.95f, 0.5f), new BasicStroke(1.0f), 0.6f
471: );
472: addRangeMarker(baseline, Layer.BACKGROUND);
473:
474: this.anchorValue = 0.0;
475: this.annotations = new java.util.ArrayList();
476:
477: }
478:
479:
484: public String getPlotType() {
485: return localizationResources.getString("Category_Plot");
486: }
487:
488:
493: public PlotOrientation getOrientation() {
494: return this.orientation;
495: }
496:
497:
503: public void setOrientation(PlotOrientation orientation) {
504: if (orientation == null) {
505: throw new IllegalArgumentException("Null 'orientation' argument.");
506: }
507: this.orientation = orientation;
508: notifyListeners(new PlotChangeEvent(this));
509: }
510:
511:
516: public RectangleInsets getAxisOffset() {
517: return this.axisOffset;
518: }
519:
520:
525: public void setAxisOffset(RectangleInsets offset) {
526: if (offset == null) {
527: throw new IllegalArgumentException("Null 'offset' argument.");
528: }
529: this.axisOffset = offset;
530: notifyListeners(new PlotChangeEvent(this));
531: }
532:
533:
534:
541: public CategoryAxis getDomainAxis() {
542: return getDomainAxis(0);
543: }
544:
545:
552: public CategoryAxis getDomainAxis(int index) {
553: CategoryAxis result = null;
554: if (index < this.domainAxes.size()) {
555: result = (CategoryAxis) this.domainAxes.get(index);
556: }
557: if (result == null) {
558: Plot parent = getParent();
559: if (parent instanceof CategoryPlot) {
560: CategoryPlot cp = (CategoryPlot) parent;
561: result = cp.getDomainAxis(index);
562: }
563: }
564: return result;
565: }
566:
567:
573: public void setDomainAxis(CategoryAxis axis) {
574: setDomainAxis(0, axis);
575: }
576:
577:
584: public void setDomainAxis(int index, CategoryAxis axis) {
585: setDomainAxis(index, axis, true);
586: }
587:
588:
596: public void setDomainAxis(int index, CategoryAxis axis, boolean notify) {
597: CategoryAxis existing = (CategoryAxis) this.domainAxes.get(index);
598: if (existing != null) {
599: existing.removeChangeListener(this);
600: }
601: if (axis != null) {
602: axis.setPlot(this);
603: }
604: this.domainAxes.set(index, axis);
605: if (axis != null) {
606: axis.configure();
607: axis.addChangeListener(this);
608: }
609: if (notify) {
610: notifyListeners(new PlotChangeEvent(this));
611: }
612: }
613:
614:
620: public void setDomainAxes(CategoryAxis[] axes) {
621: for (int i = 0; i < axes.length; i++) {
622: setDomainAxis(i, axes[i], false);
623: }
624: notifyListeners(new PlotChangeEvent(this));
625: }
626:
627:
632: public AxisLocation getDomainAxisLocation() {
633: return getDomainAxisLocation(0);
634: }
635:
636:
643: public AxisLocation getDomainAxisLocation(int index) {
644: AxisLocation result = null;
645: if (index < this.domainAxisLocations.size()) {
646: result = (AxisLocation) this.domainAxisLocations.get(index);
647: }
648: if (result == null) {
649: result = AxisLocation.getOpposite(getDomainAxisLocation(0));
650: }
651: return result;
652:
653: }
654:
655:
661: public void setDomainAxisLocation(AxisLocation location) {
662:
663: setDomainAxisLocation(location, true);
664: }
665:
666:
672: public void setDomainAxisLocation(AxisLocation location, boolean notify) {
673: if (location == null) {
674: throw new IllegalArgumentException("Null 'location' argument.");
675: }
676: setDomainAxisLocation(0, location);
677: }
678:
679:
686: public void setDomainAxisLocation(int index, AxisLocation location) {
687:
688:
689: this.domainAxisLocations.set(index, location);
690: notifyListeners(new PlotChangeEvent(this));
691: }
692:
693:
699: public RectangleEdge getDomainAxisEdge() {
700: return getDomainAxisEdge(0);
701: }
702:
703:
710: public RectangleEdge getDomainAxisEdge(int index) {
711: RectangleEdge result = null;
712: AxisLocation location = getDomainAxisLocation(index);
713: if (location != null) {
714: result = Plot.resolveDomainAxisLocation(location, this.orientation);
715: }
716: else {
717: result = RectangleEdge.opposite(getDomainAxisEdge(0));
718: }
719: return result;
720: }
721:
722:
727: public int getDomainAxisCount() {
728: return this.domainAxes.size();
729: }
730:
731:
735: public void clearDomainAxes() {
736: for (int i = 0; i < this.domainAxes.size(); i++) {
737: CategoryAxis axis = (CategoryAxis) this.domainAxes.get(i);
738: if (axis != null) {
739: axis.removeChangeListener(this);
740: }
741: }
742: this.domainAxes.clear();
743: notifyListeners(new PlotChangeEvent(this));
744: }
745:
746:
749: public void configureDomainAxes() {
750: for (int i = 0; i < this.domainAxes.size(); i++) {
751: CategoryAxis axis = (CategoryAxis) this.domainAxes.get(i);
752: if (axis != null) {
753: axis.configure();
754: }
755: }
756: }
757:
758:
765: public ValueAxis getRangeAxis() {
766: return getRangeAxis(0);
767: }
768:
769:
776: public ValueAxis getRangeAxis(int index) {
777: ValueAxis result = null;
778: if (index < this.rangeAxes.size()) {
779: result = (ValueAxis) this.rangeAxes.get(index);
780: }
781: if (result == null) {
782: Plot parent = getParent();
783: if (parent instanceof CategoryPlot) {
784: CategoryPlot cp = (CategoryPlot) parent;
785: result = cp.getRangeAxis(index);
786: }
787: }
788: return result;
789: }
790:
791:
797: public void setRangeAxis(ValueAxis axis) {
798: setRangeAxis(0, axis);
799: }
800:
801:
808: public void setRangeAxis(int index, ValueAxis axis) {
809: setRangeAxis(index, axis, true);
810: }
811:
812:
820: public void setRangeAxis(int index, ValueAxis axis, boolean notify) {
821: ValueAxis existing = (ValueAxis) this.rangeAxes.get(index);
822: if (existing != null) {
823: existing.removeChangeListener(this);
824: }
825: if (axis != null) {
826: axis.setPlot(this);
827: }
828: this.rangeAxes.set(index, axis);
829: if (axis != null) {
830: axis.configure();
831: axis.addChangeListener(this);
832: }
833: if (notify) {
834: notifyListeners(new PlotChangeEvent(this));
835: }
836: }
837:
838:
844: public void setRangeAxes(ValueAxis[] axes) {
845: for (int i = 0; i < axes.length; i++) {
846: setRangeAxis(i, axes[i], false);
847: }
848: notifyListeners(new PlotChangeEvent(this));
849: }
850:
851:
856: public AxisLocation getRangeAxisLocation() {
857: return getRangeAxisLocation(0);
858: }
859:
860:
867: public AxisLocation getRangeAxisLocation(int index) {
868: AxisLocation result = null;
869: if (index < this.rangeAxisLocations.size()) {
870: result = (AxisLocation) this.rangeAxisLocations.get(index);
871: }
872: if (result == null) {
873: result = AxisLocation.getOpposite(getRangeAxisLocation(0));
874: }
875: return result;
876: }
877:
878:
884: public void setRangeAxisLocation(AxisLocation location) {
885:
886: setRangeAxisLocation(location, true);
887: }
888:
889:
896: public void setRangeAxisLocation(AxisLocation location, boolean notify) {
897: setRangeAxisLocation(0, location, notify);
898: }
899:
900:
907: public void setRangeAxisLocation(int index, AxisLocation location) {
908: setRangeAxisLocation(index, location, true);
909: }
910:
911:
919: public void setRangeAxisLocation(int index, AxisLocation location,
920: boolean notify) {
921:
922: this.rangeAxisLocations.set(index, location);
923: if (notify) {
924: notifyListeners(new PlotChangeEvent(this));
925: }
926: }
927:
928:
933: public RectangleEdge getRangeAxisEdge() {
934: return getRangeAxisEdge(0);
935: }
936:
937:
944: public RectangleEdge getRangeAxisEdge(int index) {
945: AxisLocation location = getRangeAxisLocation(index);
946: RectangleEdge result = Plot.resolveRangeAxisLocation(
947: location, this.orientation
948: );
949: if (result == null) {
950: result = RectangleEdge.opposite(getRangeAxisEdge(0));
951: }
952: return result;
953: }
954:
955:
960: public int getRangeAxisCount() {
961: return this.rangeAxes.size();
962: }
963:
964:
968: public void clearRangeAxes() {
969: for (int i = 0; i < this.rangeAxes.size(); i++) {
970: ValueAxis axis = (ValueAxis) this.rangeAxes.get(i);
971: if (axis != null) {
972: axis.removeChangeListener(this);
973: }
974: }
975: this.rangeAxes.clear();
976: notifyListeners(new PlotChangeEvent(this));
977: }
978:
979:
982: public void configureRangeAxes() {
983: for (int i = 0; i < this.rangeAxes.size(); i++) {
984: ValueAxis axis = (ValueAxis) this.rangeAxes.get(i);
985: if (axis != null) {
986: axis.configure();
987: }
988: }
989: }
990:
991:
996: public CategoryDataset getDataset() {
997: return getDataset(0);
998: }
999:
1000:
1007: public CategoryDataset getDataset(int index) {
1008: CategoryDataset result = null;
1009: if (this.datasets.size() > index) {
1010: result = (CategoryDataset) this.datasets.get(index);
1011: }
1012: return result;
1013: }
1014:
1015:
1024: public void setDataset(CategoryDataset dataset) {
1025: setDataset(0, dataset);
1026: }
1027:
1028:
1034: public void setDataset(int index, CategoryDataset dataset) {
1035:
1036: CategoryDataset existing = (CategoryDataset) this.datasets.get(index);
1037: if (existing != null) {
1038: existing.removeChangeListener(this);
1039: }
1040: this.datasets.set(index, dataset);
1041: if (dataset != null) {
1042: dataset.addChangeListener(this);
1043: }
1044:
1045:
1046: DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
1047: datasetChanged(event);
1048:
1049: }
1050:
1051:
1058: public int getDatasetCount() {
1059: return this.datasets.size();
1060: }
1061:
1062:
1068: public void mapDatasetToDomainAxis(int index, int axisIndex) {
1069: this.datasetToDomainAxisMap.set(index, new Integer(axisIndex));
1070:
1071: datasetChanged(new DatasetChangeEvent(this, getDataset(index)));
1072: }
1073:
1074:
1082: public CategoryAxis getDomainAxisForDataset(int index) {
1083: CategoryAxis result = getDomainAxis();
1084: Integer axisIndex = (Integer) this.datasetToDomainAxisMap.get(index);
1085: if (axisIndex != null) {
1086: result = getDomainAxis(axisIndex.intValue());
1087: }
1088: return result;
1089: }
1090:
1091:
1097: public void mapDatasetToRangeAxis(int index, int axisIndex) {
1098: this.datasetToRangeAxisMap.set(index, new Integer(axisIndex));
1099:
1100: datasetChanged(new DatasetChangeEvent(this, getDataset(index)));
1101: }
1102:
1103:
1111: public ValueAxis getRangeAxisForDataset(int index) {
1112: ValueAxis result = getRangeAxis();
1113: Integer axisIndex = (Integer) this.datasetToRangeAxisMap.get(index);
1114: if (axisIndex != null) {
1115: result = getRangeAxis(axisIndex.intValue());
1116: }
1117: return result;
1118: }
1119:
1120:
1125: public CategoryItemRenderer getRenderer() {
1126: return getRenderer(0);
1127: }
1128:
1129:
1136: public CategoryItemRenderer getRenderer(int index) {
1137: CategoryItemRenderer result = null;
1138: if (this.renderers.size() > index) {
1139: result = (CategoryItemRenderer) this.renderers.get(index);
1140: }
1141: return result;
1142: }
1143:
1144:
1151: public void setRenderer(CategoryItemRenderer renderer) {
1152: setRenderer(0, renderer, true);
1153: }
1154:
1155:
1170: public void setRenderer(CategoryItemRenderer renderer, boolean notify) {
1171: setRenderer(0, renderer, notify);
1172: }
1173:
1174:
1181: public void setRenderer(int index, CategoryItemRenderer renderer) {
1182: setRenderer(index, renderer, true);
1183: }
1184:
1185:
1193: public void setRenderer(int index, CategoryItemRenderer renderer,
1194: boolean notify) {
1195:
1196:
1197: CategoryItemRenderer existing
1198: = (CategoryItemRenderer) this.renderers.get(index);
1199: if (existing != null) {
1200: existing.removeChangeListener(this);
1201: }
1202:
1203:
1204: this.renderers.set(index, renderer);
1205: if (renderer != null) {
1206: renderer.setPlot(this);
1207: renderer.addChangeListener(this);
1208: }
1209:
1210: configureDomainAxes();
1211: configureRangeAxes();
1212:
1213: if (notify) {
1214: notifyListeners(new PlotChangeEvent(this));
1215: }
1216: }
1217:
1218:
1224: public void setRenderers(CategoryItemRenderer[] renderers) {
1225: for (int i = 0; i < renderers.length; i++) {
1226: setRenderer(i, renderers[i], false);
1227: }
1228: notifyListeners(new PlotChangeEvent(this));
1229: }
1230:
1231:
1239: public CategoryItemRenderer getRendererForDataset(CategoryDataset dataset) {
1240: CategoryItemRenderer result = null;
1241: for (int i = 0; i < this.datasets.size(); i++) {
1242: if (this.datasets.get(i) == dataset) {
1243: result = (CategoryItemRenderer) this.renderers.get(i);
1244: break;
1245: }
1246: }
1247: return result;
1248: }
1249:
1250:
1258: public int getIndexOf(CategoryItemRenderer renderer) {
1259: return this.renderers.indexOf(renderer);
1260: }
1261:
1262:
1267: public DatasetRenderingOrder getDatasetRenderingOrder() {
1268: return this.renderingOrder;
1269: }
1270:
1271:
1279: public void setDatasetRenderingOrder(DatasetRenderingOrder order) {
1280: if (order == null) {
1281: throw new IllegalArgumentException("Null 'order' argument.");
1282: }
1283: this.renderingOrder = order;
1284: notifyListeners(new PlotChangeEvent(this));
1285: }
1286:
1287:
1292: public SortOrder getColumnRenderingOrder() {
1293: return this.columnRenderingOrder;
1294: }
1295:
1296:
1301: public void setColumnRenderingOrder(SortOrder order) {
1302: this.columnRenderingOrder = order;
1303: }
1304:
1305:
1310: public SortOrder getRowRenderingOrder() {
1311: return this.rowRenderingOrder;
1312: }
1313:
1314:
1319: public void setRowRenderingOrder(SortOrder order) {
1320: if (order == null) {
1321: throw new IllegalArgumentException("Null 'order' argument.");
1322: }
1323: this.rowRenderingOrder = order;
1324: }
1325:
1326:
1331: public boolean isDomainGridlinesVisible() {
1332: return this.domainGridlinesVisible;
1333: }
1334:
1335:
1344: public void setDomainGridlinesVisible(boolean visible) {
1345: if (this.domainGridlinesVisible != visible) {
1346: this.domainGridlinesVisible = visible;
1347: notifyListeners(new PlotChangeEvent(this));
1348: }
1349: }
1350:
1351:
1356: public CategoryAnchor getDomainGridlinePosition() {
1357: return this.domainGridlinePosition;
1358: }
1359:
1360:
1366: public void setDomainGridlinePosition(CategoryAnchor position) {
1367: if (position == null) {
1368: throw new IllegalArgumentException("Null 'position' argument.");
1369: }
1370: this.domainGridlinePosition = position;
1371: notifyListeners(new PlotChangeEvent(this));
1372: }
1373:
1374:
1379: public Stroke getDomainGridlineStroke() {
1380: return this.domainGridlineStroke;
1381: }
1382:
1383:
1389: public void setDomainGridlineStroke(Stroke stroke) {
1390: if (stroke == null) {
1391: throw new IllegalArgumentException("Null 'stroke' not permitted.");
1392: }
1393: this.domainGridlineStroke = stroke;
1394: notifyListeners(new PlotChangeEvent(this));
1395: }
1396:
1397:
1402: public Paint getDomainGridlinePaint() {
1403: return this.domainGridlinePaint;
1404: }
1405:
1406:
1412: public void setDomainGridlinePaint(Paint paint) {
1413: if (paint == null) {
1414: throw new IllegalArgumentException("Null 'paint' argument.");
1415: }
1416: this.domainGridlinePaint = paint;
1417: notifyListeners(new PlotChangeEvent(this));
1418: }
1419:
1420:
1425: public boolean isRangeGridlinesVisible() {
1426: return this.rangeGridlinesVisible;
1427: }
1428:
1429:
1436: public void setRangeGridlinesVisible(boolean visible) {
1437: if (this.rangeGridlinesVisible != visible) {
1438: this.rangeGridlinesVisible = visible;
1439: notifyListeners(new PlotChangeEvent(this));
1440: }
1441: }
1442:
1443:
1448: public Stroke getRangeGridlineStroke() {
1449: return this.rangeGridlineStroke;
1450: }
1451:
1452:
1458: public void setRangeGridlineStroke(Stroke stroke) {
1459: if (stroke == null) {
1460: throw new IllegalArgumentException("Null 'stroke' argument.");
1461: }
1462: this.rangeGridlineStroke = stroke;
1463: notifyListeners(new PlotChangeEvent(this));
1464: }
1465:
1466:
1471: public Paint getRangeGridlinePaint() {
1472: return this.rangeGridlinePaint;
1473: }
1474:
1475:
1481: public void setRangeGridlinePaint(Paint paint) {
1482: if (paint == null) {
1483: throw new IllegalArgumentException("Null 'paint' argument.");
1484: }
1485: this.rangeGridlinePaint = paint;
1486: notifyListeners(new PlotChangeEvent(this));
1487: }
1488:
1489:
1494: public LegendItemCollection getFixedLegendItems() {
1495: return this.fixedLegendItems;
1496: }
1497:
1498:
1505: public void setFixedLegendItems(LegendItemCollection items) {
1506: this.fixedLegendItems = items;
1507: notifyListeners(new PlotChangeEvent(this));
1508: }
1509:
1510:
1517: public LegendItemCollection getLegendItems() {
1518: LegendItemCollection result = this.fixedLegendItems;
1519: if (result == null) {
1520: result = new LegendItemCollection();
1521:
1522: int count = this.datasets.size();
1523: for (int datasetIndex = 0; datasetIndex < count; datasetIndex++) {
1524: CategoryDataset dataset = getDataset(datasetIndex);
1525: if (dataset != null) {
1526: CategoryItemRenderer renderer = getRenderer(datasetIndex);
1527: if (renderer != null) {
1528: int seriesCount = dataset.getRowCount();
1529: for (int i = 0; i < seriesCount; i++) {
1530: LegendItem item = renderer.getLegendItem(
1531: datasetIndex, i
1532: );
1533: if (item != null) {
1534: result.add(item);
1535: }
1536: }
1537: }
1538: }
1539: }
1540: }
1541: return result;
1542: }
1543:
1544:
1552: public void handleClick(int x, int y, PlotRenderingInfo info) {
1553:
1554: Rectangle2D dataArea = info.getDataArea();
1555: if (dataArea.contains(x, y)) {
1556:
1557: double java2D = 0.0;
1558: if (this.orientation == PlotOrientation.HORIZONTAL) {
1559: java2D = x;
1560: }
1561: else if (this.orientation == PlotOrientation.VERTICAL) {
1562: java2D = y;
1563: }
1564: RectangleEdge edge = Plot.resolveRangeAxisLocation(
1565: getRangeAxisLocation(), this.orientation
1566: );
1567: double value = getRangeAxis().java2DToValue(
1568: java2D, info.getDataArea(), edge
1569: );
1570: setAnchorValue(value);
1571: setRangeCrosshairValue(value);
1572: }
1573:
1574: }
1575:
1576:
1585: public void zoom(double percent) {
1586:
1587: if (percent > 0.0) {
1588: double range = getRangeAxis().getRange().getLength();
1589: double scaledRange = range * percent;
1590: getRangeAxis().setRange(
1591: this.anchorValue - scaledRange / 2.0,
1592: this.anchorValue + scaledRange / 2.0
1593: );
1594: }
1595: else {
1596: getRangeAxis().setAutoRange(true);
1597: }
1598:
1599: }
1600:
1601:
1608: public void datasetChanged(DatasetChangeEvent event) {
1609:
1610: int count = this.rangeAxes.size();
1611: for (int axisIndex = 0; axisIndex < count; axisIndex++) {
1612: ValueAxis yAxis = getRangeAxis(axisIndex);
1613: if (yAxis != null) {
1614: yAxis.configure();
1615: }
1616: }
1617: if (getParent() != null) {
1618: getParent().datasetChanged(event);
1619: }
1620: else {
1621: PlotChangeEvent e = new PlotChangeEvent(this);
1622: e.setType(ChartChangeEventType.DATASET_UPDATED);
1623: notifyListeners(e);
1624: }
1625:
1626: }
1627:
1628:
1633: public void rendererChanged(RendererChangeEvent event) {
1634: Plot parent = getParent();
1635: if (parent != null) {
1636: if (parent instanceof RendererChangeListener) {
1637: RendererChangeListener rcl = (RendererChangeListener) parent;
1638: rcl.rendererChanged(event);
1639: }
1640: else {
1641:
1642:
1643: throw new RuntimeException(
1644: "The renderer has changed and I don't know what to do!"
1645: );
1646: }
1647: }
1648: else {
1649: configureRangeAxes();
1650: PlotChangeEvent e = new PlotChangeEvent(this);
1651: notifyListeners(e);
1652: }
1653: }
1654:
1655:
1663: public void addDomainMarker(CategoryMarker marker) {
1664: addDomainMarker(marker, Layer.FOREGROUND);
1665: }
1666:
1667:
1677: public void addDomainMarker(CategoryMarker marker, Layer layer) {
1678: addDomainMarker(0, marker, layer);
1679: }
1680:
1681:
1691: public void addDomainMarker(int index, CategoryMarker marker, Layer layer) {
1692: Collection markers;
1693: if (layer == Layer.FOREGROUND) {
1694: markers = (Collection) this.foregroundDomainMarkers.get(
1695: new Integer(index)
1696: );
1697: if (markers == null) {
1698: markers = new java.util.ArrayList();
1699: this.foregroundDomainMarkers.put(new Integer(index), markers);
1700: }
1701: markers.add(marker);
1702: }
1703: else if (layer == Layer.BACKGROUND) {
1704: markers = (Collection) this.backgroundDomainMarkers.get(
1705: new Integer(index)
1706: );
1707: if (markers == null) {
1708: markers = new java.util.ArrayList();
1709: this.backgroundDomainMarkers.put(new Integer(index), markers);
1710: }
1711: markers.add(marker);
1712: }
1713: notifyListeners(new PlotChangeEvent(this));
1714: }
1715:
1716:
1720: public void clearDomainMarkers() {
1721: if (this.backgroundDomainMarkers != null) {
1722: this.backgroundDomainMarkers.clear();
1723: }
1724: if (this.foregroundDomainMarkers != null) {
1725: this.foregroundDomainMarkers.clear();
1726: }
1727: notifyListeners(new PlotChangeEvent(this));
1728: }
1729:
1730:
1737: public Collection getDomainMarkers(Layer layer) {
1738: return getDomainMarkers(0, layer);
1739: }
1740:
1741:
1750: public Collection getDomainMarkers(int index, Layer layer) {
1751: Collection result = null;
1752: Integer key = new Integer(index);
1753: if (layer == Layer.FOREGROUND) {
1754: result = (Collection) this.foregroundDomainMarkers.get(key);
1755: }
1756: else if (layer == Layer.BACKGROUND) {
1757: result = (Collection) this.backgroundDomainMarkers.get(key);
1758: }
1759: if (result != null) {
1760: result = Collections.unmodifiableCollection(result);
1761: }
1762: return result;
1763: }
1764:
1765:
1770: public void clearDomainMarkers(int index) {
1771: Integer key = new Integer(index);
1772: if (this.backgroundDomainMarkers != null) {
1773: Collection markers
1774: = (Collection) this.backgroundDomainMarkers.get(key);
1775: if (markers != null) {
1776: markers.clear();
1777: }
1778: }
1779: if (this.foregroundDomainMarkers != null) {
1780: Collection markers
1781: = (Collection) this.foregroundDomainMarkers.get(key);
1782: if (markers != null) {
1783: markers.clear();
1784: }
1785: }
1786: notifyListeners(new PlotChangeEvent(this));
1787: }
1788:
1789:
1797: public void addRangeMarker(Marker marker) {
1798: addRangeMarker(marker, Layer.FOREGROUND);
1799: }
1800:
1801:
1811: public void addRangeMarker(Marker marker, Layer layer) {
1812: addRangeMarker(0, marker, layer);
1813: }
1814:
1815:
1825: public void addRangeMarker(int index, Marker marker, Layer layer) {
1826: Collection markers;
1827: if (layer == Layer.FOREGROUND) {
1828: markers = (Collection) this.foregroundRangeMarkers.get(
1829: new Integer(index)
1830: );
1831: if (markers == null) {
1832: markers = new java.util.ArrayList();
1833: this.foregroundRangeMarkers.put(new Integer(index), markers);
1834: }
1835: markers.add(marker);
1836: }
1837: else if (layer == Layer.BACKGROUND) {
1838: markers = (Collection) this.backgroundRangeMarkers.get(
1839: new Integer(index)
1840: );
1841: if (markers == null) {
1842: markers = new java.util.ArrayList();
1843: this.backgroundRangeMarkers.put(new Integer(index), markers);
1844: }
1845: markers.add(marker);
1846: }
1847: notifyListeners(new PlotChangeEvent(this));
1848: }
1849:
1850:
1854: public void clearRangeMarkers() {
1855: if (this.backgroundRangeMarkers != null) {
1856: this.backgroundRangeMarkers.clear();
1857: }
1858: if (this.foregroundRangeMarkers != null) {
1859: this.foregroundRangeMarkers.clear();
1860: }
1861: notifyListeners(new PlotChangeEvent(this));
1862: }
1863:
1864:
1871: public Collection getRangeMarkers(Layer layer) {
1872: return getRangeMarkers(0, layer);
1873: }
1874:
1875:
1884: public Collection getRangeMarkers(int index, Layer layer) {
1885: Collection result = null;
1886: Integer key = new Integer(index);
1887: if (layer == Layer.FOREGROUND) {
1888: result = (Collection) this.foregroundRangeMarkers.get(key);
1889: }
1890: else if (layer == Layer.BACKGROUND) {
1891: result = (Collection) this.backgroundRangeMarkers.get(key);
1892: }
1893: if (result != null) {
1894: result = Collections.unmodifiableCollection(result);
1895: }
1896: return result;
1897: }
1898:
1899:
1904: public void clearRangeMarkers(int index) {
1905: Integer key = new Integer(index);
1906: if (this.backgroundRangeMarkers != null) {
1907: Collection markers
1908: = (Collection) this.backgroundRangeMarkers.get(key);
1909: if (markers != null) {
1910: markers.clear();
1911: }
1912: }
1913: if (this.foregroundRangeMarkers != null) {
1914: Collection markers
1915: = (Collection) this.foregroundRangeMarkers.get(key);
1916: if (markers != null) {
1917: markers.clear();
1918: }
1919: }
1920: notifyListeners(new PlotChangeEvent(this));
1921: }
1922:
1923:
1928: public boolean isRangeCrosshairVisible() {
1929: return this.rangeCrosshairVisible;
1930: }
1931:
1932:
1937: public void setRangeCrosshairVisible(boolean flag) {
1938:
1939: if (this.rangeCrosshairVisible != flag) {
1940: this.rangeCrosshairVisible = flag;
1941: notifyListeners(new PlotChangeEvent(this));
1942: }
1943:
1944: }
1945:
1946:
1952: public boolean isRangeCrosshairLockedOnData() {
1953: return this.rangeCrosshairLockedOnData;
1954: }
1955:
1956:
1962: public void setRangeCrosshairLockedOnData(boolean flag) {
1963:
1964: if (this.rangeCrosshairLockedOnData != flag) {
1965: this.rangeCrosshairLockedOnData = flag;
1966: notifyListeners(new PlotChangeEvent(this));
1967: }
1968:
1969: }
1970:
1971:
1976: public double getRangeCrosshairValue() {
1977: return this.rangeCrosshairValue;
1978: }
1979:
1980:
1988: public void setRangeCrosshairValue(double value) {
1989:
1990: setRangeCrosshairValue(value, true);
1991:
1992: }
1993:
1994:
2004: public void setRangeCrosshairValue(double value, boolean notify) {
2005:
2006: this.rangeCrosshairValue = value;
2007: if (isRangeCrosshairVisible() && notify) {
2008: notifyListeners(new PlotChangeEvent(this));
2009: }
2010:
2011: }
2012:
2013:
2019: public Stroke getRangeCrosshairStroke() {
2020: return this.rangeCrosshairStroke;
2021: }
2022:
2023:
2030: public void setRangeCrosshairStroke(Stroke stroke) {
2031: this.rangeCrosshairStroke = stroke;
2032: notifyListeners(new PlotChangeEvent(this));
2033: }
2034:
2035:
2040: public Paint getRangeCrosshairPaint() {
2041: return this.rangeCrosshairPaint;
2042: }
2043:
2044:
2050: public void setRangeCrosshairPaint(Paint paint) {
2051: this.rangeCrosshairPaint = paint;
2052: notifyListeners(new PlotChangeEvent(this));
2053: }
2054:
2055:
2060: public List getAnnotations() {
2061: return this.annotations;
2062: }
2063:
2064:
2070: public void addAnnotation(CategoryAnnotation annotation) {
2071: if (annotation == null) {
2072: throw new IllegalArgumentException("Null 'annotation' argument.");
2073: }
2074: this.annotations.add(annotation);
2075: notifyListeners(new PlotChangeEvent(this));
2076: }
2077:
2078:
2086: public boolean removeAnnotation(CategoryAnnotation annotation) {
2087: if (annotation == null) {
2088: throw new IllegalArgumentException("Null 'annotation' argument.");
2089: }
2090: boolean removed = this.annotations.remove(annotation);
2091: if (removed) {
2092: notifyListeners(new PlotChangeEvent(this));
2093: }
2094: return removed;
2095: }
2096:
2097:
2101: public void clearAnnotations() {
2102: this.annotations.clear();
2103: notifyListeners(new PlotChangeEvent(this));
2104: }
2105:
2106:
2115: protected AxisSpace calculateDomainAxisSpace(Graphics2D g2,
2116: Rectangle2D plotArea,
2117: AxisSpace space) {
2118:
2119: if (space == null) {
2120: space = new AxisSpace();
2121: }
2122:
2123:
2124: if (this.fixedDomainAxisSpace != null) {
2125: if (this.orientation == PlotOrientation.HORIZONTAL) {
2126: space.ensureAtLeast(
2127: this.fixedDomainAxisSpace.getLeft(), RectangleEdge.LEFT
2128: );
2129: space.ensureAtLeast(
2130: this.fixedDomainAxisSpace.getRight(), RectangleEdge.RIGHT
2131: );
2132: }
2133: else if (this.orientation == PlotOrientation.VERTICAL) {
2134: space.ensureAtLeast(
2135: this.fixedDomainAxisSpace.getTop(), RectangleEdge.TOP
2136: );
2137: space.ensureAtLeast(
2138: this.fixedDomainAxisSpace.getBottom(), RectangleEdge.BOTTOM
2139: );
2140: }
2141: }
2142: else {
2143:
2144: RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
2145: getDomainAxisLocation(), this.orientation
2146: );
2147: if (this.drawSharedDomainAxis) {
2148: space = getDomainAxis().reserveSpace(
2149: g2, this, plotArea, domainEdge, space
2150: );
2151: }
2152:
2153:
2154: for (int i = 0; i < this.domainAxes.size(); i++) {
2155: Axis xAxis = (Axis) this.domainAxes.get(i);
2156: if (xAxis != null) {
2157: RectangleEdge edge = getDomainAxisEdge(i);
2158: space = xAxis.reserveSpace(g2, this, plotArea, edge, space);
2159: }
2160: }
2161: }
2162:
2163: return space;
2164:
2165: }
2166:
2167:
2176: protected AxisSpace calculateRangeAxisSpace(Graphics2D g2,
2177: Rectangle2D plotArea,
2178: AxisSpace space) {
2179:
2180: if (space == null) {
2181: space = new AxisSpace();
2182: }
2183:
2184:
2185: if (this.fixedRangeAxisSpace != null) {
2186: if (this.orientation == PlotOrientation.HORIZONTAL) {
2187: space.ensureAtLeast(
2188: this.fixedRangeAxisSpace.getTop(), RectangleEdge.TOP
2189: );
2190: space.ensureAtLeast(
2191: this.fixedRangeAxisSpace.getBottom(), RectangleEdge.BOTTOM
2192: );
2193: }
2194: else if (this.orientation == PlotOrientation.VERTICAL) {
2195: space.ensureAtLeast(
2196: this.fixedRangeAxisSpace.getLeft(), RectangleEdge.LEFT
2197: );
2198: space.ensureAtLeast(
2199: this.fixedRangeAxisSpace.getRight(), RectangleEdge.RIGHT
2200: );
2201: }
2202: }
2203: else {
2204:
2205: for (int i = 0; i < this.rangeAxes.size(); i++) {
2206: Axis yAxis = (Axis) this.rangeAxes.get(i);
2207: if (yAxis != null) {
2208: RectangleEdge edge = getRangeAxisEdge(i);
2209: space = yAxis.reserveSpace(g2, this, plotArea, edge, space);
2210: }
2211: }
2212: }
2213: return space;
2214:
2215: }
2216:
2217:
2218:
2226: protected AxisSpace calculateAxisSpace(Graphics2D g2,
2227: Rectangle2D plotArea) {
2228: AxisSpace space = new AxisSpace();
2229: space = calculateRangeAxisSpace(g2, plotArea, space);
2230: space = calculateDomainAxisSpace(g2, plotArea, space);
2231: return space;
2232: }
2233:
2234:
2250: public void draw(Graphics2D g2, Rectangle2D area,
2251: Point2D anchor,
2252: PlotState parentState,
2253: PlotRenderingInfo state) {
2254:
2255:
2256: boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW);
2257: boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW);
2258: if (b1 || b2) {
2259: return;
2260: }
2261:
2262:
2263: if (state == null) {
2264:
2265:
2266:
2267: state = new PlotRenderingInfo(null);
2268: }
2269: state.setPlotArea(area);
2270:
2271:
2272: RectangleInsets insets = getInsets();
2273: insets.trim(area);
2274:
2275:
2276: AxisSpace space = calculateAxisSpace(g2, area);
2277: Rectangle2D dataArea = space.shrink(area, null);
2278: this.axisOffset.trim(dataArea);
2279:
2280: if (state != null) {
2281: state.setDataArea(dataArea);
2282: }
2283:
2284:
2285:
2286: if (getRenderer() != null) {
2287: getRenderer().drawBackground(g2, this, dataArea);
2288: }
2289: else {
2290: drawBackground(g2, dataArea);
2291: }
2292:
2293: Map axisStateMap = drawAxes(g2, area, dataArea, state);
2294:
2295: drawDomainGridlines(g2, dataArea);
2296:
2297: AxisState rangeAxisState = (AxisState) axisStateMap.get(getRangeAxis());
2298: if (rangeAxisState == null) {
2299: if (parentState != null) {
2300: rangeAxisState
2301: = (AxisState) parentState.getSharedAxisStates().get(
2302: getRangeAxis()
2303: );
2304: }
2305: }
2306: if (rangeAxisState != null) {
2307: drawRangeGridlines(g2, dataArea, rangeAxisState.getTicks());
2308: }
2309:
2310:
2311: for (int i = 0; i < this.renderers.size(); i++) {
2312: drawDomainMarkers(g2, dataArea, i, Layer.BACKGROUND);
2313: }
2314: for (int i = 0; i < this.renderers.size(); i++) {
2315: drawRangeMarkers(g2, dataArea, i, Layer.BACKGROUND);
2316: }
2317:
2318:
2319: boolean foundData = false;
2320: Shape savedClip = g2.getClip();
2321: g2.clip(dataArea);
2322:
2323: Composite originalComposite = g2.getComposite();
2324: g2.setComposite(AlphaComposite.getInstance(
2325: AlphaComposite.SRC_OVER, getForegroundAlpha())
2326: );
2327:
2328: DatasetRenderingOrder order = getDatasetRenderingOrder();
2329: if (order == DatasetRenderingOrder.FORWARD) {
2330: for (int i = 0; i < this.datasets.size(); i++) {
2331: foundData = render(g2, dataArea, i, state) || foundData;
2332: }
2333: }
2334: else {
2335: for (int i = this.datasets.size() - 1; i >= 0; i--) {
2336: foundData = render(g2, dataArea, i, state) || foundData;
2337: }
2338: }
2339: g2.setClip(savedClip);
2340: g2.setComposite(originalComposite);
2341:
2342: if (!foundData) {
2343: drawNoDataMessage(g2, dataArea);
2344: }
2345:
2346:
2347: if (isRangeCrosshairVisible()) {
2348: drawRangeLine(
2349: g2, dataArea, getRangeCrosshairValue(),
2350: getRangeCrosshairStroke(), getRangeCrosshairPaint()
2351: );
2352: }
2353:
2354:
2355: for (int i = 0; i < this.renderers.size(); i++) {
2356: drawDomainMarkers(g2, dataArea, i, Layer.FOREGROUND);
2357: }
2358: for (int i = 0; i < this.renderers.size(); i++) {
2359: drawRangeMarkers(g2, dataArea, i, Layer.FOREGROUND);
2360: }
2361:
2362:
2363: drawAnnotations(g2, dataArea);
2364:
2365:
2366: if (getRenderer() != null) {
2367: getRenderer().drawOutline(g2, this, dataArea);
2368: }
2369: else {
2370: drawOutline(g2, dataArea);
2371: }
2372:
2373: }
2374:
2375:
2386: protected Map drawAxes(Graphics2D g2,
2387: Rectangle2D plotArea,
2388: Rectangle2D dataArea,
2389: PlotRenderingInfo plotState) {
2390:
2391: AxisCollection axisCollection = new AxisCollection();
2392:
2393:
2394: for (int index = 0; index < this.domainAxes.size(); index++) {
2395: CategoryAxis xAxis = (CategoryAxis) this.domainAxes.get(index);
2396: if (xAxis != null) {
2397: axisCollection.add(xAxis, getDomainAxisEdge(index));
2398: }
2399: }
2400:
2401:
2402: for (int index = 0; index < this.rangeAxes.size(); index++) {
2403: ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(index);
2404: if (yAxis != null) {
2405: axisCollection.add(yAxis, getRangeAxisEdge(index));
2406: }
2407: }
2408:
2409: Map axisStateMap = new HashMap();
2410:
2411:
2412: double cursor = dataArea.getMinY() - this.axisOffset.calculateTopOutset(
2413: dataArea.getHeight());
2414: Iterator iterator = axisCollection.getAxesAtTop().iterator();
2415: while (iterator.hasNext()) {
2416: Axis axis = (Axis) iterator.next();
2417: if (axis != null) {
2418: AxisState axisState = axis.draw(g2, cursor, plotArea, dataArea,
2419: RectangleEdge.TOP, plotState);
2420: cursor = axisState.getCursor();
2421: axisStateMap.put(axis, axisState);
2422: }
2423: }
2424:
2425:
2426: cursor = dataArea.getMaxY()
2427: + this.axisOffset.calculateBottomOutset(dataArea.getHeight());
2428: iterator = axisCollection.getAxesAtBottom().iterator();
2429: while (iterator.hasNext()) {
2430: Axis axis = (Axis) iterator.next();
2431: if (axis != null) {
2432: AxisState axisState = axis.draw(g2, cursor, plotArea, dataArea,
2433: RectangleEdge.BOTTOM, plotState);
2434: cursor = axisState.getCursor();
2435: axisStateMap.put(axis, axisState);
2436: }
2437: }
2438:
2439:
2440: cursor = dataArea.getMinX()
2441: - this.axisOffset.calculateLeftOutset(dataArea.getWidth());
2442: iterator = axisCollection.getAxesAtLeft().iterator();
2443: while (iterator.hasNext()) {
2444: Axis axis = (Axis) iterator.next();
2445: if (axis != null) {
2446: AxisState axisState = axis.draw(g2, cursor, plotArea, dataArea,
2447: RectangleEdge.LEFT, plotState);
2448: cursor = axisState.getCursor();
2449: axisStateMap.put(axis, axisState);
2450: }
2451: }
2452:
2453:
2454: cursor = dataArea.getMaxX()
2455: + this.axisOffset.calculateRightOutset(dataArea.getWidth());
2456: iterator = axisCollection.getAxesAtRight().iterator();
2457: while (iterator.hasNext()) {
2458: Axis axis = (Axis) iterator.next();
2459: if (axis != null) {
2460: AxisState axisState = axis.draw(g2, cursor, plotArea, dataArea,
2461: RectangleEdge.RIGHT, plotState);
2462: cursor = axisState.getCursor();
2463: axisStateMap.put(axis, axisState);
2464: }
2465: }
2466:
2467: return axisStateMap;
2468:
2469: }
2470:
2471:
2482: public boolean render(Graphics2D g2, Rectangle2D dataArea, int index,
2483: PlotRenderingInfo info) {
2484:
2485: boolean foundData = false;
2486: CategoryDataset currentDataset = getDataset(index);
2487: CategoryItemRenderer renderer = getRenderer(index);
2488: CategoryAxis domainAxis = getDomainAxisForDataset(index);
2489: ValueAxis rangeAxis = getRangeAxisForDataset(index);
2490: boolean hasData = !DatasetUtilities.isEmptyOrNull(currentDataset);
2491: if (hasData && renderer != null) {
2492:
2493: foundData = true;
2494: CategoryItemRendererState state = renderer.initialise(
2495: g2, dataArea, this, index, info
2496: );
2497: int columnCount = currentDataset.getColumnCount();
2498: int rowCount = currentDataset.getRowCount();
2499: int passCount = renderer.getPassCount();
2500: for (int pass = 0; pass < passCount; pass++) {
2501: if (this.columnRenderingOrder == SortOrder.ASCENDING) {
2502: for (int column = 0; column < columnCount; column++) {
2503: if (this.rowRenderingOrder == SortOrder.ASCENDING) {
2504: for (int row = 0; row < rowCount; row++) {
2505: renderer.drawItem(
2506: g2, state, dataArea, this, domainAxis,
2507: rangeAxis, currentDataset, row, column, pass
2508: );
2509: }
2510: }
2511: else {
2512: for (int row = rowCount - 1; row >= 0; row--) {
2513: renderer.drawItem(
2514: g2, state, dataArea, this, domainAxis,
2515: rangeAxis, currentDataset, row, column, pass
2516: );
2517: }
2518: }
2519: }
2520: }
2521: else {
2522: for (int column = columnCount - 1; column >= 0; column--) {
2523: if (this.rowRenderingOrder == SortOrder.ASCENDING) {
2524: for (int row = 0; row < rowCount; row++) {
2525: renderer.drawItem(
2526: g2, state, dataArea, this, domainAxis,
2527: rangeAxis, currentDataset, row, column, pass
2528: );
2529: }
2530: }
2531: else {
2532: for (int row = rowCount - 1; row >= 0; row--) {
2533: renderer.drawItem(
2534: g2, state, dataArea, this, domainAxis,
2535: rangeAxis, currentDataset, row, column, pass
2536: );
2537: }
2538: }
2539: }
2540: }
2541: }
2542: }
2543: return foundData;
2544:
2545: }
2546:
2547:
2553: protected void drawDomainGridlines(Graphics2D g2, Rectangle2D dataArea) {
2554:
2555:
2556: if (isDomainGridlinesVisible()) {
2557: CategoryAnchor anchor = getDomainGridlinePosition();
2558: RectangleEdge domainAxisEdge = getDomainAxisEdge();
2559: Stroke gridStroke = getDomainGridlineStroke();
2560: Paint gridPaint = getDomainGridlinePaint();
2561: if ((gridStroke != null) && (gridPaint != null)) {
2562:
2563: CategoryDataset data = getDataset();
2564: if (data != null) {
2565: CategoryAxis axis = getDomainAxis();
2566: if (axis != null) {
2567: int columnCount = data.getColumnCount();
2568: for (int c = 0; c < columnCount; c++) {
2569: double xx = axis.getCategoryJava2DCoordinate(
2570: anchor, c, columnCount, dataArea, domainAxisEdge
2571: );
2572: CategoryItemRenderer renderer1 = getRenderer();
2573: if (renderer1 != null) {
2574: renderer1.drawDomainGridline(
2575: g2, this, dataArea, xx
2576: );
2577: }
2578: }
2579: }
2580: }
2581: }
2582: }
2583: }
2584:
2585:
2592: protected void drawRangeGridlines(Graphics2D g2, Rectangle2D dataArea,
2593: List ticks) {
2594:
2595: if (isRangeGridlinesVisible()) {
2596: Stroke gridStroke = getRangeGridlineStroke();
2597: Paint gridPaint = getRangeGridlinePaint();
2598: if ((gridStroke != null) && (gridPaint != null)) {
2599: ValueAxis axis = getRangeAxis();
2600: if (axis != null) {
2601: Iterator iterator = ticks.iterator();
2602: while (iterator.hasNext()) {
2603: ValueTick tick = (ValueTick) iterator.next();
2604: CategoryItemRenderer renderer1 = getRenderer();
2605: if (renderer1 != null) {
2606: renderer1.drawRangeGridline(
2607: g2, this, getRangeAxis(), dataArea,
2608: tick.getValue()
2609: );
2610: }
2611: }
2612: }
2613: }
2614: }
2615: }
2616:
2617:
2623: protected void drawAnnotations(Graphics2D g2, Rectangle2D dataArea) {
2624:
2625: if (getAnnotations() != null) {
2626: Iterator iterator = getAnnotations().iterator();
2627: while (iterator.hasNext()) {
2628: CategoryAnnotation annotation
2629: = (CategoryAnnotation) iterator.next();
2630: annotation.draw(
2631: g2, this, dataArea, getDomainAxis(), getRangeAxis()
2632: );
2633: }
2634: }
2635:
2636: }
2637:
2638:
2647: protected void drawDomainMarkers(Graphics2D g2, Rectangle2D dataArea,
2648: int index, Layer layer) {
2649:
2650: CategoryItemRenderer r = getRenderer(index);
2651: if (r == null) {
2652: return;
2653: }
2654:
2655: Collection markers = getDomainMarkers(index, layer);
2656: CategoryAxis axis = getDomainAxisForDataset(index);
2657: if (markers != null && axis != null) {
2658: Iterator iterator = markers.iterator();
2659: while (iterator.hasNext()) {
2660: CategoryMarker marker = (CategoryMarker) iterator.next();
2661: r.drawDomainMarker(g2, this, axis, marker, dataArea);
2662: }
2663: }
2664:
2665: }
2666:
2667:
2676: protected void drawRangeMarkers(Graphics2D g2, Rectangle2D dataArea,
2677: int index, Layer layer) {
2678:
2679: CategoryItemRenderer r = getRenderer(index);
2680: if (r == null) {
2681: return;
2682: }
2683:
2684: Collection markers = getRangeMarkers(index, layer);
2685: ValueAxis axis = getRangeAxisForDataset(index);
2686: if (markers != null && axis != null) {
2687: Iterator iterator = markers.iterator();
2688: while (iterator.hasNext()) {
2689: Marker marker = (Marker) iterator.next();
2690: r.drawRangeMarker(g2, this, axis, marker, dataArea);
2691: }
2692: }
2693:
2694: }
2695:
2696:
2706: protected void drawRangeLine(Graphics2D g2,
2707: Rectangle2D dataArea,
2708: double value, Stroke stroke, Paint paint) {
2709:
2710: double java2D = getRangeAxis().valueToJava2D(
2711: value, dataArea, getRangeAxisEdge()
2712: );
2713: Line2D line = null;
2714: if (this.orientation == PlotOrientation.HORIZONTAL) {
2715: line = new Line2D.Double(
2716: java2D, dataArea.getMinY(), java2D, dataArea.getMaxY()
2717: );
2718: }
2719: else if (this.orientation == PlotOrientation.VERTICAL) {
2720: line = new Line2D.Double(
2721: dataArea.getMinX(), java2D, dataArea.getMaxX(), java2D
2722: );
2723: }
2724: g2.setStroke(stroke);
2725: g2.setPaint(paint);
2726: g2.draw(line);
2727:
2728: }
2729:
2730:
2739: public Range getDataRange(ValueAxis axis) {
2740:
2741: Range result = null;
2742: List mappedDatasets = new ArrayList();
2743:
2744: int rangeIndex = this.rangeAxes.indexOf(axis);
2745: if (rangeIndex >= 0) {
2746: mappedDatasets.addAll(datasetsMappedToRangeAxis(rangeIndex));
2747: }
2748: else if (axis == getRangeAxis()) {
2749: mappedDatasets.addAll(datasetsMappedToRangeAxis(0));
2750: }
2751:
2752:
2753:
2754: Iterator iterator = mappedDatasets.iterator();
2755: while (iterator.hasNext()) {
2756: CategoryDataset d = (CategoryDataset) iterator.next();
2757: CategoryItemRenderer r = getRendererForDataset(d);
2758: if (r != null) {
2759: result = Range.combine(result, r.findRangeBounds(d));
2760: }
2761: }
2762: return result;
2763:
2764: }
2765:
2766:
2774: private List datasetsMappedToRangeAxis(int index) {
2775: List result = new ArrayList();
2776: for (int i = 0; i < this.datasets.size(); i++) {
2777: Object dataset = this.datasets.get(i);
2778: if (dataset != null) {
2779: Integer m = (Integer) this.datasetToRangeAxisMap.get(i);
2780: if (m == null) {
2781:
2782: if (index == 0) {
2783: result.add(dataset);
2784: }
2785: }
2786: else {
2787: if (m.intValue() == index) {
2788: result.add(dataset);
2789: }
2790: }
2791: }
2792: }
2793: return result;
2794: }
2795:
2796:
2802: public int getWeight() {
2803: return this.weight;
2804: }
2805:
2806:
2811: public void setWeight(int weight) {
2812: this.weight = weight;
2813: }
2814:
2815:
2820: public AxisSpace getFixedDomainAxisSpace() {
2821: return this.fixedDomainAxisSpace;
2822: }
2823:
2824:
2829: public void setFixedDomainAxisSpace(AxisSpace space) {
2830: this.fixedDomainAxisSpace = space;
2831: }
2832:
2833:
2838: public AxisSpace getFixedRangeAxisSpace() {
2839: return this.fixedRangeAxisSpace;
2840: }
2841:
2842:
2847: public void setFixedRangeAxisSpace(AxisSpace space) {
2848: this.fixedRangeAxisSpace = space;
2849: }
2850:
2851:
2856: public List getCategories() {
2857: List result = null;
2858: if (getDataset() != null) {
2859: result = Collections.unmodifiableList(getDataset().getColumnKeys());
2860: }
2861: return result;
2862: }
2863:
2864:
2870: public boolean getDrawSharedDomainAxis() {
2871: return this.drawSharedDomainAxis;
2872: }
2873:
2874:
2880: public void setDrawSharedDomainAxis(boolean draw) {
2881: this.drawSharedDomainAxis = draw;
2882: notifyListeners(new PlotChangeEvent(this));
2883: }
2884:
2885:
2890: public boolean isDomainZoomable() {
2891: return false;
2892: }
2893:
2894:
2899: public boolean isRangeZoomable() {
2900: return true;
2901: }
2902:
2903:
2911: public void zoomDomainAxes(double factor, PlotRenderingInfo state,
2912: Point2D source) {
2913:
2914: }
2915:
2916:
2925: public void zoomDomainAxes(double lowerPercent, double upperPercent,
2926: PlotRenderingInfo state, Point2D source) {
2927:
2928: }
2929:
2930:
2937: public void zoomRangeAxes(double factor, PlotRenderingInfo state,
2938: Point2D source) {
2939: for (int i = 0; i < this.rangeAxes.size(); i++) {
2940: ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i);
2941: if (rangeAxis != null) {
2942: rangeAxis.resizeRange(factor);
2943: }
2944: }
2945: }
2946:
2947:
2955: public void zoomRangeAxes(double lowerPercent, double upperPercent,
2956: PlotRenderingInfo state, Point2D source) {
2957: for (int i = 0; i < this.rangeAxes.size(); i++) {
2958: ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i);
2959: if (rangeAxis != null) {
2960: rangeAxis.zoomRange(lowerPercent, upperPercent);
2961: }
2962: }
2963: }
2964:
2965:
2970: public double getAnchorValue() {
2971: return this.anchorValue;
2972: }
2973:
2974:
2979: public void setAnchorValue(double value) {
2980: setAnchorValue(value, true);
2981: }
2982:
2983:
2989: public void setAnchorValue(double value, boolean notify) {
2990: this.anchorValue = value;
2991: if (notify) {
2992: notifyListeners(new PlotChangeEvent(this));
2993: }
2994: }
2995:
2996:
3003: public boolean equals(Object obj) {
3004:
3005: if (obj == this) {
3006: return true;
3007: }
3008:
3009: if (!(obj instanceof CategoryPlot)) {
3010: return false;
3011: }
3012: if (!super.equals(obj)) {
3013: return false;
3014: }
3015:
3016: CategoryPlot that = (CategoryPlot) obj;
3017:
3018: if (this.orientation != that.orientation) {
3019: return false;
3020: }
3021: if (!ObjectUtilities.equal(this.axisOffset, that.axisOffset)) {
3022: return false;
3023: }
3024: if (!this.domainAxes.equals(that.domainAxes)) {
3025: return false;
3026: }
3027: if (!this.domainAxisLocations.equals(that.domainAxisLocations)) {
3028: return false;
3029: }
3030: if (this.drawSharedDomainAxis != that.drawSharedDomainAxis) {
3031: return false;
3032: }
3033: if (!this.rangeAxes.equals(that.rangeAxes)) {
3034: return false;
3035: }
3036: if (!this.rangeAxisLocations.equals(that.rangeAxisLocations)) {
3037: return false;
3038: }
3039: if (!ObjectUtilities.equal(
3040: this.datasetToDomainAxisMap, that.datasetToDomainAxisMap
3041: )) {
3042: return false;
3043: }
3044: if (!ObjectUtilities.equal(
3045: this.datasetToRangeAxisMap, that.datasetToRangeAxisMap
3046: )) {
3047: return false;
3048: }
3049: if (!ObjectUtilities.equal(this.renderers, that.renderers)) {
3050: return false;
3051: }
3052: if (this.renderingOrder != that.renderingOrder) {
3053: return false;
3054: }
3055: if (this.columnRenderingOrder != that.columnRenderingOrder) {
3056: return false;
3057: }
3058: if (this.rowRenderingOrder != that.rowRenderingOrder) {
3059: return false;
3060: }
3061: if (this.domainGridlinesVisible != that.domainGridlinesVisible) {
3062: return false;
3063: }
3064: if (this.domainGridlinePosition != that.domainGridlinePosition) {
3065: return false;
3066: }
3067: if (!ObjectUtilities.equal(
3068: this.domainGridlineStroke, that.domainGridlineStroke
3069: )) {
3070: return false;
3071: }
3072: if (!PaintUtilities.equal(
3073: this.domainGridlinePaint, that.domainGridlinePaint
3074: )) {
3075: return false;
3076: }
3077: if (this.rangeGridlinesVisible != that.rangeGridlinesVisible) {
3078: return false;
3079: }
3080: if (!ObjectUtilities.equal(
3081: this.rangeGridlineStroke, that.rangeGridlineStroke
3082: )) {
3083: return false;
3084: }
3085: if (!PaintUtilities.equal(
3086: this.rangeGridlinePaint, that.rangeGridlinePaint
3087: )) {
3088: return false;
3089: }
3090: if (this.anchorValue != that.anchorValue) {
3091: return false;
3092: }
3093: if (this.rangeCrosshairVisible != that.rangeCrosshairVisible) {
3094: return false;
3095: }
3096: if (this.rangeCrosshairValue != that.rangeCrosshairValue) {
3097: return false;
3098: }
3099: if (!ObjectUtilities.equal(
3100: this.rangeCrosshairStroke, that.rangeCrosshairStroke
3101: )) {
3102: return false;
3103: }
3104: if (!PaintUtilities.equal(
3105: this.rangeCrosshairPaint, that.rangeCrosshairPaint
3106: )) {
3107: return false;
3108: }
3109: if (
3110: this.rangeCrosshairLockedOnData != that.rangeCrosshairLockedOnData
3111: ) {
3112: return false;
3113: }
3114: if (!ObjectUtilities.equal(
3115: this.foregroundRangeMarkers, that.foregroundRangeMarkers
3116: )) {
3117: return false;
3118: }
3119: if (!ObjectUtilities.equal(
3120: this.backgroundRangeMarkers, that.backgroundRangeMarkers
3121: )) {
3122: return false;
3123: }
3124: if (!ObjectUtilities.equal(this.annotations, that.annotations)) {
3125: return false;
3126: }
3127: if (this.weight != that.weight) {
3128: return false;
3129: }
3130: if (!ObjectUtilities.equal(
3131: this.fixedDomainAxisSpace, that.fixedDomainAxisSpace
3132: )) {
3133: return false;
3134: }
3135: if (!ObjectUtilities.equal(
3136: this.fixedRangeAxisSpace, that.fixedRangeAxisSpace
3137: )) {
3138: return false;
3139: }
3140:
3141: return true;
3142:
3143: }
3144:
3145:
3152: public Object clone() throws CloneNotSupportedException {
3153:
3154: CategoryPlot clone = (CategoryPlot) super.clone();
3155:
3156: clone.domainAxes = new ObjectList();
3157: for (int i = 0; i < this.domainAxes.size(); i++) {
3158: CategoryAxis xAxis = (CategoryAxis) this.domainAxes.get(i);
3159: if (xAxis != null) {
3160: CategoryAxis clonedAxis = (CategoryAxis) xAxis.clone();
3161: clone.setDomainAxis(i, clonedAxis);
3162: }
3163: }
3164: clone.domainAxisLocations
3165: = (ObjectList) this.domainAxisLocations.clone();
3166:
3167: clone.rangeAxes = new ObjectList();
3168: for (int i = 0; i < this.rangeAxes.size(); i++) {
3169: ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(i);
3170: if (yAxis != null) {
3171: ValueAxis clonedAxis = (ValueAxis) yAxis.clone();
3172: clone.setRangeAxis(i, clonedAxis);
3173: }
3174: }
3175: clone.rangeAxisLocations = (ObjectList) this.rangeAxisLocations.clone();
3176:
3177: clone.datasets = (ObjectList) this.datasets.clone();
3178: for (int i = 0; i < clone.datasets.size(); i++) {
3179: CategoryDataset dataset = clone.getDataset(i);
3180: if (dataset != null) {
3181: dataset.addChangeListener(clone);
3182: }
3183: }
3184: clone.datasetToDomainAxisMap
3185: = (ObjectList) this.datasetToDomainAxisMap.clone();
3186: clone.datasetToRangeAxisMap
3187: = (ObjectList) this.datasetToRangeAxisMap.clone();
3188: clone.renderers = (ObjectList) this.renderers.clone();
3189: if (this.fixedDomainAxisSpace != null) {
3190: clone.fixedDomainAxisSpace = (AxisSpace) ObjectUtilities.clone(
3191: this.fixedDomainAxisSpace
3192: );
3193: }
3194: if (this.fixedRangeAxisSpace != null) {
3195: clone.fixedRangeAxisSpace = (AxisSpace) ObjectUtilities.clone(
3196: this.fixedRangeAxisSpace
3197: );
3198: }
3199:
3200: return clone;
3201:
3202: }
3203:
3204:
3211: private void writeObject(ObjectOutputStream stream) throws IOException {
3212: stream.defaultWriteObject();
3213: SerialUtilities.writeStroke(this.domainGridlineStroke, stream);
3214: SerialUtilities.writePaint(this.domainGridlinePaint, stream);
3215: SerialUtilities.writeStroke(this.rangeGridlineStroke, stream);
3216: SerialUtilities.writePaint(this.rangeGridlinePaint, stream);
3217: SerialUtilities.writeStroke(this.rangeCrosshairStroke, stream);
3218: SerialUtilities.writePaint(this.rangeCrosshairPaint, stream);
3219: }
3220:
3221:
3229: private void readObject(ObjectInputStream stream)
3230: throws IOException, ClassNotFoundException {
3231:
3232: stream.defaultReadObject();
3233: this.domainGridlineStroke = SerialUtilities.readStroke(stream);
3234: this.domainGridlinePaint = SerialUtilities.readPaint(stream);
3235: this.rangeGridlineStroke = SerialUtilities.readStroke(stream);
3236: this.rangeGridlinePaint = SerialUtilities.readPaint(stream);
3237: this.rangeCrosshairStroke = SerialUtilities.readStroke(stream);
3238: this.rangeCrosshairPaint = SerialUtilities.readPaint(stream);
3239:
3240: for (int i = 0; i < this.domainAxes.size(); i++) {
3241: CategoryAxis xAxis = (CategoryAxis) this.domainAxes.get(i);
3242: if (xAxis != null) {
3243: xAxis.setPlot(this);
3244: xAxis.addChangeListener(this);
3245: }
3246: }
3247: for (int i = 0; i < this.rangeAxes.size(); i++) {
3248: ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(i);
3249: if (yAxis != null) {
3250: yAxis.setPlot(this);
3251: yAxis.addChangeListener(this);
3252: }
3253: }
3254: int datasetCount = this.datasets.size();
3255: for (int i = 0; i < datasetCount; i++) {
3256: Dataset dataset = (Dataset) this.datasets.get(i);
3257: if (dataset != null) {
3258: dataset.addChangeListener(this);
3259: }
3260: }
3261: int rendererCount = this.renderers.size();
3262: for (int i = 0; i < rendererCount; i++) {
3263: CategoryItemRenderer renderer
3264: = (CategoryItemRenderer) this.renderers.get(i);
3265: if (renderer != null) {
3266: renderer.addChangeListener(this);
3267: }
3268: }
3269:
3270: }
3271:
3272: }