1 81 82 package org.jfree.chart.plot; 83 84 import java.awt.Graphics2D ; 85 import java.awt.geom.Point2D ; 86 import java.awt.geom.Rectangle2D ; 87 import java.io.Serializable ; 88 import java.util.Collections ; 89 import java.util.Iterator ; 90 import java.util.List ; 91 92 import org.jfree.chart.LegendItemCollection; 93 import org.jfree.chart.axis.AxisSpace; 94 import org.jfree.chart.axis.AxisState; 95 import org.jfree.chart.axis.NumberAxis; 96 import org.jfree.chart.axis.ValueAxis; 97 import org.jfree.chart.event.PlotChangeEvent; 98 import org.jfree.chart.event.PlotChangeListener; 99 import org.jfree.chart.renderer.xy.XYItemRenderer; 100 import org.jfree.data.Range; 101 import org.jfree.ui.RectangleEdge; 102 import org.jfree.ui.RectangleInsets; 103 import org.jfree.util.ObjectUtilities; 104 import org.jfree.util.PublicCloneable; 105 106 110 public class CombinedDomainXYPlot extends XYPlot 111 implements Cloneable , PublicCloneable, 112 Serializable , 113 PlotChangeListener { 114 115 116 private static final long serialVersionUID = -7765545541261907383L; 117 118 119 private List subplots; 120 121 122 private int totalWeight = 0; 123 124 125 private double gap = 5.0; 126 127 128 private transient Rectangle2D [] subplotAreas; 129 132 135 public CombinedDomainXYPlot() { 136 this(new NumberAxis()); 137 } 138 139 145 public CombinedDomainXYPlot(ValueAxis domainAxis) { 146 147 super( 148 null, domainAxis, 150 null, null ); 153 154 this.subplots = new java.util.ArrayList (); 155 156 } 157 158 163 public String getPlotType() { 164 return "Combined_Domain_XYPlot"; 165 } 166 167 173 public void setOrientation(PlotOrientation orientation) { 174 175 super.setOrientation(orientation); 176 Iterator iterator = this.subplots.iterator(); 177 while (iterator.hasNext()) { 178 XYPlot plot = (XYPlot) iterator.next(); 179 plot.setOrientation(orientation); 180 } 181 182 } 183 184 192 public Range getDataRange(ValueAxis axis) { 193 194 Range result = null; 195 if (this.subplots != null) { 196 Iterator iterator = this.subplots.iterator(); 197 while (iterator.hasNext()) { 198 XYPlot subplot = (XYPlot) iterator.next(); 199 result = Range.combine(result, subplot.getDataRange(axis)); 200 } 201 } 202 return result; 203 204 } 205 206 211 public double getGap() { 212 return this.gap; 213 } 214 215 221 public void setGap(double gap) { 222 this.gap = gap; 223 notifyListeners(new PlotChangeEvent(this)); 224 } 225 226 234 public void add(XYPlot subplot) { 235 add(subplot, 1); 237 } 238 239 250 public void add(XYPlot subplot, int weight) { 251 252 if (subplot == null) { 253 throw new IllegalArgumentException ("Null 'subplot' argument."); 254 } 255 if (weight <= 0) { 256 throw new IllegalArgumentException ("Require weight >= 1."); 257 } 258 259 subplot.setParent(this); 261 subplot.setWeight(weight); 262 subplot.setInsets(new RectangleInsets(0.0, 0.0, 0.0, 0.0), false); 263 subplot.setDomainAxis(null); 264 subplot.addChangeListener(this); 265 this.subplots.add(subplot); 266 267 this.totalWeight += weight; 269 270 ValueAxis axis = getDomainAxis(); 271 if (axis != null) { 272 axis.configure(); 273 } 274 275 notifyListeners(new PlotChangeEvent(this)); 276 277 } 278 279 285 public void remove(XYPlot subplot) { 286 if (subplot == null) { 287 throw new IllegalArgumentException (" Null 'subplot' argument."); 288 } 289 int position = -1; 290 int size = this.subplots.size(); 291 int i = 0; 292 while (position == -1 && i < size) { 293 if (this.subplots.get(i) == subplot) { 294 position = i; 295 } 296 i++; 297 } 298 if (position != -1) { 299 this.subplots.remove(position); 300 subplot.setParent(null); 301 subplot.removeChangeListener(this); 302 this.totalWeight -= subplot.getWeight(); 303 304 ValueAxis domain = getDomainAxis(); 305 if (domain != null) { 306 domain.configure(); 307 } 308 notifyListeners(new PlotChangeEvent(this)); 309 } 310 } 311 312 317 public List getSubplots() { 318 return Collections.unmodifiableList(this.subplots); 319 } 320 321 329 protected AxisSpace calculateAxisSpace(Graphics2D g2, 330 Rectangle2D plotArea) { 331 332 AxisSpace space = new AxisSpace(); 333 PlotOrientation orientation = getOrientation(); 334 335 AxisSpace fixed = getFixedDomainAxisSpace(); 337 if (fixed != null) { 338 if (orientation == PlotOrientation.HORIZONTAL) { 339 space.setLeft(fixed.getLeft()); 340 space.setRight(fixed.getRight()); 341 } 342 else if (orientation == PlotOrientation.VERTICAL) { 343 space.setTop(fixed.getTop()); 344 space.setBottom(fixed.getBottom()); 345 } 346 } 347 else { 348 ValueAxis xAxis = getDomainAxis(); 349 RectangleEdge xEdge = Plot.resolveDomainAxisLocation( 350 getDomainAxisLocation(), orientation 351 ); 352 if (xAxis != null) { 353 space = xAxis.reserveSpace(g2, this, plotArea, xEdge, space); 354 } 355 } 356 357 Rectangle2D adjustedPlotArea = space.shrink(plotArea, null); 358 359 int n = this.subplots.size(); 361 this.subplotAreas = new Rectangle2D [n]; 362 double x = adjustedPlotArea.getX(); 363 double y = adjustedPlotArea.getY(); 364 double usableSize = 0.0; 365 if (orientation == PlotOrientation.HORIZONTAL) { 366 usableSize = adjustedPlotArea.getWidth() - this.gap * (n - 1); 367 } 368 else if (orientation == PlotOrientation.VERTICAL) { 369 usableSize = adjustedPlotArea.getHeight() - this.gap * (n - 1); 370 } 371 372 for (int i = 0; i < n; i++) { 373 XYPlot plot = (XYPlot) this.subplots.get(i); 374 375 if (orientation == PlotOrientation.HORIZONTAL) { 377 double w = usableSize * plot.getWeight() / this.totalWeight; 378 this.subplotAreas[i] = new Rectangle2D.Double ( 379 x, y, w, adjustedPlotArea.getHeight() 380 ); 381 x = x + w + this.gap; 382 } 383 else if (orientation == PlotOrientation.VERTICAL) { 384 double h = usableSize * plot.getWeight() / this.totalWeight; 385 this.subplotAreas[i] = new Rectangle2D.Double ( 386 x, y, adjustedPlotArea.getWidth(), h 387 ); 388 y = y + h + this.gap; 389 } 390 391 AxisSpace subSpace = plot.calculateRangeAxisSpace( 392 g2, this.subplotAreas[i], null 393 ); 394 space.ensureAtLeast(subSpace); 395 396 } 397 398 return space; 399 } 400 401 413 public void draw(Graphics2D g2, 414 Rectangle2D area, 415 Point2D anchor, 416 PlotState parentState, 417 PlotRenderingInfo info) { 418 419 if (info != null) { 421 info.setPlotArea(area); 422 } 423 424 RectangleInsets insets = getInsets(); 426 insets.trim(area); 427 428 AxisSpace space = calculateAxisSpace(g2, area); 429 Rectangle2D dataArea = space.shrink(area, null); 430 431 setFixedRangeAxisSpaceForSubplots(space); 433 434 ValueAxis axis = getDomainAxis(); 436 RectangleEdge edge = getDomainAxisEdge(); 437 double cursor = RectangleEdge.coordinate(dataArea, edge); 438 AxisState axisState = axis.draw(g2, cursor, area, dataArea, edge, info); 439 if (parentState == null) { 440 parentState = new PlotState(); 441 } 442 parentState.getSharedAxisStates().put(axis, axisState); 443 444 for (int i = 0; i < this.subplots.size(); i++) { 446 XYPlot plot = (XYPlot) this.subplots.get(i); 447 PlotRenderingInfo subplotInfo = null; 448 if (info != null) { 449 subplotInfo = new PlotRenderingInfo(info.getOwner()); 450 info.addSubplotInfo(subplotInfo); 451 } 452 plot.draw( 453 g2, this.subplotAreas[i], anchor, parentState, subplotInfo 454 ); 455 } 456 457 if (info != null) { 458 info.setDataArea(dataArea); 459 } 460 461 } 462 463 468 public LegendItemCollection getLegendItems() { 469 LegendItemCollection result = getFixedLegendItems(); 470 if (result == null) { 471 result = new LegendItemCollection(); 472 if (this.subplots != null) { 473 Iterator iterator = this.subplots.iterator(); 474 while (iterator.hasNext()) { 475 XYPlot plot = (XYPlot) iterator.next(); 476 LegendItemCollection more = plot.getLegendItems(); 477 result.addAll(more); 478 } 479 } 480 } 481 return result; 482 } 483 484 491 public void zoomRangeAxes(double factor, PlotRenderingInfo info, 492 Point2D source) { 493 XYPlot subplot = findSubplot(info, source); 494 if (subplot != null) { 495 subplot.zoomRangeAxes(factor, info, source); 496 } 497 } 498 499 507 public void zoomRangeAxes(double lowerPercent, double upperPercent, 508 PlotRenderingInfo info, Point2D source) { 509 XYPlot subplot = findSubplot(info, source); 510 if (subplot != null) { 511 subplot.zoomRangeAxes(lowerPercent, upperPercent, info, source); 512 } 513 } 514 515 524 public XYPlot findSubplot(PlotRenderingInfo info, Point2D source) { 525 XYPlot result = null; 526 int subplotIndex = info.getSubplotIndex(source); 527 if (subplotIndex >= 0) { 528 result = (XYPlot) this.subplots.get(subplotIndex); 529 } 530 return result; 531 } 532 533 542 public void setRenderer(XYItemRenderer renderer) { 543 544 super.setRenderer(renderer); 548 Iterator iterator = this.subplots.iterator(); 549 while (iterator.hasNext()) { 550 XYPlot plot = (XYPlot) iterator.next(); 551 plot.setRenderer(renderer); 552 } 553 554 } 555 556 562 protected void setFixedRangeAxisSpaceForSubplots(AxisSpace space) { 563 564 Iterator iterator = this.subplots.iterator(); 565 while (iterator.hasNext()) { 566 XYPlot plot = (XYPlot) iterator.next(); 567 plot.setFixedRangeAxisSpace(space); 568 } 569 570 } 571 572 579 public void handleClick(int x, int y, PlotRenderingInfo info) { 580 Rectangle2D dataArea = info.getDataArea(); 581 if (dataArea.contains(x, y)) { 582 for (int i = 0; i < this.subplots.size(); i++) { 583 XYPlot subplot = (XYPlot) this.subplots.get(i); 584 PlotRenderingInfo subplotInfo = info.getSubplotInfo(i); 585 subplot.handleClick(x, y, subplotInfo); 586 } 587 } 588 } 589 590 596 public void plotChanged(PlotChangeEvent event) { 597 notifyListeners(event); 598 } 599 600 607 public boolean equals(Object obj) { 608 609 if (obj == null) { 610 return false; 611 } 612 613 if (obj == this) { 614 return true; 615 } 616 617 if (!(obj instanceof CombinedDomainXYPlot)) { 618 return false; 619 } 620 if (!super.equals(obj)) { 621 return false; 622 } 623 624 CombinedDomainXYPlot p = (CombinedDomainXYPlot) obj; 625 if (this.totalWeight != p.totalWeight) { 626 return false; 627 } 628 if (this.gap != p.gap) { 629 return false; 630 } 631 if (!ObjectUtilities.equal(this.subplots, p.subplots)) { 632 return false; 633 } 634 635 return true; 636 } 637 638 646 public Object clone() throws CloneNotSupportedException { 647 648 CombinedDomainXYPlot result = (CombinedDomainXYPlot) super.clone(); 649 result.subplots = (List ) ObjectUtilities.deepClone(this.subplots); 650 for (Iterator it = result.subplots.iterator(); it.hasNext();) { 651 Plot child = (Plot) it.next(); 652 child.setParent(result); 653 } 654 655 ValueAxis domainAxis = result.getDomainAxis(); 658 if (domainAxis != null) { 659 domainAxis.configure(); 660 } 661 662 return result; 663 664 } 665 666 } 667 | Popular Tags |