1 98 99 package org.jfree.chart.axis; 100 101 import java.awt.Font ; 102 import java.awt.FontMetrics ; 103 import java.awt.Graphics2D ; 104 import java.awt.Polygon ; 105 import java.awt.Shape ; 106 import java.awt.font.LineMetrics ; 107 import java.awt.geom.AffineTransform ; 108 import java.awt.geom.Line2D ; 109 import java.awt.geom.Rectangle2D ; 110 import java.io.IOException ; 111 import java.io.ObjectInputStream ; 112 import java.io.ObjectOutputStream ; 113 import java.io.Serializable ; 114 import java.util.Iterator ; 115 import java.util.List ; 116 117 import org.jfree.chart.event.AxisChangeEvent; 118 import org.jfree.chart.plot.Plot; 119 import org.jfree.data.Range; 120 import org.jfree.io.SerialUtilities; 121 import org.jfree.text.TextUtilities; 122 import org.jfree.ui.RectangleEdge; 123 import org.jfree.ui.RectangleInsets; 124 import org.jfree.util.ObjectUtilities; 125 import org.jfree.util.PublicCloneable; 126 127 132 public abstract class ValueAxis extends Axis 133 implements Cloneable , PublicCloneable, 134 Serializable { 135 136 137 private static final long serialVersionUID = 3698345477322391456L; 138 139 140 public static final Range DEFAULT_RANGE = new Range(0.0, 1.0); 141 142 143 public static final boolean DEFAULT_AUTO_RANGE = true; 144 145 146 public static final boolean DEFAULT_INVERTED = false; 147 148 149 public static final double DEFAULT_AUTO_RANGE_MINIMUM_SIZE = 0.00000001; 150 151 152 public static final double DEFAULT_LOWER_MARGIN = 0.05; 153 154 155 public static final double DEFAULT_UPPER_MARGIN = 0.05; 156 157 158 public static final double DEFAULT_LOWER_BOUND = 0.0; 159 160 161 public static final double DEFAULT_UPPER_BOUND = 1.0; 162 163 164 public static final boolean DEFAULT_AUTO_TICK_UNIT_SELECTION = true; 165 166 167 public static final int MAXIMUM_TICK_COUNT = 500; 168 169 173 private boolean positiveArrowVisible; 174 175 179 private boolean negativeArrowVisible; 180 181 182 private transient Shape upArrow; 183 184 185 private transient Shape downArrow; 186 187 188 private transient Shape leftArrow; 189 190 191 private transient Shape rightArrow; 192 193 194 private boolean inverted; 195 196 197 private Range range; 198 199 203 private boolean autoRange; 204 205 206 private double autoRangeMinimumSize; 207 208 213 private double upperMargin; 214 215 220 private double lowerMargin; 221 222 227 private double fixedAutoRange; 228 229 233 private boolean autoTickUnitSelection; 234 235 236 private TickUnitSource standardTickUnits; 237 238 239 private int autoTickIndex; 240 241 242 private boolean verticalTickLabels; 243 244 251 protected ValueAxis(String label, TickUnitSource standardTickUnits) { 252 253 super(label); 254 255 this.positiveArrowVisible = false; 256 this.negativeArrowVisible = false; 257 258 this.range = DEFAULT_RANGE; 259 this.autoRange = DEFAULT_AUTO_RANGE; 260 261 this.inverted = DEFAULT_INVERTED; 262 this.autoRangeMinimumSize = DEFAULT_AUTO_RANGE_MINIMUM_SIZE; 263 264 this.lowerMargin = DEFAULT_LOWER_MARGIN; 265 this.upperMargin = DEFAULT_UPPER_MARGIN; 266 267 this.fixedAutoRange = 0.0; 268 269 this.autoTickUnitSelection = DEFAULT_AUTO_TICK_UNIT_SELECTION; 270 this.standardTickUnits = standardTickUnits; 271 272 Polygon p1 = new Polygon (); 273 p1.addPoint(0, 0); 274 p1.addPoint(-2, 2); 275 p1.addPoint(2, 2); 276 277 this.upArrow = p1; 278 279 Polygon p2 = new Polygon (); 280 p2.addPoint(0, 0); 281 p2.addPoint(-2, -2); 282 p2.addPoint(2, -2); 283 284 this.downArrow = p2; 285 286 Polygon p3 = new Polygon (); 287 p3.addPoint(0, 0); 288 p3.addPoint(-2, -2); 289 p3.addPoint(-2, 2); 290 291 this.rightArrow = p3; 292 293 Polygon p4 = new Polygon (); 294 p4.addPoint(0, 0); 295 p4.addPoint(2, -2); 296 p4.addPoint(2, 2); 297 298 this.leftArrow = p4; 299 300 this.verticalTickLabels = false; 301 302 } 303 304 310 public boolean isVerticalTickLabels() { 311 return this.verticalTickLabels; 312 } 313 314 322 public void setVerticalTickLabels(boolean flag) { 323 if (this.verticalTickLabels != flag) { 324 this.verticalTickLabels = flag; 325 notifyListeners(new AxisChangeEvent(this)); 326 } 327 } 328 329 335 public boolean isPositiveArrowVisible() { 336 return this.positiveArrowVisible; 337 } 338 339 346 public void setPositiveArrowVisible(boolean visible) { 347 this.positiveArrowVisible = visible; 348 notifyListeners(new AxisChangeEvent(this)); 349 } 350 351 357 public boolean isNegativeArrowVisible() { 358 return this.negativeArrowVisible; 359 } 360 361 368 public void setNegativeArrowVisible(boolean visible) { 369 this.negativeArrowVisible = visible; 370 notifyListeners(new AxisChangeEvent(this)); 371 } 372 373 379 public Shape getUpArrow() { 380 return this.upArrow; 381 } 382 383 390 public void setUpArrow(Shape arrow) { 391 if (arrow == null) { 392 throw new IllegalArgumentException ("Null 'arrow' argument."); 393 } 394 this.upArrow = arrow; 395 notifyListeners(new AxisChangeEvent(this)); 396 } 397 398 404 public Shape getDownArrow() { 405 return this.downArrow; 406 } 407 408 415 public void setDownArrow(Shape arrow) { 416 if (arrow == null) { 417 throw new IllegalArgumentException ("Null 'arrow' argument."); 418 } 419 this.downArrow = arrow; 420 notifyListeners(new AxisChangeEvent(this)); 421 } 422 423 429 public Shape getLeftArrow() { 430 return this.leftArrow; 431 } 432 433 440 public void setLeftArrow(Shape arrow) { 441 if (arrow == null) { 442 throw new IllegalArgumentException ("Null 'arrow' argument."); 443 } 444 this.leftArrow = arrow; 445 notifyListeners(new AxisChangeEvent(this)); 446 } 447 448 454 public Shape getRightArrow() { 455 return this.rightArrow; 456 } 457 458 465 public void setRightArrow(Shape arrow) { 466 if (arrow == null) { 467 throw new IllegalArgumentException ("Null 'arrow' argument."); 468 } 469 this.rightArrow = arrow; 470 notifyListeners(new AxisChangeEvent(this)); 471 } 472 473 481 protected void drawAxisLine(Graphics2D g2, double cursor, 482 Rectangle2D dataArea, RectangleEdge edge) { 483 Line2D axisLine = null; 484 if (edge == RectangleEdge.TOP) { 485 axisLine = new Line2D.Double ( 486 dataArea.getX(), cursor, dataArea.getMaxX(), cursor 487 ); 488 } 489 else if (edge == RectangleEdge.BOTTOM) { 490 axisLine = new Line2D.Double ( 491 dataArea.getX(), cursor, dataArea.getMaxX(), cursor 492 ); 493 } 494 else if (edge == RectangleEdge.LEFT) { 495 axisLine = new Line2D.Double ( 496 cursor, dataArea.getY(), cursor, dataArea.getMaxY() 497 ); 498 } 499 else if (edge == RectangleEdge.RIGHT) { 500 axisLine = new Line2D.Double ( 501 cursor, dataArea.getY(), cursor, dataArea.getMaxY() 502 ); 503 } 504 g2.setPaint(getAxisLinePaint()); 505 g2.setStroke(getAxisLineStroke()); 506 g2.draw(axisLine); 507 508 boolean drawUpOrRight = false; 509 boolean drawDownOrLeft = false; 510 if (this.positiveArrowVisible) { 511 if (this.inverted) { 512 drawDownOrLeft = true; 513 } 514 else { 515 drawUpOrRight = true; 516 } 517 } 518 if (this.negativeArrowVisible) { 519 if (this.inverted) { 520 drawUpOrRight = true; 521 } 522 else { 523 drawDownOrLeft = true; 524 } 525 } 526 if (drawUpOrRight) { 527 double x = 0.0; 528 double y = 0.0; 529 Shape arrow = null; 530 if (edge == RectangleEdge.TOP || edge == RectangleEdge.BOTTOM) { 531 x = dataArea.getMaxX(); 532 y = cursor; 533 arrow = this.rightArrow; 534 } 535 else if (edge == RectangleEdge.LEFT 536 || edge == RectangleEdge.RIGHT) { 537 x = cursor; 538 y = dataArea.getMinY(); 539 arrow = this.upArrow; 540 } 541 542 AffineTransform transformer = new AffineTransform (); 544 transformer.setToTranslation(x, y); 545 Shape shape = transformer.createTransformedShape(arrow); 546 g2.fill(shape); 547 g2.draw(shape); 548 } 549 550 if (drawDownOrLeft) { 551 double x = 0.0; 552 double y = 0.0; 553 Shape arrow = null; 554 if (edge == RectangleEdge.TOP || edge == RectangleEdge.BOTTOM) { 555 x = dataArea.getMinX(); 556 y = cursor; 557 arrow = this.leftArrow; 558 } 559 else if (edge == RectangleEdge.LEFT 560 || edge == RectangleEdge.RIGHT) { 561 x = cursor; 562 y = dataArea.getMaxY(); 563 arrow = this.downArrow; 564 } 565 566 AffineTransform transformer = new AffineTransform (); 568 transformer.setToTranslation(x, y); 569 Shape shape = transformer.createTransformedShape(arrow); 570 g2.fill(shape); 571 g2.draw(shape); 572 } 573 574 } 575 576 586 protected float[] calculateAnchorPoint(ValueTick tick, 587 double cursor, 588 Rectangle2D dataArea, 589 RectangleEdge edge) { 590 591 RectangleInsets insets = getTickLabelInsets(); 592 float[] result = new float[2]; 593 if (edge == RectangleEdge.TOP) { 594 result[0] = (float) valueToJava2D(tick.getValue(), dataArea, edge); 595 result[1] = (float) (cursor - insets.getBottom() - 2.0); 596 } 597 else if (edge == RectangleEdge.BOTTOM) { 598 result[0] = (float) valueToJava2D(tick.getValue(), dataArea, edge); 599 result[1] = (float) (cursor + insets.getTop() + 2.0); 600 } 601 else if (edge == RectangleEdge.LEFT) { 602 result[0] = (float) (cursor - insets.getLeft() - 2.0); 603 result[1] = (float) valueToJava2D(tick.getValue(), dataArea, edge); 604 } 605 else if (edge == RectangleEdge.RIGHT) { 606 result[0] = (float) (cursor + insets.getRight() + 2.0); 607 result[1] = (float) valueToJava2D(tick.getValue(), dataArea, edge); 608 } 609 return result; 610 } 611 612 623 protected AxisState drawTickMarksAndLabels(Graphics2D g2, 624 double cursor, 625 Rectangle2D plotArea, 626 Rectangle2D dataArea, 627 RectangleEdge edge) { 628 629 AxisState state = new AxisState(cursor); 630 631 if (isAxisLineVisible()) { 632 drawAxisLine(g2, cursor, dataArea, edge); 633 } 634 635 double ol = getTickMarkOutsideLength(); 636 double il = getTickMarkInsideLength(); 637 638 List ticks = refreshTicks(g2, state, dataArea, edge); 639 state.setTicks(ticks); 640 g2.setFont(getTickLabelFont()); 641 Iterator iterator = ticks.iterator(); 642 while (iterator.hasNext()) { 643 ValueTick tick = (ValueTick) iterator.next(); 644 if (isTickLabelsVisible()) { 645 g2.setPaint(getTickLabelPaint()); 646 float[] anchorPoint = calculateAnchorPoint( 647 tick, cursor, dataArea, edge 648 ); 649 TextUtilities.drawRotatedString( 650 tick.getText(), g2, 651 anchorPoint[0], anchorPoint[1], 652 tick.getTextAnchor(), 653 tick.getAngle(), 654 tick.getRotationAnchor() 655 ); 656 } 657 658 if (isTickMarksVisible()) { 659 float xx = (float) valueToJava2D( 660 tick.getValue(), dataArea, edge 661 ); 662 Line2D mark = null; 663 g2.setStroke(getTickMarkStroke()); 664 g2.setPaint(getTickMarkPaint()); 665 if (edge == RectangleEdge.LEFT) { 666 mark = new Line2D.Double (cursor - ol, xx, cursor + il, xx); 667 } 668 else if (edge == RectangleEdge.RIGHT) { 669 mark = new Line2D.Double (cursor + ol, xx, cursor - il, xx); 670 } 671 else if (edge == RectangleEdge.TOP) { 672 mark = new Line2D.Double (xx, cursor - ol, xx, cursor + il); 673 } 674 else if (edge == RectangleEdge.BOTTOM) { 675 mark = new Line2D.Double (xx, cursor + ol, xx, cursor - il); 676 } 677 g2.draw(mark); 678 } 679 } 680 681 double used = 0.0; 684 if (isTickLabelsVisible()) { 685 if (edge == RectangleEdge.LEFT) { 686 used += findMaximumTickLabelWidth( 687 ticks, g2, plotArea, isVerticalTickLabels() 688 ); 689 state.cursorLeft(used); 690 } 691 else if (edge == RectangleEdge.RIGHT) { 692 used = findMaximumTickLabelWidth( 693 ticks, g2, plotArea, isVerticalTickLabels() 694 ); 695 state.cursorRight(used); 696 } 697 else if (edge == RectangleEdge.TOP) { 698 used = findMaximumTickLabelHeight( 699 ticks, g2, plotArea, isVerticalTickLabels() 700 ); 701 state.cursorUp(used); 702 } 703 else if (edge == RectangleEdge.BOTTOM) { 704 used = findMaximumTickLabelHeight( 705 ticks, g2, plotArea, isVerticalTickLabels() 706 ); 707 state.cursorDown(used); 708 } 709 } 710 711 return state; 712 } 713 714 726 public AxisSpace reserveSpace(Graphics2D g2, Plot plot, 727 Rectangle2D plotArea, 728 RectangleEdge edge, AxisSpace space) { 729 730 if (space == null) { 732 space = new AxisSpace(); 733 } 734 735 if (!isVisible()) { 737 return space; 738 } 739 740 double dimension = getFixedDimension(); 742 if (dimension > 0.0) { 743 space.ensureAtLeast(dimension, edge); 744 } 745 746 double tickLabelHeight = 0.0; 748 double tickLabelWidth = 0.0; 749 if (isTickLabelsVisible()) { 750 g2.setFont(getTickLabelFont()); 751 List ticks = refreshTicks(g2, new AxisState(), plotArea, edge); 752 if (RectangleEdge.isTopOrBottom(edge)) { 753 tickLabelHeight = findMaximumTickLabelHeight( 754 ticks, g2, plotArea, isVerticalTickLabels() 755 ); 756 } 757 else if (RectangleEdge.isLeftOrRight(edge)) { 758 tickLabelWidth = findMaximumTickLabelWidth( 759 ticks, g2, plotArea, isVerticalTickLabels() 760 ); 761 } 762 } 763 764 Rectangle2D labelEnclosure = getLabelEnclosure(g2, edge); 766 double labelHeight = 0.0; 767 double labelWidth = 0.0; 768 if (RectangleEdge.isTopOrBottom(edge)) { 769 labelHeight = labelEnclosure.getHeight(); 770 space.add(labelHeight + tickLabelHeight, edge); 771 } 772 else if (RectangleEdge.isLeftOrRight(edge)) { 773 labelWidth = labelEnclosure.getWidth(); 774 space.add(labelWidth + tickLabelWidth, edge); 775 } 776 777 return space; 778 779 } 780 781 792 protected double findMaximumTickLabelHeight(List ticks, 793 Graphics2D g2, 794 Rectangle2D drawArea, 795 boolean vertical) { 796 797 RectangleInsets insets = getTickLabelInsets(); 798 Font font = getTickLabelFont(); 799 double maxHeight = 0.0; 800 if (vertical) { 801 FontMetrics fm = g2.getFontMetrics(font); 802 Iterator iterator = ticks.iterator(); 803 while (iterator.hasNext()) { 804 Tick tick = (Tick) iterator.next(); 805 Rectangle2D labelBounds = TextUtilities.getTextBounds( 806 tick.getText(), g2, fm 807 ); 808 if (labelBounds.getWidth() + insets.getTop() 809 + insets.getBottom() > maxHeight) { 810 maxHeight = labelBounds.getWidth() 811 + insets.getTop() + insets.getBottom(); 812 } 813 } 814 } 815 else { 816 LineMetrics metrics = font.getLineMetrics( 817 "ABCxyz", g2.getFontRenderContext() 818 ); 819 maxHeight = metrics.getHeight() 820 + insets.getTop() + insets.getBottom(); 821 } 822 return maxHeight; 823 824 } 825 826 837 protected double findMaximumTickLabelWidth(List ticks, 838 Graphics2D g2, 839 Rectangle2D drawArea, 840 boolean vertical) { 841 842 RectangleInsets insets = getTickLabelInsets(); 843 Font font = getTickLabelFont(); 844 double maxWidth = 0.0; 845 if (!vertical) { 846 FontMetrics fm = g2.getFontMetrics(font); 847 Iterator iterator = ticks.iterator(); 848 while (iterator.hasNext()) { 849 Tick tick = (Tick) iterator.next(); 850 Rectangle2D labelBounds = TextUtilities.getTextBounds( 851 tick.getText(), g2, fm 852 ); 853 if (labelBounds.getWidth() + insets.getLeft() 854 + insets.getRight() > maxWidth) { 855 maxWidth = labelBounds.getWidth() 856 + insets.getLeft() + insets.getRight(); 857 } 858 } 859 } 860 else { 861 LineMetrics metrics = font.getLineMetrics( 862 "ABCxyz", g2.getFontRenderContext() 863 ); 864 maxWidth = metrics.getHeight() 865 + insets.getTop() + insets.getBottom(); 866 } 867 return maxWidth; 868 869 } 870 871 880 public boolean isInverted() { 881 return this.inverted; 882 } 883 884 890 public void setInverted(boolean flag) { 891 892 if (this.inverted != flag) { 893 this.inverted = flag; 894 notifyListeners(new AxisChangeEvent(this)); 895 } 896 897 } 898 899 905 public boolean isAutoRange() { 906 return this.autoRange; 907 } 908 909 916 public void setAutoRange(boolean auto) { 917 setAutoRange(auto, true); 918 } 919 920 927 protected void setAutoRange(boolean auto, boolean notify) { 928 if (this.autoRange != auto) { 929 this.autoRange = auto; 930 if (this.autoRange) { 931 autoAdjustRange(); 932 } 933 if (notify) { 934 notifyListeners(new AxisChangeEvent(this)); 935 } 936 } 937 } 938 939 945 public double getAutoRangeMinimumSize() { 946 return this.autoRangeMinimumSize; 947 } 948 949 955 public void setAutoRangeMinimumSize(double size) { 956 setAutoRangeMinimumSize(size, true); 957 } 958 959 969 public void setAutoRangeMinimumSize(double size, boolean notify) { 970 971 if (size <= 0.0) { 973 throw new IllegalArgumentException ( 974 "NumberAxis.setAutoRangeMinimumSize(double): must be > 0.0."); 975 } 976 977 if (this.autoRangeMinimumSize != size) { 979 this.autoRangeMinimumSize = size; 980 if (this.autoRange) { 981 autoAdjustRange(); 982 } 983 if (notify) { 984 notifyListeners(new AxisChangeEvent(this)); 985 } 986 } 987 988 } 989 990 998 public double getLowerMargin() { 999 return this.lowerMargin; 1000 } 1001 1002 1010 public void setLowerMargin(double margin) { 1011 this.lowerMargin = margin; 1012 if (isAutoRange()) { 1013 autoAdjustRange(); 1014 } 1015 notifyListeners(new AxisChangeEvent(this)); 1016 } 1017 1018 1026 public double getUpperMargin() { 1027 return this.upperMargin; 1028 } 1029 1030 1038 public void setUpperMargin(double margin) { 1039 this.upperMargin = margin; 1040 if (isAutoRange()) { 1041 autoAdjustRange(); 1042 } 1043 notifyListeners(new AxisChangeEvent(this)); 1044 } 1045 1046 1051 public double getFixedAutoRange() { 1052 return this.fixedAutoRange; 1053 } 1054 1055 1060 public void setFixedAutoRange(double length) { 1061 1062 this.fixedAutoRange = length; 1063 notifyListeners(new AxisChangeEvent(this)); 1064 1065 } 1066 1067 1072 public double getLowerBound() { 1073 return this.range.getLowerBound(); 1074 } 1075 1076 1082 public void setLowerBound(double min) { 1083 if (this.range.getUpperBound() > min) { 1084 setRange(new Range(min, this.range.getUpperBound())); 1085 } 1086 else { 1087 setRange(new Range(min, min + 1.0)); 1088 } 1089 } 1090 1091 1096 public double getUpperBound() { 1097 return this.range.getUpperBound(); 1098 } 1099 1100 1106 public void setUpperBound(double max) { 1107 1108 if (this.range.getLowerBound() < max) { 1109 setRange(new Range(this.range.getLowerBound(), max)); 1110 } 1111 else { 1112 setRange(max - 1.0, max); 1113 } 1114 1115 } 1116 1117 1122 public Range getRange() { 1123 return this.range; 1124 } 1125 1126 1133 public void setRange(Range range) { 1134 setRange(range, true, true); 1136 } 1137 1138 1149 public void setRange(Range range, boolean turnOffAutoRange, 1150 boolean notify) { 1151 if (range == null) { 1152 throw new IllegalArgumentException ("Null 'range' argument."); 1153 } 1154 if (turnOffAutoRange) { 1155 this.autoRange = false; 1156 } 1157 this.range = range; 1158 if (notify) { 1159 notifyListeners(new AxisChangeEvent(this)); 1160 } 1161 } 1162 1163 1171 public void setRange(double lower, double upper) { 1172 setRange(new Range(lower, upper)); 1173 } 1174 1175 1182 public void setRangeWithMargins(Range range) { 1183 setRangeWithMargins(range, true, true); 1184 } 1185 1186 1199 public void setRangeWithMargins(Range range, boolean turnOffAutoRange, 1200 boolean notify) { 1201 if (range == null) { 1202 throw new IllegalArgumentException ("Null 'range' argument."); 1203 } 1204 setRange( 1205 Range.expand(range, getLowerMargin(), getUpperMargin()), 1206 turnOffAutoRange, notify 1207 ); 1208 } 1209 1210 1218 public void setRangeWithMargins(double lower, double upper) { 1219 setRangeWithMargins(new Range(lower, upper)); 1220 } 1221 1222 1229 public void setRangeAboutValue(double value, double length) { 1230 setRange(new Range(value - length / 2, value + length / 2)); 1231 } 1232 1233 1240 public boolean isAutoTickUnitSelection() { 1241 return this.autoTickUnitSelection; 1242 } 1243 1244 1251 public void setAutoTickUnitSelection(boolean flag) { 1252 setAutoTickUnitSelection(flag, true); 1253 } 1254 1255 1262 public void setAutoTickUnitSelection(boolean flag, boolean notify) { 1263 1264 if (this.autoTickUnitSelection != flag) { 1265 this.autoTickUnitSelection = flag; 1266 if (notify) { 1267 notifyListeners(new AxisChangeEvent(this)); 1268 } 1269 } 1270 } 1271 1272 1277 public TickUnitSource getStandardTickUnits() { 1278 return this.standardTickUnits; 1279 } 1280 1281 1291 public void setStandardTickUnits(TickUnitSource source) { 1292 this.standardTickUnits = source; 1293 notifyListeners(new AxisChangeEvent(this)); 1294 } 1295 1296 1308 public abstract double valueToJava2D(double value, Rectangle2D area, 1309 RectangleEdge edge); 1310 1311 1321 public double lengthToJava2D(double length, Rectangle2D area, 1322 RectangleEdge edge) { 1323 double zero = valueToJava2D(0.0, area, edge); 1324 double l = valueToJava2D(length, area, edge); 1325 return Math.abs(l - zero); 1326 } 1327 1328 1338 public abstract double java2DToValue(double java2DValue, 1339 Rectangle2D area, 1340 RectangleEdge edge); 1341 1342 1348 protected abstract void autoAdjustRange(); 1349 1350 1356 public void centerRange(double value) { 1357 1358 double central = this.range.getCentralValue(); 1359 Range adjusted = new Range( 1360 this.range.getLowerBound() + value - central, 1361 this.range.getUpperBound() + value - central 1362 ); 1363 setRange(adjusted); 1364 1365 } 1366 1367 1377 public void resizeRange(double percent) { 1378 resizeRange(percent, this.range.getCentralValue()); 1379 } 1380 1381 1392 public void resizeRange(double percent, double anchorValue) { 1393 1394 if (percent > 0.0) { 1395 double halfLength = this.range.getLength() * percent / 2; 1396 Range adjusted = new Range( 1397 anchorValue - halfLength, anchorValue + halfLength 1398 ); 1399 setRange(adjusted); 1400 } 1401 else { 1402 setAutoRange(true); 1403 } 1404 1405 } 1406 1407 1413 public void zoomRange(double lowerPercent, double upperPercent) { 1414 double start = this.range.getLowerBound(); 1415 double length = this.range.getLength(); 1416 Range adjusted = null; 1417 if (isInverted()) { 1418 adjusted = new Range(start + (length * (1 - upperPercent)), 1419 start + (length * (1 - lowerPercent))); 1420 } 1421 else { 1422 adjusted = new Range( 1423 start + length * lowerPercent, start + length * upperPercent 1424 ); 1425 } 1426 setRange(adjusted); 1427 } 1428 1429 1434 protected int getAutoTickIndex() { 1435 return this.autoTickIndex; 1436 } 1437 1438 1443 protected void setAutoTickIndex(int index) { 1444 this.autoTickIndex = index; 1445 } 1446 1447 1454 public boolean equals(Object obj) { 1455 1456 if (obj == this) { 1457 return true; 1458 } 1459 1460 if (!(obj instanceof ValueAxis)) { 1461 return false; 1462 } 1463 if (!super.equals(obj)) { 1464 return false; 1465 } 1466 ValueAxis that = (ValueAxis) obj; 1467 1468 1469 if (this.positiveArrowVisible != that.positiveArrowVisible) { 1470 return false; 1471 } 1472 if (this.negativeArrowVisible != that.negativeArrowVisible) { 1473 return false; 1474 } 1475 if (this.inverted != that.inverted) { 1476 return false; 1477 } 1478 if (!ObjectUtilities.equal(this.range, that.range)) { 1479 return false; 1480 } 1481 if (this.autoRange != that.autoRange) { 1482 return false; 1483 } 1484 if (this.autoRangeMinimumSize != that.autoRangeMinimumSize) { 1485 return false; 1486 } 1487 if (this.upperMargin != that.upperMargin) { 1488 return false; 1489 } 1490 if (this.lowerMargin != that.lowerMargin) { 1491 return false; 1492 } 1493 if (this.fixedAutoRange != that.fixedAutoRange) { 1494 return false; 1495 } 1496 if (this.autoTickUnitSelection != that.autoTickUnitSelection) { 1497 return false; 1498 } 1499 if (!ObjectUtilities.equal(this.standardTickUnits, 1500 that.standardTickUnits)) { 1501 return false; 1502 } 1503 if (this.verticalTickLabels != that.verticalTickLabels) { 1504 return false; 1505 } 1506 1507 return true; 1508 1509 } 1510 1511 1519 public Object clone() throws CloneNotSupportedException { 1520 ValueAxis clone = (ValueAxis) super.clone(); 1521 return clone; 1522 } 1523 1524 1531 private void writeObject(ObjectOutputStream stream) throws IOException { 1532 1533 stream.defaultWriteObject(); 1534 SerialUtilities.writeShape(this.upArrow, stream); 1535 SerialUtilities.writeShape(this.downArrow, stream); 1536 SerialUtilities.writeShape(this.leftArrow, stream); 1537 SerialUtilities.writeShape(this.rightArrow, stream); 1538 1539 } 1540 1541 1549 private void readObject(ObjectInputStream stream) 1550 throws IOException , ClassNotFoundException { 1551 1552 stream.defaultReadObject(); 1553 this.upArrow = SerialUtilities.readShape(stream); 1554 this.downArrow = SerialUtilities.readShape(stream); 1555 this.leftArrow = SerialUtilities.readShape(stream); 1556 this.rightArrow = SerialUtilities.readShape(stream); 1557 1558 } 1559 1560} 1561 | Popular Tags |