1 55 56 package org.jfree.chart.plot; 57 58 import java.awt.Graphics2D ; 59 import java.awt.geom.Point2D ; 60 import java.awt.geom.Rectangle2D ; 61 import java.io.IOException ; 62 import java.io.ObjectInputStream ; 63 import java.io.Serializable ; 64 import java.util.Collections ; 65 import java.util.Iterator ; 66 import java.util.List ; 67 68 import org.jfree.chart.LegendItemCollection; 69 import org.jfree.chart.axis.AxisSpace; 70 import org.jfree.chart.axis.AxisState; 71 import org.jfree.chart.axis.NumberAxis; 72 import org.jfree.chart.axis.ValueAxis; 73 import org.jfree.chart.event.PlotChangeEvent; 74 import org.jfree.chart.event.PlotChangeListener; 75 import org.jfree.data.Range; 76 import org.jfree.ui.RectangleEdge; 77 import org.jfree.ui.RectangleInsets; 78 import org.jfree.util.ObjectUtilities; 79 import org.jfree.util.PublicCloneable; 80 81 84 public class CombinedRangeCategoryPlot extends CategoryPlot 85 implements Zoomable, 86 Cloneable , PublicCloneable, 87 Serializable , 88 PlotChangeListener { 89 90 91 private static final long serialVersionUID = 7260210007554504515L; 92 93 94 private List subplots; 95 96 97 private int totalWeight; 98 99 100 private double gap; 101 102 103 private transient Rectangle2D [] subplotArea; 105 108 public CombinedRangeCategoryPlot() { 109 this(new NumberAxis()); 110 } 111 112 117 public CombinedRangeCategoryPlot(ValueAxis rangeAxis) { 118 super(null, null, rangeAxis, null); 119 this.subplots = new java.util.ArrayList (); 120 this.totalWeight = 0; 121 this.gap = 5.0; 122 } 123 124 129 public double getGap() { 130 return this.gap; 131 } 132 133 139 public void setGap(double gap) { 140 this.gap = gap; 141 notifyListeners(new PlotChangeEvent(this)); 142 } 143 144 150 public void add(CategoryPlot subplot) { 151 add(subplot, 1); 153 } 154 155 162 public void add(CategoryPlot subplot, int weight) { 163 if (subplot == null) { 164 throw new IllegalArgumentException ("Null 'subplot' argument."); 165 } 166 if (weight <= 0) { 167 throw new IllegalArgumentException ("Require weight >= 1."); 168 } 169 subplot.setParent(this); 171 subplot.setWeight(weight); 172 subplot.setInsets(new RectangleInsets(0.0, 0.0, 0.0, 0.0)); 173 subplot.setRangeAxis(null); 174 subplot.setOrientation(getOrientation()); 175 subplot.addChangeListener(this); 176 this.subplots.add(subplot); 177 this.totalWeight += weight; 178 179 ValueAxis axis = getRangeAxis(); 181 if (axis != null) { 182 axis.configure(); 183 } 184 notifyListeners(new PlotChangeEvent(this)); 185 } 186 187 192 public void remove(CategoryPlot subplot) { 193 if (subplot == null) { 194 throw new IllegalArgumentException (" Null 'subplot' argument."); 195 } 196 int position = -1; 197 int size = this.subplots.size(); 198 int i = 0; 199 while (position == -1 && i < size) { 200 if (this.subplots.get(i) == subplot) { 201 position = i; 202 } 203 i++; 204 } 205 if (position != -1) { 206 this.subplots.remove(position); 207 subplot.setParent(null); 208 subplot.removeChangeListener(this); 209 this.totalWeight -= subplot.getWeight(); 210 211 ValueAxis range = getRangeAxis(); 212 if (range != null) { 213 range.configure(); 214 } 215 216 ValueAxis range2 = getRangeAxis(1); 217 if (range2 != null) { 218 range2.configure(); 219 } 220 notifyListeners(new PlotChangeEvent(this)); 221 } 222 } 223 224 229 public List getSubplots() { 230 return Collections.unmodifiableList(this.subplots); 231 } 232 233 241 protected AxisSpace calculateAxisSpace(Graphics2D g2, 242 Rectangle2D plotArea) { 243 244 AxisSpace space = new AxisSpace(); 245 PlotOrientation orientation = getOrientation(); 246 247 AxisSpace fixed = getFixedRangeAxisSpace(); 249 if (fixed != null) { 250 if (orientation == PlotOrientation.VERTICAL) { 251 space.setLeft(fixed.getLeft()); 252 space.setRight(fixed.getRight()); 253 } 254 else if (orientation == PlotOrientation.HORIZONTAL) { 255 space.setTop(fixed.getTop()); 256 space.setBottom(fixed.getBottom()); 257 } 258 } 259 else { 260 ValueAxis valueAxis = getRangeAxis(); 261 RectangleEdge valueEdge = Plot.resolveRangeAxisLocation( 262 getRangeAxisLocation(), orientation 263 ); 264 if (valueAxis != null) { 265 space = valueAxis.reserveSpace( 266 g2, this, plotArea, valueEdge, space 267 ); 268 } 269 } 270 271 Rectangle2D adjustedPlotArea = space.shrink(plotArea, null); 272 int n = this.subplots.size(); 274 275 this.subplotArea = new Rectangle2D [n]; 278 double x = adjustedPlotArea.getX(); 279 double y = adjustedPlotArea.getY(); 280 double usableSize = 0.0; 281 if (orientation == PlotOrientation.VERTICAL) { 282 usableSize = adjustedPlotArea.getWidth() - this.gap * (n - 1); 283 } 284 else if (orientation == PlotOrientation.HORIZONTAL) { 285 usableSize = adjustedPlotArea.getHeight() - this.gap * (n - 1); 286 } 287 288 for (int i = 0; i < n; i++) { 289 CategoryPlot plot = (CategoryPlot) this.subplots.get(i); 290 291 if (orientation == PlotOrientation.VERTICAL) { 293 double w = usableSize * plot.getWeight() / this.totalWeight; 294 this.subplotArea[i] = new Rectangle2D.Double ( 295 x, y, w, adjustedPlotArea.getHeight() 296 ); 297 x = x + w + this.gap; 298 } 299 else if (orientation == PlotOrientation.HORIZONTAL) { 300 double h = usableSize * plot.getWeight() / this.totalWeight; 301 this.subplotArea[i] = new Rectangle2D.Double ( 302 x, y, adjustedPlotArea.getWidth(), h 303 ); 304 y = y + h + this.gap; 305 } 306 307 AxisSpace subSpace = plot.calculateDomainAxisSpace( 308 g2, this.subplotArea[i], null 309 ); 310 space.ensureAtLeast(subSpace); 311 312 } 313 314 return space; 315 } 316 317 330 public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor, 331 PlotState parentState, 332 PlotRenderingInfo info) { 333 334 if (info != null) { 336 info.setPlotArea(area); 337 } 338 339 RectangleInsets insets = getInsets(); 341 insets.trim(area); 342 343 AxisSpace space = calculateAxisSpace(g2, area); 345 Rectangle2D dataArea = space.shrink(area, null); 346 347 setFixedDomainAxisSpaceForSubplots(space); 349 350 ValueAxis axis = getRangeAxis(); 352 RectangleEdge rangeEdge = getRangeAxisEdge(); 353 double cursor = RectangleEdge.coordinate(dataArea, rangeEdge); 354 AxisState state = axis.draw( 355 g2, cursor, area, dataArea, rangeEdge, info 356 ); 357 if (parentState == null) { 358 parentState = new PlotState(); 359 } 360 parentState.getSharedAxisStates().put(axis, state); 361 362 for (int i = 0; i < this.subplots.size(); i++) { 364 CategoryPlot plot = (CategoryPlot) this.subplots.get(i); 365 PlotRenderingInfo subplotInfo = null; 366 if (info != null) { 367 subplotInfo = new PlotRenderingInfo(info.getOwner()); 368 info.addSubplotInfo(subplotInfo); 369 } 370 plot.draw(g2, this.subplotArea[i], null, parentState, subplotInfo); 371 } 372 373 if (info != null) { 374 info.setDataArea(dataArea); 375 } 376 377 } 378 379 384 public void setOrientation(PlotOrientation orientation) { 385 386 super.setOrientation(orientation); 387 388 Iterator iterator = this.subplots.iterator(); 389 while (iterator.hasNext()) { 390 CategoryPlot plot = (CategoryPlot) iterator.next(); 391 plot.setOrientation(orientation); 392 } 393 394 } 395 396 404 public Range getDataRange(ValueAxis axis) { 405 406 Range result = null; 407 if (this.subplots != null) { 408 Iterator iterator = this.subplots.iterator(); 409 while (iterator.hasNext()) { 410 CategoryPlot subplot = (CategoryPlot) iterator.next(); 411 result = Range.combine(result, subplot.getDataRange(axis)); 412 } 413 } 414 return result; 415 416 } 417 418 423 public LegendItemCollection getLegendItems() { 424 LegendItemCollection result = getFixedLegendItems(); 425 if (result == null) { 426 result = new LegendItemCollection(); 427 if (this.subplots != null) { 428 Iterator iterator = this.subplots.iterator(); 429 while (iterator.hasNext()) { 430 CategoryPlot plot = (CategoryPlot) iterator.next(); 431 LegendItemCollection more = plot.getLegendItems(); 432 result.addAll(more); 433 } 434 } 435 } 436 return result; 437 } 438 439 445 protected void setFixedDomainAxisSpaceForSubplots(AxisSpace space) { 446 447 Iterator iterator = this.subplots.iterator(); 448 while (iterator.hasNext()) { 449 CategoryPlot plot = (CategoryPlot) iterator.next(); 450 plot.setFixedDomainAxisSpace(space); 451 } 452 453 } 454 455 463 public void handleClick(int x, int y, PlotRenderingInfo info) { 464 465 Rectangle2D dataArea = info.getDataArea(); 466 if (dataArea.contains(x, y)) { 467 for (int i = 0; i < this.subplots.size(); i++) { 468 CategoryPlot subplot = (CategoryPlot) this.subplots.get(i); 469 PlotRenderingInfo subplotInfo = info.getSubplotInfo(i); 470 subplot.handleClick(x, y, subplotInfo); 471 } 472 } 473 474 } 475 476 482 public void plotChanged(PlotChangeEvent event) { 483 notifyListeners(event); 484 } 485 486 493 public boolean equals(Object obj) { 494 if (obj == this) { 495 return true; 496 } 497 if (!(obj instanceof CombinedRangeCategoryPlot)) { 498 return false; 499 } 500 if (!super.equals(obj)) { 501 return false; 502 } 503 CombinedRangeCategoryPlot that = (CombinedRangeCategoryPlot) obj; 504 if (!ObjectUtilities.equal(this.subplots, that.subplots)) { 505 return false; 506 } 507 if (this.totalWeight != that.totalWeight) { 508 return false; 509 } 510 if (this.gap != that.gap) { 511 return false; 512 } 513 return true; 514 } 515 516 524 public Object clone() throws CloneNotSupportedException { 525 CombinedRangeCategoryPlot result 526 = (CombinedRangeCategoryPlot) super.clone(); 527 result.subplots = (List ) ObjectUtilities.deepClone(this.subplots); 528 for (Iterator it = result.subplots.iterator(); it.hasNext();) { 529 Plot child = (Plot) it.next(); 530 child.setParent(result); 531 } 532 533 ValueAxis rangeAxis = result.getRangeAxis(); 536 if (rangeAxis != null) { 537 rangeAxis.configure(); 538 } 539 540 return result; 541 } 542 543 551 private void readObject(ObjectInputStream stream) 552 throws IOException , ClassNotFoundException { 553 554 stream.defaultReadObject(); 555 556 ValueAxis rangeAxis = getRangeAxis(); 559 if (rangeAxis != null) { 560 rangeAxis.configure(); 561 } 562 563 } 564 565 } 566 | Popular Tags |