1 84 85 package org.jfree.chart.plot; 86 87 import java.awt.Graphics2D ; 88 import java.awt.geom.Point2D ; 89 import java.awt.geom.Rectangle2D ; 90 import java.io.Serializable ; 91 import java.util.Collections ; 92 import java.util.Iterator ; 93 import java.util.List ; 94 95 import org.jfree.chart.LegendItemCollection; 96 import org.jfree.chart.axis.AxisSpace; 97 import org.jfree.chart.axis.AxisState; 98 import org.jfree.chart.axis.NumberAxis; 99 import org.jfree.chart.axis.ValueAxis; 100 import org.jfree.chart.event.PlotChangeEvent; 101 import org.jfree.chart.event.PlotChangeListener; 102 import org.jfree.chart.renderer.xy.XYItemRenderer; 103 import org.jfree.data.Range; 104 import org.jfree.ui.RectangleEdge; 105 import org.jfree.ui.RectangleInsets; 106 import org.jfree.util.ObjectUtilities; 107 import org.jfree.util.PublicCloneable; 108 109 113 public class CombinedRangeXYPlot extends XYPlot 114 implements Zoomable, 115 Cloneable , PublicCloneable, 116 Serializable , 117 PlotChangeListener { 118 119 120 private static final long serialVersionUID = -5177814085082031168L; 121 122 123 private List subplots; 124 125 126 private int totalWeight = 0; 127 128 129 private double gap = 5.0; 130 131 132 private transient Rectangle2D [] subplotAreas; 133 134 137 public CombinedRangeXYPlot() { 138 this(new NumberAxis()); 139 } 140 141 146 public CombinedRangeXYPlot(ValueAxis rangeAxis) { 147 148 super(null, null, 150 rangeAxis, 151 null); 152 153 this.subplots = new java.util.ArrayList (); 154 155 } 156 157 162 public String getPlotType() { 163 return localizationResources.getString("Combined_Range_XYPlot"); 164 } 165 166 171 public double getGap() { 172 return this.gap; 173 } 174 175 180 public void setGap(double gap) { 181 this.gap = gap; 182 } 183 184 189 public void add(XYPlot subplot) { 190 add(subplot, 1); 191 } 192 193 201 public void add(XYPlot subplot, int weight) { 202 203 if (weight <= 0) { 205 String msg = "The 'weight' must be positive."; 206 throw new IllegalArgumentException (msg); 207 } 208 209 subplot.setParent(this); 211 subplot.setWeight(weight); 212 subplot.setInsets(new RectangleInsets(0.0, 0.0, 0.0, 0.0)); 213 subplot.setRangeAxis(null); 214 subplot.addChangeListener(this); 215 this.subplots.add(subplot); 216 217 this.totalWeight += weight; 219 configureRangeAxes(); 220 notifyListeners(new PlotChangeEvent(this)); 221 222 } 223 224 229 public void remove(XYPlot subplot) { 230 if (subplot == null) { 231 throw new IllegalArgumentException (" Null 'subplot' argument."); 232 } 233 int position = -1; 234 int size = this.subplots.size(); 235 int i = 0; 236 while (position == -1 && i < size) { 237 if (this.subplots.get(i) == subplot) { 238 position = i; 239 } 240 i++; 241 } 242 if (position != -1) { 243 subplot.setParent(null); 244 subplot.removeChangeListener(this); 245 this.totalWeight -= subplot.getWeight(); 246 configureRangeAxes(); 247 notifyListeners(new PlotChangeEvent(this)); 248 } 249 } 250 251 256 public List getSubplots() { 257 return Collections.unmodifiableList(this.subplots); 258 } 259 260 268 protected AxisSpace calculateAxisSpace(Graphics2D g2, 269 Rectangle2D plotArea) { 270 271 AxisSpace space = new AxisSpace(); 272 PlotOrientation orientation = getOrientation(); 273 274 AxisSpace fixed = getFixedRangeAxisSpace(); 276 if (fixed != null) { 277 if (orientation == PlotOrientation.VERTICAL) { 278 space.setLeft(fixed.getLeft()); 279 space.setRight(fixed.getRight()); 280 } 281 else if (orientation == PlotOrientation.HORIZONTAL) { 282 space.setTop(fixed.getTop()); 283 space.setBottom(fixed.getBottom()); 284 } 285 } 286 else { 287 ValueAxis valueAxis = getRangeAxis(); 288 RectangleEdge valueEdge = Plot.resolveRangeAxisLocation( 289 getRangeAxisLocation(), orientation 290 ); 291 if (valueAxis != null) { 292 space = valueAxis.reserveSpace( 293 g2, this, plotArea, valueEdge, space 294 ); 295 } 296 } 297 298 Rectangle2D adjustedPlotArea = space.shrink(plotArea, null); 299 int n = this.subplots.size(); 301 302 this.subplotAreas = new Rectangle2D [n]; 305 double x = adjustedPlotArea.getX(); 306 double y = adjustedPlotArea.getY(); 307 double usableSize = 0.0; 308 if (orientation == PlotOrientation.VERTICAL) { 309 usableSize = adjustedPlotArea.getWidth() - this.gap * (n - 1); 310 } 311 else if (orientation == PlotOrientation.HORIZONTAL) { 312 usableSize = adjustedPlotArea.getHeight() - this.gap * (n - 1); 313 } 314 315 for (int i = 0; i < n; i++) { 316 XYPlot plot = (XYPlot) this.subplots.get(i); 317 318 if (orientation == PlotOrientation.VERTICAL) { 320 double w = usableSize * plot.getWeight() / this.totalWeight; 321 this.subplotAreas[i] = new Rectangle2D.Double ( 322 x, y, w, adjustedPlotArea.getHeight() 323 ); 324 x = x + w + this.gap; 325 } 326 else if (orientation == PlotOrientation.HORIZONTAL) { 327 double h = usableSize * plot.getWeight() / this.totalWeight; 328 this.subplotAreas[i] = new Rectangle2D.Double ( 329 x, y, adjustedPlotArea.getWidth(), h 330 ); 331 y = y + h + this.gap; 332 } 333 334 AxisSpace subSpace = plot.calculateDomainAxisSpace( 335 g2, this.subplotAreas[i], null 336 ); 337 space.ensureAtLeast(subSpace); 338 339 } 340 341 return space; 342 } 343 344 356 public void draw(Graphics2D g2, 357 Rectangle2D area, 358 Point2D anchor, 359 PlotState parentState, 360 PlotRenderingInfo info) { 361 362 if (info != null) { 364 info.setPlotArea(area); 365 } 366 367 RectangleInsets insets = getInsets(); 369 insets.trim(area); 370 371 AxisSpace space = calculateAxisSpace(g2, area); 372 Rectangle2D dataArea = space.shrink(area, null); 373 375 setFixedDomainAxisSpaceForSubplots(space); 377 378 ValueAxis axis = getRangeAxis(); 380 RectangleEdge edge = getRangeAxisEdge(); 381 double cursor = RectangleEdge.coordinate(dataArea, edge); 382 AxisState axisState = axis.draw(g2, cursor, area, dataArea, edge, info); 383 384 if (parentState == null) { 385 parentState = new PlotState(); 386 } 387 parentState.getSharedAxisStates().put(axis, axisState); 388 389 for (int i = 0; i < this.subplots.size(); i++) { 391 XYPlot plot = (XYPlot) this.subplots.get(i); 392 PlotRenderingInfo subplotInfo = null; 393 if (info != null) { 394 subplotInfo = new PlotRenderingInfo(info.getOwner()); 395 info.addSubplotInfo(subplotInfo); 396 } 397 plot.draw( 398 g2, this.subplotAreas[i], anchor, parentState, subplotInfo 399 ); 400 } 401 402 if (info != null) { 403 info.setDataArea(dataArea); 404 } 405 406 } 407 408 413 public LegendItemCollection getLegendItems() { 414 LegendItemCollection result = getFixedLegendItems(); 415 if (result == null) { 416 result = new LegendItemCollection(); 417 418 if (this.subplots != null) { 419 Iterator iterator = this.subplots.iterator(); 420 while (iterator.hasNext()) { 421 XYPlot plot = (XYPlot) iterator.next(); 422 LegendItemCollection more = plot.getLegendItems(); 423 result.addAll(more); 424 } 425 } 426 } 427 return result; 428 } 429 430 437 public void zoomDomainAxes(double factor, PlotRenderingInfo info, 438 Point2D source) { 439 XYPlot subplot = findSubplot(info, source); 440 if (subplot != null) { 441 subplot.zoomDomainAxes(factor, info, source); 442 } 443 } 444 445 453 public void zoomDomainAxes(double lowerPercent, double upperPercent, 454 PlotRenderingInfo info, Point2D source) { 455 XYPlot subplot = findSubplot(info, source); 456 if (subplot != null) { 457 subplot.zoomDomainAxes(lowerPercent, upperPercent, info, source); 458 } 459 } 460 461 470 public XYPlot findSubplot(PlotRenderingInfo info, Point2D source) { 471 XYPlot result = null; 472 int subplotIndex = info.getSubplotIndex(source); 473 if (subplotIndex >= 0) { 474 result = (XYPlot) this.subplots.get(subplotIndex); 475 } 476 return result; 477 } 478 479 488 public void setRenderer(XYItemRenderer renderer) { 489 490 super.setRenderer(renderer); 494 Iterator iterator = this.subplots.iterator(); 495 while (iterator.hasNext()) { 496 XYPlot plot = (XYPlot) iterator.next(); 497 plot.setRenderer(renderer); 498 } 499 500 } 501 502 507 public void setOrientation(PlotOrientation orientation) { 508 509 super.setOrientation(orientation); 510 511 Iterator iterator = this.subplots.iterator(); 512 while (iterator.hasNext()) { 513 XYPlot plot = (XYPlot) iterator.next(); 514 plot.setOrientation(orientation); 515 } 516 517 } 518 519 527 public Range getDataRange(ValueAxis axis) { 528 529 Range result = null; 530 if (this.subplots != null) { 531 Iterator iterator = this.subplots.iterator(); 532 while (iterator.hasNext()) { 533 XYPlot subplot = (XYPlot) iterator.next(); 534 result = Range.combine(result, subplot.getDataRange(axis)); 535 } 536 } 537 return result; 538 539 } 540 541 547 protected void setFixedDomainAxisSpaceForSubplots(AxisSpace space) { 548 549 Iterator iterator = this.subplots.iterator(); 550 while (iterator.hasNext()) { 551 XYPlot plot = (XYPlot) iterator.next(); 552 plot.setFixedDomainAxisSpace(space); 553 } 554 555 } 556 557 564 public void handleClick(int x, int y, PlotRenderingInfo info) { 565 566 Rectangle2D dataArea = info.getDataArea(); 567 if (dataArea.contains(x, y)) { 568 for (int i = 0; i < this.subplots.size(); i++) { 569 XYPlot subplot = (XYPlot) this.subplots.get(i); 570 PlotRenderingInfo subplotInfo = info.getSubplotInfo(i); 571 subplot.handleClick(x, y, subplotInfo); 572 } 573 } 574 575 } 576 577 583 public void plotChanged(PlotChangeEvent event) { 584 notifyListeners(event); 585 } 586 587 594 public boolean equals(Object obj) { 595 596 if (obj == this) { 597 return true; 598 } 599 600 if (!(obj instanceof CombinedRangeXYPlot)) { 601 return false; 602 } 603 if (!super.equals(obj)) { 604 return false; 605 } 606 CombinedRangeXYPlot that = (CombinedRangeXYPlot) obj; 607 if (!ObjectUtilities.equal(this.subplots, that.subplots)) { 608 return false; 609 } 610 if (this.totalWeight != that.totalWeight) { 611 return false; 612 } 613 if (this.gap != that.gap) { 614 return false; 615 } 616 return true; 617 } 618 619 627 public Object clone() throws CloneNotSupportedException { 628 629 CombinedRangeXYPlot result = (CombinedRangeXYPlot) super.clone(); 630 result.subplots = (List ) ObjectUtilities.deepClone(this.subplots); 631 for (Iterator it = result.subplots.iterator(); it.hasNext();) { 632 Plot child = (Plot) it.next(); 633 child.setParent(result); 634 } 635 636 ValueAxis rangeAxis = result.getRangeAxis(); 639 if (rangeAxis != null) { 640 rangeAxis.configure(); 641 } 642 643 return result; 644 } 645 646 } 647 | Popular Tags |