1 129 130 package org.jfree.chart.plot; 131 132 import java.awt.AlphaComposite ; 133 import java.awt.BasicStroke ; 134 import java.awt.Color ; 135 import java.awt.Composite ; 136 import java.awt.Font ; 137 import java.awt.Graphics2D ; 138 import java.awt.Paint ; 139 import java.awt.Shape ; 140 import java.awt.Stroke ; 141 import java.awt.geom.Line2D ; 142 import java.awt.geom.Point2D ; 143 import java.awt.geom.Rectangle2D ; 144 import java.io.IOException ; 145 import java.io.ObjectInputStream ; 146 import java.io.ObjectOutputStream ; 147 import java.io.Serializable ; 148 import java.util.ArrayList ; 149 import java.util.Collection ; 150 import java.util.Collections ; 151 import java.util.HashMap ; 152 import java.util.Iterator ; 153 import java.util.List ; 154 import java.util.Map ; 155 import java.util.ResourceBundle ; 156 157 import org.jfree.chart.LegendItem; 158 import org.jfree.chart.LegendItemCollection; 159 import org.jfree.chart.annotations.CategoryAnnotation; 160 import org.jfree.chart.axis.Axis; 161 import org.jfree.chart.axis.AxisCollection; 162 import org.jfree.chart.axis.AxisLocation; 163 import org.jfree.chart.axis.AxisSpace; 164 import org.jfree.chart.axis.AxisState; 165 import org.jfree.chart.axis.CategoryAnchor; 166 import org.jfree.chart.axis.CategoryAxis; 167 import org.jfree.chart.axis.ValueAxis; 168 import org.jfree.chart.axis.ValueTick; 169 import org.jfree.chart.event.ChartChangeEventType; 170 import org.jfree.chart.event.PlotChangeEvent; 171 import org.jfree.chart.event.RendererChangeEvent; 172 import org.jfree.chart.event.RendererChangeListener; 173 import org.jfree.chart.renderer.category.CategoryItemRenderer; 174 import org.jfree.chart.renderer.category.CategoryItemRendererState; 175 import org.jfree.data.Range; 176 import org.jfree.data.category.CategoryDataset; 177 import org.jfree.data.general.Dataset; 178 import org.jfree.data.general.DatasetChangeEvent; 179 import org.jfree.data.general.DatasetUtilities; 180 import org.jfree.io.SerialUtilities; 181 import org.jfree.ui.Layer; 182 import org.jfree.ui.RectangleEdge; 183 import org.jfree.ui.RectangleInsets; 184 import org.jfree.util.ObjectList; 185 import org.jfree.util.ObjectUtilities; 186 import org.jfree.util.PublicCloneable; 187 import org.jfree.util.SortOrder; 188 189 193 public class CategoryPlot extends Plot 194 implements ValueAxisPlot, 195 Zoomable, 196 RendererChangeListener, 197 Cloneable , PublicCloneable, Serializable { 198 199 200 private static final long serialVersionUID = -3537691700434728188L; 201 202 206 public static final boolean DEFAULT_DOMAIN_GRIDLINES_VISIBLE = false; 207 208 212 public static final boolean DEFAULT_RANGE_GRIDLINES_VISIBLE = true; 213 214 215 public static final Stroke DEFAULT_GRIDLINE_STROKE = new BasicStroke (0.5f, 216 BasicStroke.CAP_BUTT, 217 BasicStroke.JOIN_BEVEL, 218 0.0f, 219 new float[] {2.0f, 2.0f}, 220 0.0f); 221 222 223 public static final Paint DEFAULT_GRIDLINE_PAINT = Color.lightGray; 224 225 226 public static final Font DEFAULT_VALUE_LABEL_FONT 227 = new Font ("SansSerif", Font.PLAIN, 10); 228 229 230 protected static ResourceBundle localizationResources 231 = ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle"); 232 233 234 private PlotOrientation orientation; 235 236 237 private RectangleInsets axisOffset; 238 239 240 private ObjectList domainAxes; 241 242 243 private ObjectList domainAxisLocations; 244 245 249 private boolean drawSharedDomainAxis; 250 251 252 private ObjectList rangeAxes; 253 254 255 private ObjectList rangeAxisLocations; 256 257 258 private ObjectList datasets; 259 260 261 private ObjectList datasetToDomainAxisMap; 262 263 264 private ObjectList datasetToRangeAxisMap; 265 266 267 private ObjectList renderers; 268 269 270 private DatasetRenderingOrder renderingOrder 271 = DatasetRenderingOrder.REVERSE; 272 273 277 private SortOrder columnRenderingOrder = SortOrder.ASCENDING; 278 279 283 private SortOrder rowRenderingOrder = SortOrder.ASCENDING; 284 285 289 private boolean domainGridlinesVisible; 290 291 292 private CategoryAnchor domainGridlinePosition; 293 294 295 private transient Stroke domainGridlineStroke; 296 297 298 private transient Paint domainGridlinePaint; 299 300 304 private boolean rangeGridlinesVisible; 305 306 307 private transient Stroke rangeGridlineStroke; 308 309 310 private transient Paint rangeGridlinePaint; 311 312 313 private double anchorValue; 314 315 316 private boolean rangeCrosshairVisible; 317 318 319 private double rangeCrosshairValue; 320 321 322 private transient Stroke rangeCrosshairStroke; 323 324 325 private transient Paint rangeCrosshairPaint; 326 327 331 private boolean rangeCrosshairLockedOnData = true; 332 333 334 private Map foregroundDomainMarkers; 335 336 337 private Map backgroundDomainMarkers; 338 339 340 private Map foregroundRangeMarkers; 341 342 343 private Map backgroundRangeMarkers; 344 345 350 private List annotations; 351 352 356 private int weight; 357 358 359 private AxisSpace fixedDomainAxisSpace; 360 361 362 private AxisSpace fixedRangeAxisSpace; 363 364 368 private LegendItemCollection fixedLegendItems; 369 370 373 public CategoryPlot() { 374 this(null, null, null, null); 375 } 376 377 386 public CategoryPlot(CategoryDataset dataset, 387 CategoryAxis domainAxis, 388 ValueAxis rangeAxis, 389 CategoryItemRenderer renderer) { 390 391 super(); 392 393 this.orientation = PlotOrientation.VERTICAL; 394 395 this.domainAxes = new ObjectList(); 397 this.domainAxisLocations = new ObjectList(); 398 this.rangeAxes = new ObjectList(); 399 this.rangeAxisLocations = new ObjectList(); 400 401 this.datasetToDomainAxisMap = new ObjectList(); 402 this.datasetToRangeAxisMap = new ObjectList(); 403 404 this.renderers = new ObjectList(); 405 406 this.datasets = new ObjectList(); 407 this.datasets.set(0, dataset); 408 if (dataset != null) { 409 dataset.addChangeListener(this); 410 } 411 412 this.axisOffset = RectangleInsets.ZERO_INSETS; 413 414 setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT, false); 415 setRangeAxisLocation(AxisLocation.TOP_OR_LEFT, false); 416 417 this.renderers.set(0, renderer); 418 if (renderer != null) { 419 renderer.setPlot(this); 420 renderer.addChangeListener(this); 421 } 422 423 this.domainAxes.set(0, domainAxis); 424 this.mapDatasetToDomainAxis(0, 0); 425 if (domainAxis != null) { 426 domainAxis.setPlot(this); 427 domainAxis.addChangeListener(this); 428 } 429 this.drawSharedDomainAxis = false; 430 431 this.rangeAxes.set(0, rangeAxis); 432 this.mapDatasetToRangeAxis(0, 0); 433 if (rangeAxis != null) { 434 rangeAxis.setPlot(this); 435 rangeAxis.addChangeListener(this); 436 } 437 438 configureDomainAxes(); 439 configureRangeAxes(); 440 441 this.domainGridlinesVisible = DEFAULT_DOMAIN_GRIDLINES_VISIBLE; 442 this.domainGridlinePosition = CategoryAnchor.MIDDLE; 443 this.domainGridlineStroke = DEFAULT_GRIDLINE_STROKE; 444 this.domainGridlinePaint = DEFAULT_GRIDLINE_PAINT; 445 446 this.rangeGridlinesVisible = DEFAULT_RANGE_GRIDLINES_VISIBLE; 447 this.rangeGridlineStroke = DEFAULT_GRIDLINE_STROKE; 448 this.rangeGridlinePaint = DEFAULT_GRIDLINE_PAINT; 449 450 this.foregroundDomainMarkers = new HashMap (); 451 this.backgroundDomainMarkers = new HashMap (); 452 this.foregroundRangeMarkers = new HashMap (); 453 this.backgroundRangeMarkers = new HashMap (); 454 455 Marker baseline = new ValueMarker( 456 0.0, new Color (0.8f, 0.8f, 0.8f, 0.5f), new BasicStroke (1.0f), 457 new Color (0.85f, 0.85f, 0.95f, 0.5f), new BasicStroke (1.0f), 0.6f 458 ); 459 addRangeMarker(baseline, Layer.BACKGROUND); 460 461 this.anchorValue = 0.0; 462 this.annotations = new java.util.ArrayList (); 463 464 } 465 466 471 public String getPlotType() { 472 return localizationResources.getString("Category_Plot"); 473 } 474 475 480 public PlotOrientation getOrientation() { 481 return this.orientation; 482 } 483 484 490 public void setOrientation(PlotOrientation orientation) { 491 if (orientation == null) { 492 throw new IllegalArgumentException ("Null 'orientation' argument."); 493 } 494 this.orientation = orientation; 495 notifyListeners(new PlotChangeEvent(this)); 496 } 497 498 503 public RectangleInsets getAxisOffset() { 504 return this.axisOffset; 505 } 506 507 512 public void setAxisOffset(RectangleInsets offset) { 513 if (offset == null) { 514 throw new IllegalArgumentException ("Null 'offset' argument."); 515 } 516 this.axisOffset = offset; 517 notifyListeners(new PlotChangeEvent(this)); 518 } 519 520 521 528 public CategoryAxis getDomainAxis() { 529 return getDomainAxis(0); 530 } 531 532 539 public CategoryAxis getDomainAxis(int index) { 540 CategoryAxis result = null; 541 if (index < this.domainAxes.size()) { 542 result = (CategoryAxis) this.domainAxes.get(index); 543 } 544 if (result == null) { 545 Plot parent = getParent(); 546 if (parent instanceof CategoryPlot) { 547 CategoryPlot cp = (CategoryPlot) parent; 548 result = cp.getDomainAxis(index); 549 } 550 } 551 return result; 552 } 553 554 560 public void setDomainAxis(CategoryAxis axis) { 561 setDomainAxis(0, axis); 562 } 563 564 571 public void setDomainAxis(int index, CategoryAxis axis) { 572 setDomainAxis(index, axis, true); 573 } 574 575 583 public void setDomainAxis(int index, CategoryAxis axis, boolean notify) { 584 CategoryAxis existing = (CategoryAxis) this.domainAxes.get(index); 585 if (existing != null) { 586 existing.removeChangeListener(this); 587 } 588 if (axis != null) { 589 axis.setPlot(this); 590 } 591 this.domainAxes.set(index, axis); 592 if (axis != null) { 593 axis.configure(); 594 axis.addChangeListener(this); 595 } 596 if (notify) { 597 notifyListeners(new PlotChangeEvent(this)); 598 } 599 } 600 601 607 public void setDomainAxes(CategoryAxis[] axes) { 608 for (int i = 0; i < axes.length; i++) { 609 setDomainAxis(i, axes[i], false); 610 } 611 notifyListeners(new PlotChangeEvent(this)); 612 } 613 614 619 public AxisLocation getDomainAxisLocation() { 620 return getDomainAxisLocation(0); 621 } 622 623 630 public AxisLocation getDomainAxisLocation(int index) { 631 AxisLocation result = null; 632 if (index < this.domainAxisLocations.size()) { 633 result = (AxisLocation) this.domainAxisLocations.get(index); 634 } 635 if (result == null) { 636 result = AxisLocation.getOpposite(getDomainAxisLocation(0)); 637 } 638 return result; 639 640 } 641 642 648 public void setDomainAxisLocation(AxisLocation location) { 649 setDomainAxisLocation(location, true); 651 } 652 653 659 public void setDomainAxisLocation(AxisLocation location, boolean notify) { 660 if (location == null) { 661 throw new IllegalArgumentException ("Null 'location' argument."); 662 } 663 setDomainAxisLocation(0, location); 664 } 665 666 673 public void setDomainAxisLocation(int index, AxisLocation location) { 674 this.domainAxisLocations.set(index, location); 677 notifyListeners(new PlotChangeEvent(this)); 678 } 679 680 686 public RectangleEdge getDomainAxisEdge() { 687 return getDomainAxisEdge(0); 688 } 689 690 697 public RectangleEdge getDomainAxisEdge(int index) { 698 RectangleEdge result = null; 699 AxisLocation location = getDomainAxisLocation(index); 700 if (location != null) { 701 result = Plot.resolveDomainAxisLocation(location, this.orientation); 702 } 703 else { 704 result = RectangleEdge.opposite(getDomainAxisEdge(0)); 705 } 706 return result; 707 } 708 709 713 public void clearDomainAxes() { 714 for (int i = 0; i < this.domainAxes.size(); i++) { 715 CategoryAxis axis = (CategoryAxis) this.domainAxes.get(i); 716 if (axis != null) { 717 axis.removeChangeListener(this); 718 } 719 } 720 this.domainAxes.clear(); 721 notifyListeners(new PlotChangeEvent(this)); 722 } 723 724 727 public void configureDomainAxes() { 728 for (int i = 0; i < this.domainAxes.size(); i++) { 729 CategoryAxis axis = (CategoryAxis) this.domainAxes.get(i); 730 if (axis != null) { 731 axis.configure(); 732 } 733 } 734 } 735 736 743 public ValueAxis getRangeAxis() { 744 return getRangeAxis(0); 745 } 746 747 754 public ValueAxis getRangeAxis(int index) { 755 ValueAxis result = null; 756 if (index < this.rangeAxes.size()) { 757 result = (ValueAxis) this.rangeAxes.get(index); 758 } 759 if (result == null) { 760 Plot parent = getParent(); 761 if (parent instanceof CategoryPlot) { 762 CategoryPlot cp = (CategoryPlot) parent; 763 result = cp.getRangeAxis(index); 764 } 765 } 766 return result; 767 } 768 769 775 public void setRangeAxis(ValueAxis axis) { 776 setRangeAxis(0, axis); 777 } 778 779 786 public void setRangeAxis(int index, ValueAxis axis) { 787 setRangeAxis(index, axis, true); 788 } 789 790 798 public void setRangeAxis(int index, ValueAxis axis, boolean notify) { 799 ValueAxis existing = (ValueAxis) this.rangeAxes.get(index); 800 if (existing != null) { 801 existing.removeChangeListener(this); 802 } 803 if (axis != null) { 804 axis.setPlot(this); 805 } 806 this.rangeAxes.set(index, axis); 807 if (axis != null) { 808 axis.configure(); 809 axis.addChangeListener(this); 810 } 811 if (notify) { 812 notifyListeners(new PlotChangeEvent(this)); 813 } 814 } 815 816 822 public void setRangeAxes(ValueAxis[] axes) { 823 for (int i = 0; i < axes.length; i++) { 824 setRangeAxis(i, axes[i], false); 825 } 826 notifyListeners(new PlotChangeEvent(this)); 827 } 828 829 834 public AxisLocation getRangeAxisLocation() { 835 return getRangeAxisLocation(0); 836 } 837 838 845 public AxisLocation getRangeAxisLocation(int index) { 846 AxisLocation result = null; 847 if (index < this.rangeAxisLocations.size()) { 848 result = (AxisLocation) this.rangeAxisLocations.get(index); 849 } 850 if (result == null) { 851 result = AxisLocation.getOpposite(getRangeAxisLocation(0)); 852 } 853 return result; 854 } 855 856 862 public void setRangeAxisLocation(AxisLocation location) { 863 setRangeAxisLocation(location, true); 865 } 866 867 874 public void setRangeAxisLocation(AxisLocation location, boolean notify) { 875 setRangeAxisLocation(0, location, notify); 876 } 877 878 885 public void setRangeAxisLocation(int index, AxisLocation location) { 886 setRangeAxisLocation(index, location, true); 887 } 888 889 897 public void setRangeAxisLocation(int index, AxisLocation location, 898 boolean notify) { 899 this.rangeAxisLocations.set(index, location); 901 if (notify) { 902 notifyListeners(new PlotChangeEvent(this)); 903 } 904 } 905 906 911 public RectangleEdge getRangeAxisEdge() { 912 return getRangeAxisEdge(0); 913 } 914 915 922 public RectangleEdge getRangeAxisEdge(int index) { 923 AxisLocation location = getRangeAxisLocation(index); 924 RectangleEdge result = Plot.resolveRangeAxisLocation( 925 location, this.orientation 926 ); 927 if (result == null) { 928 result = RectangleEdge.opposite(getRangeAxisEdge(0)); 929 } 930 return result; 931 } 932 933 937 public void clearRangeAxes() { 938 for (int i = 0; i < this.rangeAxes.size(); i++) { 939 ValueAxis axis = (ValueAxis) this.rangeAxes.get(i); 940 if (axis != null) { 941 axis.removeChangeListener(this); 942 } 943 } 944 this.rangeAxes.clear(); 945 notifyListeners(new PlotChangeEvent(this)); 946 } 947 948 951 public void configureRangeAxes() { 952 for (int i = 0; i < this.rangeAxes.size(); i++) { 953 ValueAxis axis = (ValueAxis) this.rangeAxes.get(i); 954 if (axis != null) { 955 axis.configure(); 956 } 957 } 958 } 959 960 965 public CategoryDataset getDataset() { 966 return getDataset(0); 967 } 968 969 976 public CategoryDataset getDataset(int index) { 977 CategoryDataset result = null; 978 if (this.datasets.size() > index) { 979 result = (CategoryDataset) this.datasets.get(index); 980 } 981 return result; 982 } 983 984 993 public void setDataset(CategoryDataset dataset) { 994 setDataset(0, dataset); 995 } 996 997 1003 public void setDataset(int index, CategoryDataset dataset) { 1004 1005 CategoryDataset existing = (CategoryDataset) this.datasets.get(index); 1006 if (existing != null) { 1007 existing.removeChangeListener(this); 1008 } 1009 this.datasets.set(index, dataset); 1010 if (dataset != null) { 1011 dataset.addChangeListener(this); 1012 } 1013 1014 DatasetChangeEvent event = new DatasetChangeEvent(this, dataset); 1016 datasetChanged(event); 1017 1018 } 1019 1020 1026 public void mapDatasetToDomainAxis(int index, int axisIndex) { 1027 this.datasetToDomainAxisMap.set(index, new Integer (axisIndex)); 1028 datasetChanged(new DatasetChangeEvent(this, getDataset(index))); 1030 } 1031 1032 1040 public CategoryAxis getDomainAxisForDataset(int index) { 1041 CategoryAxis result = getDomainAxis(); 1042 Integer axisIndex = (Integer ) this.datasetToDomainAxisMap.get(index); 1043 if (axisIndex != null) { 1044 result = getDomainAxis(axisIndex.intValue()); 1045 } 1046 return result; 1047 } 1048 1049 1055 public void mapDatasetToRangeAxis(int index, int axisIndex) { 1056 this.datasetToRangeAxisMap.set(index, new Integer (axisIndex)); 1057 datasetChanged(new DatasetChangeEvent(this, getDataset(index))); 1059 } 1060 1061 1069 public ValueAxis getRangeAxisForDataset(int index) { 1070 ValueAxis result = getRangeAxis(); 1071 Integer axisIndex = (Integer ) this.datasetToRangeAxisMap.get(index); 1072 if (axisIndex != null) { 1073 result = getRangeAxis(axisIndex.intValue()); 1074 } 1075 return result; 1076 } 1077 1078 1083 public CategoryItemRenderer getRenderer() { 1084 return getRenderer(0); 1085 } 1086 1087 1094 public CategoryItemRenderer getRenderer(int index) { 1095 CategoryItemRenderer result = null; 1096 if (this.renderers.size() > index) { 1097 result = (CategoryItemRenderer) this.renderers.get(index); 1098 } 1099 return result; 1100 } 1101 1102 1109 public void setRenderer(CategoryItemRenderer renderer) { 1110 setRenderer(0, renderer, true); 1111 } 1112 1113 1128 public void setRenderer(CategoryItemRenderer renderer, boolean notify) { 1129 setRenderer(0, renderer, notify); 1130 } 1131 1132 1139 public void setRenderer(int index, CategoryItemRenderer renderer) { 1140 setRenderer(index, renderer, true); 1141 } 1142 1143 1151 public void setRenderer(int index, CategoryItemRenderer renderer, 1152 boolean notify) { 1153 1154 CategoryItemRenderer existing 1156 = (CategoryItemRenderer) this.renderers.get(index); 1157 if (existing != null) { 1158 existing.removeChangeListener(this); 1159 } 1160 1161 this.renderers.set(index, renderer); 1163 if (renderer != null) { 1164 renderer.setPlot(this); 1165 renderer.addChangeListener(this); 1166 } 1167 1168 configureDomainAxes(); 1169 configureRangeAxes(); 1170 1171 if (notify) { 1172 notifyListeners(new PlotChangeEvent(this)); 1173 } 1174 } 1175 1176 1184 public CategoryItemRenderer getRendererForDataset(CategoryDataset dataset) { 1185 CategoryItemRenderer result = null; 1186 for (int i = 0; i < this.datasets.size(); i++) { 1187 if (this.datasets.get(i) == dataset) { 1188 result = (CategoryItemRenderer) this.renderers.get(i); 1189 break; 1190 } 1191 } 1192 return result; 1193 } 1194 1195 1203 public int getIndexOf(CategoryItemRenderer renderer) { 1204 return this.renderers.indexOf(renderer); 1205 } 1206 1207 1212 public DatasetRenderingOrder getDatasetRenderingOrder() { 1213 return this.renderingOrder; 1214 } 1215 1216 1224 public void setDatasetRenderingOrder(DatasetRenderingOrder order) { 1225 if (order == null) { 1226 throw new IllegalArgumentException ("Null 'order' argument."); 1227 } 1228 this.renderingOrder = order; 1229 notifyListeners(new PlotChangeEvent(this)); 1230 } 1231 1232 1237 public SortOrder getColumnRenderingOrder() { 1238 return this.columnRenderingOrder; 1239 } 1240 1241 1246 public void setColumnRenderingOrder(SortOrder order) { 1247 this.columnRenderingOrder = order; 1248 } 1249 1250 1255 public SortOrder getRowRenderingOrder() { 1256 return this.rowRenderingOrder; 1257 } 1258 1259 1264 public void setRowRenderingOrder(SortOrder order) { 1265 if (order == null) { 1266 throw new IllegalArgumentException ("Null 'order' argument."); 1267 } 1268 this.rowRenderingOrder = order; 1269 } 1270 1271 1276 public boolean isDomainGridlinesVisible() { 1277 return this.domainGridlinesVisible; 1278 } 1279 1280 1289 public void setDomainGridlinesVisible(boolean visible) { 1290 if (this.domainGridlinesVisible != visible) { 1291 this.domainGridlinesVisible = visible; 1292 notifyListeners(new PlotChangeEvent(this)); 1293 } 1294 } 1295 1296 1301 public CategoryAnchor getDomainGridlinePosition() { 1302 return this.domainGridlinePosition; 1303 } 1304 1305 1310 public void setDomainGridlinePosition(CategoryAnchor position) { 1311 this.domainGridlinePosition = position; 1312 notifyListeners(new PlotChangeEvent(this)); 1313 } 1314 1315 1320 public Stroke getDomainGridlineStroke() { 1321 return this.domainGridlineStroke; 1322 } 1323 1324 1330 public void setDomainGridlineStroke(Stroke stroke) { 1331 this.domainGridlineStroke = stroke; 1332 notifyListeners(new PlotChangeEvent(this)); 1333 } 1334 1335 1340 public Paint getDomainGridlinePaint() { 1341 return this.domainGridlinePaint; 1342 } 1343 1344 1350 public void setDomainGridlinePaint(Paint paint) { 1351 this.domainGridlinePaint = paint; 1352 notifyListeners(new PlotChangeEvent(this)); 1353 } 1354 1355 1360 public boolean isRangeGridlinesVisible() { 1361 return this.rangeGridlinesVisible; 1362 } 1363 1364 1371 public void setRangeGridlinesVisible(boolean visible) { 1372 if (this.rangeGridlinesVisible != visible) { 1373 this.rangeGridlinesVisible = visible; 1374 notifyListeners(new PlotChangeEvent(this)); 1375 } 1376 } 1377 1378 1383 public Stroke getRangeGridlineStroke() { 1384 return this.rangeGridlineStroke; 1385 } 1386 1387 1393 public void setRangeGridlineStroke(Stroke stroke) { 1394 this.rangeGridlineStroke = stroke; 1395 notifyListeners(new PlotChangeEvent(this)); 1396 } 1397 1398 1403 public Paint getRangeGridlinePaint() { 1404 return this.rangeGridlinePaint; 1405 } 1406 1407 1413 public void setRangeGridlinePaint(Paint paint) { 1414 this.rangeGridlinePaint = paint; 1415 notifyListeners(new PlotChangeEvent(this)); 1416 } 1417 1418 1423 public LegendItemCollection getFixedLegendItems() { 1424 return this.fixedLegendItems; 1425 } 1426 1427 1434 public void setFixedLegendItems(LegendItemCollection items) { 1435 this.fixedLegendItems = items; 1436 notifyListeners(new PlotChangeEvent(this)); 1437 } 1438 1439 1446 public LegendItemCollection getLegendItems() { 1447 LegendItemCollection result = this.fixedLegendItems; 1448 if (result == null) { 1449 result = new LegendItemCollection(); 1450 int count = this.datasets.size(); 1452 for (int datasetIndex = 0; datasetIndex < count; datasetIndex++) { 1453 CategoryDataset dataset = getDataset(datasetIndex); 1454 if (dataset != null) { 1455 CategoryItemRenderer renderer = getRenderer(datasetIndex); 1456 if (renderer != null) { 1457 int seriesCount = dataset.getRowCount(); 1458 for (int i = 0; i < seriesCount; i++) { 1459 LegendItem item = renderer.getLegendItem( 1460 datasetIndex, i 1461 ); 1462 if (item != null) { 1463 result.add(item); 1464 } 1465 } 1466 } 1467 } 1468 } 1469 } 1470 return result; 1471 } 1472 1473 1481 public void handleClick(int x, int y, PlotRenderingInfo info) { 1482 1483 Rectangle2D dataArea = info.getDataArea(); 1484 if (dataArea.contains(x, y)) { 1485 double java2D = 0.0; 1487 if (this.orientation == PlotOrientation.HORIZONTAL) { 1488 java2D = x; 1489 } 1490 else if (this.orientation == PlotOrientation.VERTICAL) { 1491 java2D = y; 1492 } 1493 RectangleEdge edge = Plot.resolveRangeAxisLocation( 1494 getRangeAxisLocation(), this.orientation 1495 ); 1496 double value = getRangeAxis().java2DToValue( 1497 java2D, info.getDataArea(), edge 1498 ); 1499 setAnchorValue(value); 1500 setRangeCrosshairValue(value); 1501 } 1502 1503 } 1504 1505 1514 public void zoom(double percent) { 1515 1516 if (percent > 0.0) { 1517 double range = getRangeAxis().getRange().getLength(); 1518 double scaledRange = range * percent; 1519 getRangeAxis().setRange( 1520 this.anchorValue - scaledRange / 2.0, 1521 this.anchorValue + scaledRange / 2.0 1522 ); 1523 } 1524 else { 1525 getRangeAxis().setAutoRange(true); 1526 } 1527 1528 } 1529 1530 1537 public void datasetChanged(DatasetChangeEvent event) { 1538 1539 int count = this.rangeAxes.size(); 1540 for (int axisIndex = 0; axisIndex < count; axisIndex++) { 1541 ValueAxis yAxis = getRangeAxis(axisIndex); 1542 if (yAxis != null) { 1543 yAxis.configure(); 1544 } 1545 } 1546 if (getParent() != null) { 1547 getParent().datasetChanged(event); 1548 } 1549 else { 1550 PlotChangeEvent e = new PlotChangeEvent(this); 1551 e.setType(ChartChangeEventType.DATASET_UPDATED); 1552 notifyListeners(e); 1553 } 1554 1555 } 1556 1557 1562 public void rendererChanged(RendererChangeEvent event) { 1563 Plot parent = getParent(); 1564 if (parent != null) { 1565 if (parent instanceof RendererChangeListener) { 1566 RendererChangeListener rcl = (RendererChangeListener) parent; 1567 rcl.rendererChanged(event); 1568 } 1569 else { 1570 throw new RuntimeException ( 1573 "The renderer has changed and I don't know what to do!" 1574 ); 1575 } 1576 } 1577 else { 1578 PlotChangeEvent e = new PlotChangeEvent(this); 1579 notifyListeners(e); 1580 } 1581 } 1582 1583 1591 public void addDomainMarker(CategoryMarker marker) { 1592 addDomainMarker(marker, Layer.FOREGROUND); 1593 } 1594 1595 1605 public void addDomainMarker(CategoryMarker marker, Layer layer) { 1606 addDomainMarker(0, marker, layer); 1607 } 1608 1609 1619 public void addDomainMarker(int index, CategoryMarker marker, Layer layer) { 1620 Collection markers; 1621 if (layer == Layer.FOREGROUND) { 1622 markers = (Collection ) this.foregroundDomainMarkers.get( 1623 new Integer (index) 1624 ); 1625 if (markers == null) { 1626 markers = new java.util.ArrayList (); 1627 this.foregroundDomainMarkers.put(new Integer (index), markers); 1628 } 1629 markers.add(marker); 1630 } 1631 else if (layer == Layer.BACKGROUND) { 1632 markers = (Collection ) this.backgroundDomainMarkers.get( 1633 new Integer (index) 1634 ); 1635 if (markers == null) { 1636 markers = new java.util.ArrayList (); 1637 this.backgroundDomainMarkers.put(new Integer (index), markers); 1638 } 1639 markers.add(marker); 1640 } 1641 notifyListeners(new PlotChangeEvent(this)); 1642 } 1643 1644 1648 public void clearDomainMarkers() { 1649 if (this.backgroundDomainMarkers != null) { 1650 this.backgroundDomainMarkers.clear(); 1651 } 1652 if (this.foregroundDomainMarkers != null) { 1653 this.foregroundDomainMarkers.clear(); 1654 } 1655 notifyListeners(new PlotChangeEvent(this)); 1656 } 1657 1658 1665 public Collection getDomainMarkers(Layer layer) { 1666 return getDomainMarkers(0, layer); 1667 } 1668 1669 1678 public Collection getDomainMarkers(int index, Layer layer) { 1679 Collection result = null; 1680 Integer key = new Integer (index); 1681 if (layer == Layer.FOREGROUND) { 1682 result = (Collection ) this.foregroundDomainMarkers.get(key); 1683 } 1684 else if (layer == Layer.BACKGROUND) { 1685 result = (Collection ) this.backgroundDomainMarkers.get(key); 1686 } 1687 if (result != null) { 1688 result = Collections.unmodifiableCollection(result); 1689 } 1690 return result; 1691 } 1692 1693 1698 public void clearDomainMarkers(int index) { 1699 Integer key = new Integer (index); 1700 if (this.backgroundDomainMarkers != null) { 1701 Collection markers 1702 = (Collection ) this.backgroundDomainMarkers.get(key); 1703 if (markers != null) { 1704 markers.clear(); 1705 } 1706 } 1707 if (this.foregroundDomainMarkers != null) { 1708 Collection markers 1709 = (Collection ) this.foregroundDomainMarkers.get(key); 1710 if (markers != null) { 1711 markers.clear(); 1712 } 1713 } 1714 notifyListeners(new PlotChangeEvent(this)); 1715 } 1716 1717 1725 public void addRangeMarker(Marker marker) { 1726 addRangeMarker(marker, Layer.FOREGROUND); 1727 } 1728 1729 1739 public void addRangeMarker(Marker marker, Layer layer) { 1740 addRangeMarker(0, marker, layer); 1741 } 1742 1743 1753 public void addRangeMarker(int index, Marker marker, Layer layer) { 1754 Collection markers; 1755 if (layer == Layer.FOREGROUND) { 1756 markers = (Collection ) this.foregroundRangeMarkers.get( 1757 new Integer (index) 1758 ); 1759 if (markers == null) { 1760 markers = new java.util.ArrayList (); 1761 this.foregroundRangeMarkers.put(new Integer (index), markers); 1762 } 1763 markers.add(marker); 1764 } 1765 else if (layer == Layer.BACKGROUND) { 1766 markers = (Collection ) this.backgroundRangeMarkers.get( 1767 new Integer (index) 1768 ); 1769 if (markers == null) { 1770 markers = new java.util.ArrayList (); 1771 this.backgroundRangeMarkers.put(new Integer (index), markers); 1772 } 1773 markers.add(marker); 1774 } 1775 notifyListeners(new PlotChangeEvent(this)); 1776 } 1777 1778 1782 public void clearRangeMarkers() { 1783 if (this.backgroundRangeMarkers != null) { 1784 this.backgroundRangeMarkers.clear(); 1785 } 1786 if (this.foregroundRangeMarkers != null) { 1787 this.foregroundRangeMarkers.clear(); 1788 } 1789 notifyListeners(new PlotChangeEvent(this)); 1790 } 1791 1792 1799 public Collection getRangeMarkers(Layer layer) { 1800 return getRangeMarkers(0, layer); 1801 } 1802 1803 1812 public Collection getRangeMarkers(int index, Layer layer) { 1813 Collection result = null; 1814 Integer key = new Integer (index); 1815 if (layer == Layer.FOREGROUND) { 1816 result = (Collection ) this.foregroundRangeMarkers.get(key); 1817 } 1818 else if (layer == Layer.BACKGROUND) { 1819 result = (Collection ) this.backgroundRangeMarkers.get(key); 1820 } 1821 if (result != null) { 1822 result = Collections.unmodifiableCollection(result); 1823 } 1824 return result; 1825 } 1826 1827 1832 public void clearRangeMarkers(int index) { 1833 Integer key = new Integer (index); 1834 if (this.backgroundRangeMarkers != null) { 1835 Collection markers 1836 = (Collection ) this.backgroundRangeMarkers.get(key); 1837 if (markers != null) { 1838 markers.clear(); 1839 } 1840 } 1841 if (this.foregroundRangeMarkers != null) { 1842 Collection markers 1843 = (Collection ) this.foregroundRangeMarkers.get(key); 1844 if (markers != null) { 1845 markers.clear(); 1846 } 1847 } 1848 notifyListeners(new PlotChangeEvent(this)); 1849 } 1850 1851 1856 public boolean isRangeCrosshairVisible() { 1857 return this.rangeCrosshairVisible; 1858 } 1859 1860 1865 public void setRangeCrosshairVisible(boolean flag) { 1866 1867 if (this.rangeCrosshairVisible != flag) { 1868 this.rangeCrosshairVisible = flag; 1869 notifyListeners(new PlotChangeEvent(this)); 1870 } 1871 1872 } 1873 1874 1880 public boolean isRangeCrosshairLockedOnData() { 1881 return this.rangeCrosshairLockedOnData; 1882 } 1883 1884 1890 public void setRangeCrosshairLockedOnData(boolean flag) { 1891 1892 if (this.rangeCrosshairLockedOnData != flag) { 1893 this.rangeCrosshairLockedOnData = flag; 1894 notifyListeners(new PlotChangeEvent(this)); 1895 } 1896 1897 } 1898 1899 1904 public double getRangeCrosshairValue() { 1905 return this.rangeCrosshairValue; 1906 } 1907 1908 1916 public void setRangeCrosshairValue(double value) { 1917 1918 setRangeCrosshairValue(value, true); 1919 1920 } 1921 1922 1932 public void setRangeCrosshairValue(double value, boolean notify) { 1933 1934 this.rangeCrosshairValue = value; 1935 if (isRangeCrosshairVisible() && notify) { 1936 notifyListeners(new PlotChangeEvent(this)); 1937 } 1938 1939 } 1940 1941 1947 public Stroke getRangeCrosshairStroke() { 1948 return this.rangeCrosshairStroke; 1949 } 1950 1951 1958 public void setRangeCrosshairStroke(Stroke stroke) { 1959 this.rangeCrosshairStroke = stroke; 1960 notifyListeners(new PlotChangeEvent(this)); 1961 } 1962 1963 1968 public Paint getRangeCrosshairPaint() { 1969 return this.rangeCrosshairPaint; 1970 } 1971 1972 1978 public void setRangeCrosshairPaint(Paint paint) { 1979 this.rangeCrosshairPaint = paint; 1980 notifyListeners(new PlotChangeEvent(this)); 1981 } 1982 1983 1988 public List getAnnotations() { 1989 return this.annotations; 1990 } 1991 1992 1998 public void addAnnotation(CategoryAnnotation annotation) { 1999 if (annotation == null) { 2000 throw new IllegalArgumentException ("Null 'annotation' argument."); 2001 } 2002 this.annotations.add(annotation); 2003 notifyListeners(new PlotChangeEvent(this)); 2004 } 2005 2006 2014 public boolean removeAnnotation(CategoryAnnotation annotation) { 2015 if (annotation == null) { 2016 throw new IllegalArgumentException ("Null 'annotation' argument."); 2017 } 2018 boolean removed = this.annotations.remove(annotation); 2019 if (removed) { 2020 notifyListeners(new PlotChangeEvent(this)); 2021 } 2022 return removed; 2023 } 2024 2025 2029 public void clearAnnotations() { 2030 this.annotations.clear(); 2031 notifyListeners(new PlotChangeEvent(this)); 2032 } 2033 2034 2043 protected AxisSpace calculateDomainAxisSpace(Graphics2D g2, 2044 Rectangle2D plotArea, 2045 AxisSpace space) { 2046 2047 if (space == null) { 2048 space = new AxisSpace(); 2049 } 2050 2051 if (this.fixedDomainAxisSpace != null) { 2053 if (this.orientation == PlotOrientation.HORIZONTAL) { 2054 space.ensureAtLeast( 2055 this.fixedDomainAxisSpace.getLeft(), RectangleEdge.LEFT 2056 ); 2057 space.ensureAtLeast( 2058 this.fixedDomainAxisSpace.getRight(), RectangleEdge.RIGHT 2059 ); 2060 } 2061 else if (this.orientation == PlotOrientation.VERTICAL) { 2062 space.ensureAtLeast( 2063 this.fixedDomainAxisSpace.getTop(), RectangleEdge.TOP 2064 ); 2065 space.ensureAtLeast( 2066 this.fixedDomainAxisSpace.getBottom(), RectangleEdge.BOTTOM 2067 ); 2068 } 2069 } 2070 else { 2071 RectangleEdge domainEdge = Plot.resolveDomainAxisLocation( 2073 getDomainAxisLocation(), this.orientation 2074 ); 2075 if (this.drawSharedDomainAxis) { 2076 space = getDomainAxis().reserveSpace( 2077 g2, this, plotArea, domainEdge, space 2078 ); 2079 } 2080 2081 for (int i = 0; i < this.domainAxes.size(); i++) { 2083 Axis xAxis = (Axis) this.domainAxes.get(i); 2084 if (xAxis != null) { 2085 RectangleEdge edge = getDomainAxisEdge(i); 2086 space = xAxis.reserveSpace(g2, this, plotArea, edge, space); 2087 } 2088 } 2089 } 2090 2091 return space; 2092 2093 } 2094 2095 2104 protected AxisSpace calculateRangeAxisSpace(Graphics2D g2, 2105 Rectangle2D plotArea, 2106 AxisSpace space) { 2107 2108 if (space == null) { 2109 space = new AxisSpace(); 2110 } 2111 2112 if (this.fixedRangeAxisSpace != null) { 2114 if (this.orientation == PlotOrientation.HORIZONTAL) { 2115 space.ensureAtLeast( 2116 this.fixedRangeAxisSpace.getTop(), RectangleEdge.TOP 2117 ); 2118 space.ensureAtLeast( 2119 this.fixedRangeAxisSpace.getBottom(), RectangleEdge.BOTTOM 2120 ); 2121 } 2122 else if (this.orientation == PlotOrientation.VERTICAL) { 2123 space.ensureAtLeast( 2124 this.fixedRangeAxisSpace.getLeft(), RectangleEdge.LEFT 2125 ); 2126 space.ensureAtLeast( 2127 this.fixedRangeAxisSpace.getRight(), RectangleEdge.RIGHT 2128 ); 2129 } 2130 } 2131 else { 2132 for (int i = 0; i < this.rangeAxes.size(); i++) { 2134 Axis yAxis = (Axis) this.rangeAxes.get(i); 2135 if (yAxis != null) { 2136 RectangleEdge edge = getRangeAxisEdge(i); 2137 space = yAxis.reserveSpace(g2, this, plotArea, edge, space); 2138 } 2139 } 2140 } 2141 return space; 2142 2143 } 2144 2145 2146 2154 protected AxisSpace calculateAxisSpace(Graphics2D g2, 2155 Rectangle2D plotArea) { 2156 AxisSpace space = new AxisSpace(); 2157 space = calculateRangeAxisSpace(g2, plotArea, space); 2158 space = calculateDomainAxisSpace(g2, plotArea, space); 2159 return space; 2160 } 2161 2162 2178 public void draw(Graphics2D g2, Rectangle2D area, 2179 Point2D anchor, 2180 PlotState parentState, 2181 PlotRenderingInfo state) { 2182 2183 boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW); 2185 boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW); 2186 if (b1 || b2) { 2187 return; 2188 } 2189 2190 if (state != null) { 2192 state.setPlotArea(area); 2193 } 2194 2195 RectangleInsets insets = getInsets(); 2197 insets.trim(area); 2198 2199 AxisSpace space = calculateAxisSpace(g2, area); 2201 Rectangle2D dataArea = space.shrink(area, null); 2202 this.axisOffset.trim(dataArea); 2203 2204 if (state != null) { 2205 state.setDataArea(dataArea); 2206 } 2207 2208 if (getRenderer() != null) { 2211 getRenderer().drawBackground(g2, this, dataArea); 2212 } 2213 else { 2214 drawBackground(g2, dataArea); 2215 } 2216 2217 Map axisStateMap = drawAxes(g2, area, dataArea, state); 2218 2219 drawDomainGridlines(g2, dataArea); 2220 2221 AxisState rangeAxisState = (AxisState) axisStateMap.get(getRangeAxis()); 2222 if (rangeAxisState == null) { 2223 if (parentState != null) { 2224 rangeAxisState 2225 = (AxisState) parentState.getSharedAxisStates().get( 2226 getRangeAxis() 2227 ); 2228 } 2229 } 2230 if (rangeAxisState != null) { 2231 drawRangeGridlines(g2, dataArea, rangeAxisState.getTicks()); 2232 } 2233 2234 for (int i = 0; i < this.renderers.size(); i++) { 2236 drawDomainMarkers(g2, dataArea, i, Layer.BACKGROUND); 2237 } 2238 for (int i = 0; i < this.renderers.size(); i++) { 2239 drawRangeMarkers(g2, dataArea, i, Layer.BACKGROUND); 2240 } 2241 2242 boolean foundData = false; 2244 Shape savedClip = g2.getClip(); 2245 g2.clip(dataArea); 2246 Composite originalComposite = g2.getComposite(); 2248 g2.setComposite(AlphaComposite.getInstance( 2249 AlphaComposite.SRC_OVER, getForegroundAlpha()) 2250 ); 2251 2252 DatasetRenderingOrder order = getDatasetRenderingOrder(); 2253 if (order == DatasetRenderingOrder.FORWARD) { 2254 for (int i = 0; i < this.datasets.size(); i++) { 2255 foundData = render(g2, dataArea, i, state) || foundData; 2256 } 2257 } 2258 else { for (int i = this.datasets.size() - 1; i >= 0; i--) { 2260 foundData = render(g2, dataArea, i, state) || foundData; 2261 } 2262 } 2263 g2.setClip(savedClip); 2264 g2.setComposite(originalComposite); 2265 2266 if (!foundData) { 2267 drawNoDataMessage(g2, dataArea); 2268 } 2269 2270 if (isRangeCrosshairVisible()) { 2272 drawRangeLine( 2273 g2, dataArea, getRangeCrosshairValue(), 2274 getRangeCrosshairStroke(), getRangeCrosshairPaint() 2275 ); 2276 } 2277 2278 for (int i = 0; i < this.renderers.size(); i++) { 2280 drawDomainMarkers(g2, dataArea, i, Layer.FOREGROUND); 2281 } 2282 for (int i = 0; i < this.renderers.size(); i++) { 2283 drawRangeMarkers(g2, dataArea, i, Layer.FOREGROUND); 2284 } 2285 2286 drawAnnotations(g2, dataArea); 2288 2289 if (getRenderer() != null) { 2291 getRenderer().drawOutline(g2, this, dataArea); 2292 } 2293 else { 2294 drawOutline(g2, dataArea); 2295 } 2296 2297 } 2298 2299 2310 protected Map drawAxes(Graphics2D g2, 2311 Rectangle2D plotArea, 2312 Rectangle2D dataArea, 2313 PlotRenderingInfo plotState) { 2314 2315 AxisCollection axisCollection = new AxisCollection(); 2316 2317 for (int index = 0; index < this.domainAxes.size(); index++) { 2319 CategoryAxis xAxis = (CategoryAxis) this.domainAxes.get(index); 2320 if (xAxis != null) { 2321 axisCollection.add(xAxis, getDomainAxisEdge(index)); 2322 } 2323 } 2324 2325 for (int index = 0; index < this.rangeAxes.size(); index++) { 2327 ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(index); 2328 if (yAxis != null) { 2329 axisCollection.add(yAxis, getRangeAxisEdge(index)); 2330 } 2331 } 2332 2333 Map axisStateMap = new HashMap (); 2334 2335 double cursor = dataArea.getMinY() - this.axisOffset.calculateTopOutset( 2337 dataArea.getHeight() 2338 ); 2339 Iterator iterator = axisCollection.getAxesAtTop().iterator(); 2340 while (iterator.hasNext()) { 2341 Axis axis = (Axis) iterator.next(); 2342 if (axis != null) { 2343 AxisState axisState = axis.draw( 2344 g2, cursor, plotArea, dataArea, RectangleEdge.TOP, plotState 2345 ); 2346 cursor = axisState.getCursor(); 2347 axisStateMap.put(axis, axisState); 2348 } 2349 } 2350 2351 cursor = dataArea.getMaxY() 2353 + this.axisOffset.calculateBottomOutset(dataArea.getHeight()); 2354 iterator = axisCollection.getAxesAtBottom().iterator(); 2355 while (iterator.hasNext()) { 2356 Axis axis = (Axis) iterator.next(); 2357 if (axis != null) { 2358 AxisState axisState = axis.draw( 2359 g2, cursor, plotArea, dataArea, RectangleEdge.BOTTOM, 2360 plotState 2361 ); 2362 cursor = axisState.getCursor(); 2363 axisStateMap.put(axis, axisState); 2364 } 2365 } 2366 2367 cursor = dataArea.getMinX() 2369 - this.axisOffset.calculateLeftOutset(dataArea.getWidth()); 2370 iterator = axisCollection.getAxesAtLeft().iterator(); 2371 while (iterator.hasNext()) { 2372 Axis axis = (Axis) iterator.next(); 2373 if (axis != null) { 2374 AxisState axisState = axis.draw( 2375 g2, cursor, plotArea, dataArea, RectangleEdge.LEFT, 2376 plotState 2377 ); 2378 cursor = axisState.getCursor(); 2379 axisStateMap.put(axis, axisState); 2380 } 2381 } 2382 2383 cursor = dataArea.getMaxX() 2385 + this.axisOffset.calculateRightOutset(dataArea.getWidth()); 2386 iterator = axisCollection.getAxesAtRight().iterator(); 2387 while (iterator.hasNext()) { 2388 Axis axis = (Axis) iterator.next(); 2389 if (axis != null) { 2390 AxisState axisState = axis.draw( 2391 g2, cursor, plotArea, dataArea, RectangleEdge.RIGHT, 2392 plotState 2393 ); 2394 cursor = axisState.getCursor(); 2395 axisStateMap.put(axis, axisState); 2396 } 2397 } 2398 2399 return axisStateMap; 2400 2401 } 2402 2403 2414 public boolean render(Graphics2D g2, Rectangle2D dataArea, int index, 2415 PlotRenderingInfo info) { 2416 2417 boolean foundData = false; 2418 CategoryDataset currentDataset = getDataset(index); 2419 CategoryItemRenderer renderer = getRenderer(index); 2420 CategoryAxis domainAxis = getDomainAxisForDataset(index); 2421 ValueAxis rangeAxis = getRangeAxisForDataset(index); 2422 boolean hasData = !DatasetUtilities.isEmptyOrNull(currentDataset); 2423 if (hasData && renderer != null) { 2424 2425 foundData = true; 2426 CategoryItemRendererState state = renderer.initialise( 2427 g2, dataArea, this, index, info 2428 ); 2429 int columnCount = currentDataset.getColumnCount(); 2430 int rowCount = currentDataset.getRowCount(); 2431 int passCount = renderer.getPassCount(); 2432 for (int pass = 0; pass < passCount; pass++) { 2433 if (this.columnRenderingOrder == SortOrder.ASCENDING) { 2434 for (int column = 0; column < columnCount; column++) { 2435 if (this.rowRenderingOrder == SortOrder.ASCENDING) { 2436 for (int row = 0; row < rowCount; row++) { 2437 renderer.drawItem( 2438 g2, state, dataArea, this, domainAxis, 2439 rangeAxis, currentDataset, row, column, pass 2440 ); 2441 } 2442 } 2443 else { 2444 for (int row = rowCount - 1; row >= 0; row--) { 2445 renderer.drawItem( 2446 g2, state, dataArea, this, domainAxis, 2447 rangeAxis, currentDataset, row, column, pass 2448 ); 2449 } 2450 } 2451 } 2452 } 2453 else { 2454 for (int column = columnCount - 1; column >= 0; column--) { 2455 if (this.rowRenderingOrder == SortOrder.ASCENDING) { 2456 for (int row = 0; row < rowCount; row++) { 2457 renderer.drawItem( 2458 g2, state, dataArea, this, domainAxis, 2459 rangeAxis, currentDataset, row, column, pass 2460 ); 2461 } 2462 } 2463 else { 2464 for (int row = rowCount - 1; row >= 0; row--) { 2465 renderer.drawItem( 2466 g2, state, dataArea, this, domainAxis, 2467 rangeAxis, currentDataset, row, column, pass 2468 ); 2469 } 2470 } 2471 } 2472 } 2473 } 2474 } 2475 return foundData; 2476 2477 } 2478 2479 2485 protected void drawDomainGridlines(Graphics2D g2, Rectangle2D dataArea) { 2486 2487 if (isDomainGridlinesVisible()) { 2489 CategoryAnchor anchor = getDomainGridlinePosition(); 2490 RectangleEdge domainAxisEdge = getDomainAxisEdge(); 2491 Stroke gridStroke = getDomainGridlineStroke(); 2492 Paint gridPaint = getDomainGridlinePaint(); 2493 if ((gridStroke != null) && (gridPaint != null)) { 2494 CategoryDataset data = getDataset(); 2496 if (data != null) { 2497 CategoryAxis axis = getDomainAxis(); 2498 if (axis != null) { 2499 int columnCount = data.getColumnCount(); 2500 for (int c = 0; c < columnCount; c++) { 2501 double xx = axis.getCategoryJava2DCoordinate( 2502 anchor, c, columnCount, dataArea, domainAxisEdge 2503 ); 2504 CategoryItemRenderer renderer1 = getRenderer(); 2505 if (renderer1 != null) { 2506 renderer1.drawDomainGridline( 2507 g2, this, dataArea, xx 2508 ); 2509 } 2510 } 2511 } 2512 } 2513 } 2514 } 2515 } 2516 2517 2524 protected void drawRangeGridlines(Graphics2D g2, Rectangle2D dataArea, 2525 List ticks) { 2526 if (isRangeGridlinesVisible()) { 2528 Stroke gridStroke = getRangeGridlineStroke(); 2529 Paint gridPaint = getRangeGridlinePaint(); 2530 if ((gridStroke != null) && (gridPaint != null)) { 2531 ValueAxis axis = getRangeAxis(); 2532 if (axis != null) { 2533 Iterator iterator = ticks.iterator(); 2534 while (iterator.hasNext()) { 2535 ValueTick tick = (ValueTick) iterator.next(); 2536 CategoryItemRenderer renderer1 = getRenderer(); 2537 if (renderer1 != null) { 2538 renderer1.drawRangeGridline( 2539 g2, this, getRangeAxis(), dataArea, 2540 tick.getValue() 2541 ); 2542 } 2543 } 2544 } 2545 } 2546 } 2547 } 2548 2549 2555 protected void drawAnnotations(Graphics2D g2, Rectangle2D dataArea) { 2556 2557 if (getAnnotations() != null) { 2558 Iterator iterator = getAnnotations().iterator(); 2559 while (iterator.hasNext()) { 2560 CategoryAnnotation annotation 2561 = (CategoryAnnotation) iterator.next(); 2562 annotation.draw( 2563 g2, this, dataArea, getDomainAxis(), getRangeAxis() 2564 ); 2565 } 2566 } 2567 2568 } 2569 2570 2579 protected void drawDomainMarkers(Graphics2D g2, Rectangle2D dataArea, 2580 int index, Layer layer) { 2581 2582 CategoryItemRenderer r = getRenderer(index); 2583 if (r == null) { 2584 return; 2585 } 2586 2587 Collection markers = getDomainMarkers(index, layer); 2588 CategoryAxis axis = getDomainAxisForDataset(index); 2589 if (markers != null && axis != null) { 2590 Iterator iterator = markers.iterator(); 2591 while (iterator.hasNext()) { 2592 CategoryMarker marker = (CategoryMarker) iterator.next(); 2593 r.drawDomainMarker(g2, this, axis, marker, dataArea); 2594 } 2595 } 2596 2597 } 2598 2599 2608 protected void drawRangeMarkers(Graphics2D g2, Rectangle2D dataArea, 2609 int index, Layer layer) { 2610 2611 CategoryItemRenderer r = getRenderer(index); 2612 if (r == null) { 2613 return; 2614 } 2615 2616 Collection markers = getRangeMarkers(index, layer); 2617 ValueAxis axis = getRangeAxisForDataset(index); 2618 if (markers != null && axis != null) { 2619 Iterator iterator = markers.iterator(); 2620 while (iterator.hasNext()) { 2621 Marker marker = (Marker) iterator.next(); 2622 r.drawRangeMarker(g2, this, axis, marker, dataArea); 2623 } 2624 } 2625 2626 } 2627 2628 2638 protected void drawRangeLine(Graphics2D g2, 2639 Rectangle2D dataArea, 2640 double value, Stroke stroke, Paint paint) { 2641 2642 double java2D = getRangeAxis().valueToJava2D( 2643 value, dataArea, getRangeAxisEdge() 2644 ); 2645 Line2D line = null; 2646 if (this.orientation == PlotOrientation.HORIZONTAL) { 2647 line = new Line2D.Double ( 2648 java2D, dataArea.getMinY(), java2D, dataArea.getMaxY() 2649 ); 2650 } 2651 else if (this.orientation == PlotOrientation.VERTICAL) { 2652 line = new Line2D.Double ( 2653 dataArea.getMinX(), java2D, dataArea.getMaxX(), java2D 2654 ); 2655 } 2656 g2.setStroke(stroke); 2657 g2.setPaint(paint); 2658 g2.draw(line); 2659 2660 } 2661 2662 2671 public Range getDataRange(ValueAxis axis) { 2672 2673 Range result = null; 2674 List mappedDatasets = new ArrayList (); 2675 2676 int rangeIndex = this.rangeAxes.indexOf(axis); 2677 if (rangeIndex >= 0) { 2678 mappedDatasets.addAll(datasetsMappedToRangeAxis(rangeIndex)); 2679 } 2680 else if (axis == getRangeAxis()) { 2681 mappedDatasets.addAll(datasetsMappedToRangeAxis(0)); 2682 } 2683 2684 Iterator iterator = mappedDatasets.iterator(); 2687 while (iterator.hasNext()) { 2688 CategoryDataset d = (CategoryDataset) iterator.next(); 2689 CategoryItemRenderer r = getRendererForDataset(d); 2690 if (r != null) { 2691 result = Range.combine(result, r.findRangeBounds(d)); 2692 } 2693 } 2694 return result; 2695 2696 } 2697 2698 2706 private List datasetsMappedToRangeAxis(int index) { 2707 List result = new ArrayList (); 2708 for (int i = 0; i < this.datasets.size(); i++) { 2709 Object dataset = this.datasets.get(i); 2710 if (dataset != null) { 2711 Integer m = (Integer ) this.datasetToRangeAxisMap.get(i); 2712 if (m == null) { if (index == 0) { 2715 result.add(dataset); 2716 } 2717 } 2718 else { 2719 if (m.intValue() == index) { 2720 result.add(dataset); 2721 } 2722 } 2723 } 2724 } 2725 return result; 2726 } 2727 2728 2734 public int getWeight() { 2735 return this.weight; 2736 } 2737 2738 2743 public void setWeight(int weight) { 2744 this.weight = weight; 2745 } 2746 2747 2752 public AxisSpace getFixedDomainAxisSpace() { 2753 return this.fixedDomainAxisSpace; 2754 } 2755 2756 2761 public void setFixedDomainAxisSpace(AxisSpace space) { 2762 this.fixedDomainAxisSpace = space; 2763 } 2764 2765 2770 public AxisSpace getFixedRangeAxisSpace() { 2771 return this.fixedRangeAxisSpace; 2772 } 2773 2774 2779 public void setFixedRangeAxisSpace(AxisSpace space) { 2780 this.fixedRangeAxisSpace = space; 2781 } 2782 2783 2788 public List getCategories() { 2789 List result = null; 2790 if (getDataset() != null) { 2791 result = Collections.unmodifiableList(getDataset().getColumnKeys()); 2792 } 2793 return result; 2794 } 2795 2796 2802 public boolean getDrawSharedDomainAxis() { 2803 return this.drawSharedDomainAxis; 2804 } 2805 2806 2812 public void setDrawSharedDomainAxis(boolean draw) { 2813 this.drawSharedDomainAxis = draw; 2814 notifyListeners(new PlotChangeEvent(this)); 2815 } 2816 2817 2822 public boolean isDomainZoomable() { 2823 return false; 2824 } 2825 2826 2831 public boolean isRangeZoomable() { 2832 return true; 2833 } 2834 2835 2843 public void zoomDomainAxes(double factor, PlotRenderingInfo state, 2844 Point2D source) { 2845 } 2847 2848 2857 public void zoomDomainAxes(double lowerPercent, double upperPercent, 2858 PlotRenderingInfo state, Point2D source) { 2859 } 2861 2862 2869 public void zoomRangeAxes(double factor, PlotRenderingInfo state, 2870 Point2D source) { 2871 for (int i = 0; i < this.rangeAxes.size(); i++) { 2872 ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i); 2873 if (rangeAxis != null) { 2874 rangeAxis.resizeRange(factor); 2875 } 2876 } 2877 } 2878 2879 2887 public void zoomRangeAxes(double lowerPercent, double upperPercent, 2888 PlotRenderingInfo state, Point2D source) { 2889 for (int i = 0; i < this.rangeAxes.size(); i++) { 2890 ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i); 2891 if (rangeAxis != null) { 2892 rangeAxis.zoomRange(lowerPercent, upperPercent); 2893 } 2894 } 2895 } 2896 2897 2902 public double getAnchorValue() { 2903 return this.anchorValue; 2904 } 2905 2906 2911 public void setAnchorValue(double value) { 2912 setAnchorValue(value, true); 2913 } 2914 2915 2921 public void setAnchorValue(double value, boolean notify) { 2922 this.anchorValue = value; 2923 if (notify) { 2924 notifyListeners(new PlotChangeEvent(this)); 2925 } 2926 } 2927 2928 2935 public boolean equals(Object obj) { 2936 2937 if (obj == this) { 2938 return true; 2939 } 2940 2941 if (!(obj instanceof CategoryPlot)) { 2942 return false; 2943 } 2944 if (!super.equals(obj)) { 2945 return false; 2946 } 2947 2948 CategoryPlot that = (CategoryPlot) obj; 2949 2950 if (this.orientation != that.orientation) { 2951 return false; 2952 } 2953 if (!ObjectUtilities.equal(this.axisOffset, that.axisOffset)) { 2954 return false; 2955 } 2956 if (!this.domainAxes.equals(that.domainAxes)) { 2957 return false; 2958 } 2959 if (!this.domainAxisLocations.equals(that.domainAxisLocations)) { 2960 return false; 2961 } 2962 if (this.drawSharedDomainAxis != that.drawSharedDomainAxis) { 2963 return false; 2964 } 2965 if (!this.rangeAxes.equals(that.rangeAxes)) { 2966 return false; 2967 } 2968 if (!this.rangeAxisLocations.equals(that.rangeAxisLocations)) { 2969 return false; 2970 } 2971 if (!ObjectUtilities.equal( 2972 this.datasetToDomainAxisMap, that.datasetToDomainAxisMap 2973 )) { 2974 return false; 2975 } 2976 if (!ObjectUtilities.equal( 2977 this.datasetToRangeAxisMap, that.datasetToRangeAxisMap 2978 )) { 2979 return false; 2980 } 2981 if (!ObjectUtilities.equal(this.renderers, that.renderers)) { 2982 return false; 2983 } 2984 if (this.renderingOrder != that.renderingOrder) { 2985 return false; 2986 } 2987 if (this.columnRenderingOrder != that.columnRenderingOrder) { 2988 return false; 2989 } 2990 if (this.rowRenderingOrder != that.rowRenderingOrder) { 2991 return false; 2992 } 2993 if (this.domainGridlinesVisible != that.domainGridlinesVisible) { 2994 return false; 2995 } 2996 if (this.domainGridlinePosition != that.domainGridlinePosition) { 2997 return false; 2998 } 2999 if (!ObjectUtilities.equal( 3000 this.domainGridlineStroke, that.domainGridlineStroke 3001 )) { 3002 return false; 3003 } 3004 if (!ObjectUtilities.equal( 3005 this.domainGridlinePaint, that.domainGridlinePaint 3006 )) { 3007 return false; 3008 } 3009 if (this.rangeGridlinesVisible != that.rangeGridlinesVisible) { 3010 return false; 3011 } 3012 if (!ObjectUtilities.equal( 3013 this.rangeGridlineStroke, that.rangeGridlineStroke 3014 )) { 3015 return false; 3016 } 3017 if (!ObjectUtilities.equal( 3018 this.rangeGridlinePaint, that.rangeGridlinePaint 3019 )) { 3020 return false; 3021 } 3022 if (this.anchorValue != that.anchorValue) { 3023 return false; 3024 } 3025 if (this.rangeCrosshairVisible != that.rangeCrosshairVisible) { 3026 return false; 3027 } 3028 if (this.rangeCrosshairValue != that.rangeCrosshairValue) { 3029 return false; 3030 } 3031 if (!ObjectUtilities.equal( 3032 this.rangeCrosshairStroke, that.rangeCrosshairStroke 3033 )) { 3034 return false; 3035 } 3036 if (!ObjectUtilities.equal( 3037 this.rangeCrosshairPaint, that.rangeCrosshairPaint 3038 )) { 3039 return false; 3040 } 3041 if ( 3042 this.rangeCrosshairLockedOnData != that.rangeCrosshairLockedOnData 3043 ) { 3044 return false; 3045 } 3046 if (!ObjectUtilities.equal( 3047 this.foregroundRangeMarkers, that.foregroundRangeMarkers 3048 )) { 3049 return false; 3050 } 3051 if (!ObjectUtilities.equal( 3052 this.backgroundRangeMarkers, that.backgroundRangeMarkers 3053 )) { 3054 return false; 3055 } 3056 if (!ObjectUtilities.equal(this.annotations, that.annotations)) { 3057 return false; 3058 } 3059 if (this.weight != that.weight) { 3060 return false; 3061 } 3062 if (!ObjectUtilities.equal( 3063 this.fixedDomainAxisSpace, that.fixedDomainAxisSpace 3064 )) { 3065 return false; 3066 } 3067 if (!ObjectUtilities.equal( 3068 this.fixedRangeAxisSpace, that.fixedRangeAxisSpace 3069 )) { 3070 return false; 3071 } 3072 3073 return true; 3074 3075 } 3076 3077 3084 public Object clone() throws CloneNotSupportedException { 3085 3086 CategoryPlot clone = (CategoryPlot) super.clone(); 3087 3088 clone.domainAxes = new ObjectList(); 3089 for (int i = 0; i < this.domainAxes.size(); i++) { 3090 CategoryAxis xAxis = (CategoryAxis) this.domainAxes.get(i); 3091 if (xAxis != null) { 3092 CategoryAxis clonedAxis = (CategoryAxis) xAxis.clone(); 3093 clone.setDomainAxis(i, clonedAxis); 3094 } 3095 } 3096 clone.domainAxisLocations 3097 = (ObjectList) this.domainAxisLocations.clone(); 3098 3099 clone.rangeAxes = new ObjectList(); 3100 for (int i = 0; i < this.rangeAxes.size(); i++) { 3101 ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(i); 3102 if (yAxis != null) { 3103 ValueAxis clonedAxis = (ValueAxis) yAxis.clone(); 3104 clone.setRangeAxis(i, clonedAxis); 3105 } 3106 } 3107 clone.rangeAxisLocations = (ObjectList) this.rangeAxisLocations.clone(); 3108 3109 clone.datasets = (ObjectList) this.datasets.clone(); 3110 for (int i = 0; i < clone.datasets.size(); i++) { 3111 CategoryDataset dataset = clone.getDataset(i); 3112 if (dataset != null) { 3113 dataset.addChangeListener(clone); 3114 } 3115 } 3116 clone.datasetToDomainAxisMap 3117 = (ObjectList) this.datasetToDomainAxisMap.clone(); 3118 clone.datasetToRangeAxisMap 3119 = (ObjectList) this.datasetToRangeAxisMap.clone(); 3120 clone.renderers = (ObjectList) this.renderers.clone(); 3121 if (this.fixedDomainAxisSpace != null) { 3122 clone.fixedDomainAxisSpace = (AxisSpace) ObjectUtilities.clone( 3123 this.fixedDomainAxisSpace 3124 ); 3125 } 3126 if (this.fixedRangeAxisSpace != null) { 3127 clone.fixedRangeAxisSpace = (AxisSpace) ObjectUtilities.clone( 3128 this.fixedRangeAxisSpace 3129 ); 3130 } 3131 3132 return clone; 3133 3134 } 3135 3136 3143 private void writeObject(ObjectOutputStream stream) throws IOException { 3144 stream.defaultWriteObject(); 3145 SerialUtilities.writeStroke(this.domainGridlineStroke, stream); 3146 SerialUtilities.writePaint(this.domainGridlinePaint, stream); 3147 SerialUtilities.writeStroke(this.rangeGridlineStroke, stream); 3148 SerialUtilities.writePaint(this.rangeGridlinePaint, stream); 3149 SerialUtilities.writeStroke(this.rangeCrosshairStroke, stream); 3150 SerialUtilities.writePaint(this.rangeCrosshairPaint, stream); 3151 } 3152 3153 3161 private void readObject(ObjectInputStream stream) 3162 throws IOException , ClassNotFoundException { 3163 3164 stream.defaultReadObject(); 3165 this.domainGridlineStroke = SerialUtilities.readStroke(stream); 3166 this.domainGridlinePaint = SerialUtilities.readPaint(stream); 3167 this.rangeGridlineStroke = SerialUtilities.readStroke(stream); 3168 this.rangeGridlinePaint = SerialUtilities.readPaint(stream); 3169 this.rangeCrosshairStroke = SerialUtilities.readStroke(stream); 3170 this.rangeCrosshairPaint = SerialUtilities.readPaint(stream); 3171 3172 for (int i = 0; i < this.domainAxes.size(); i++) { 3173 CategoryAxis xAxis = (CategoryAxis) this.domainAxes.get(i); 3174 if (xAxis != null) { 3175 xAxis.setPlot(this); 3176 xAxis.addChangeListener(this); 3177 } 3178 } 3179 for (int i = 0; i < this.rangeAxes.size(); i++) { 3180 ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(i); 3181 if (yAxis != null) { 3182 yAxis.setPlot(this); 3183 yAxis.addChangeListener(this); 3184 } 3185 } 3186 int datasetCount = this.datasets.size(); 3187 for (int i = 0; i < datasetCount; i++) { 3188 Dataset dataset = (Dataset) this.datasets.get(i); 3189 if (dataset != null) { 3190 dataset.addChangeListener(this); 3191 } 3192 } 3193 int rendererCount = this.renderers.size(); 3194 for (int i = 0; i < rendererCount; i++) { 3195 CategoryItemRenderer renderer 3196 = (CategoryItemRenderer) this.renderers.get(i); 3197 if (renderer != null) { 3198 renderer.addChangeListener(this); 3199 } 3200 } 3201 3202 } 3203 3204} 3205 | Popular Tags |