1 54 55 package org.jfree.chart.plot; 56 57 import java.awt.Graphics2D ; 58 import java.awt.geom.Point2D ; 59 import java.awt.geom.Rectangle2D ; 60 import java.io.Serializable ; 61 import java.util.Collections ; 62 import java.util.Iterator ; 63 import java.util.List ; 64 65 import org.jfree.chart.LegendItemCollection; 66 import org.jfree.chart.axis.AxisSpace; 67 import org.jfree.chart.axis.AxisState; 68 import org.jfree.chart.axis.CategoryAxis; 69 import org.jfree.chart.event.PlotChangeEvent; 70 import org.jfree.chart.event.PlotChangeListener; 71 import org.jfree.ui.RectangleEdge; 72 import org.jfree.ui.RectangleInsets; 73 import org.jfree.util.ObjectUtilities; 74 import org.jfree.util.PublicCloneable; 75 76 79 public class CombinedDomainCategoryPlot extends CategoryPlot 80 implements Zoomable, 81 Cloneable , PublicCloneable, 82 Serializable , 83 PlotChangeListener { 84 85 86 private static final long serialVersionUID = 8207194522653701572L; 87 88 89 private List subplots; 90 91 92 private int totalWeight; 93 94 95 private double gap; 96 97 98 private transient Rectangle2D [] subplotAreas; 99 101 104 public CombinedDomainCategoryPlot() { 105 this(new CategoryAxis()); 106 } 107 108 114 public CombinedDomainCategoryPlot(CategoryAxis domainAxis) { 115 super(null, domainAxis, null, null); 116 this.subplots = new java.util.ArrayList (); 117 this.totalWeight = 0; 118 this.gap = 5.0; 119 } 120 121 126 public double getGap() { 127 return this.gap; 128 } 129 130 136 public void setGap(double gap) { 137 this.gap = gap; 138 notifyListeners(new PlotChangeEvent(this)); 139 } 140 141 147 public void add(CategoryPlot subplot) { 148 add(subplot, 1); 149 } 150 151 158 public void add(CategoryPlot subplot, int weight) { 159 if (subplot == null) { 160 throw new IllegalArgumentException ("Null 'subplot' argument."); 161 } 162 if (weight < 1) { 163 throw new IllegalArgumentException ("Require weight >= 1."); 164 } 165 subplot.setParent(this); 166 subplot.setWeight(weight); 167 subplot.setInsets(new RectangleInsets(0.0, 0.0, 0.0, 0.0)); 168 subplot.setDomainAxis(null); 169 subplot.setOrientation(getOrientation()); 170 subplot.addChangeListener(this); 171 this.subplots.add(subplot); 172 this.totalWeight += weight; 173 CategoryAxis axis = getDomainAxis(); 174 if (axis != null) { 175 axis.configure(); 176 } 177 notifyListeners(new PlotChangeEvent(this)); 178 } 179 180 188 public void remove(CategoryPlot subplot) { 189 if (subplot == null) { 190 throw new IllegalArgumentException ("Null 'subplot' argument."); 191 } 192 int position = -1; 193 int size = this.subplots.size(); 194 int i = 0; 195 while (position == -1 && i < size) { 196 if (this.subplots.get(i) == subplot) { 197 position = i; 198 } 199 i++; 200 } 201 if (position != -1) { 202 this.subplots.remove(position); 203 subplot.setParent(null); 204 subplot.removeChangeListener(this); 205 this.totalWeight -= subplot.getWeight(); 206 207 CategoryAxis domain = getDomainAxis(); 208 if (domain != null) { 209 domain.configure(); 210 } 211 notifyListeners(new PlotChangeEvent(this)); 212 } 213 } 214 215 220 public List getSubplots() { 221 return Collections.unmodifiableList(this.subplots); 222 } 223 224 233 public CategoryPlot findSubplot(PlotRenderingInfo info, Point2D source) { 234 CategoryPlot result = null; 235 int subplotIndex = info.getSubplotIndex(source); 236 if (subplotIndex >= 0) { 237 result = (CategoryPlot) this.subplots.get(subplotIndex); 238 } 239 return result; 240 } 241 242 249 public void zoomRangeAxes(double factor, PlotRenderingInfo info, 250 Point2D source) { 251 CategoryPlot subplot = findSubplot(info, source); 252 if (subplot != null) { 253 subplot.zoomRangeAxes(factor, info, source); 254 } 255 } 256 257 265 public void zoomRangeAxes(double lowerPercent, double upperPercent, 266 PlotRenderingInfo info, Point2D source) { 267 CategoryPlot subplot = findSubplot(info, source); 268 if (subplot != null) { 269 subplot.zoomRangeAxes(lowerPercent, upperPercent, info, source); 270 } 271 } 272 273 281 protected AxisSpace calculateAxisSpace(Graphics2D g2, 282 Rectangle2D plotArea) { 283 284 AxisSpace space = new AxisSpace(); 285 PlotOrientation orientation = getOrientation(); 286 287 AxisSpace fixed = getFixedDomainAxisSpace(); 289 if (fixed != null) { 290 if (orientation == PlotOrientation.HORIZONTAL) { 291 space.setLeft(fixed.getLeft()); 292 space.setRight(fixed.getRight()); 293 } 294 else if (orientation == PlotOrientation.VERTICAL) { 295 space.setTop(fixed.getTop()); 296 space.setBottom(fixed.getBottom()); 297 } 298 } 299 else { 300 CategoryAxis categoryAxis = getDomainAxis(); 301 RectangleEdge categoryEdge = Plot.resolveDomainAxisLocation( 302 getDomainAxisLocation(), orientation 303 ); 304 if (categoryAxis != null) { 305 space = categoryAxis.reserveSpace( 306 g2, this, plotArea, categoryEdge, space 307 ); 308 } 309 else { 310 if (getDrawSharedDomainAxis()) { 311 space = getDomainAxis().reserveSpace( 312 g2, this, plotArea, categoryEdge, space 313 ); 314 } 315 } 316 } 317 318 Rectangle2D adjustedPlotArea = space.shrink(plotArea, null); 319 320 int n = this.subplots.size(); 322 this.subplotAreas = new Rectangle2D [n]; 323 double x = adjustedPlotArea.getX(); 324 double y = adjustedPlotArea.getY(); 325 double usableSize = 0.0; 326 if (orientation == PlotOrientation.HORIZONTAL) { 327 usableSize = adjustedPlotArea.getWidth() - this.gap * (n - 1); 328 } 329 else if (orientation == PlotOrientation.VERTICAL) { 330 usableSize = adjustedPlotArea.getHeight() - this.gap * (n - 1); 331 } 332 333 for (int i = 0; i < n; i++) { 334 CategoryPlot plot = (CategoryPlot) this.subplots.get(i); 335 336 if (orientation == PlotOrientation.HORIZONTAL) { 338 double w = usableSize * plot.getWeight() / this.totalWeight; 339 this.subplotAreas[i] = new Rectangle2D.Double ( 340 x, y, w, adjustedPlotArea.getHeight() 341 ); 342 x = x + w + this.gap; 343 } 344 else if (orientation == PlotOrientation.VERTICAL) { 345 double h = usableSize * plot.getWeight() / this.totalWeight; 346 this.subplotAreas[i] = new Rectangle2D.Double ( 347 x, y, adjustedPlotArea.getWidth(), h 348 ); 349 y = y + h + this.gap; 350 } 351 352 AxisSpace subSpace = plot.calculateRangeAxisSpace( 353 g2, this.subplotAreas[i], null 354 ); 355 space.ensureAtLeast(subSpace); 356 357 } 358 359 return space; 360 } 361 362 375 public void draw(Graphics2D g2, 376 Rectangle2D area, 377 Point2D anchor, 378 PlotState parentState, 379 PlotRenderingInfo info) { 380 381 if (info != null) { 383 info.setPlotArea(area); 384 } 385 386 RectangleInsets insets = getInsets(); 388 area.setRect( 389 area.getX() + insets.getLeft(), 390 area.getY() + insets.getTop(), 391 area.getWidth() - insets.getLeft() - insets.getRight(), 392 area.getHeight() - insets.getTop() - insets.getBottom() 393 ); 394 395 396 setFixedRangeAxisSpaceForSubplots(null); 398 AxisSpace space = calculateAxisSpace(g2, area); 399 Rectangle2D dataArea = space.shrink(area, null); 400 401 setFixedRangeAxisSpaceForSubplots(space); 403 404 CategoryAxis axis = getDomainAxis(); 406 RectangleEdge domainEdge = getDomainAxisEdge(); 407 double cursor = RectangleEdge.coordinate(dataArea, domainEdge); 408 AxisState axisState = axis.draw( 409 g2, cursor, area, dataArea, domainEdge, info 410 ); 411 if (parentState == null) { 412 parentState = new PlotState(); 413 } 414 parentState.getSharedAxisStates().put(axis, axisState); 415 416 for (int i = 0; i < this.subplots.size(); i++) { 418 CategoryPlot plot = (CategoryPlot) this.subplots.get(i); 419 PlotRenderingInfo subplotInfo = null; 420 if (info != null) { 421 subplotInfo = new PlotRenderingInfo(info.getOwner()); 422 info.addSubplotInfo(subplotInfo); 423 } 424 plot.draw(g2, this.subplotAreas[i], null, parentState, subplotInfo); 425 } 426 427 if (info != null) { 428 info.setDataArea(dataArea); 429 } 430 431 } 432 433 439 protected void setFixedRangeAxisSpaceForSubplots(AxisSpace space) { 440 441 Iterator iterator = this.subplots.iterator(); 442 while (iterator.hasNext()) { 443 CategoryPlot plot = (CategoryPlot) iterator.next(); 444 plot.setFixedRangeAxisSpace(space); 445 } 446 447 } 448 449 454 public void setOrientation(PlotOrientation orientation) { 455 456 super.setOrientation(orientation); 457 458 Iterator iterator = this.subplots.iterator(); 459 while (iterator.hasNext()) { 460 CategoryPlot plot = (CategoryPlot) iterator.next(); 461 plot.setOrientation(orientation); 462 } 463 464 } 465 466 471 public LegendItemCollection getLegendItems() { 472 LegendItemCollection result = getFixedLegendItems(); 473 if (result == null) { 474 result = new LegendItemCollection(); 475 if (this.subplots != null) { 476 Iterator iterator = this.subplots.iterator(); 477 while (iterator.hasNext()) { 478 CategoryPlot plot = (CategoryPlot) iterator.next(); 479 LegendItemCollection more = plot.getLegendItems(); 480 result.addAll(more); 481 } 482 } 483 } 484 return result; 485 } 486 487 493 public List getCategories() { 494 495 List result = new java.util.ArrayList (); 496 497 if (this.subplots != null) { 498 Iterator iterator = this.subplots.iterator(); 499 while (iterator.hasNext()) { 500 CategoryPlot plot = (CategoryPlot) iterator.next(); 501 List more = plot.getCategories(); 502 Iterator moreIterator = more.iterator(); 503 while (moreIterator.hasNext()) { 504 Comparable category = (Comparable ) moreIterator.next(); 505 if (!result.contains(category)) { 506 result.add(category); 507 } 508 } 509 } 510 } 511 512 return Collections.unmodifiableList(result); 513 } 514 515 523 public void handleClick(int x, int y, PlotRenderingInfo info) { 524 525 Rectangle2D dataArea = info.getDataArea(); 526 if (dataArea.contains(x, y)) { 527 for (int i = 0; i < this.subplots.size(); i++) { 528 CategoryPlot subplot = (CategoryPlot) this.subplots.get(i); 529 PlotRenderingInfo subplotInfo = info.getSubplotInfo(i); 530 subplot.handleClick(x, y, subplotInfo); 531 } 532 } 533 534 } 535 536 542 public void plotChanged(PlotChangeEvent event) { 543 notifyListeners(event); 544 } 545 546 553 public boolean equals(Object obj) { 554 if (obj == this) { 555 return true; 556 } 557 if (!(obj instanceof CombinedDomainCategoryPlot)) { 558 return false; 559 } 560 if (!super.equals(obj)) { 561 return false; 562 } 563 CombinedDomainCategoryPlot plot = (CombinedDomainCategoryPlot) obj; 564 if (!ObjectUtilities.equal(this.subplots, plot.subplots)) { 565 return false; 566 } 567 if (this.totalWeight != plot.totalWeight) { 568 return false; 569 } 570 if (this.gap != plot.gap) { 571 return false; 572 } 573 return true; 574 } 575 576 584 public Object clone() throws CloneNotSupportedException { 585 586 CombinedDomainCategoryPlot result 587 = (CombinedDomainCategoryPlot) super.clone(); 588 result.subplots = (List ) ObjectUtilities.deepClone(this.subplots); 589 for (Iterator it = result.subplots.iterator(); it.hasNext();) { 590 Plot child = (Plot) it.next(); 591 child.setParent(result); 592 } 593 return result; 594 595 } 596 597 } 598 | Popular Tags |