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 units.add(new NumberTickUnit(1000000, numberFormat)); 803 units.add(new NumberTickUnit(10000000, numberFormat)); 804 units.add(new NumberTickUnit(100000000, numberFormat)); 805 units.add(new NumberTickUnit(1000000000, numberFormat)); 806 units.add(new NumberTickUnit(10000000000.0, numberFormat)); 807 808 units.add(new NumberTickUnit(0.00000025, numberFormat)); 809 units.add(new NumberTickUnit(0.0000025, numberFormat)); 810 units.add(new NumberTickUnit(0.000025, numberFormat)); 811 units.add(new NumberTickUnit(0.00025, numberFormat)); 812 units.add(new NumberTickUnit(0.0025, numberFormat)); 813 units.add(new NumberTickUnit(0.025, numberFormat)); 814 units.add(new NumberTickUnit(0.25, numberFormat)); 815 units.add(new NumberTickUnit(2.5, numberFormat)); 816 units.add(new NumberTickUnit(25, numberFormat)); 817 units.add(new NumberTickUnit(250, numberFormat)); 818 units.add(new NumberTickUnit(2500, numberFormat)); 819 units.add(new NumberTickUnit(25000, numberFormat)); 820 units.add(new NumberTickUnit(250000, numberFormat)); 821 units.add(new NumberTickUnit(2500000, numberFormat)); 822 units.add(new NumberTickUnit(25000000, numberFormat)); 823 units.add(new NumberTickUnit(250000000, numberFormat)); 824 units.add(new NumberTickUnit(2500000000.0, numberFormat)); 825 units.add(new NumberTickUnit(25000000000.0, numberFormat)); 826 827 units.add(new NumberTickUnit(0.0000005, numberFormat)); 828 units.add(new NumberTickUnit(0.000005, numberFormat)); 829 units.add(new NumberTickUnit(0.00005, numberFormat)); 830 units.add(new NumberTickUnit(0.0005, numberFormat)); 831 units.add(new NumberTickUnit(0.005, numberFormat)); 832 units.add(new NumberTickUnit(0.05, numberFormat)); 833 units.add(new NumberTickUnit(0.5, numberFormat)); 834 units.add(new NumberTickUnit(5L, numberFormat)); 835 units.add(new NumberTickUnit(50L, numberFormat)); 836 units.add(new NumberTickUnit(500L, numberFormat)); 837 units.add(new NumberTickUnit(5000L, numberFormat)); 838 units.add(new NumberTickUnit(50000L, numberFormat)); 839 units.add(new NumberTickUnit(500000L, numberFormat)); 840 units.add(new NumberTickUnit(5000000L, numberFormat)); 841 units.add(new NumberTickUnit(50000000L, numberFormat)); 842 units.add(new NumberTickUnit(500000000L, numberFormat)); 843 units.add(new NumberTickUnit(5000000000L, numberFormat)); 844 units.add(new NumberTickUnit(50000000000L, numberFormat)); 845 846 return units; 847 848 } 849 850 858 public static TickUnitSource createIntegerTickUnits(Locale locale) { 859 860 TickUnits units = new TickUnits(); 861 862 NumberFormat numberFormat = NumberFormat.getNumberInstance(locale); 863 864 units.add(new NumberTickUnit(1, numberFormat)); 865 units.add(new NumberTickUnit(2, numberFormat)); 866 units.add(new NumberTickUnit(5, numberFormat)); 867 units.add(new NumberTickUnit(10, numberFormat)); 868 units.add(new NumberTickUnit(20, numberFormat)); 869 units.add(new NumberTickUnit(50, numberFormat)); 870 units.add(new NumberTickUnit(100, numberFormat)); 871 units.add(new NumberTickUnit(200, numberFormat)); 872 units.add(new NumberTickUnit(500, numberFormat)); 873 units.add(new NumberTickUnit(1000, numberFormat)); 874 units.add(new NumberTickUnit(2000, numberFormat)); 875 units.add(new NumberTickUnit(5000, numberFormat)); 876 units.add(new NumberTickUnit(10000, numberFormat)); 877 units.add(new NumberTickUnit(20000, numberFormat)); 878 units.add(new NumberTickUnit(50000, numberFormat)); 879 units.add(new NumberTickUnit(100000, numberFormat)); 880 units.add(new NumberTickUnit(200000, numberFormat)); 881 units.add(new NumberTickUnit(500000, numberFormat)); 882 units.add(new NumberTickUnit(1000000, numberFormat)); 883 units.add(new NumberTickUnit(2000000, numberFormat)); 884 units.add(new NumberTickUnit(5000000, numberFormat)); 885 units.add(new NumberTickUnit(10000000, numberFormat)); 886 units.add(new NumberTickUnit(20000000, numberFormat)); 887 units.add(new NumberTickUnit(50000000, numberFormat)); 888 units.add(new NumberTickUnit(100000000, numberFormat)); 889 units.add(new NumberTickUnit(200000000, numberFormat)); 890 units.add(new NumberTickUnit(500000000, numberFormat)); 891 units.add(new NumberTickUnit(1000000000, numberFormat)); 892 units.add(new NumberTickUnit(2000000000, numberFormat)); 893 units.add(new NumberTickUnit(5000000000.0, numberFormat)); 894 units.add(new NumberTickUnit(10000000000.0, numberFormat)); 895 896 return units; 897 898 } 899 900 907 protected double estimateMaximumTickLabelHeight(Graphics2D g2) { 908 909 RectangleInsets tickLabelInsets = getTickLabelInsets(); 910 double result = tickLabelInsets.getTop() + tickLabelInsets.getBottom(); 911 912 Font tickLabelFont = getTickLabelFont(); 913 FontRenderContext frc = g2.getFontRenderContext(); 914 result += tickLabelFont.getLineMetrics("123", frc).getHeight(); 915 return result; 916 917 } 918 919 932 protected double estimateMaximumTickLabelWidth(Graphics2D g2, 933 TickUnit unit) { 934 935 RectangleInsets tickLabelInsets = getTickLabelInsets(); 936 double result = tickLabelInsets.getLeft() + tickLabelInsets.getRight(); 937 938 if (isVerticalTickLabels()) { 939 FontRenderContext frc = g2.getFontRenderContext(); 942 LineMetrics lm = getTickLabelFont().getLineMetrics("0", frc); 943 result += lm.getHeight(); 944 } 945 else { 946 FontMetrics fm = g2.getFontMetrics(getTickLabelFont()); 948 Range range = getRange(); 949 double lower = range.getLowerBound(); 950 double upper = range.getUpperBound(); 951 String lowerStr = unit.valueToString(lower); 952 String upperStr = unit.valueToString(upper); 953 double w1 = fm.stringWidth(lowerStr); 954 double w2 = fm.stringWidth(upperStr); 955 result += Math.max(w1, w2); 956 } 957 958 return result; 959 960 } 961 962 971 protected void selectAutoTickUnit(Graphics2D g2, 972 Rectangle2D dataArea, 973 RectangleEdge edge) { 974 975 if (RectangleEdge.isTopOrBottom(edge)) { 976 selectHorizontalAutoTickUnit(g2, dataArea, edge); 977 } 978 else if (RectangleEdge.isLeftOrRight(edge)) { 979 selectVerticalAutoTickUnit(g2, dataArea, edge); 980 } 981 982 } 983 984 993 protected void selectHorizontalAutoTickUnit(Graphics2D g2, 994 Rectangle2D dataArea, 995 RectangleEdge edge) { 996 997 double tickLabelWidth = estimateMaximumTickLabelWidth( 998 g2, getTickUnit() 999 ); 1000 1001 TickUnitSource tickUnits = getStandardTickUnits(); 1003 TickUnit unit1 = tickUnits.getCeilingTickUnit(getTickUnit()); 1004 double unit1Width = lengthToJava2D(unit1.getSize(), dataArea, edge); 1005 1006 double guess = (tickLabelWidth / unit1Width) * unit1.getSize(); 1008 1009 NumberTickUnit unit2 1010 = (NumberTickUnit) tickUnits.getCeilingTickUnit(guess); 1011 double unit2Width = lengthToJava2D(unit2.getSize(), dataArea, edge); 1012 1013 tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit2); 1014 if (tickLabelWidth > unit2Width) { 1015 unit2 = (NumberTickUnit) tickUnits.getLargerTickUnit(unit2); 1016 } 1017 1018 setTickUnit(unit2, false, false); 1019 1020 } 1021 1022 1031 protected void selectVerticalAutoTickUnit(Graphics2D g2, 1032 Rectangle2D dataArea, 1033 RectangleEdge edge) { 1034 1035 double tickLabelHeight = estimateMaximumTickLabelHeight(g2); 1036 1037 TickUnitSource tickUnits = getStandardTickUnits(); 1039 TickUnit unit1 = tickUnits.getCeilingTickUnit(getTickUnit()); 1040 double unitHeight = lengthToJava2D(unit1.getSize(), dataArea, edge); 1041 1042 double guess = (tickLabelHeight / unitHeight) * unit1.getSize(); 1044 1045 NumberTickUnit unit2 1046 = (NumberTickUnit) tickUnits.getCeilingTickUnit(guess); 1047 double unit2Height = lengthToJava2D(unit2.getSize(), dataArea, edge); 1048 1049 tickLabelHeight = estimateMaximumTickLabelHeight(g2); 1050 if (tickLabelHeight > unit2Height) { 1051 unit2 = (NumberTickUnit) tickUnits.getLargerTickUnit(unit2); 1052 } 1053 1054 setTickUnit(unit2, false, false); 1055 1056 } 1057 1058 1070 public List refreshTicks(Graphics2D g2, 1071 AxisState state, 1072 Rectangle2D dataArea, 1073 RectangleEdge edge) { 1074 1075 List result = new java.util.ArrayList (); 1076 if (RectangleEdge.isTopOrBottom(edge)) { 1077 result = refreshTicksHorizontal(g2, dataArea, edge); 1078 } 1079 else if (RectangleEdge.isLeftOrRight(edge)) { 1080 result = refreshTicksVertical(g2, dataArea, edge); 1081 } 1082 return result; 1083 1084 } 1085 1086 1096 protected List refreshTicksHorizontal(Graphics2D g2, 1097 Rectangle2D dataArea, 1098 RectangleEdge edge) { 1099 1100 List result = new java.util.ArrayList (); 1101 1102 Font tickLabelFont = getTickLabelFont(); 1103 g2.setFont(tickLabelFont); 1104 1105 if (isAutoTickUnitSelection()) { 1106 selectAutoTickUnit(g2, dataArea, edge); 1107 } 1108 1109 double size = getTickUnit().getSize(); 1110 int count = calculateVisibleTickCount(); 1111 double lowestTickValue = calculateLowestVisibleTickValue(); 1112 1113 if (count <= ValueAxis.MAXIMUM_TICK_COUNT) { 1114 for (int i = 0; i < count; i++) { 1115 double currentTickValue = lowestTickValue + (i * size); 1116 String tickLabel; 1117 NumberFormat formatter = getNumberFormatOverride(); 1118 if (formatter != null) { 1119 tickLabel = formatter.format(currentTickValue); 1120 } 1121 else { 1122 tickLabel = getTickUnit().valueToString(currentTickValue); 1123 } 1124 TextAnchor anchor = null; 1125 TextAnchor rotationAnchor = null; 1126 double angle = 0.0; 1127 if (isVerticalTickLabels()) { 1128 anchor = TextAnchor.CENTER_RIGHT; 1129 rotationAnchor = TextAnchor.CENTER_RIGHT; 1130 if (edge == RectangleEdge.TOP) { 1131 angle = Math.PI / 2.0; 1132 } 1133 else { 1134 angle = -Math.PI / 2.0; 1135 } 1136 } 1137 else { 1138 if (edge == RectangleEdge.TOP) { 1139 anchor = TextAnchor.BOTTOM_CENTER; 1140 rotationAnchor = TextAnchor.BOTTOM_CENTER; 1141 } 1142 else { 1143 anchor = TextAnchor.TOP_CENTER; 1144 rotationAnchor = TextAnchor.TOP_CENTER; 1145 } 1146 } 1147 1148 Tick tick = new NumberTick( 1149 new Double (currentTickValue), tickLabel, anchor, 1150 rotationAnchor, angle 1151 ); 1152 result.add(tick); 1153 } 1154 } 1155 return result; 1156 1157 } 1158 1159 1170 protected List refreshTicksVertical(Graphics2D g2, 1171 Rectangle2D dataArea, 1172 RectangleEdge edge) { 1173 1174 List result = new java.util.ArrayList (); 1175 result.clear(); 1176 1177 Font tickLabelFont = getTickLabelFont(); 1178 g2.setFont(tickLabelFont); 1179 if (isAutoTickUnitSelection()) { 1180 selectAutoTickUnit(g2, dataArea, edge); 1181 } 1182 1183 double size = getTickUnit().getSize(); 1184 int count = calculateVisibleTickCount(); 1185 double lowestTickValue = calculateLowestVisibleTickValue(); 1186 1187 if (count <= ValueAxis.MAXIMUM_TICK_COUNT) { 1188 for (int i = 0; i < count; i++) { 1189 double currentTickValue = lowestTickValue + (i * size); 1190 String tickLabel; 1191 NumberFormat formatter = getNumberFormatOverride(); 1192 if (formatter != null) { 1193 tickLabel = formatter.format(currentTickValue); 1194 } 1195 else { 1196 tickLabel = getTickUnit().valueToString(currentTickValue); 1197 } 1198 1199 TextAnchor anchor = null; 1200 TextAnchor rotationAnchor = null; 1201 double angle = 0.0; 1202 if (isVerticalTickLabels()) { 1203 if (edge == RectangleEdge.LEFT) { 1204 anchor = TextAnchor.BOTTOM_CENTER; 1205 rotationAnchor = TextAnchor.BOTTOM_CENTER; 1206 angle = -Math.PI / 2.0; 1207 } 1208 else { 1209 anchor = TextAnchor.BOTTOM_CENTER; 1210 rotationAnchor = TextAnchor.BOTTOM_CENTER; 1211 angle = Math.PI / 2.0; 1212 } 1213 } 1214 else { 1215 if (edge == RectangleEdge.LEFT) { 1216 anchor = TextAnchor.CENTER_RIGHT; 1217 rotationAnchor = TextAnchor.CENTER_RIGHT; 1218 } 1219 else { 1220 anchor = TextAnchor.CENTER_LEFT; 1221 rotationAnchor = TextAnchor.CENTER_LEFT; 1222 } 1223 } 1224 1225 Tick tick = new NumberTick( 1226 new Double (currentTickValue), tickLabel, anchor, 1227 rotationAnchor, angle 1228 ); 1229 result.add(tick); 1230 } 1231 } 1232 return result; 1233 1234 } 1235 1236 1244 public Object clone() throws CloneNotSupportedException { 1245 NumberAxis clone = (NumberAxis) super.clone(); 1246 if (this.numberFormatOverride != null) { 1247 clone.numberFormatOverride 1248 = (NumberFormat ) this.numberFormatOverride.clone(); 1249 } 1250 return clone; 1251 } 1252 1253 1260 public boolean equals(Object obj) { 1261 if (obj == this) { 1262 return true; 1263 } 1264 if (!(obj instanceof NumberAxis)) { 1265 return false; 1266 } 1267 if (!super.equals(obj)) { 1268 return false; 1269 } 1270 NumberAxis that = (NumberAxis) obj; 1271 if (this.autoRangeIncludesZero != that.autoRangeIncludesZero) { 1272 return false; 1273 } 1274 if (this.autoRangeStickyZero != that.autoRangeStickyZero) { 1275 return false; 1276 } 1277 if (!ObjectUtilities.equal(this.tickUnit, that.tickUnit)) { 1278 return false; 1279 } 1280 if (!ObjectUtilities.equal(this.numberFormatOverride, 1281 that.numberFormatOverride)) { 1282 return false; 1283 } 1284 return true; 1285 } 1286 1287 1292 public int hashCode() { 1293 if (getLabel() != null) { 1294 return getLabel().hashCode(); 1295 } 1296 else { 1297 return 0; 1298 } 1299 } 1300 1301} 1302 | Popular Tags |