1 167 168 package org.jfree.chart.plot; 169 170 import java.awt.AlphaComposite ; 171 import java.awt.BasicStroke ; 172 import java.awt.Color ; 173 import java.awt.Composite ; 174 import java.awt.Graphics2D ; 175 import java.awt.Paint ; 176 import java.awt.Shape ; 177 import java.awt.Stroke ; 178 import java.awt.geom.Line2D ; 179 import java.awt.geom.Point2D ; 180 import java.awt.geom.Rectangle2D ; 181 import java.io.IOException ; 182 import java.io.ObjectInputStream ; 183 import java.io.ObjectOutputStream ; 184 import java.io.Serializable ; 185 import java.util.ArrayList ; 186 import java.util.Collection ; 187 import java.util.Collections ; 188 import java.util.HashMap ; 189 import java.util.Iterator ; 190 import java.util.List ; 191 import java.util.Map ; 192 import java.util.ResourceBundle ; 193 import java.util.TreeMap ; 194 195 import org.jfree.chart.LegendItem; 196 import org.jfree.chart.LegendItemCollection; 197 import org.jfree.chart.annotations.XYAnnotation; 198 import org.jfree.chart.axis.Axis; 199 import org.jfree.chart.axis.AxisCollection; 200 import org.jfree.chart.axis.AxisLocation; 201 import org.jfree.chart.axis.AxisSpace; 202 import org.jfree.chart.axis.AxisState; 203 import org.jfree.chart.axis.ValueAxis; 204 import org.jfree.chart.axis.ValueTick; 205 import org.jfree.chart.event.ChartChangeEventType; 206 import org.jfree.chart.event.PlotChangeEvent; 207 import org.jfree.chart.event.RendererChangeEvent; 208 import org.jfree.chart.event.RendererChangeListener; 209 import org.jfree.chart.renderer.xy.XYItemRenderer; 210 import org.jfree.chart.renderer.xy.XYItemRendererState; 211 import org.jfree.data.Range; 212 import org.jfree.data.general.Dataset; 213 import org.jfree.data.general.DatasetChangeEvent; 214 import org.jfree.data.general.DatasetUtilities; 215 import org.jfree.data.xy.XYDataset; 216 import org.jfree.io.SerialUtilities; 217 import org.jfree.ui.Layer; 218 import org.jfree.ui.RectangleEdge; 219 import org.jfree.ui.RectangleInsets; 220 import org.jfree.util.ObjectList; 221 import org.jfree.util.ObjectUtilities; 222 import org.jfree.util.PublicCloneable; 223 224 235 public class XYPlot extends Plot implements ValueAxisPlot, 236 Zoomable, 237 RendererChangeListener, 238 Cloneable , PublicCloneable, 239 Serializable { 240 241 242 private static final long serialVersionUID = 7044148245716569264L; 243 244 245 public static final Stroke DEFAULT_GRIDLINE_STROKE = new BasicStroke ( 246 0.5f, 247 BasicStroke.CAP_BUTT, 248 BasicStroke.JOIN_BEVEL, 249 0.0f, 250 new float[] {2.0f, 2.0f}, 251 0.0f 252 ); 253 254 255 public static final Paint DEFAULT_GRIDLINE_PAINT = Color.lightGray; 256 257 258 public static final boolean DEFAULT_CROSSHAIR_VISIBLE = false; 259 260 261 public static final Stroke DEFAULT_CROSSHAIR_STROKE 262 = DEFAULT_GRIDLINE_STROKE; 263 264 265 public static final Paint DEFAULT_CROSSHAIR_PAINT = Color.blue; 266 267 268 protected static ResourceBundle localizationResources 269 = ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle"); 270 271 272 private PlotOrientation orientation; 273 274 275 private RectangleInsets axisOffset; 276 277 278 private ObjectList domainAxes; 279 280 281 private ObjectList domainAxisLocations; 282 283 284 private ObjectList rangeAxes; 285 286 287 private ObjectList rangeAxisLocations; 288 289 290 private ObjectList datasets; 291 292 293 private ObjectList renderers; 294 295 300 private Map datasetToDomainAxisMap; 301 302 307 private Map datasetToRangeAxisMap; 308 309 310 private transient Point2D quadrantOrigin = new Point2D.Double (0.0, 0.0); 311 312 313 private transient Paint [] quadrantPaint 314 = new Paint [] {null, null, null, null}; 315 316 317 private boolean domainGridlinesVisible; 318 319 320 private transient Stroke domainGridlineStroke; 321 322 323 private transient Paint domainGridlinePaint; 324 325 326 private boolean rangeGridlinesVisible; 327 328 329 private transient Stroke rangeGridlineStroke; 330 331 332 private transient Paint rangeGridlinePaint; 333 334 338 private boolean rangeZeroBaselineVisible; 339 340 341 private transient Stroke rangeZeroBaselineStroke; 342 343 344 private transient Paint rangeZeroBaselinePaint; 345 346 347 private boolean domainCrosshairVisible; 348 349 350 private double domainCrosshairValue; 351 352 353 private transient Stroke domainCrosshairStroke; 354 355 356 private transient Paint domainCrosshairPaint; 357 358 362 private boolean domainCrosshairLockedOnData = true; 363 364 365 private boolean rangeCrosshairVisible; 366 367 368 private double rangeCrosshairValue; 369 370 371 private transient Stroke rangeCrosshairStroke; 372 373 374 private transient Paint rangeCrosshairPaint; 375 376 380 private boolean rangeCrosshairLockedOnData = true; 381 382 383 private Map foregroundDomainMarkers; 384 385 386 private Map backgroundDomainMarkers; 387 388 389 private Map foregroundRangeMarkers; 390 391 392 private Map backgroundRangeMarkers; 393 394 399 private List annotations; 400 401 402 private transient Paint domainTickBandPaint; 403 404 405 private transient Paint rangeTickBandPaint; 406 407 408 private AxisSpace fixedDomainAxisSpace; 409 410 411 private AxisSpace fixedRangeAxisSpace; 412 413 417 private DatasetRenderingOrder datasetRenderingOrder 418 = DatasetRenderingOrder.REVERSE; 419 420 424 private SeriesRenderingOrder seriesRenderingOrder 425 = SeriesRenderingOrder.REVERSE; 426 427 431 private int weight; 432 433 437 private LegendItemCollection fixedLegendItems; 438 439 442 public XYPlot() { 443 this(null, null, null, null); 444 } 445 446 454 public XYPlot(XYDataset dataset, 455 ValueAxis domainAxis, 456 ValueAxis rangeAxis, 457 XYItemRenderer renderer) { 458 459 super(); 460 461 this.orientation = PlotOrientation.VERTICAL; 462 this.weight = 1; this.axisOffset = RectangleInsets.ZERO_INSETS; 464 465 this.domainAxes = new ObjectList(); 467 this.domainAxisLocations = new ObjectList(); 468 this.foregroundDomainMarkers = new HashMap (); 469 this.backgroundDomainMarkers = new HashMap (); 470 471 this.rangeAxes = new ObjectList(); 472 this.rangeAxisLocations = new ObjectList(); 473 this.foregroundRangeMarkers = new HashMap (); 474 this.backgroundRangeMarkers = new HashMap (); 475 476 this.datasets = new ObjectList(); 477 this.renderers = new ObjectList(); 478 479 this.datasetToDomainAxisMap = new TreeMap (); 480 this.datasetToRangeAxisMap = new TreeMap (); 481 482 this.datasets.set(0, dataset); 483 if (dataset != null) { 484 dataset.addChangeListener(this); 485 } 486 487 this.renderers.set(0, renderer); 488 if (renderer != null) { 489 renderer.setPlot(this); 490 renderer.addChangeListener(this); 491 } 492 493 this.domainAxes.set(0, domainAxis); 494 this.mapDatasetToDomainAxis(0, 0); 495 if (domainAxis != null) { 496 domainAxis.setPlot(this); 497 domainAxis.addChangeListener(this); 498 } 499 this.domainAxisLocations.set(0, AxisLocation.BOTTOM_OR_LEFT); 500 501 this.rangeAxes.set(0, rangeAxis); 502 this.mapDatasetToRangeAxis(0, 0); 503 if (rangeAxis != null) { 504 rangeAxis.setPlot(this); 505 rangeAxis.addChangeListener(this); 506 } 507 this.rangeAxisLocations.set(0, AxisLocation.BOTTOM_OR_LEFT); 508 509 configureDomainAxes(); 510 configureRangeAxes(); 511 512 this.domainGridlinesVisible = true; 513 this.domainGridlineStroke = DEFAULT_GRIDLINE_STROKE; 514 this.domainGridlinePaint = DEFAULT_GRIDLINE_PAINT; 515 516 this.rangeGridlinesVisible = true; 517 this.rangeGridlineStroke = DEFAULT_GRIDLINE_STROKE; 518 this.rangeGridlinePaint = DEFAULT_GRIDLINE_PAINT; 519 520 this.rangeZeroBaselineVisible = false; 521 this.rangeZeroBaselinePaint = Color.black; 522 this.rangeZeroBaselineStroke = new BasicStroke (0.5f); 523 524 this.domainCrosshairVisible = false; 525 this.domainCrosshairValue = 0.0; 526 this.domainCrosshairStroke = DEFAULT_CROSSHAIR_STROKE; 527 this.domainCrosshairPaint = DEFAULT_CROSSHAIR_PAINT; 528 529 this.rangeCrosshairVisible = false; 530 this.rangeCrosshairValue = 0.0; 531 this.rangeCrosshairStroke = DEFAULT_CROSSHAIR_STROKE; 532 this.rangeCrosshairPaint = DEFAULT_CROSSHAIR_PAINT; 533 534 this.annotations = new java.util.ArrayList (); 535 536 } 537 538 543 public String getPlotType() { 544 return localizationResources.getString("XY_Plot"); 545 } 546 547 552 public PlotOrientation getOrientation() { 553 return this.orientation; 554 } 555 556 561 public void setOrientation(PlotOrientation orientation) { 562 if (orientation == null) { 563 throw new IllegalArgumentException ("Null 'orientation' argument."); 564 } 565 if (orientation != this.orientation) { 566 this.orientation = orientation; 567 notifyListeners(new PlotChangeEvent(this)); 568 } 569 } 570 571 576 public RectangleInsets getAxisOffset() { 577 return this.axisOffset; 578 } 579 580 585 public void setAxisOffset(RectangleInsets offset) { 586 if (offset == null) { 587 throw new IllegalArgumentException ("Null 'offset' argument."); 588 } 589 this.axisOffset = offset; 590 notifyListeners(new PlotChangeEvent(this)); 591 } 592 593 600 public ValueAxis getDomainAxis() { 601 return getDomainAxis(0); 602 } 603 604 611 public ValueAxis getDomainAxis(int index) { 612 ValueAxis result = null; 613 if (index < this.domainAxes.size()) { 614 result = (ValueAxis) this.domainAxes.get(index); 615 } 616 if (result == null) { 617 Plot parent = getParent(); 618 if (parent instanceof XYPlot) { 619 XYPlot xy = (XYPlot) parent; 620 result = xy.getDomainAxis(index); 621 } 622 } 623 return result; 624 } 625 626 632 public void setDomainAxis(ValueAxis axis) { 633 setDomainAxis(0, axis); 634 } 635 636 643 public void setDomainAxis(int index, ValueAxis axis) { 644 setDomainAxis(index, axis, true); 645 } 646 647 655 public void setDomainAxis(int index, ValueAxis axis, boolean notify) { 656 ValueAxis existing = getDomainAxis(index); 657 if (existing != null) { 658 existing.removeChangeListener(this); 659 } 660 if (axis != null) { 661 axis.setPlot(this); 662 } 663 this.domainAxes.set(index, axis); 664 if (axis != null) { 665 axis.configure(); 666 axis.addChangeListener(this); 667 } 668 if (notify) { 669 notifyListeners(new PlotChangeEvent(this)); 670 } 671 } 672 673 679 public void setDomainAxes(ValueAxis[] axes) { 680 for (int i = 0; i < axes.length; i++) { 681 setDomainAxis(i, axes[i], false); 682 } 683 notifyListeners(new PlotChangeEvent(this)); 684 } 685 686 691 public AxisLocation getDomainAxisLocation() { 692 return (AxisLocation) this.domainAxisLocations.get(0); 693 } 694 695 701 public void setDomainAxisLocation(AxisLocation location) { 702 setDomainAxisLocation(location, true); 704 } 705 706 713 public void setDomainAxisLocation(AxisLocation location, boolean notify) { 714 if (location == null) { 715 throw new IllegalArgumentException ("Null 'location' argument."); 716 } 717 this.domainAxisLocations.set(0, location); 718 if (notify) { 719 notifyListeners(new PlotChangeEvent(this)); 720 } 721 } 722 723 729 public RectangleEdge getDomainAxisEdge() { 730 return Plot.resolveDomainAxisLocation( 731 getDomainAxisLocation(), this.orientation 732 ); 733 } 734 735 740 public int getDomainAxisCount() { 741 return this.domainAxes.size(); 742 } 743 744 748 public void clearDomainAxes() { 749 for (int i = 0; i < this.domainAxes.size(); i++) { 750 ValueAxis axis = (ValueAxis) this.domainAxes.get(i); 751 if (axis != null) { 752 axis.removeChangeListener(this); 753 } 754 } 755 this.domainAxes.clear(); 756 notifyListeners(new PlotChangeEvent(this)); 757 } 758 759 762 public void configureDomainAxes() { 763 for (int i = 0; i < this.domainAxes.size(); i++) { 764 ValueAxis axis = (ValueAxis) this.domainAxes.get(i); 765 if (axis != null) { 766 axis.configure(); 767 } 768 } 769 } 770 771 780 public AxisLocation getDomainAxisLocation(int index) { 781 AxisLocation result = null; 782 if (index < this.domainAxisLocations.size()) { 783 result = (AxisLocation) this.domainAxisLocations.get(index); 784 } 785 if (result == null) { 786 result = AxisLocation.getOpposite(getDomainAxisLocation()); 787 } 788 return result; 789 } 790 791 798 public void setDomainAxisLocation(int index, AxisLocation location) { 799 this.domainAxisLocations.set(index, location); 800 notifyListeners(new PlotChangeEvent(this)); 801 } 802 803 810 public RectangleEdge getDomainAxisEdge(int index) { 811 AxisLocation location = getDomainAxisLocation(index); 812 RectangleEdge result = Plot.resolveDomainAxisLocation( 813 location, this.orientation 814 ); 815 if (result == null) { 816 result = RectangleEdge.opposite(getDomainAxisEdge()); 817 } 818 return result; 819 } 820 821 828 public ValueAxis getRangeAxis() { 829 return getRangeAxis(0); 830 } 831 832 839 public void setRangeAxis(ValueAxis axis) { 840 841 if (axis != null) { 842 axis.setPlot(this); 843 } 844 845 ValueAxis existing = getRangeAxis(); 847 if (existing != null) { 848 existing.removeChangeListener(this); 849 } 850 851 this.rangeAxes.set(0, axis); 852 if (axis != null) { 853 axis.configure(); 854 axis.addChangeListener(this); 855 } 856 notifyListeners(new PlotChangeEvent(this)); 857 858 } 859 860 865 public AxisLocation getRangeAxisLocation() { 866 return (AxisLocation) this.rangeAxisLocations.get(0); 867 } 868 869 875 public void setRangeAxisLocation(AxisLocation location) { 876 setRangeAxisLocation(location, true); 878 } 879 880 887 public void setRangeAxisLocation(AxisLocation location, boolean notify) { 888 if (location == null) { 889 throw new IllegalArgumentException ("Null 'location' argument."); 890 } 891 this.rangeAxisLocations.set(0, location); 892 if (notify) { 893 notifyListeners(new PlotChangeEvent(this)); 894 } 895 896 } 897 898 903 public RectangleEdge getRangeAxisEdge() { 904 return Plot.resolveRangeAxisLocation( 905 getRangeAxisLocation(), this.orientation 906 ); 907 } 908 909 916 public ValueAxis getRangeAxis(int index) { 917 ValueAxis result = null; 918 if (index < this.rangeAxes.size()) { 919 result = (ValueAxis) this.rangeAxes.get(index); 920 } 921 if (result == null) { 922 Plot parent = getParent(); 923 if (parent instanceof XYPlot) { 924 XYPlot xy = (XYPlot) parent; 925 result = xy.getRangeAxis(index); 926 } 927 } 928 return result; 929 } 930 931 938 public void setRangeAxis(int index, ValueAxis axis) { 939 setRangeAxis(index, axis, true); 940 } 941 942 949 public void setRangeAxis(int index, ValueAxis axis, boolean notify) { 950 ValueAxis existing = getRangeAxis(index); 951 if (existing != null) { 952 existing.removeChangeListener(this); 953 } 954 if (axis != null) { 955 axis.setPlot(this); 956 } 957 this.rangeAxes.set(index, axis); 958 if (axis != null) { 959 axis.configure(); 960 axis.addChangeListener(this); 961 } 962 if (notify) { 963 notifyListeners(new PlotChangeEvent(this)); 964 } 965 } 966 967 973 public void setRangeAxes(ValueAxis[] axes) { 974 for (int i = 0; i < axes.length; i++) { 975 setRangeAxis(i, axes[i], false); 976 } 977 notifyListeners(new PlotChangeEvent(this)); 978 } 979 980 985 public int getRangeAxisCount() { 986 return this.rangeAxes.size(); 987 } 988 989 993 public void clearRangeAxes() { 994 for (int i = 0; i < this.rangeAxes.size(); i++) { 995 ValueAxis axis = (ValueAxis) this.rangeAxes.get(i); 996 if (axis != null) { 997 axis.removeChangeListener(this); 998 } 999 } 1000 this.rangeAxes.clear(); 1001 notifyListeners(new PlotChangeEvent(this)); 1002 } 1003 1004 1007 public void configureRangeAxes() { 1008 for (int i = 0; i < this.rangeAxes.size(); i++) { 1009 ValueAxis axis = (ValueAxis) this.rangeAxes.get(i); 1010 if (axis != null) { 1011 axis.configure(); 1012 } 1013 } 1014 } 1015 1016 1025 public AxisLocation getRangeAxisLocation(int index) { 1026 AxisLocation result = null; 1027 if (index < this.rangeAxisLocations.size()) { 1028 result = (AxisLocation) this.rangeAxisLocations.get(index); 1029 } 1030 if (result == null) { 1031 result = AxisLocation.getOpposite(getRangeAxisLocation()); 1032 } 1033 return result; 1034 } 1035 1036 1043 public void setRangeAxisLocation(int index, AxisLocation location) { 1044 this.rangeAxisLocations.set(index, location); 1045 notifyListeners(new PlotChangeEvent(this)); 1046 } 1047 1048 1055 public RectangleEdge getRangeAxisEdge(int index) { 1056 AxisLocation location = getRangeAxisLocation(index); 1057 RectangleEdge result = Plot.resolveRangeAxisLocation( 1058 location, this.orientation 1059 ); 1060 if (result == null) { 1061 result = RectangleEdge.opposite(getRangeAxisEdge()); 1062 } 1063 return result; 1064 } 1065 1066 1071 public XYDataset getDataset() { 1072 return getDataset(0); 1073 } 1074 1075 1082 public XYDataset getDataset(int index) { 1083 XYDataset result = null; 1084 if (this.datasets.size() > index) { 1085 result = (XYDataset) this.datasets.get(index); 1086 } 1087 return result; 1088 } 1089 1090 1096 public void setDataset(XYDataset dataset) { 1097 setDataset(0, dataset); 1098 } 1099 1100 1106 public void setDataset(int index, XYDataset dataset) { 1107 XYDataset existing = getDataset(index); 1108 if (existing != null) { 1109 existing.removeChangeListener(this); 1110 } 1111 this.datasets.set(index, dataset); 1112 if (dataset != null) { 1113 dataset.addChangeListener(this); 1114 } 1115 1116 DatasetChangeEvent event = new DatasetChangeEvent(this, dataset); 1118 datasetChanged(event); 1119 } 1120 1121 1126 public int getDatasetCount() { 1127 return this.datasets.size(); 1128 } 1129 1130 1138 public int indexOf(XYDataset dataset) { 1139 int result = -1; 1140 for (int i = 0; i < this.datasets.size(); i++) { 1141 if (dataset == this.datasets.get(i)) { 1142 result = i; 1143 break; 1144 } 1145 } 1146 return result; 1147 } 1148 1149 1156 public void mapDatasetToDomainAxis(int index, int axisIndex) { 1157 this.datasetToDomainAxisMap.put( 1158 new Integer (index), new Integer (axisIndex) 1159 ); 1160 datasetChanged(new DatasetChangeEvent(this, getDataset(index))); 1162 } 1163 1164 1171 public void mapDatasetToRangeAxis(int index, int axisIndex) { 1172 this.datasetToRangeAxisMap.put( 1173 new Integer (index), new Integer (axisIndex) 1174 ); 1175 datasetChanged(new DatasetChangeEvent(this, getDataset(index))); 1177 } 1178 1179 1184 public XYItemRenderer getRenderer() { 1185 return getRenderer(0); 1186 } 1187 1188 1195 public XYItemRenderer getRenderer(int index) { 1196 XYItemRenderer result = null; 1197 if (this.renderers.size() > index) { 1198 result = (XYItemRenderer) this.renderers.get(index); 1199 } 1200 return result; 1201 1202 } 1203 1204 1211 public void setRenderer(XYItemRenderer renderer) { 1212 setRenderer(0, renderer); 1213 } 1214 1215 1222 public void setRenderer(int index, XYItemRenderer renderer) { 1223 XYItemRenderer existing = getRenderer(index); 1224 if (existing != null) { 1225 existing.removeChangeListener(this); 1226 } 1227 this.renderers.set(index, renderer); 1228 if (renderer != null) { 1229 renderer.setPlot(this); 1230 renderer.addChangeListener(this); 1231 } 1232 configureDomainAxes(); 1233 configureRangeAxes(); 1234 notifyListeners(new PlotChangeEvent(this)); 1235 } 1236 1237 1242 public DatasetRenderingOrder getDatasetRenderingOrder() { 1243 return this.datasetRenderingOrder; 1244 } 1245 1246 1254 public void setDatasetRenderingOrder(DatasetRenderingOrder order) { 1255 if (order == null) { 1256 throw new IllegalArgumentException ("Null 'order' argument."); 1257 } 1258 this.datasetRenderingOrder = order; 1259 notifyListeners(new PlotChangeEvent(this)); 1260 } 1261 1262 1267 public SeriesRenderingOrder getSeriesRenderingOrder() { 1268 return this.seriesRenderingOrder; 1269 } 1270 1271 1279 public void setSeriesRenderingOrder(SeriesRenderingOrder order) { 1280 if (order == null) { 1281 throw new IllegalArgumentException ("Null 'order' argument."); 1282 } 1283 this.seriesRenderingOrder = order; 1284 notifyListeners(new PlotChangeEvent(this)); 1285 } 1286 1287 1295 public int getIndexOf(XYItemRenderer renderer) { 1296 return this.renderers.indexOf(renderer); 1297 } 1298 1299 1308 public XYItemRenderer getRendererForDataset(XYDataset dataset) { 1309 XYItemRenderer result = null; 1310 for (int i = 0; i < this.datasets.size(); i++) { 1311 if (this.datasets.get(i) == dataset) { 1312 result = (XYItemRenderer) this.renderers.get(i); 1313 if (result == null) { 1314 result = getRenderer(); 1315 } 1316 break; 1317 } 1318 } 1319 return result; 1320 } 1321 1322 1328 public int getWeight() { 1329 return this.weight; 1330 } 1331 1332 1337 public void setWeight(int weight) { 1338 this.weight = weight; 1339 } 1340 1341 1347 public boolean isDomainGridlinesVisible() { 1348 return this.domainGridlinesVisible; 1349 } 1350 1351 1360 public void setDomainGridlinesVisible(boolean visible) { 1361 if (this.domainGridlinesVisible != visible) { 1362 this.domainGridlinesVisible = visible; 1363 notifyListeners(new PlotChangeEvent(this)); 1364 } 1365 } 1366 1367 1373 public Stroke getDomainGridlineStroke() { 1374 return this.domainGridlineStroke; 1375 } 1376 1377 1384 public void setDomainGridlineStroke(Stroke stroke) { 1385 this.domainGridlineStroke = stroke; 1386 notifyListeners(new PlotChangeEvent(this)); 1387 } 1388 1389 1395 public Paint getDomainGridlinePaint() { 1396 return this.domainGridlinePaint; 1397 } 1398 1399 1406 public void setDomainGridlinePaint(Paint paint) { 1407 this.domainGridlinePaint = paint; 1408 notifyListeners(new PlotChangeEvent(this)); 1409 } 1410 1411 1417 public boolean isRangeGridlinesVisible() { 1418 return this.rangeGridlinesVisible; 1419 } 1420 1421 1430 public void setRangeGridlinesVisible(boolean visible) { 1431 if (this.rangeGridlinesVisible != visible) { 1432 this.rangeGridlinesVisible = visible; 1433 notifyListeners(new PlotChangeEvent(this)); 1434 } 1435 } 1436 1437 1443 public Stroke getRangeGridlineStroke() { 1444 return this.rangeGridlineStroke; 1445 } 1446 1447 1453 public void setRangeGridlineStroke(Stroke stroke) { 1454 if (stroke == null) { 1455 throw new IllegalArgumentException ("Null 'stroke' argument."); 1456 } 1457 this.rangeGridlineStroke = stroke; 1458 notifyListeners(new PlotChangeEvent(this)); 1459 } 1460 1461 1467 public Paint getRangeGridlinePaint() { 1468 return this.rangeGridlinePaint; 1469 } 1470 1471 1477 public void setRangeGridlinePaint(Paint paint) { 1478 this.rangeGridlinePaint = paint; 1479 notifyListeners(new PlotChangeEvent(this)); 1480 } 1481 1482 1488 public boolean isRangeZeroBaselineVisible() { 1489 return this.rangeZeroBaselineVisible; 1490 } 1491 1492 1499 public void setRangeZeroBaselineVisible(boolean visible) { 1500 this.rangeZeroBaselineVisible = visible; 1501 notifyListeners(new PlotChangeEvent(this)); 1502 } 1503 1504 1509 public Stroke getRangeZeroBaselineStroke() { 1510 return this.rangeZeroBaselineStroke; 1511 } 1512 1513 1519 public void setRangeZeroBaselineStroke(Stroke stroke) { 1520 if (stroke == null) { 1521 throw new IllegalArgumentException ("Null 'stroke' argument."); 1522 } 1523 this.rangeZeroBaselineStroke = stroke; 1524 notifyListeners(new PlotChangeEvent(this)); 1525 } 1526 1527 1533 public Paint getRangeZeroBaselinePaint() { 1534 return this.rangeZeroBaselinePaint; 1535 } 1536 1537 1543 public void setRangeZeroBaselinePaint(Paint paint) { 1544 this.rangeZeroBaselinePaint = paint; 1545 notifyListeners(new PlotChangeEvent(this)); 1546 } 1547 1548 1554 public Paint getDomainTickBandPaint() { 1555 return this.domainTickBandPaint; 1556 } 1557 1558 1563 public void setDomainTickBandPaint(Paint paint) { 1564 this.domainTickBandPaint = paint; 1565 notifyListeners(new PlotChangeEvent(this)); 1566 } 1567 1568 1574 public Paint getRangeTickBandPaint() { 1575 return this.rangeTickBandPaint; 1576 } 1577 1578 1583 public void setRangeTickBandPaint(Paint paint) { 1584 this.rangeTickBandPaint = paint; 1585 notifyListeners(new PlotChangeEvent(this)); 1586 } 1587 1588 1594 public Point2D getQuadrantOrigin() { 1595 return this.quadrantOrigin; 1596 } 1597 1598 1604 public void setQuadrantOrigin(Point2D origin) { 1605 if (origin == null) { 1606 throw new IllegalArgumentException ("Null 'origin' argument."); 1607 } 1608 this.quadrantOrigin = origin; 1609 notifyListeners(new PlotChangeEvent(this)); 1610 } 1611 1612 1619 public Paint getQuadrantPaint(int index) { 1620 if (index < 0 || index > 3) { 1621 throw new IllegalArgumentException ( 1622 "The index should be in the range 0 to 3." 1623 ); 1624 } 1625 return this.quadrantPaint[index]; 1626 } 1627 1628 1635 public void setQuadrantPaint(int index, Paint paint) { 1636 if (index < 0 || index > 3) { 1637 throw new IllegalArgumentException ( 1638 "The index should be in the range 0 to 3." 1639 ); 1640 } 1641 this.quadrantPaint[index] = paint; 1642 notifyListeners(new PlotChangeEvent(this)); 1643 } 1644 1645 1654 public void addDomainMarker(Marker marker) { 1655 addDomainMarker(marker, Layer.FOREGROUND); 1657 } 1658 1659 1669 public void addDomainMarker(Marker marker, Layer layer) { 1670 addDomainMarker(0, marker, layer); 1671 } 1672 1673 1677 public void clearDomainMarkers() { 1678 if (this.foregroundDomainMarkers != null) { 1679 this.foregroundDomainMarkers.clear(); 1680 } 1681 if (this.backgroundDomainMarkers != null) { 1682 this.backgroundDomainMarkers.clear(); 1683 } 1684 notifyListeners(new PlotChangeEvent(this)); 1685 } 1686 1687 1693 public void clearDomainMarkers(int index) { 1694 Integer key = new Integer (index); 1695 if (this.backgroundDomainMarkers != null) { 1696 Collection markers 1697 = (Collection ) this.backgroundDomainMarkers.get(key); 1698 if (markers != null) { 1699 markers.clear(); 1700 } 1701 } 1702 if (this.foregroundRangeMarkers != null) { 1703 Collection markers 1704 = (Collection ) this.foregroundDomainMarkers.get(key); 1705 if (markers != null) { 1706 markers.clear(); 1707 } 1708 } 1709 notifyListeners(new PlotChangeEvent(this)); 1710 } 1711 1712 1724 public void addDomainMarker(int index, Marker marker, Layer layer) { 1725 Collection markers; 1726 if (layer == Layer.FOREGROUND) { 1727 markers = (Collection ) this.foregroundDomainMarkers.get( 1728 new Integer (index) 1729 ); 1730 if (markers == null) { 1731 markers = new java.util.ArrayList (); 1732 this.foregroundDomainMarkers.put(new Integer (index), markers); 1733 } 1734 markers.add(marker); 1735 } 1736 else if (layer == Layer.BACKGROUND) { 1737 markers = (Collection ) this.backgroundDomainMarkers.get( 1738 new Integer (index) 1739 ); 1740 if (markers == null) { 1741 markers = new java.util.ArrayList (); 1742 this.backgroundDomainMarkers.put(new Integer (index), markers); 1743 } 1744 markers.add(marker); 1745 } 1746 notifyListeners(new PlotChangeEvent(this)); 1747 } 1748 1749 1758 public void addRangeMarker(Marker marker) { 1759 addRangeMarker(marker, Layer.FOREGROUND); 1760 } 1761 1762 1772 public void addRangeMarker(Marker marker, Layer layer) { 1773 addRangeMarker(0, marker, layer); 1774 } 1775 1776 1780 public void clearRangeMarkers() { 1781 if (this.foregroundRangeMarkers != null) { 1782 this.foregroundRangeMarkers.clear(); 1783 } 1784 if (this.backgroundRangeMarkers != null) { 1785 this.backgroundRangeMarkers.clear(); 1786 } 1787 notifyListeners(new PlotChangeEvent(this)); 1788 } 1789 1790 1801 public void addRangeMarker(int index, Marker marker, Layer layer) { 1802 Collection markers; 1803 if (layer == Layer.FOREGROUND) { 1804 markers = (Collection ) this.foregroundRangeMarkers.get( 1805 new Integer (index) 1806 ); 1807 if (markers == null) { 1808 markers = new java.util.ArrayList (); 1809 this.foregroundRangeMarkers.put(new Integer (index), markers); 1810 } 1811 markers.add(marker); 1812 } 1813 else if (layer == Layer.BACKGROUND) { 1814 markers = (Collection ) this.backgroundRangeMarkers.get( 1815 new Integer (index) 1816 ); 1817 if (markers == null) { 1818 markers = new java.util.ArrayList (); 1819 this.backgroundRangeMarkers.put(new Integer (index), markers); 1820 } 1821 markers.add(marker); 1822 } 1823 notifyListeners(new PlotChangeEvent(this)); 1824 } 1825 1826 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 1857 public void addAnnotation(XYAnnotation annotation) { 1858 if (annotation == null) { 1859 throw new IllegalArgumentException ("Null 'annotation' argument."); 1860 } 1861 this.annotations.add(annotation); 1862 notifyListeners(new PlotChangeEvent(this)); 1863 } 1864 1865 1873 public boolean removeAnnotation(XYAnnotation annotation) { 1874 if (annotation == null) { 1875 throw new IllegalArgumentException ("Null 'annotation' argument."); 1876 } 1877 boolean removed = this.annotations.remove(annotation); 1878 if (removed) { 1879 notifyListeners(new PlotChangeEvent(this)); 1880 } 1881 return removed; 1882 } 1883 1884 1888 public void clearAnnotations() { 1889 this.annotations.clear(); 1890 notifyListeners(new PlotChangeEvent(this)); 1891 } 1892 1893 1901 protected AxisSpace calculateAxisSpace(Graphics2D g2, 1902 Rectangle2D plotArea) { 1903 AxisSpace space = new AxisSpace(); 1904 space = calculateDomainAxisSpace(g2, plotArea, space); 1905 space = calculateRangeAxisSpace(g2, plotArea, space); 1906 return space; 1907 } 1908 1909 1918 protected AxisSpace calculateDomainAxisSpace(Graphics2D g2, 1919 Rectangle2D plotArea, 1920 AxisSpace space) { 1921 1922 if (space == null) { 1923 space = new AxisSpace(); 1924 } 1925 1926 if (this.fixedDomainAxisSpace != null) { 1928 if (this.orientation == PlotOrientation.HORIZONTAL) { 1929 space.ensureAtLeast( 1930 this.fixedDomainAxisSpace.getLeft(), RectangleEdge.LEFT 1931 ); 1932 space.ensureAtLeast( 1933 this.fixedDomainAxisSpace.getRight(), RectangleEdge.RIGHT 1934 ); 1935 } 1936 else if (this.orientation == PlotOrientation.VERTICAL) { 1937 space.ensureAtLeast( 1938 this.fixedDomainAxisSpace.getTop(), RectangleEdge.TOP 1939 ); 1940 space.ensureAtLeast( 1941 this.fixedDomainAxisSpace.getBottom(), RectangleEdge.BOTTOM 1942 ); 1943 } 1944 } 1945 else { 1946 for (int i = 0; i < this.domainAxes.size(); i++) { 1948 Axis axis = (Axis) this.domainAxes.get(i); 1949 if (axis != null) { 1950 RectangleEdge edge = getDomainAxisEdge(i); 1951 space = axis.reserveSpace(g2, this, plotArea, edge, space); 1952 } 1953 } 1954 } 1955 1956 return space; 1957 1958 } 1959 1960 1969 protected AxisSpace calculateRangeAxisSpace(Graphics2D g2, 1970 Rectangle2D plotArea, 1971 AxisSpace space) { 1972 1973 if (space == null) { 1974 space = new AxisSpace(); 1975 } 1976 1977 if (this.fixedRangeAxisSpace != null) { 1979 if (this.orientation == PlotOrientation.HORIZONTAL) { 1980 space.ensureAtLeast( 1981 this.fixedRangeAxisSpace.getTop(), RectangleEdge.TOP 1982 ); 1983 space.ensureAtLeast( 1984 this.fixedRangeAxisSpace.getBottom(), RectangleEdge.BOTTOM 1985 ); 1986 } 1987 else if (this.orientation == PlotOrientation.VERTICAL) { 1988 space.ensureAtLeast( 1989 this.fixedRangeAxisSpace.getLeft(), RectangleEdge.LEFT 1990 ); 1991 space.ensureAtLeast( 1992 this.fixedRangeAxisSpace.getRight(), RectangleEdge.RIGHT 1993 ); 1994 } 1995 } 1996 else { 1997 for (int i = 0; i < this.rangeAxes.size(); i++) { 1999 Axis axis = (Axis) this.rangeAxes.get(i); 2000 if (axis != null) { 2001 RectangleEdge edge = getRangeAxisEdge(i); 2002 space = axis.reserveSpace(g2, this, plotArea, edge, space); 2003 } 2004 } 2005 } 2006 return space; 2007 2008 } 2009 2010 2022 public void draw(Graphics2D g2, 2023 Rectangle2D area, 2024 Point2D anchor, 2025 PlotState parentState, 2026 PlotRenderingInfo info) { 2027 2028 boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW); 2030 boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW); 2031 if (b1 || b2) { 2032 return; 2033 } 2034 2035 if (info != null) { 2037 info.setPlotArea(area); 2038 } 2039 2040 RectangleInsets insets = getInsets(); 2042 insets.trim(area); 2043 2044 AxisSpace space = calculateAxisSpace(g2, area); 2045 Rectangle2D dataArea = space.shrink(area, null); 2046 this.axisOffset.trim(dataArea); 2047 2048 if (info != null) { 2049 info.setDataArea(dataArea); 2050 } 2051 2052 drawBackground(g2, dataArea); 2054 Map axisStateMap = drawAxes(g2, area, dataArea, info); 2055 2056 if (anchor != null && !dataArea.contains(anchor)) { 2057 anchor = null; 2058 } 2059 CrosshairState crosshairState = new CrosshairState(); 2060 crosshairState.setCrosshairDistance(Double.POSITIVE_INFINITY); 2061 crosshairState.setAnchor(anchor); 2062 crosshairState.setCrosshairX(getDomainCrosshairValue()); 2063 crosshairState.setCrosshairY(getRangeCrosshairValue()); 2064 Shape originalClip = g2.getClip(); 2065 Composite originalComposite = g2.getComposite(); 2066 2067 g2.clip(dataArea); 2068 g2.setComposite( 2069 AlphaComposite.getInstance( 2070 AlphaComposite.SRC_OVER, getForegroundAlpha() 2071 ) 2072 ); 2073 2074 AxisState domainAxisState 2075 = (AxisState) axisStateMap.get(getDomainAxis()); 2076 if (domainAxisState == null) { 2077 if (parentState != null) { 2078 domainAxisState 2079 = (AxisState) parentState.getSharedAxisStates().get( 2080 getDomainAxis() 2081 ); 2082 } 2083 } 2084 if (domainAxisState != null) { 2085 drawDomainTickBands(g2, dataArea, domainAxisState.getTicks()); 2086 drawDomainGridlines(g2, dataArea, domainAxisState.getTicks()); 2087 } 2088 2089 AxisState rangeAxisState = (AxisState) axisStateMap.get(getRangeAxis()); 2090 if (rangeAxisState == null) { 2091 if (parentState != null) { 2092 rangeAxisState 2093 = (AxisState) parentState.getSharedAxisStates().get( 2094 getRangeAxis() 2095 ); 2096 } 2097 } 2098 if (rangeAxisState != null) { 2099 drawRangeTickBands(g2, dataArea, rangeAxisState.getTicks()); 2100 drawRangeGridlines(g2, dataArea, rangeAxisState.getTicks()); 2101 drawZeroRangeBaseline(g2, dataArea); 2102 } 2103 2104 for (int i = 0; i < this.renderers.size(); i++) { 2106 drawDomainMarkers(g2, dataArea, i, Layer.BACKGROUND); 2107 } 2108 for (int i = 0; i < this.renderers.size(); i++) { 2109 drawRangeMarkers(g2, dataArea, i, Layer.BACKGROUND); 2110 } 2111 2112 boolean foundData = false; 2114 DatasetRenderingOrder order = getDatasetRenderingOrder(); 2115 if (order == DatasetRenderingOrder.FORWARD) { 2116 2117 int rendererCount = this.renderers.size(); 2119 for (int i = 0; i < rendererCount; i++) { 2120 XYItemRenderer r = getRenderer(i); 2121 if (r != null) { 2122 ValueAxis domainAxis = getDomainAxisForDataset(i); 2123 ValueAxis rangeAxis = getRangeAxisForDataset(i); 2124 r.drawAnnotations( 2125 g2, dataArea, domainAxis, rangeAxis, 2126 Layer.BACKGROUND, info 2127 ); 2128 } 2129 } 2130 2131 for (int i = 0; i < getDatasetCount(); i++) { 2133 foundData = render(g2, dataArea, i, info, crosshairState) 2134 || foundData; 2135 } 2136 2137 for (int i = 0; i < rendererCount; i++) { 2139 XYItemRenderer r = getRenderer(i); 2140 if (r != null) { 2141 ValueAxis domainAxis = getDomainAxisForDataset(i); 2142 ValueAxis rangeAxis = getRangeAxisForDataset(i); 2143 r.drawAnnotations( 2144 g2, dataArea, domainAxis, rangeAxis, 2145 Layer.FOREGROUND, info 2146 ); 2147 } 2148 } 2149 2150 } 2151 else if (order == DatasetRenderingOrder.REVERSE) { 2152 2153 int rendererCount = this.renderers.size(); 2155 for (int i = rendererCount - 1; i >= 0; i--) { 2156 XYItemRenderer r = getRenderer(i); 2157 if (r != null) { 2158 ValueAxis domainAxis = getDomainAxisForDataset(i); 2159 ValueAxis rangeAxis = getRangeAxisForDataset(i); 2160 r.drawAnnotations( 2161 g2, dataArea, domainAxis, rangeAxis, 2162 Layer.BACKGROUND, info 2163 ); 2164 } 2165 } 2166 2167 for (int i = getDatasetCount() - 1; i >= 0; i--) { 2168 foundData = render(g2, dataArea, i, info, crosshairState) 2169 || foundData; 2170 } 2171 2172 for (int i = rendererCount - 1; i >= 0; i--) { 2174 XYItemRenderer r = getRenderer(i); 2175 if (r != null) { 2176 ValueAxis domainAxis = getDomainAxisForDataset(i); 2177 ValueAxis rangeAxis = getRangeAxisForDataset(i); 2178 r.drawAnnotations( 2179 g2, dataArea, domainAxis, rangeAxis, 2180 Layer.FOREGROUND, info 2181 ); 2182 } 2183 } 2184 2185 } 2186 2187 PlotOrientation orient = getOrientation(); 2188 2189 if (!this.domainCrosshairLockedOnData && anchor != null) { 2191 double xx = getDomainAxis().java2DToValue( 2192 anchor.getX(), dataArea, getDomainAxisEdge() 2193 ); 2194 crosshairState.setCrosshairX(xx); 2195 } 2196 setDomainCrosshairValue(crosshairState.getCrosshairX(), false); 2197 if (isDomainCrosshairVisible()) { 2198 double x = getDomainCrosshairValue(); 2199 Paint paint = getDomainCrosshairPaint(); 2200 Stroke stroke = getDomainCrosshairStroke(); 2201 if (orient == PlotOrientation.HORIZONTAL) { 2202 drawHorizontalLine(g2, dataArea, x, stroke, paint); 2203 } 2204 else if (orient == PlotOrientation.VERTICAL) { 2205 drawVerticalLine(g2, dataArea, x, stroke, paint); 2206 } 2207 } 2208 2209 if (!this.rangeCrosshairLockedOnData && anchor != null) { 2211 double yy = getRangeAxis().java2DToValue( 2212 anchor.getY(), dataArea, getRangeAxisEdge() 2213 ); 2214 crosshairState.setCrosshairX(yy); 2215 } 2216 setRangeCrosshairValue(crosshairState.getCrosshairY(), false); 2217 if (isRangeCrosshairVisible() 2218 && getRangeAxis().getRange().contains(getRangeCrosshairValue())) { 2219 double y = getRangeCrosshairValue(); 2220 Paint paint = getRangeCrosshairPaint(); 2221 Stroke stroke = getRangeCrosshairStroke(); 2222 if (orient == PlotOrientation.HORIZONTAL) { 2223 drawVerticalLine(g2, dataArea, y, stroke, paint); 2224 } 2225 else if (orient == PlotOrientation.VERTICAL) { 2226 drawHorizontalLine(g2, dataArea, y, stroke, paint); 2227 } 2228 } 2229 2230 if (!foundData) { 2231 drawNoDataMessage(g2, dataArea); 2232 } 2233 2234 for (int i = 0; i < this.renderers.size(); i++) { 2235 drawDomainMarkers(g2, dataArea, i, Layer.FOREGROUND); 2236 } 2237 for (int i = 0; i < this.renderers.size(); i++) { 2238 drawRangeMarkers(g2, dataArea, i, Layer.FOREGROUND); 2239 } 2240 2241 drawAnnotations(g2, dataArea, info); 2242 g2.setClip(originalClip); 2243 g2.setComposite(originalComposite); 2244 2245 drawOutline(g2, dataArea); 2246 2247 } 2248 2249 2255 public void drawBackground(Graphics2D g2, Rectangle2D area) { 2256 fillBackground(g2, area); 2257 drawQuadrants(g2, area); 2258 drawBackgroundImage(g2, area); 2259 } 2260 2261 2267 protected void drawQuadrants(Graphics2D g2, Rectangle2D area) { 2268 boolean somethingToDraw = false; 2272 2273 ValueAxis xAxis = getDomainAxis(); 2274 double x = this.quadrantOrigin.getX(); 2275 double xx = xAxis.valueToJava2D(x, area, getDomainAxisEdge()); 2276 2277 ValueAxis yAxis = getRangeAxis(); 2278 double y = this.quadrantOrigin.getY(); 2279 double yy = yAxis.valueToJava2D(y, area, getRangeAxisEdge()); 2280 2281 double xmin = xAxis.getLowerBound(); 2282 double xxmin = xAxis.valueToJava2D(xmin, area, getDomainAxisEdge()); 2283 2284 double xmax = xAxis.getUpperBound(); 2285 double xxmax = xAxis.valueToJava2D(xmax, area, getDomainAxisEdge()); 2286 2287 double ymin = yAxis.getLowerBound(); 2288 double yymin = yAxis.valueToJava2D(ymin, area, getRangeAxisEdge()); 2289 2290 double ymax = yAxis.getUpperBound(); 2291 double yymax = yAxis.valueToJava2D(ymax, area, getRangeAxisEdge()); 2292 2293 Rectangle2D [] r = new Rectangle2D [] {null, null, null, null}; 2294 if (this.quadrantPaint[0] != null) { 2295 if (x > xmin && y < ymax) { 2296 if (this.orientation == PlotOrientation.HORIZONTAL) { 2297 r[0] = new Rectangle2D.Double ( 2298 Math.min(yymax, yy), Math.min(xxmin, xx), 2299 Math.abs(yy - yymax), Math.abs(xx - xxmin) 2300 ); 2301 } 2302 else { r[0] = new Rectangle2D.Double ( 2304 Math.min(xxmin, xx), Math.min(yymax, yy), 2305 Math.abs(xx - xxmin), Math.abs(yy - yymax) 2306 ); 2307 } 2308 somethingToDraw = true; 2309 } 2310 } 2311 if (this.quadrantPaint[1] != null) { 2312 if (x < xmax && y < ymax) { 2313 if (this.orientation == PlotOrientation.HORIZONTAL) { 2314 r[1] = new Rectangle2D.Double ( 2315 Math.min(yymax, yy), Math.min(xxmax, xx), 2316 Math.abs(yy - yymax), Math.abs(xx - xxmax) 2317 ); 2318 } 2319 else { r[1] = new Rectangle2D.Double ( 2321 Math.min(xx, xxmax), Math.min(yymax, yy), 2322 Math.abs(xx - xxmax), Math.abs(yy - yymax) 2323 ); 2324 } 2325 somethingToDraw = true; 2326 } 2327 } 2328 if (this.quadrantPaint[2] != null) { 2329 if (x > xmin && y > ymin) { 2330 if (this.orientation == PlotOrientation.HORIZONTAL) { 2331 r[2] = new Rectangle2D.Double ( 2332 Math.min(yymin, yy), Math.min(xxmin, xx), 2333 Math.abs(yy - yymin), Math.abs(xx - xxmin) 2334 ); 2335 } 2336 else { r[2] = new Rectangle2D.Double ( 2338 Math.min(xxmin, xx), Math.min(yymin, yy), 2339 Math.abs(xx - xxmin), Math.abs(yy - yymin) 2340 ); 2341 } 2342 somethingToDraw = true; 2343 } 2344 } 2345 if (this.quadrantPaint[3] != null) { 2346 if (x < xmax && y > ymin) { 2347 if (this.orientation == PlotOrientation.HORIZONTAL) { 2348 r[3] = new Rectangle2D.Double ( 2349 Math.min(yymin, yy), Math.min(xxmax, xx), 2350 Math.abs(yy - yymin), Math.abs(xx - xxmax) 2351 ); 2352 } 2353 else { r[3] = new Rectangle2D.Double ( 2355 Math.min(xx, xxmax), Math.min(yymin, yy), 2356 Math.abs(xx - xxmax), Math.abs(yy - yymin) 2357 ); 2358 } 2359 somethingToDraw = true; 2360 } 2361 } 2362 if (somethingToDraw) { 2363 Composite originalComposite = g2.getComposite(); 2364 g2.setComposite( 2365 AlphaComposite.getInstance( 2366 AlphaComposite.SRC_OVER, getBackgroundAlpha() 2367 ) 2368 ); 2369 for (int i = 0; i < 4; i++) { 2370 if (this.quadrantPaint[i] != null && r[i] != null) { 2371 g2.setPaint(this.quadrantPaint[i]); 2372 g2.fill(r[i]); 2373 } 2374 } 2375 g2.setComposite(originalComposite); 2376 } 2377 } 2378 2379 2386 public void drawDomainTickBands(Graphics2D g2, Rectangle2D dataArea, 2387 List ticks) { 2388 Paint bandPaint = getDomainTickBandPaint(); 2390 if (bandPaint != null) { 2391 boolean fillBand = false; 2392 ValueAxis xAxis = getDomainAxis(); 2393 double previous = xAxis.getLowerBound(); 2394 Iterator iterator = ticks.iterator(); 2395 while (iterator.hasNext()) { 2396 ValueTick tick = (ValueTick) iterator.next(); 2397 double current = tick.getValue(); 2398 if (fillBand) { 2399 getRenderer().fillDomainGridBand( 2400 g2, this, xAxis, dataArea, previous, current 2401 ); 2402 } 2403 previous = current; 2404 fillBand = !fillBand; 2405 } 2406 double end = xAxis.getUpperBound(); 2407 if (fillBand) { 2408 getRenderer().fillDomainGridBand( 2409 g2, this, xAxis, dataArea, previous, end 2410 ); 2411 } 2412 } 2413 } 2414 2415 2422 public void drawRangeTickBands(Graphics2D g2, Rectangle2D dataArea, 2423 List ticks) { 2424 2425 Paint bandPaint = getRangeTickBandPaint(); 2427 if (bandPaint != null) { 2428 boolean fillBand = false; 2429 ValueAxis axis = getRangeAxis(); 2430 double previous = axis.getLowerBound(); 2431 Iterator iterator = ticks.iterator(); 2432 while (iterator.hasNext()) { 2433 ValueTick tick = (ValueTick) iterator.next(); 2434 double current = tick.getValue(); 2435 if (fillBand) { 2436 getRenderer().fillRangeGridBand( 2437 g2, this, axis, dataArea, previous, current 2438 ); 2439 } 2440 previous = current; 2441 fillBand = !fillBand; 2442 } 2443 double end = axis.getUpperBound(); 2444 if (fillBand) { 2445 getRenderer().fillRangeGridBand( 2446 g2, this, axis, dataArea, previous, end 2447 ); 2448 } 2449 } 2450 } 2451 2452 2463 protected Map drawAxes(Graphics2D g2, 2464 Rectangle2D plotArea, 2465 Rectangle2D dataArea, 2466 PlotRenderingInfo plotState) { 2467 2468 AxisCollection axisCollection = new AxisCollection(); 2469 2470 for (int index = 0; index < this.domainAxes.size(); index++) { 2472 ValueAxis axis = (ValueAxis) this.domainAxes.get(index); 2473 if (axis != null) { 2474 axisCollection.add(axis, getDomainAxisEdge(index)); 2475 } 2476 } 2477 2478 for (int index = 0; index < this.rangeAxes.size(); index++) { 2480 ValueAxis yAxis = (ValueAxis) this.rangeAxes.get(index); 2481 if (yAxis != null) { 2482 axisCollection.add(yAxis, getRangeAxisEdge(index)); 2483 } 2484 } 2485 2486 Map axisStateMap = new HashMap (); 2487 2488 double cursor = dataArea.getMinY() - this.axisOffset.calculateTopOutset( 2490 dataArea.getHeight() 2491 ); 2492 Iterator iterator = axisCollection.getAxesAtTop().iterator(); 2493 while (iterator.hasNext()) { 2494 ValueAxis axis = (ValueAxis) iterator.next(); 2495 AxisState info = axis.draw( 2496 g2, cursor, plotArea, dataArea, RectangleEdge.TOP, plotState 2497 ); 2498 cursor = info.getCursor(); 2499 axisStateMap.put(axis, info); 2500 } 2501 2502 cursor = dataArea.getMaxY() 2504 + this.axisOffset.calculateBottomOutset(dataArea.getHeight()); 2505 iterator = axisCollection.getAxesAtBottom().iterator(); 2506 while (iterator.hasNext()) { 2507 ValueAxis axis = (ValueAxis) iterator.next(); 2508 AxisState info = axis.draw( 2509 g2, cursor, plotArea, dataArea, RectangleEdge.BOTTOM, plotState 2510 ); 2511 cursor = info.getCursor(); 2512 axisStateMap.put(axis, info); 2513 } 2514 2515 cursor = dataArea.getMinX() 2517 - this.axisOffset.calculateLeftOutset(dataArea.getWidth()); 2518 iterator = axisCollection.getAxesAtLeft().iterator(); 2519 while (iterator.hasNext()) { 2520 ValueAxis axis = (ValueAxis) iterator.next(); 2521 AxisState info = axis.draw( 2522 g2, cursor, plotArea, dataArea, RectangleEdge.LEFT, plotState 2523 ); 2524 cursor = info.getCursor(); 2525 axisStateMap.put(axis, info); 2526 } 2527 2528 cursor = dataArea.getMaxX() 2530 + this.axisOffset.calculateRightOutset(dataArea.getWidth()); 2531 iterator = axisCollection.getAxesAtRight().iterator(); 2532 while (iterator.hasNext()) { 2533 ValueAxis axis = (ValueAxis) iterator.next(); 2534 AxisState info = axis.draw( 2535 g2, cursor, plotArea, dataArea, RectangleEdge.RIGHT, plotState 2536 ); 2537 cursor = info.getCursor(); 2538 axisStateMap.put(axis, info); 2539 } 2540 2541 return axisStateMap; 2542 } 2543 2544 2560 public boolean render(Graphics2D g2, 2561 Rectangle2D dataArea, 2562 int index, 2563 PlotRenderingInfo info, 2564 CrosshairState crosshairState) { 2565 2566 boolean foundData = false; 2567 XYDataset dataset = getDataset(index); 2568 if (!DatasetUtilities.isEmptyOrNull(dataset)) { 2569 foundData = true; 2570 ValueAxis xAxis = getDomainAxisForDataset(index); 2571 ValueAxis yAxis = getRangeAxisForDataset(index); 2572 XYItemRenderer renderer = getRenderer(index); 2573 if (renderer == null) { 2574 renderer = getRenderer(); 2575 } 2576 2577 XYItemRendererState state = renderer.initialise( 2578 g2, dataArea, this, dataset, info 2579 ); 2580 int passCount = renderer.getPassCount(); 2581 2582 SeriesRenderingOrder seriesOrder = getSeriesRenderingOrder(); 2583 if (seriesOrder == SeriesRenderingOrder.REVERSE) { 2584 for (int pass = 0; pass < passCount; pass++) { 2586 int seriesCount = dataset.getSeriesCount(); 2587 for (int series = seriesCount-1; series >= 0 ; series--) { 2588 int itemCount = dataset.getItemCount(series); 2589 for (int item = 0; item < itemCount; item++) { 2590 renderer.drawItem( 2591 g2, state, dataArea, info, 2592 this, xAxis, yAxis, dataset, series, item, 2593 crosshairState, pass 2594 ); 2595 } 2596 } 2597 } 2598 } 2599 else { 2600 for (int pass = 0; pass < passCount; pass++) { 2602 int seriesCount = dataset.getSeriesCount(); 2603 for (int series = 0; series < seriesCount; series++) { 2604 int itemCount = dataset.getItemCount(series); 2605 for (int item = 0; item < itemCount; item++) { 2606 renderer.drawItem( 2607 g2, state, dataArea, info, 2608 this, xAxis, yAxis, dataset, series, item, 2609 crosshairState, pass 2610 ); 2611 } 2612 } 2613 } 2614 } 2615 } 2616 return foundData; 2617 } 2618 2619 2626 public ValueAxis getDomainAxisForDataset(int index) { 2627 2628 if (index < 0 || index >= getDatasetCount()) { 2629 throw new IllegalArgumentException ("Index 'index' out of bounds."); 2630 } 2631 2632 ValueAxis valueAxis = null; 2633 Integer axisIndex = (Integer ) this.datasetToDomainAxisMap.get( 2634 new Integer (index) 2635 ); 2636 if (axisIndex != null) { 2637 valueAxis = getDomainAxis(axisIndex.intValue()); 2638 } 2639 else { 2640 valueAxis = getDomainAxis(0); 2641 } 2642 return valueAxis; 2643 2644 } 2645 2646 2653 public ValueAxis getRangeAxisForDataset(int index) { 2654 2655 if (index < 0 || index >= getDatasetCount()) { 2656 throw new IllegalArgumentException ("Index 'index' out of bounds."); 2657 } 2658 2659 ValueAxis valueAxis = null; 2660 Integer axisIndex 2661 = (Integer ) this.datasetToRangeAxisMap.get(new Integer (index)); 2662 if (axisIndex != null) { 2663 valueAxis = getRangeAxis(axisIndex.intValue()); 2664 } 2665 else { 2666 valueAxis = getRangeAxis(0); 2667 } 2668 return valueAxis; 2669 2670 } 2671 2672 2679 protected void drawDomainGridlines(Graphics2D g2, Rectangle2D dataArea, 2680 List ticks) { 2681 2682 if (getRenderer() == null) { 2684 return; 2685 } 2686 2687 if (isDomainGridlinesVisible()) { 2689 Stroke gridStroke = getDomainGridlineStroke(); 2690 Paint gridPaint = getDomainGridlinePaint(); 2691 if ((gridStroke != null) && (gridPaint != null)) { 2692 Iterator iterator = ticks.iterator(); 2693 while (iterator.hasNext()) { 2694 ValueTick tick = (ValueTick) iterator.next(); 2695 getRenderer().drawDomainGridLine( 2696 g2, this, getDomainAxis(), dataArea, tick.getValue() 2697 ); 2698 } 2699 } 2700 } 2701 } 2702 2703 2711 protected void drawRangeGridlines(Graphics2D g2, Rectangle2D area, 2712 List ticks) { 2713 2714 if (isRangeGridlinesVisible()) { 2716 Stroke gridStroke = getRangeGridlineStroke(); 2717 Paint gridPaint = getRangeGridlinePaint(); 2718 ValueAxis axis = getRangeAxis(); 2719 if (axis != null) { 2720 Iterator iterator = ticks.iterator(); 2721 while (iterator.hasNext()) { 2722 ValueTick tick = (ValueTick) iterator.next(); 2723 if (tick.getValue() != 0.0 2724 || !isRangeZeroBaselineVisible()) { 2725 getRenderer().drawRangeLine( 2726 g2, this, getRangeAxis(), area, 2727 tick.getValue(), gridPaint, gridStroke 2728 ); 2729 } 2730 } 2731 } 2732 } 2733 } 2734 2735 2741 protected void drawZeroRangeBaseline(Graphics2D g2, Rectangle2D area) { 2742 if (isRangeZeroBaselineVisible()) { 2743 getRenderer().drawRangeLine( 2744 g2, this, getRangeAxis(), area, 2745 0.0, this.rangeZeroBaselinePaint, this.rangeZeroBaselineStroke 2746 ); 2747 } 2748 } 2749 2750 2757 public void drawAnnotations(Graphics2D g2, 2758 Rectangle2D dataArea, 2759 PlotRenderingInfo info) { 2760 2761 Iterator iterator = this.annotations.iterator(); 2762 while (iterator.hasNext()) { 2763 XYAnnotation annotation = (XYAnnotation) iterator.next(); 2764 ValueAxis xAxis = getDomainAxis(); 2765 ValueAxis yAxis = getRangeAxis(); 2766 annotation.draw(g2, this, dataArea, xAxis, yAxis, 0, info); 2767 } 2768 2769 } 2770 2771 2780 protected void drawDomainMarkers(Graphics2D g2, Rectangle2D dataArea, 2781 int index, Layer layer) { 2782 2783 XYItemRenderer r = getRenderer(index); 2784 if (r == null) { 2785 return; 2786 } 2787 2788 Collection markers = getDomainMarkers(index, layer); 2789 ValueAxis axis = getDomainAxisForDataset(index); 2790 if (markers != null && axis != null) { 2791 Iterator iterator = markers.iterator(); 2792 while (iterator.hasNext()) { 2793 Marker marker = (Marker) iterator.next(); 2794 r.drawDomainMarker(g2, this, axis, marker, dataArea); 2795 } 2796 } 2797 2798 } 2799 2800 2809 protected void drawRangeMarkers(Graphics2D g2, Rectangle2D dataArea, 2810 int index, Layer layer) { 2811 2812 XYItemRenderer r = getRenderer(index); 2813 if (r == null) { 2814 return; 2815 } 2816 2817 Collection markers = getRangeMarkers(index, layer); 2818 ValueAxis axis = getRangeAxis(index); 2819 if (markers != null && axis != null) { 2821 Iterator iterator = markers.iterator(); 2822 while (iterator.hasNext()) { 2823 Marker marker = (Marker) iterator.next(); 2824 r.drawRangeMarker(g2, this, axis, marker, dataArea); 2825 } 2826 } 2827 2828 } 2829 2830 2837 public Collection getDomainMarkers(Layer layer) { 2838 return getDomainMarkers(0, layer); 2839 } 2840 2841 2848 public Collection getRangeMarkers(Layer layer) { 2849 return getRangeMarkers(0, layer); 2850 } 2851 2852 2861 public Collection getDomainMarkers(int index, Layer layer) { 2862 Collection result = null; 2863 Integer key = new Integer (index); 2864 if (layer == Layer.FOREGROUND) { 2865 result = (Collection ) this.foregroundDomainMarkers.get(key); 2866 } 2867 else if (layer == Layer.BACKGROUND) { 2868 result = (Collection ) this.backgroundDomainMarkers.get(key); 2869 } 2870 if (result != null) { 2871 result = Collections.unmodifiableCollection(result); 2872 } 2873 return result; 2874 } 2875 2876 2885 public Collection getRangeMarkers(int index, Layer layer) { 2886 Collection result = null; 2887 Integer key = new Integer (index); 2888 if (layer == Layer.FOREGROUND) { 2889 result = (Collection ) this.foregroundRangeMarkers.get(key); 2890 } 2891 else if (layer == Layer.BACKGROUND) { 2892 result = (Collection ) this.backgroundRangeMarkers.get(key); 2893 } 2894 if (result != null) { 2895 result = Collections.unmodifiableCollection(result); 2896 } 2897 return result; 2898 } 2899 2900 2910 protected void drawHorizontalLine(Graphics2D g2, Rectangle2D dataArea, 2911 double value, Stroke stroke, 2912 Paint paint) { 2913 2914 ValueAxis axis = getRangeAxis(); 2915 if (getOrientation() == PlotOrientation.HORIZONTAL) { 2916 axis = getDomainAxis(); 2917 } 2918 if (axis.getRange().contains(value)) { 2919 double yy = axis.valueToJava2D(value, dataArea, RectangleEdge.LEFT); 2920 Line2D line = new Line2D.Double ( 2921 dataArea.getMinX(), yy, dataArea.getMaxX(), yy 2922 ); 2923 g2.setStroke(stroke); 2924 g2.setPaint(paint); 2925 g2.draw(line); 2926 } 2927 2928 } 2929 2930 2939 protected void drawVerticalLine(Graphics2D g2, Rectangle2D dataArea, 2940 double value, Stroke stroke, Paint paint) { 2941 2942 ValueAxis axis = getDomainAxis(); 2943 if (getOrientation() == PlotOrientation.HORIZONTAL) { 2944 axis = getRangeAxis(); 2945 } 2946 if (axis.getRange().contains(value)) { 2947 double xx = axis.valueToJava2D( 2948 value, dataArea, RectangleEdge.BOTTOM 2949 ); 2950 Line2D line = new Line2D.Double ( 2951 xx, dataArea.getMinY(), xx, dataArea.getMaxY() 2952 ); 2953 g2.setStroke(stroke); 2954 g2.setPaint(paint); 2955 g2.draw(line); 2956 } 2957 2958 } 2959 2960 2967 public void handleClick(int x, int y, PlotRenderingInfo info) { 2968 2969 Rectangle2D dataArea = info.getDataArea(); 2970 if (dataArea.contains(x, y)) { 2971 ValueAxis da = getDomainAxis(); 2973 if (da != null) { 2974 double hvalue = da.java2DToValue( 2975 x, info.getDataArea(), getDomainAxisEdge() 2976 ); 2977 2978 setDomainCrosshairValue(hvalue); 2979 } 2980 2981 ValueAxis ra = getRangeAxis(); 2983 if (ra != null) { 2984 double vvalue = ra.java2DToValue( 2985 y, info.getDataArea(), getRangeAxisEdge() 2986 ); 2987 setRangeCrosshairValue(vvalue); 2988 } 2989 } 2990 } 2991 2992 3000 private List getDatasetsMappedToDomainAxis(Integer axisIndex) { 3001 if (axisIndex == null) { 3002 throw new IllegalArgumentException ("Null 'axisIndex' argument."); 3003 } 3004 List result = new ArrayList (); 3005 for (int i = 0; i < this.datasets.size(); i++) { 3006 Integer mappedAxis = (Integer ) this.datasetToDomainAxisMap.get( 3007 new Integer (i) 3008 ); 3009 if (mappedAxis == null) { 3010 if (axisIndex.equals(ZERO)) { 3011 result.add(this.datasets.get(i)); 3012 } 3013 } 3014 else { 3015 if (mappedAxis.equals(axisIndex)) { 3016 result.add(this.datasets.get(i)); 3017 } 3018 } 3019 } 3020 return result; 3021 } 3022 3023 3031 private List getDatasetsMappedToRangeAxis(Integer axisIndex) { 3032 if (axisIndex == null) { 3033 throw new IllegalArgumentException ("Null 'axisIndex' argument."); 3034 } 3035 List result = new ArrayList (); 3036 for (int i = 0; i < this.datasets.size(); i++) { 3037 Integer mappedAxis = (Integer ) this.datasetToRangeAxisMap.get( 3038 new Integer (i) 3039 ); 3040 if (mappedAxis == null) { 3041 if (axisIndex.equals(ZERO)) { 3042 result.add(this.datasets.get(i)); 3043 } 3044 } 3045 else { 3046 if (mappedAxis.equals(axisIndex)) { 3047 result.add(this.datasets.get(i)); 3048 } 3049 } 3050 } 3051 return result; 3052 } 3053 3054 3061 protected int getDomainAxisIndex(ValueAxis axis) { 3062 int result = this.domainAxes.indexOf(axis); 3063 if (result < 0) { 3064 Plot parent = getParent(); 3066 if (parent instanceof XYPlot) { 3067 XYPlot p = (XYPlot) parent; 3068 result = p.getDomainAxisIndex(axis); 3069 } 3070 } 3071 return result; 3072 } 3073 3074 3081 protected int getRangeAxisIndex(ValueAxis axis) { 3082 int result = this.rangeAxes.indexOf(axis); 3083 if (result < 0) { 3084 Plot parent = getParent(); 3086 if (parent instanceof XYPlot) { 3087 XYPlot p = (XYPlot) parent; 3088 result = p.getRangeAxisIndex(axis); 3089 } 3090 } 3091 return result; 3092 } 3093 3094 3101 public Range getDataRange(ValueAxis axis) { 3102 3103 Range result = null; 3104 List mappedDatasets = new ArrayList (); 3105 boolean isDomainAxis = true; 3106 3107 int domainIndex = getDomainAxisIndex(axis); 3109 if (domainIndex >= 0) { 3110 isDomainAxis = true; 3111 mappedDatasets.addAll( 3112 getDatasetsMappedToDomainAxis(new Integer (domainIndex)) 3113 ); 3114 } 3115 3116 int rangeIndex = getRangeAxisIndex(axis); 3118 if (rangeIndex >= 0) { 3119 isDomainAxis = false; 3120 mappedDatasets.addAll( 3121 getDatasetsMappedToRangeAxis(new Integer (rangeIndex)) 3122 ); 3123 } 3124 3125 Iterator iterator = mappedDatasets.iterator(); 3128 while (iterator.hasNext()) { 3129 XYDataset d = (XYDataset) iterator.next(); 3130 if (d != null) { 3131 XYItemRenderer r = getRendererForDataset(d); 3132 if (isDomainAxis) { 3133 if (r != null) { 3134 result = Range.combine(result, r.findDomainBounds(d)); 3135 } 3136 else { 3137 result = Range.combine( 3138 result, DatasetUtilities.findDomainBounds(d) 3139 ); 3140 } 3141 } 3142 else { 3143 if (r != null) { 3144 result = Range.combine(result, r.findRangeBounds(d)); 3145 } 3146 else { 3147 result = Range.combine( 3148 result, DatasetUtilities.findRangeBounds(d) 3149 ); 3150 } 3151 } 3152 } 3153 } 3154 return result; 3155 3156 } 3157 3158 3165 public void datasetChanged(DatasetChangeEvent event) { 3166 configureDomainAxes(); 3167 configureRangeAxes(); 3168 if (getParent() != null) { 3169 getParent().datasetChanged(event); 3170 } 3171 else { 3172 PlotChangeEvent e = new PlotChangeEvent(this); 3173 e.setType(ChartChangeEventType.DATASET_UPDATED); 3174 notifyListeners(e); 3175 } 3176 } 3177 3178 3183 public void rendererChanged(RendererChangeEvent event) { 3184 notifyListeners(new PlotChangeEvent(this)); 3185 } 3186 3187 3192 public boolean isDomainCrosshairVisible() { 3193 return this.domainCrosshairVisible; 3194 } 3195 3196 3201 public void setDomainCrosshairVisible(boolean flag) { 3202 3203 if (this.domainCrosshairVisible != flag) { 3204 this.domainCrosshairVisible = flag; 3205 notifyListeners(new PlotChangeEvent(this)); 3206 } 3207 3208 } 3209 3210 3216 public boolean isDomainCrosshairLockedOnData() { 3217 return this.domainCrosshairLockedOnData; 3218 } 3219 3220 3226 public void setDomainCrosshairLockedOnData(boolean flag) { 3227 3228 if (this.domainCrosshairLockedOnData != flag) { 3229 this.domainCrosshairLockedOnData = flag; 3230 notifyListeners(new PlotChangeEvent(this)); 3231 } 3232 3233 } 3234 3235 3240 public double getDomainCrosshairValue() { 3241 return this.domainCrosshairValue; 3242 } 3243 3244 3250 public void setDomainCrosshairValue(double value) { 3251 setDomainCrosshairValue(value, true); 3252 } 3253 3254 3262 public void setDomainCrosshairValue(double value, boolean notify) { 3263 this.domainCrosshairValue = value; 3264 if (isDomainCrosshairVisible() && notify) { 3265 notifyListeners(new PlotChangeEvent(this)); 3266 } 3267 } 3268 3269 3274 public Stroke getDomainCrosshairStroke() { 3275 return this.domainCrosshairStroke; 3276 } 3277 3278 3284 public void setDomainCrosshairStroke(Stroke stroke) { 3285 this.domainCrosshairStroke = stroke; 3286 notifyListeners(new PlotChangeEvent(this)); 3287 } 3288 3289 3294 public Paint getDomainCrosshairPaint() { 3295 return this.domainCrosshairPaint; 3296 } 3297 3298 3304 public void setDomainCrosshairPaint(Paint paint) { 3305 this.domainCrosshairPaint = paint; 3306 notifyListeners(new PlotChangeEvent(this)); 3307 } 3308 3309 3314 public boolean isRangeCrosshairVisible() { 3315 return this.rangeCrosshairVisible; 3316 } 3317 3318 3323 public void setRangeCrosshairVisible(boolean flag) { 3324 3325 if (this.rangeCrosshairVisible != flag) { 3326 this.rangeCrosshairVisible = flag; 3327 notifyListeners(new PlotChangeEvent(this)); 3328 } 3329 3330 } 3331 3332 3338 public boolean isRangeCrosshairLockedOnData() { 3339 return this.rangeCrosshairLockedOnData; 3340 } 3341 3342 3348 public void setRangeCrosshairLockedOnData(boolean flag) { 3349 3350 if (this.rangeCrosshairLockedOnData != flag) { 3351 this.rangeCrosshairLockedOnData = flag; 3352 notifyListeners(new PlotChangeEvent(this)); 3353 } 3354 3355 } 3356 3357 3362 public double getRangeCrosshairValue() { 3363 return this.rangeCrosshairValue; 3364 } 3365 3366 3374 public void setRangeCrosshairValue(double value) { 3375 setRangeCrosshairValue(value, true); 3376 } 3377 3378 3388 public void setRangeCrosshairValue(double value, boolean notify) { 3389 this.rangeCrosshairValue = value; 3390 if (isRangeCrosshairVisible() && notify) { 3391 notifyListeners(new PlotChangeEvent(this)); 3392 } 3393 } 3394 3395 3400 public Stroke getRangeCrosshairStroke() { 3401 return this.rangeCrosshairStroke; 3402 } 3403 3404 3410 public void setRangeCrosshairStroke(Stroke stroke) { 3411 this.rangeCrosshairStroke = stroke; 3412 notifyListeners(new PlotChangeEvent(this)); 3413 } 3414 3415 3420 public Paint getRangeCrosshairPaint() { 3421 return this.rangeCrosshairPaint; 3422 } 3423 3424 3430 public void setRangeCrosshairPaint(Paint paint) { 3431 this.rangeCrosshairPaint = paint; 3432 notifyListeners(new PlotChangeEvent(this)); 3433 } 3434 3435 3440 public AxisSpace getFixedDomainAxisSpace() { 3441 return this.fixedDomainAxisSpace; 3442 } 3443 3444 3449 public void setFixedDomainAxisSpace(AxisSpace space) { 3450 this.fixedDomainAxisSpace = space; 3451 } 3452 3453 3458 public AxisSpace getFixedRangeAxisSpace() { 3459 return this.fixedRangeAxisSpace; 3460 } 3461 3462 3467 public void setFixedRangeAxisSpace(AxisSpace space) { 3468 this.fixedRangeAxisSpace = space; 3469 } 3470 3471 3478 public void zoomDomainAxes(double factor, PlotRenderingInfo info, 3479 Point2D source) { 3480 for (int i = 0; i < this.domainAxes.size(); i++) { 3481 ValueAxis domainAxis = (ValueAxis) this.domainAxes.get(i); 3482 if (domainAxis != null) { 3483 domainAxis.resizeRange(factor); 3484 } 3485 } 3486 } 3487 3488 3500 public void zoomDomainAxes(double lowerPercent, double upperPercent, 3501 PlotRenderingInfo info, Point2D source) { 3502 for (int i = 0; i < this.domainAxes.size(); i++) { 3503 ValueAxis domainAxis = (ValueAxis) this.domainAxes.get(i); 3504 if (domainAxis != null) { 3505 domainAxis.zoomRange(lowerPercent, upperPercent); 3506 } 3507 } 3508 } 3509 3510 3517 public void zoomRangeAxes(double factor, PlotRenderingInfo info, 3518 Point2D source) { 3519 for (int i = 0; i < this.rangeAxes.size(); i++) { 3520 ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i); 3521 if (rangeAxis != null) { 3522 rangeAxis.resizeRange(factor); 3523 } 3524 } 3525 } 3526 3527 3535 public void zoomRangeAxes(double lowerPercent, double upperPercent, 3536 PlotRenderingInfo info, Point2D source) { 3537 for (int i = 0; i < this.rangeAxes.size(); i++) { 3538 ValueAxis rangeAxis = (ValueAxis) this.rangeAxes.get(i); 3539 if (rangeAxis != null) { 3540 rangeAxis.zoomRange(lowerPercent, upperPercent); 3541 } 3542 } 3543 } 3544 3545 3550 public boolean isDomainZoomable() { 3551 return true; 3552 } 3553 3554 3559 public boolean isRangeZoomable() { 3560 return true; 3561 } 3562 3563 3569 public int getSeriesCount() { 3570 int result = 0; 3571 XYDataset dataset = getDataset(); 3572 if (dataset != null) { 3573 result = dataset.getSeriesCount(); 3574 } 3575 return result; 3576 } 3577 3578 3583 public LegendItemCollection getFixedLegendItems() { 3584 return this.fixedLegendItems; 3585 } 3586 3587 3594 public void setFixedLegendItems(LegendItemCollection items) { 3595 this.fixedLegendItems = items; 3596 notifyListeners(new PlotChangeEvent(this)); 3597 } 3598 3599 3606 public LegendItemCollection getLegendItems() { 3607 if (this.fixedLegendItems != null) { 3608 return this.fixedLegendItems; 3609 } 3610 LegendItemCollection result = new LegendItemCollection(); 3611 int count = this.datasets.size(); 3612 for (int datasetIndex = 0; datasetIndex < count; datasetIndex++) { 3613 XYDataset dataset = getDataset(datasetIndex); 3614 if (dataset != null) { 3615 XYItemRenderer renderer = getRenderer(datasetIndex); 3616 if (renderer == null) { 3617 renderer = getRenderer(0); 3618 } 3619 if (renderer != null) { 3620 int seriesCount = dataset.getSeriesCount(); 3621 for (int i = 0; i < seriesCount; i++) { 3622 if (renderer.isSeriesVisible(i) 3623 && renderer.isSeriesVisibleInLegend(i)) { 3624 LegendItem item = renderer.getLegendItem( 3625 datasetIndex, i 3626 ); 3627 if (item != null) { 3628 result.add(item); 3629 } 3630 } 3631 } 3632 } 3633 } 3634 } 3635 return result; 3636 } 3637 3638 3645 public boolean equals(Object obj) { 3646 3647 if (obj == this) { 3648 return true; 3649 } 3650 if (!(obj instanceof XYPlot)) { 3651 return false; 3652 } 3653 if (!super.equals(obj)) { 3654 return false; 3655 } 3656 3657 XYPlot that = (XYPlot) obj; 3658 if (this.weight != that.weight) { 3659 return false; 3660 } 3661 if (this.orientation != that.orientation) { 3662 return false; 3663 } 3664 if (!this.domainAxes.equals(that.domainAxes)) { 3665 return false; 3666 } 3667 if (!this.domainAxisLocations.equals(that.domainAxisLocations)) { 3668 return false; 3669 } 3670 if (this.rangeCrosshairLockedOnData 3671 != that.rangeCrosshairLockedOnData) { 3672 return false; 3673 } 3674 if (this.domainGridlinesVisible != that.domainGridlinesVisible) { 3675 return false; 3676 } 3677 if (this.rangeGridlinesVisible != that.rangeGridlinesVisible) { 3678 return false; 3679 } 3680 if (this.rangeZeroBaselineVisible != that.rangeZeroBaselineVisible) { 3681 return false; 3682 } 3683 if (this.domainCrosshairVisible != that.domainCrosshairVisible) { 3684 return false; 3685 } 3686 if (this.domainCrosshairValue != that.domainCrosshairValue) { 3687 return false; 3688 } 3689 if (this.domainCrosshairLockedOnData 3690 != that.domainCrosshairLockedOnData) { 3691 return false; 3692 } 3693 if (this.rangeCrosshairVisible != that.rangeCrosshairVisible) { 3694 return false; 3695 } 3696 if (this.rangeCrosshairValue != that.rangeCrosshairValue) { 3697 return false; 3698 } 3699 if (!ObjectUtilities.equal(this.axisOffset, that.axisOffset)) { 3700 return false; 3701 } 3702 if (!ObjectUtilities.equal(this.renderers, that.renderers)) { 3703 return false; 3704 } 3705 if (!ObjectUtilities.equal(this.rangeAxes, that.rangeAxes)) { 3706 return false; 3707 } 3708 if (!this.rangeAxisLocations.equals(that.rangeAxisLocations)) { 3709 return false; 3710 } 3711 if (!ObjectUtilities.equal( 3712 this.datasetToDomainAxisMap, that.datasetToDomainAxisMap 3713 )) { 3714 return false; 3715 } 3716 if (!ObjectUtilities.equal( 3717 this.datasetToRangeAxisMap, that.datasetToRangeAxisMap 3718 )) { 3719 return false; 3720 } 3721 if (!ObjectUtilities.equal( 3722 this.domainGridlineStroke, that.domainGridlineStroke)) { 3723 return false; 3724 } 3725 if (!ObjectUtilities.equal( 3726 this.domainGridlinePaint, that.domainGridlinePaint)) { 3727 return false; 3728 } 3729 if (!ObjectUtilities.equal( 3730 this.rangeGridlineStroke, that.rangeGridlineStroke)) { 3731 return false; 3732 } 3733 if (!ObjectUtilities.equal( 3734 this.rangeGridlinePaint, that.rangeGridlinePaint)) { 3735 return false; 3736 } 3737 if (!ObjectUtilities.equal( 3738 this.rangeZeroBaselinePaint, that.rangeZeroBaselinePaint 3739 )) { 3740 return false; 3741 } 3742 if (!ObjectUtilities.equal( 3743 this.rangeZeroBaselineStroke, that.rangeZeroBaselineStroke 3744 )) { 3745 return false; 3746 } 3747 if (!ObjectUtilities.equal( 3748 this.domainCrosshairStroke, that.domainCrosshairStroke 3749 )) { 3750 return false; 3751 } 3752 if (!ObjectUtilities.equal( 3753 this.domainCrosshairPaint, that.domainCrosshairPaint 3754 )) { 3755 return false; 3756 } 3757 if (!ObjectUtilities.equal( 3758 this.rangeCrosshairStroke, that.rangeCrosshairStroke 3759 )) { 3760 return false; 3761 } 3762 if (!ObjectUtilities.equal( 3763 this.rangeCrosshairPaint, that.rangeCrosshairPaint 3764 )) { 3765 return false; 3766 } 3767 if (!ObjectUtilities.equal( 3768 this.foregroundDomainMarkers, that.foregroundDomainMarkers 3769 )) { 3770 return false; 3771 } 3772 if (!ObjectUtilities.equal( 3773 this.backgroundDomainMarkers, that.backgroundDomainMarkers 3774 )) { 3775 return false; 3776 } 3777 if (!ObjectUtilities.equal( 3778 this.foregroundRangeMarkers, that.foregroundRangeMarkers 3779 )) { 3780 return false; 3781 } 3782 if (!ObjectUtilities.equal( 3783 this.backgroundRangeMarkers, that.backgroundRangeMarkers 3784 )) { 3785 return false; 3786 } 3787 if (!ObjectUtilities.equal( 3788 this.foregroundDomainMarkers, that.foregroundDomainMarkers 3789 )) { 3790 return false; 3791 } 3792 if (!ObjectUtilities.equal( 3793 this.backgroundDomainMarkers, that.backgroundDomainMarkers 3794 )) { 3795 return false; 3796 } 3797 if (!ObjectUtilities.equal( 3798 this.foregroundRangeMarkers, that.foregroundRangeMarkers 3799 )) { 3800 return false; 3801 } 3802 if (!ObjectUtilities.equal( 3803 this.backgroundRangeMarkers, that.backgroundRangeMarkers 3804 )) { 3805 return false; 3806 } 3807 if (!ObjectUtilities.equal( 3808 this.annotations, that.annotations 3809 )) { 3810 return false; 3811 } 3812 return true; 3813 3814 } 3815 3816 3824 public Object clone() throws CloneNotSupportedException { 3825 3826 XYPlot clone = (XYPlot) super.clone(); 3827 clone.domainAxes = (ObjectList) ObjectUtilities.clone(this.domainAxes); 3828 for (int i = 0; i < this.domainAxes.size(); i++) { 3829 ValueAxis axis = (ValueAxis) this.domainAxes.get(i); 3830 if (axis != null) { 3831 ValueAxis clonedAxis = (ValueAxis) axis.clone(); 3832 clone.domainAxes.set(i, clonedAxis); 3833 clonedAxis.setPlot(clone); 3834 clonedAxis.addChangeListener(clone); 3835 } 3836 } 3837 clone.domainAxisLocations 3838 = (ObjectList) this.domainAxisLocations.clone(); 3839 3840 clone.rangeAxes = (ObjectList) ObjectUtilities.clone(this.rangeAxes); 3841 for (int i = 0; i < this.rangeAxes.size(); i++) { 3842 ValueAxis axis = (ValueAxis) this.rangeAxes.get(i); 3843 if (axis != null) { 3844 ValueAxis clonedAxis = (ValueAxis) axis.clone(); 3845 clone.rangeAxes.set(i, clonedAxis); 3846 clonedAxis.setPlot(clone); 3847 clonedAxis.addChangeListener(clone); 3848 } 3849 } 3850 clone.rangeAxisLocations 3851 = (ObjectList) ObjectUtilities.clone(this.rangeAxisLocations); 3852 3853 clone.datasets = (ObjectList) ObjectUtilities.clone(this.datasets); 3855 for (int i = 0; i < clone.datasets.size(); ++i) { 3856 XYDataset d = getDataset(i); 3857 if (d != null) { 3858 d.addChangeListener(clone); 3859 } 3860 } 3861 3862 clone.datasetToDomainAxisMap = new TreeMap (); 3863 clone.datasetToDomainAxisMap.putAll(this.datasetToDomainAxisMap); 3864 clone.datasetToRangeAxisMap = new TreeMap (); 3865 clone.datasetToRangeAxisMap.putAll(this.datasetToRangeAxisMap); 3866 3867 clone.renderers = (ObjectList) ObjectUtilities.clone(this.renderers); 3868 for (int i = 0; i < this.renderers.size(); i++) { 3869 XYItemRenderer renderer2 = (XYItemRenderer) this.renderers.get(i); 3870 if (renderer2 instanceof PublicCloneable) { 3871 PublicCloneable pc = (PublicCloneable) renderer2; 3872 clone.renderers.set(i, pc.clone()); 3873 } 3874 } 3875 clone.foregroundDomainMarkers = (Map ) ObjectUtilities.clone( 3876 this.foregroundDomainMarkers 3877 ); 3878 clone.backgroundDomainMarkers = (Map ) ObjectUtilities.clone( 3879 this.backgroundDomainMarkers 3880 ); 3881 clone.foregroundRangeMarkers = (Map ) ObjectUtilities.clone( 3882 this.foregroundRangeMarkers 3883 ); 3884 clone.backgroundRangeMarkers = (Map ) ObjectUtilities.clone( 3885 this.backgroundRangeMarkers 3886 ); 3887 clone.annotations = (List ) ObjectUtilities.deepClone(this.annotations); 3888 if (this.fixedDomainAxisSpace != null) { 3889 clone.fixedDomainAxisSpace = (AxisSpace) ObjectUtilities.clone( 3890 this.fixedDomainAxisSpace 3891 ); 3892 } 3893 if (this.fixedRangeAxisSpace != null) { 3894 clone.fixedRangeAxisSpace = (AxisSpace) ObjectUtilities.clone( 3895 this.fixedRangeAxisSpace 3896 ); 3897 } 3898 return clone; 3899 3900 } 3901 3902 3909 private void writeObject(ObjectOutputStream stream) throws IOException { 3910 stream.defaultWriteObject(); 3911 SerialUtilities.writeStroke(this.domainGridlineStroke, stream); 3912 SerialUtilities.writePaint(this.domainGridlinePaint, stream); 3913 SerialUtilities.writeStroke(this.rangeGridlineStroke, stream); 3914 SerialUtilities.writePaint(this.rangeGridlinePaint, stream); 3915 SerialUtilities.writeStroke(this.rangeZeroBaselineStroke, stream); 3916 SerialUtilities.writePaint(this.rangeZeroBaselinePaint, stream); 3917 SerialUtilities.writeStroke(this.domainCrosshairStroke, stream); 3918 SerialUtilities.writePaint(this.domainCrosshairPaint, stream); 3919 SerialUtilities.writeStroke(this.rangeCrosshairStroke, stream); 3920 SerialUtilities.writePaint(this.rangeCrosshairPaint, stream); 3921 SerialUtilities.writePaint(this.domainTickBandPaint, stream); 3922 SerialUtilities.writePaint(this.rangeTickBandPaint, stream); 3923 SerialUtilities.writePoint2D(this.quadrantOrigin, stream); 3924 for (int i = 0; i < 4; i++) { 3925 SerialUtilities.writePaint(this.quadrantPaint[i], stream); 3926 } 3927 } 3928 3929 3937 private void readObject(ObjectInputStream stream) 3938 throws IOException , ClassNotFoundException { 3939 3940 stream.defaultReadObject(); 3941 this.domainGridlineStroke = SerialUtilities.readStroke(stream); 3942 this.domainGridlinePaint = SerialUtilities.readPaint(stream); 3943 this.rangeGridlineStroke = SerialUtilities.readStroke(stream); 3944 this.rangeGridlinePaint = SerialUtilities.readPaint(stream); 3945 this.rangeZeroBaselineStroke = SerialUtilities.readStroke(stream); 3946 this.rangeZeroBaselinePaint = SerialUtilities.readPaint(stream); 3947 this.domainCrosshairStroke = SerialUtilities.readStroke(stream); 3948 this.domainCrosshairPaint = SerialUtilities.readPaint(stream); 3949 this.rangeCrosshairStroke = SerialUtilities.readStroke(stream); 3950 this.rangeCrosshairPaint = SerialUtilities.readPaint(stream); 3951 this.domainTickBandPaint = SerialUtilities.readPaint(stream); 3952 this.rangeTickBandPaint = SerialUtilities.readPaint(stream); 3953 this.quadrantOrigin = SerialUtilities.readPoint2D(stream); 3954 this.quadrantPaint = new Paint [4]; 3955 for (int i = 0; i < 4; i++) { 3956 this.quadrantPaint[i] = SerialUtilities.readPaint(stream); 3957 } 3958 3959 int domainAxisCount = this.domainAxes.size(); 3962 for (int i = 0; i < domainAxisCount; i++) { 3963 Axis axis = (Axis) this.domainAxes.get(i); 3964 if (axis != null) { 3965 axis.setPlot(this); 3966 axis.addChangeListener(this); 3967 } 3968 } 3969 int rangeAxisCount = this.rangeAxes.size(); 3970 for (int i = 0; i < rangeAxisCount; i++) { 3971 Axis axis = (Axis) this.rangeAxes.get(i); 3972 if (axis != null) { 3973 axis.setPlot(this); 3974 axis.addChangeListener(this); 3975 } 3976 } 3977 int datasetCount = this.datasets.size(); 3978 for (int i = 0; i < datasetCount; i++) { 3979 Dataset dataset = (Dataset) this.datasets.get(i); 3980 if (dataset != null) { 3981 dataset.addChangeListener(this); 3982 } 3983 } 3984 int rendererCount = this.renderers.size(); 3985 for (int i = 0; i < rendererCount; i++) { 3986 XYItemRenderer renderer = (XYItemRenderer) this.renderers.get(i); 3987 if (renderer != null) { 3988 renderer.addChangeListener(this); 3989 } 3990 } 3991 3992 } 3993 3994} 3995 | Popular Tags |