| 1 87 88 package org.jfree.chart.axis; 89 90 import java.awt.Font ; 91 import java.awt.FontMetrics ; 92 import java.awt.Graphics2D ; 93 import java.awt.font.FontRenderContext ; 94 import java.awt.font.LineMetrics ; 95 import java.awt.geom.Rectangle2D ; 96 import java.io.Serializable ; 97 import java.text.DecimalFormat ; 98 import java.text.NumberFormat ; 99 import java.util.List ; 100 import java.util.Locale ; 101 102 import org.jfree.chart.event.AxisChangeEvent; 103 import org.jfree.chart.plot.Plot; 104 import org.jfree.chart.plot.PlotRenderingInfo; 105 import org.jfree.chart.plot.ValueAxisPlot; 106 import org.jfree.data.Range; 107 import org.jfree.data.RangeType; 108 import org.jfree.ui.RectangleEdge; 109 import org.jfree.ui.RectangleInsets; 110 import org.jfree.ui.TextAnchor; 111 import org.jfree.util.ObjectUtilities; 112 113 125 public class NumberAxis extends ValueAxis implements Cloneable , Serializable { 126 127 128 private static final long serialVersionUID = 2805933088476185789L; 129 130 131 public static final boolean DEFAULT_AUTO_RANGE_INCLUDES_ZERO = true; 132 133 134 public static final boolean DEFAULT_AUTO_RANGE_STICKY_ZERO = true; 135 136 137 public static final NumberTickUnit 138 DEFAULT_TICK_UNIT = new NumberTickUnit(1.0, new DecimalFormat ("0")); 139 140 141 public static final boolean DEFAULT_VERTICAL_TICK_LABELS = false; 142 143 147 private RangeType rangeType; 148 149 154 private boolean autoRangeIncludesZero; 155 156 161 private boolean autoRangeStickyZero; 162 163 164 private NumberTickUnit tickUnit; 165 166 167 private NumberFormat numberFormatOverride; 168 169 170 private MarkerAxisBand markerBand; 171 172 175 public NumberAxis() { 176 this(null); 177 } 178 179 184 public NumberAxis(String label) { 185 super(label, NumberAxis.createStandardTickUnits()); 186 this.rangeType = RangeType.FULL; 187 this.autoRangeIncludesZero = DEFAULT_AUTO_RANGE_INCLUDES_ZERO; 188 this.autoRangeStickyZero = DEFAULT_AUTO_RANGE_STICKY_ZERO; 189 this.tickUnit = DEFAULT_TICK_UNIT; 190 this.numberFormatOverride = null; 191 this.markerBand = null; 192 } 193 194 199 public RangeType getRangeType() { 200 return this.rangeType; 201 } 202 203 208 public void setRangeType(RangeType rangeType) { 209 if (rangeType == null) { 210 throw new IllegalArgumentException ("Null 'rangeType' argument."); 211 } 212 this.rangeType = rangeType; 213 notifyListeners(new AxisChangeEvent(this)); 214 } 215 216 222 public boolean getAutoRangeIncludesZero() { 223 return this.autoRangeIncludesZero; 224 } 225 226 237 public void setAutoRangeIncludesZero(boolean flag) { 238 if (this.autoRangeIncludesZero != flag) { 239 this.autoRangeIncludesZero = flag; 240 if (isAutoRange()) { 241 autoAdjustRange(); 242 } 243 notifyListeners(new AxisChangeEvent(this)); 244 } 245 } 246 247 253 public boolean getAutoRangeStickyZero() { 254 return this.autoRangeStickyZero; 255 } 256 257 263 public void setAutoRangeStickyZero(boolean flag) { 264 if (this.autoRangeStickyZero != flag) { 265 this.autoRangeStickyZero = flag; 266 if (isAutoRange()) { 267 autoAdjustRange(); 268 } 269 notifyListeners(new AxisChangeEvent(this)); 270 } 271 } 272 273 278 public NumberTickUnit getTickUnit() { 279 return this.tickUnit; 280 } 281 282 291 public void setTickUnit(NumberTickUnit unit) { 292 setTickUnit(unit, true, true); 294 } 295 296 307 public void setTickUnit(NumberTickUnit unit, boolean notify, 308 boolean turnOffAutoSelect) { 309 310 if (unit == null) { 311 throw new IllegalArgumentException ("Null 'unit' argument."); 312 } 313 this.tickUnit = unit; 314 if (turnOffAutoSelect) { 315 setAutoTickUnitSelection(false, false); 316 } 317 if (notify) { 318 notifyListeners(new AxisChangeEvent(this)); 319 } 320 321 } 322 323 329 public NumberFormat getNumberFormatOverride() { 330 return this.numberFormatOverride; 331 } 332 333 339 public void setNumberFormatOverride(NumberFormat formatter) { 340 this.numberFormatOverride = formatter; 341 notifyListeners(new AxisChangeEvent(this)); 342 } 343 344 349 public MarkerAxisBand getMarkerBand() { 350 return this.markerBand; 351 } 352 353 361 public void setMarkerBand(MarkerAxisBand band) { 362 this.markerBand = band; 363 notifyListeners(new AxisChangeEvent(this)); 364 } 365 366 370 public void configure() { 371 if (isAutoRange()) { 372 autoAdjustRange(); 373 } 374 } 375 376 379 protected void autoAdjustRange() { 380 381 Plot plot = getPlot(); 382 if (plot == null) { 383 return; } 385 386 if (plot instanceof ValueAxisPlot) { 387 ValueAxisPlot vap = (ValueAxisPlot) plot; 388 389 Range r = vap.getDataRange(this); 390 if (r == null) { 391 r = new Range(DEFAULT_LOWER_BOUND, DEFAULT_UPPER_BOUND); 392 } 393 394 double upper = r.getUpperBound(); 395 double lower = r.getLowerBound(); 396 if (this.rangeType == RangeType.POSITIVE) { 397 lower = Math.max(0.0, lower); 398 upper = Math.max(0.0, upper); 399 } 400 else if (this.rangeType == RangeType.NEGATIVE) { 401 lower = Math.min(0.0, lower); 402 upper = Math.min(0.0, upper); 403 } 404 405 if (getAutoRangeIncludesZero()) { 406 lower = Math.min(lower, 0.0); 407 upper = Math.max(upper, 0.0); 408 } 409 double range = upper - lower; 410 411 double fixedAutoRange = getFixedAutoRange(); 413 if (fixedAutoRange > 0.0) { 414 lower = upper - fixedAutoRange; 415 } 416 else { 417 double minRange = getAutoRangeMinimumSize(); 419 if (range < minRange) { 420 double expand = (minRange - range) / 2; 421 upper = upper + expand; 422 lower = lower - expand; 423 if (this.rangeType == RangeType.POSITIVE) { 424 if (lower < 0.0) { 425 upper = upper - lower; 426 lower = 0.0; 427 } 428 } 429 else if (this.rangeType == RangeType.NEGATIVE) { 430 if (upper > 0.0) { 431 lower = lower - upper; 432 upper = 0.0; 433 } 434 } 435 } 436 437 if (getAutoRangeStickyZero()) { 438 if (upper <= 0.0) { 439 upper = Math.min(0.0, upper + getUpperMargin() * range); 440 } 441 else { 442 upper = upper + getUpperMargin() * range; 443 } 444 if (lower >= 0.0) { 445 lower = Math.max(0.0, lower - getLowerMargin() * range); 446 } 447 else { 448 lower = lower - getLowerMargin() * range; 449 } 450 } 451 else { 452 upper = upper + getUpperMargin() * range; 453 lower = lower - getLowerMargin() * range; 454 } 455 } 456 457 setRange(new Range(lower, upper), false, false); 458 } 459 460 } 461 462 474 public double valueToJava2D(double value, Rectangle2D area, 475 RectangleEdge edge) { 476 477 Range range = getRange(); 478 double axisMin = range.getLowerBound(); 479 double axisMax = range.getUpperBound(); 480 481 double min = 0.0; 482 double max = 0.0; 483 if (RectangleEdge.isTopOrBottom(edge)) { 484 min = area.getX(); 485 max = area.getMaxX(); 486 } 487 else if (RectangleEdge.isLeftOrRight(edge)) { 488 max = area.getMinY(); 489 min = area.getMaxY(); 490 } 491 if (isInverted()) { 492 return max 493 - ((value - axisMin) / (axisMax - axisMin)) * (max - min); 494 } 495 else { 496 return min 497 + ((value - axisMin) / (axisMax - axisMin)) * (max - min); 498 } 499 500 } 501 502 512 public double java2DToValue(double java2DValue, Rectangle2D area, 513 RectangleEdge edge) { 514 515 Range range = getRange(); 516 double axisMin = range.getLowerBound(); 517 double axisMax = range.getUpperBound(); 518 519 double min = 0.0; 520 double max = 0.0; 521 if (RectangleEdge.isTopOrBottom(edge)) { 522 min = area.getX(); 523 max = area.getMaxX(); 524 } 525 else if (RectangleEdge.isLeftOrRight(edge)) { 526 min = area.getMaxY(); 527 max = area.getY(); 528 } 529 if (isInverted()) { 530 return axisMax 531 - (java2DValue - min) / (max - min) * (axisMax - axisMin); 532 } 533 else { 534 return axisMin 535 + (java2DValue - min) / (max - min) * (axisMax - axisMin); 536 } 537 538 } 539 540 545 protected double calculateLowestVisibleTickValue() { 546 547 double unit = getTickUnit().getSize(); 548 double index = Math.ceil(getRange().getLowerBound() / unit); 549 return index * unit; 550 551 } 552 553 558 protected double calculateHighestVisibleTickValue() { 559 560 double unit = getTickUnit().getSize(); 561 double index = Math.floor(getRange().getUpperBound() / unit); 562 return index * unit; 563 564 } 565 566 571 protected int calculateVisibleTickCount() { 572 573 double unit = getTickUnit().getSize(); 574 Range range = getRange(); 575 return (int) (Math.floor(range.getUpperBound() / unit) 576 - Math.ceil(range.getLowerBound() / unit) + 1); 577 578 } 579 580 596 public AxisState draw(Graphics2D g2, 597 double cursor, 598 Rectangle2D plotArea, 599 Rectangle2D dataArea, 600 RectangleEdge edge, 601 PlotRenderingInfo plotState) { 602 603 AxisState state = null; 604 if (!isVisible()) { 606 state = new AxisState(cursor); 607 List ticks = refreshTicks(g2, state, dataArea, edge); 610 state.setTicks(ticks); 611 return state; 612 } 613 614 state = drawTickMarksAndLabels(g2, cursor, plotArea, dataArea, edge); 616 617 625 state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state); 627 628 return state; 629 630 } 631 632 641 public static TickUnitSource createStandardTickUnits() { 642 643 TickUnits units = new TickUnits(); 644 DecimalFormat df0 = new DecimalFormat ("0.00000000"); 645 DecimalFormat df1 = new DecimalFormat ("0.0000000"); 646 DecimalFormat df2 = new DecimalFormat ("0.000000"); 647 DecimalFormat df3 = new DecimalFormat ("0.00000"); 648 DecimalFormat df4 = new DecimalFormat ("0.0000"); 649 DecimalFormat df5 = new DecimalFormat ("0.000"); 650 DecimalFormat df6 = new DecimalFormat ("0.00"); 651 DecimalFormat df7 = new DecimalFormat ("0.0"); 652 DecimalFormat df8 = new DecimalFormat ("#,##0"); 653 DecimalFormat df9 = new DecimalFormat ("#,###,##0"); 654 DecimalFormat df10 = new DecimalFormat ("#,###,###,##0"); 655 656 units.add(new NumberTickUnit(0.0000001, df1)); 659 units.add(new NumberTickUnit(0.000001, df2)); 660 units.add(new NumberTickUnit(0.00001, df3)); 661 units.add(new NumberTickUnit(0.0001, df4)); 662 units.add(new NumberTickUnit(0.001, df5)); 663 units.add(new NumberTickUnit(0.01, df6)); 664 units.add(new NumberTickUnit(0.1, df7)); 665 units.add(new NumberTickUnit(1, df8)); 666 units.add(new NumberTickUnit(10, df8)); 667 units.add(new NumberTickUnit(100, df8)); 668 units.add(new NumberTickUnit(1000, df8)); 669 units.add(new NumberTickUnit(10000, df8)); 670 units.add(new NumberTickUnit(100000, df8)); 671 units.add(new NumberTickUnit(1000000, df9)); 672 units.add(new NumberTickUnit(10000000, df9)); 673 units.add(new NumberTickUnit(100000000, df9)); 674 units.add(new NumberTickUnit(1000000000, df10)); 675 units.add(new NumberTickUnit(10000000000.0, df10)); 676 units.add(new NumberTickUnit(100000000000.0, df10)); 677 678 units.add(new NumberTickUnit(0.00000025, df0)); 679 units.add(new NumberTickUnit(0.0000025, df1)); 680 units.add(new NumberTickUnit(0.000025, df2)); 681 units.add(new NumberTickUnit(0.00025, df3)); 682 units.add(new NumberTickUnit(0.0025, df4)); 683 units.add(new NumberTickUnit(0.025, df5)); 684 units.add(new NumberTickUnit(0.25, df6)); 685 units.add(new NumberTickUnit(2.5, df7)); 686 units.add(new NumberTickUnit(25, df8)); 687 units.add(new NumberTickUnit(250, df8)); 688 units.add(new NumberTickUnit(2500, df8)); 689 units.add(new NumberTickUnit(25000, df8)); 690 units.add(new NumberTickUnit(250000, df8)); 691 units.add(new NumberTickUnit(2500000, df9)); 692 units.add(new NumberTickUnit(25000000, df9)); 693 units.add(new NumberTickUnit(250000000, df9)); 694 units.add(new NumberTickUnit(2500000000.0, df10)); 695 units.add(new NumberTickUnit(25000000000.0, df10)); 696 units.add(new NumberTickUnit(250000000000.0, df10)); 697 698 units.add(new NumberTickUnit(0.0000005, df1)); 699 units.add(new NumberTickUnit(0.000005, df2)); 700 units.add(new NumberTickUnit(0.00005, df3)); 701 units.add(new NumberTickUnit(0.0005, df4)); 702 units.add(new NumberTickUnit(0.005, df5)); 703 units.add(new NumberTickUnit(0.05, df6)); 704 units.add(new NumberTickUnit(0.5, df7)); 705 units.add(new NumberTickUnit(5L, df8)); 706 units.add(new NumberTickUnit(50L, df8)); 707 units.add(new NumberTickUnit(500L, df8)); 708 units.add(new NumberTickUnit(5000L, df8)); 709 units.add(new NumberTickUnit(50000L, df8)); 710 units.add(new NumberTickUnit(500000L, df8)); 711 units.add(new NumberTickUnit(5000000L, df9)); 712 units.add(new NumberTickUnit(50000000L, df9)); 713 units.add(new NumberTickUnit(500000000L, df9)); 714 units.add(new NumberTickUnit(5000000000L, df10)); 715 units.add(new NumberTickUnit(50000000000L, df10)); 716 units.add(new NumberTickUnit(500000000000L, df10)); 717 718 return units; 719 720 } 721 722 727 public static TickUnitSource createIntegerTickUnits() { 728 729 TickUnits units = new TickUnits(); 730 DecimalFormat df0 = new DecimalFormat ("0"); 731 DecimalFormat df1 = new DecimalFormat ("#,##0"); 732 units.add(new NumberTickUnit(1, df0)); 733 units.add(new NumberTickUnit(2, df0)); 734 units.add(new NumberTickUnit(5, df0)); 735 units.add(new NumberTickUnit(10, df0)); 736 units.add(new NumberTickUnit(20, df0)); 737 units.add(new NumberTickUnit(50, df0)); 738 units.add(new NumberTickUnit(100, df0)); 739 units.add(new NumberTickUnit(200, df0)); 740 units.add(new NumberTickUnit(500, df0)); 741 units.add(new NumberTickUnit(1000, df1)); 742 units.add(new NumberTickUnit(2000, df1)); 743 units.add(new NumberTickUnit(5000, df1)); 744 units.add(new NumberTickUnit(10000, df1)); 745 units.add(new NumberTickUnit(20000, df1)); 746 units.add(new NumberTickUnit(50000, df1)); 747 units.add(new NumberTickUnit(100000, df1)); 748 units.add(new NumberTickUnit(200000, df1)); 749 units.add(new NumberTickUnit(500000, df1)); 750 units.add(new NumberTickUnit(1000000, df1)); 751 units.add(new NumberTickUnit(2000000, df1)); 752 units.add(new NumberTickUnit(5000000, df1)); 753 units.add(new NumberTickUnit(10000000, df1)); 754 units.add(new NumberTickUnit(20000000, df1)); 755 units.add(new NumberTickUnit(50000000, df1)); 756 units.add(new NumberTickUnit(100000000, df1)); 757 units.add(new NumberTickUnit(200000000, df1)); 758 units.add(new NumberTickUnit(500000000, df1)); 759 units.add(new NumberTickUnit(1000000000, df1)); 760 units.add(new NumberTickUnit(2000000000, df1)); 761 units.add(new NumberTickUnit(5000000000.0, df1)); 762 units.add(new NumberTickUnit(10000000000.0, df1)); 763 764 return units; 765 766 } 767 768 781 public static TickUnitSource createStandardTickUnits(Locale locale) { 782 783 TickUnits units = new TickUnits(); 784 785 NumberFormat numberFormat = NumberFormat.getNumberInstance(locale); 786 787 units.add(new NumberTickUnit(0.0000001, numberFormat)); 790 units.add(new NumberTickUnit(0.000001, numberFormat)); 791 units.add(new NumberTickUnit(0.00001, numberFormat)); 792 units.add(new NumberTickUnit(0.0001, numberFormat)); 793 units.add(new NumberTickUnit(0.001, numberFormat)); 794 units.add(new NumberTickUnit(0.01, numberFormat)); 795 units.add(new NumberTickUnit(0.1, numberFormat)); 796 units.add(new NumberTickUnit(1, numberFormat)); 797 units.add(new NumberTickUnit(10, numberFormat)); 798 units.add(new NumberTickUnit(100, numberFormat)); 799 units.add(new NumberTickUnit(1000, numberFormat)); 800 units.add(new NumberTickUnit(10000, numberFormat)); 801 units.add(new NumberTickUnit(100000, numberFormat)); 802
|