1:
95:
96: package ;
97:
98: import ;
99: import ;
100: import ;
101: import ;
102: import ;
103: import ;
104: import ;
105: import ;
106: import ;
107: import ;
108: import ;
109:
110: import ;
111: import ;
112: import ;
113: import ;
114: import ;
115: import ;
116: import ;
117: import ;
118: import ;
119: import ;
120:
121:
133: public class NumberAxis extends ValueAxis implements Cloneable, Serializable {
134:
135:
136: private static final long serialVersionUID = 2805933088476185789L;
137:
138:
139: public static final boolean DEFAULT_AUTO_RANGE_INCLUDES_ZERO = true;
140:
141:
142: public static final boolean DEFAULT_AUTO_RANGE_STICKY_ZERO = true;
143:
144:
145: public static final NumberTickUnit DEFAULT_TICK_UNIT = new NumberTickUnit(
146: 1.0, new DecimalFormat("0"));
147:
148:
149: public static final boolean DEFAULT_VERTICAL_TICK_LABELS = false;
150:
151:
155: private RangeType rangeType;
156:
157:
162: private boolean autoRangeIncludesZero;
163:
164:
169: private boolean autoRangeStickyZero;
170:
171:
172: private NumberTickUnit tickUnit;
173:
174:
175: private NumberFormat numberFormatOverride;
176:
177:
178: private MarkerAxisBand markerBand;
179:
180:
183: public NumberAxis() {
184: this(null);
185: }
186:
187:
192: public NumberAxis(String label) {
193: super(label, NumberAxis.createStandardTickUnits());
194: this.rangeType = RangeType.FULL;
195: this.autoRangeIncludesZero = DEFAULT_AUTO_RANGE_INCLUDES_ZERO;
196: this.autoRangeStickyZero = DEFAULT_AUTO_RANGE_STICKY_ZERO;
197: this.tickUnit = DEFAULT_TICK_UNIT;
198: this.numberFormatOverride = null;
199: this.markerBand = null;
200: }
201:
202:
209: public RangeType getRangeType() {
210: return this.rangeType;
211: }
212:
213:
220: public void setRangeType(RangeType rangeType) {
221: if (rangeType == null) {
222: throw new IllegalArgumentException("Null 'rangeType' argument.");
223: }
224: this.rangeType = rangeType;
225: notifyListeners(new AxisChangeEvent(this));
226: }
227:
228:
234: public boolean getAutoRangeIncludesZero() {
235: return this.autoRangeIncludesZero;
236: }
237:
238:
251: public void setAutoRangeIncludesZero(boolean flag) {
252: if (this.autoRangeIncludesZero != flag) {
253: this.autoRangeIncludesZero = flag;
254: if (isAutoRange()) {
255: autoAdjustRange();
256: }
257: notifyListeners(new AxisChangeEvent(this));
258: }
259: }
260:
261:
269: public boolean getAutoRangeStickyZero() {
270: return this.autoRangeStickyZero;
271: }
272:
273:
281: public void setAutoRangeStickyZero(boolean flag) {
282: if (this.autoRangeStickyZero != flag) {
283: this.autoRangeStickyZero = flag;
284: if (isAutoRange()) {
285: autoAdjustRange();
286: }
287: notifyListeners(new AxisChangeEvent(this));
288: }
289: }
290:
291:
304: public NumberTickUnit getTickUnit() {
305: return this.tickUnit;
306: }
307:
308:
320: public void setTickUnit(NumberTickUnit unit) {
321:
322: setTickUnit(unit, true, true);
323: }
324:
325:
336: public void setTickUnit(NumberTickUnit unit, boolean notify,
337: boolean turnOffAutoSelect) {
338:
339: if (unit == null) {
340: throw new IllegalArgumentException("Null 'unit' argument.");
341: }
342: this.tickUnit = unit;
343: if (turnOffAutoSelect) {
344: setAutoTickUnitSelection(false, false);
345: }
346: if (notify) {
347: notifyListeners(new AxisChangeEvent(this));
348: }
349:
350: }
351:
352:
360: public NumberFormat getNumberFormatOverride() {
361: return this.numberFormatOverride;
362: }
363:
364:
372: public void setNumberFormatOverride(NumberFormat formatter) {
373: this.numberFormatOverride = formatter;
374: notifyListeners(new AxisChangeEvent(this));
375: }
376:
377:
384: public MarkerAxisBand getMarkerBand() {
385: return this.markerBand;
386: }
387:
388:
398: public void setMarkerBand(MarkerAxisBand band) {
399: this.markerBand = band;
400: notifyListeners(new AxisChangeEvent(this));
401: }
402:
403:
407: public void configure() {
408: if (isAutoRange()) {
409: autoAdjustRange();
410: }
411: }
412:
413:
416: protected void autoAdjustRange() {
417:
418: Plot plot = getPlot();
419: if (plot == null) {
420: return;
421: }
422:
423: if (plot instanceof ValueAxisPlot) {
424: ValueAxisPlot vap = (ValueAxisPlot) plot;
425:
426: Range r = vap.getDataRange(this);
427: if (r == null) {
428: r = getDefaultAutoRange();
429: }
430:
431: double upper = r.getUpperBound();
432: double lower = r.getLowerBound();
433: if (this.rangeType == RangeType.POSITIVE) {
434: lower = Math.max(0.0, lower);
435: upper = Math.max(0.0, upper);
436: }
437: else if (this.rangeType == RangeType.NEGATIVE) {
438: lower = Math.min(0.0, lower);
439: upper = Math.min(0.0, upper);
440: }
441:
442: if (getAutoRangeIncludesZero()) {
443: lower = Math.min(lower, 0.0);
444: upper = Math.max(upper, 0.0);
445: }
446: double range = upper - lower;
447:
448:
449: double fixedAutoRange = getFixedAutoRange();
450: if (fixedAutoRange > 0.0) {
451: lower = upper - fixedAutoRange;
452: }
453: else {
454:
455: double minRange = getAutoRangeMinimumSize();
456: if (range < minRange) {
457: double expand = (minRange - range) / 2;
458: upper = upper + expand;
459: lower = lower - expand;
460: if (lower == upper) {
461: double adjust = Math.abs(lower) / 10.0;
462: lower = lower - adjust;
463: upper = upper + adjust;
464: }
465: if (this.rangeType == RangeType.POSITIVE) {
466: if (lower < 0.0) {
467: upper = upper - lower;
468: lower = 0.0;
469: }
470: }
471: else if (this.rangeType == RangeType.NEGATIVE) {
472: if (upper > 0.0) {
473: lower = lower - upper;
474: upper = 0.0;
475: }
476: }
477: }
478:
479: if (getAutoRangeStickyZero()) {
480: if (upper <= 0.0) {
481: upper = Math.min(0.0, upper + getUpperMargin() * range);
482: }
483: else {
484: upper = upper + getUpperMargin() * range;
485: }
486: if (lower >= 0.0) {
487: lower = Math.max(0.0, lower - getLowerMargin() * range);
488: }
489: else {
490: lower = lower - getLowerMargin() * range;
491: }
492: }
493: else {
494: upper = upper + getUpperMargin() * range;
495: lower = lower - getLowerMargin() * range;
496: }
497: }
498:
499: setRange(new Range(lower, upper), false, false);
500: }
501:
502: }
503:
504:
518: public double valueToJava2D(double value, Rectangle2D area,
519: RectangleEdge edge) {
520:
521: Range range = getRange();
522: double axisMin = range.getLowerBound();
523: double axisMax = range.getUpperBound();
524:
525: double min = 0.0;
526: double max = 0.0;
527: if (RectangleEdge.isTopOrBottom(edge)) {
528: min = area.getX();
529: max = area.getMaxX();
530: }
531: else if (RectangleEdge.isLeftOrRight(edge)) {
532: max = area.getMinY();
533: min = area.getMaxY();
534: }
535: if (isInverted()) {
536: return max
537: - ((value - axisMin) / (axisMax - axisMin)) * (max - min);
538: }
539: else {
540: return min
541: + ((value - axisMin) / (axisMax - axisMin)) * (max - min);
542: }
543:
544: }
545:
546:
558: public double java2DToValue(double java2DValue, Rectangle2D area,
559: RectangleEdge edge) {
560:
561: Range range = getRange();
562: double axisMin = range.getLowerBound();
563: double axisMax = range.getUpperBound();
564:
565: double min = 0.0;
566: double max = 0.0;
567: if (RectangleEdge.isTopOrBottom(edge)) {
568: min = area.getX();
569: max = area.getMaxX();
570: }
571: else if (RectangleEdge.isLeftOrRight(edge)) {
572: min = area.getMaxY();
573: max = area.getY();
574: }
575: if (isInverted()) {
576: return axisMax
577: - (java2DValue - min) / (max - min) * (axisMax - axisMin);
578: }
579: else {
580: return axisMin
581: + (java2DValue - min) / (max - min) * (axisMax - axisMin);
582: }
583:
584: }
585:
586:
593: protected double calculateLowestVisibleTickValue() {
594:
595: double unit = getTickUnit().getSize();
596: double index = Math.ceil(getRange().getLowerBound() / unit);
597: return index * unit;
598:
599: }
600:
601:
608: protected double calculateHighestVisibleTickValue() {
609:
610: double unit = getTickUnit().getSize();
611: double index = Math.floor(getRange().getUpperBound() / unit);
612: return index * unit;
613:
614: }
615:
616:
621: protected int calculateVisibleTickCount() {
622:
623: double unit = getTickUnit().getSize();
624: Range range = getRange();
625: return (int) (Math.floor(range.getUpperBound() / unit)
626: - Math.ceil(range.getLowerBound() / unit) + 1);
627:
628: }
629:
630:
646: public AxisState draw(Graphics2D g2,
647: double cursor,
648: Rectangle2D plotArea,
649: Rectangle2D dataArea,
650: RectangleEdge edge,
651: PlotRenderingInfo plotState) {
652:
653: AxisState state = null;
654:
655: if (!isVisible()) {
656: state = new AxisState(cursor);
657:
658:
659: List ticks = refreshTicks(g2, state, dataArea, edge);
660: state.setTicks(ticks);
661: return state;
662: }
663:
664:
665: state = drawTickMarksAndLabels(g2, cursor, plotArea, dataArea, edge);
666:
667:
668:
669:
670:
671:
672:
673:
674:
675:
676: state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state);
677:
678: return state;
679:
680: }
681:
682:
694: public static TickUnitSource createStandardTickUnits() {
695:
696: TickUnits units = new TickUnits();
697: DecimalFormat df0 = new DecimalFormat("0.00000000");
698: DecimalFormat df1 = new DecimalFormat("0.0000000");
699: DecimalFormat df2 = new DecimalFormat("0.000000");
700: DecimalFormat df3 = new DecimalFormat("0.00000");
701: DecimalFormat df4 = new DecimalFormat("0.0000");
702: DecimalFormat df5 = new DecimalFormat("0.000");
703: DecimalFormat df6 = new DecimalFormat("0.00");
704: DecimalFormat df7 = new DecimalFormat("0.0");
705: DecimalFormat df8 = new DecimalFormat("#,##0");
706: DecimalFormat df9 = new DecimalFormat("#,###,##0");
707: DecimalFormat df10 = new DecimalFormat("#,###,###,##0");
708:
709:
710:
711: units.add(new NumberTickUnit(0.0000001, df1));
712: units.add(new NumberTickUnit(0.000001, df2));
713: units.add(new NumberTickUnit(0.00001, df3));
714: units.add(new NumberTickUnit(0.0001, df4));
715: units.add(new NumberTickUnit(0.001, df5));
716: units.add(new NumberTickUnit(0.01, df6));
717: units.add(new NumberTickUnit(0.1, df7));
718: units.add(new NumberTickUnit(1, df8));
719: units.add(new NumberTickUnit(10, df8));
720: units.add(new NumberTickUnit(100, df8));
721: units.add(new NumberTickUnit(1000, df8));
722: units.add(new NumberTickUnit(10000, df8));
723: units.add(new NumberTickUnit(100000, df8));
724: units.add(new NumberTickUnit(1000000, df9));
725: units.add(new NumberTickUnit(10000000, df9));
726: units.add(new NumberTickUnit(100000000, df9));
727: units.add(new NumberTickUnit(1000000000, df10));
728: units.add(new NumberTickUnit(10000000000.0, df10));
729: units.add(new NumberTickUnit(100000000000.0, df10));
730:
731: units.add(new NumberTickUnit(0.00000025, df0));
732: units.add(new NumberTickUnit(0.0000025, df1));
733: units.add(new NumberTickUnit(0.000025, df2));
734: units.add(new NumberTickUnit(0.00025, df3));
735: units.add(new NumberTickUnit(0.0025, df4));
736: units.add(new NumberTickUnit(0.025, df5));
737: units.add(new NumberTickUnit(0.25, df6));
738: units.add(new NumberTickUnit(2.5, df7));
739: units.add(new NumberTickUnit(25, df8));
740: units.add(new NumberTickUnit(250, df8));
741: units.add(new NumberTickUnit(2500, df8));
742: units.add(new NumberTickUnit(25000, df8));
743: units.add(new NumberTickUnit(250000, df8));
744: units.add(new NumberTickUnit(2500000, df9));
745: units.add(new NumberTickUnit(25000000, df9));
746: units.add(new NumberTickUnit(250000000, df9));
747: units.add(new NumberTickUnit(2500000000.0, df10));
748: units.add(new NumberTickUnit(25000000000.0, df10));
749: units.add(new NumberTickUnit(250000000000.0, df10));
750:
751: units.add(new NumberTickUnit(0.0000005, df1));
752: units.add(new NumberTickUnit(0.000005, df2));
753: units.add(new NumberTickUnit(0.00005, df3));
754: units.add(new NumberTickUnit(0.0005, df4));
755: units.add(new NumberTickUnit(0.005, df5));
756: units.add(new NumberTickUnit(0.05, df6));
757: units.add(new NumberTickUnit(0.5, df7));
758: units.add(new NumberTickUnit(5L, df8));
759: units.add(new NumberTickUnit(50L, df8));
760: units.add(new NumberTickUnit(500L, df8));
761: units.add(new NumberTickUnit(5000L, df8));
762: units.add(new NumberTickUnit(50000L, df8));
763: units.add(new NumberTickUnit(500000L, df8));
764: units.add(new NumberTickUnit(5000000L, df9));
765: units.add(new NumberTickUnit(50000000L, df9));
766: units.add(new NumberTickUnit(500000000L, df9));
767: units.add(new NumberTickUnit(5000000000L, df10));
768: units.add(new NumberTickUnit(50000000000L, df10));
769: units.add(new NumberTickUnit(500000000000L, df10));
770:
771: return units;
772:
773: }
774:
775:
783: public static TickUnitSource createIntegerTickUnits() {
784:
785: TickUnits units = new TickUnits();
786: DecimalFormat df0 = new DecimalFormat("0");
787: DecimalFormat df1 = new DecimalFormat("#,##0");
788: units.add(new NumberTickUnit(1, df0));
789: units.add(new NumberTickUnit(2, df0));
790: units.add(new NumberTickUnit(5, df0));
791: units.add(new NumberTickUnit(10, df0));
792: units.add(new NumberTickUnit(20, df0));
793: units.add(new NumberTickUnit(50, df0));
794: units.add(new NumberTickUnit(100, df0));
795: units.add(new NumberTickUnit(200, df0));
796: units.add(new NumberTickUnit(500, df0));
797: units.add(new NumberTickUnit(1000, df1));
798: units.add(new NumberTickUnit(2000, df1));
799: units.add(new NumberTickUnit(5000, df1));
800: units.add(new NumberTickUnit(10000, df1));
801: units.add(new NumberTickUnit(20000, df1));
802: units.add(new NumberTickUnit(50000, df1));
803: units.add(new NumberTickUnit(100000, df1));
804: units.add(new NumberTickUnit(200000, df1));
805: units.add(new NumberTickUnit(500000, df1));
806: units.add(new NumberTickUnit(1000000, df1));
807: units.add(new NumberTickUnit(2000000, df1));
808: units.add(new NumberTickUnit(5000000, df1));
809: units.add(new NumberTickUnit(10000000, df1));
810: units.add(new NumberTickUnit(20000000, df1));
811: units.add(new NumberTickUnit(50000000, df1));
812: units.add(new NumberTickUnit(100000000, df1));
813: units.add(new NumberTickUnit(200000000, df1));
814: units.add(new NumberTickUnit(500000000, df1));
815: units.add(new NumberTickUnit(1000000000, df1));
816: units.add(new NumberTickUnit(2000000000, df1));
817: units.add(new NumberTickUnit(5000000000.0, df1));
818: units.add(new NumberTickUnit(10000000000.0, df1));
819:
820: return units;
821:
822: }
823:
824:
839: public static TickUnitSource createStandardTickUnits(Locale locale) {
840:
841: TickUnits units = new TickUnits();
842:
843: NumberFormat numberFormat = NumberFormat.getNumberInstance(locale);
844:
845:
846:
847: units.add(new NumberTickUnit(0.0000001, numberFormat));
848: units.add(new NumberTickUnit(0.000001, numberFormat));
849: units.add(new NumberTickUnit(0.00001, numberFormat));
850: units.add(new NumberTickUnit(0.0001, numberFormat));
851: units.add(new NumberTickUnit(0.001, numberFormat));
852: units.add(new NumberTickUnit(0.01, numberFormat));
853: units.add(new NumberTickUnit(0.1, numberFormat));
854: units.add(new NumberTickUnit(1, numberFormat));
855: units.add(new NumberTickUnit(10, numberFormat));
856: units.add(new NumberTickUnit(100, numberFormat));
857: units.add(new NumberTickUnit(1000, numberFormat));
858: units.add(new NumberTickUnit(10000, numberFormat));
859: units.add(new NumberTickUnit(100000, numberFormat));
860: units.add(new NumberTickUnit(1000000, numberFormat));
861: units.add(new NumberTickUnit(10000000, numberFormat));
862: units.add(new NumberTickUnit(100000000, numberFormat));
863: units.add(new NumberTickUnit(1000000000, numberFormat));
864: units.add(new NumberTickUnit(10000000000.0, numberFormat));
865:
866: units.add(new NumberTickUnit(0.00000025, numberFormat));
867: units.add(new NumberTickUnit(0.0000025, numberFormat));
868: units.add(new NumberTickUnit(0.000025, numberFormat));
869: units.add(new NumberTickUnit(0.00025, numberFormat));
870: units.add(new NumberTickUnit(0.0025, numberFormat));
871: units.add(new NumberTickUnit(0.025, numberFormat));
872: units.add(new NumberTickUnit(0.25, numberFormat));
873: units.add(new NumberTickUnit(2.5, numberFormat));
874: units.add(new NumberTickUnit(25, numberFormat));
875: units.add(new NumberTickUnit(250, numberFormat));
876: units.add(new NumberTickUnit(2500, numberFormat));
877: units.add(new NumberTickUnit(25000, numberFormat));
878: units.add(new NumberTickUnit(250000, numberFormat));
879: units.add(new NumberTickUnit(2500000, numberFormat));
880: units.add(new NumberTickUnit(25000000, numberFormat));
881: units.add(new NumberTickUnit(250000000, numberFormat));
882: units.add(new NumberTickUnit(2500000000.0, numberFormat));
883: units.add(new NumberTickUnit(25000000000.0, numberFormat));
884:
885: units.add(new NumberTickUnit(0.0000005, numberFormat));
886: units.add(new NumberTickUnit(0.000005, numberFormat));
887: units.add(new NumberTickUnit(0.00005, numberFormat));
888: units.add(new NumberTickUnit(0.0005, numberFormat));
889: units.add(new NumberTickUnit(0.005, numberFormat));
890: units.add(new NumberTickUnit(0.05, numberFormat));
891: units.add(new NumberTickUnit(0.5, numberFormat));
892: units.add(new NumberTickUnit(5L, numberFormat));
893: units.add(new NumberTickUnit(50L, numberFormat));
894: units.add(new NumberTickUnit(500L, numberFormat));
895: units.add(new NumberTickUnit(5000L, numberFormat));
896: units.add(new NumberTickUnit(50000L, numberFormat));
897: units.add(new NumberTickUnit(500000L, numberFormat));
898: units.add(new NumberTickUnit(5000000L, numberFormat));
899: units.add(new NumberTickUnit(50000000L, numberFormat));
900: units.add(new NumberTickUnit(500000000L, numberFormat));
901: units.add(new NumberTickUnit(5000000000L, numberFormat));
902: units.add(new NumberTickUnit(50000000000L, numberFormat));
903:
904: return units;
905:
906: }
907:
908:
918: public static TickUnitSource createIntegerTickUnits(Locale locale) {
919:
920: TickUnits units = new TickUnits();
921:
922: NumberFormat numberFormat = NumberFormat.getNumberInstance(locale);
923:
924: units.add(new NumberTickUnit(1, numberFormat));
925: units.add(new NumberTickUnit(2, numberFormat));
926: units.add(new NumberTickUnit(5, numberFormat));
927: units.add(new NumberTickUnit(10, numberFormat));
928: units.add(new NumberTickUnit(20, numberFormat));
929: units.add(new NumberTickUnit(50, numberFormat));
930: units.add(new NumberTickUnit(100, numberFormat));
931: units.add(new NumberTickUnit(200, numberFormat));
932: units.add(new NumberTickUnit(500, numberFormat));
933: units.add(new NumberTickUnit(1000, numberFormat));
934: units.add(new NumberTickUnit(2000, numberFormat));
935: units.add(new NumberTickUnit(5000, numberFormat));
936: units.add(new NumberTickUnit(10000, numberFormat));
937: units.add(new NumberTickUnit(20000, numberFormat));
938: units.add(new NumberTickUnit(50000, numberFormat));
939: units.add(new NumberTickUnit(100000, numberFormat));
940: units.add(new NumberTickUnit(200000, numberFormat));
941: units.add(new NumberTickUnit(500000, numberFormat));
942: units.add(new NumberTickUnit(1000000, numberFormat));
943: units.add(new NumberTickUnit(2000000, numberFormat));
944: units.add(new NumberTickUnit(5000000, numberFormat));
945: units.add(new NumberTickUnit(10000000, numberFormat));
946: units.add(new NumberTickUnit(20000000, numberFormat));
947: units.add(new NumberTickUnit(50000000, numberFormat));
948: units.add(new NumberTickUnit(100000000, numberFormat));
949: units.add(new NumberTickUnit(200000000, numberFormat));
950: units.add(new NumberTickUnit(500000000, numberFormat));
951: units.add(new NumberTickUnit(1000000000, numberFormat));
952: units.add(new NumberTickUnit(2000000000, numberFormat));
953: units.add(new NumberTickUnit(5000000000.0, numberFormat));
954: units.add(new NumberTickUnit(10000000000.0, numberFormat));
955:
956: return units;
957:
958: }
959:
960:
967: protected double estimateMaximumTickLabelHeight(Graphics2D g2) {
968:
969: RectangleInsets tickLabelInsets = getTickLabelInsets();
970: double result = tickLabelInsets.getTop() + tickLabelInsets.getBottom();
971:
972: Font tickLabelFont = getTickLabelFont();
973: FontRenderContext frc = g2.getFontRenderContext();
974: result += tickLabelFont.getLineMetrics("123", frc).getHeight();
975: return result;
976:
977: }
978:
979:
992: protected double estimateMaximumTickLabelWidth(Graphics2D g2,
993: TickUnit unit) {
994:
995: RectangleInsets tickLabelInsets = getTickLabelInsets();
996: double result = tickLabelInsets.getLeft() + tickLabelInsets.getRight();
997:
998: if (isVerticalTickLabels()) {
999:
1000:
1001: FontRenderContext frc = g2.getFontRenderContext();
1002: LineMetrics lm = getTickLabelFont().getLineMetrics("0", frc);
1003: result += lm.getHeight();
1004: }
1005: else {
1006:
1007: FontMetrics fm = g2.getFontMetrics(getTickLabelFont());
1008: Range range = getRange();
1009: double lower = range.getLowerBound();
1010: double upper = range.getUpperBound();
1011: String lowerStr = "";
1012: String upperStr = "";
1013: NumberFormat formatter = getNumberFormatOverride();
1014: if (formatter != null) {
1015: lowerStr = formatter.format(lower);
1016: upperStr = formatter.format(upper);
1017: }
1018: else {
1019: lowerStr = unit.valueToString(lower);
1020: upperStr = unit.valueToString(upper);
1021: }
1022: double w1 = fm.stringWidth(lowerStr);
1023: double w2 = fm.stringWidth(upperStr);
1024: result += Math.max(w1, w2);
1025: }
1026:
1027: return result;
1028:
1029: }
1030:
1031:
1040: protected void selectAutoTickUnit(Graphics2D g2,
1041: Rectangle2D dataArea,
1042: RectangleEdge edge) {
1043:
1044: if (RectangleEdge.isTopOrBottom(edge)) {
1045: selectHorizontalAutoTickUnit(g2, dataArea, edge);
1046: }
1047: else if (RectangleEdge.isLeftOrRight(edge)) {
1048: selectVerticalAutoTickUnit(g2, dataArea, edge);
1049: }
1050:
1051: }
1052:
1053:
1062: protected void selectHorizontalAutoTickUnit(Graphics2D g2,
1063: Rectangle2D dataArea,
1064: RectangleEdge edge) {
1065:
1066: double tickLabelWidth = estimateMaximumTickLabelWidth(
1067: g2, getTickUnit()
1068: );
1069:
1070:
1071: TickUnitSource tickUnits = getStandardTickUnits();
1072: TickUnit unit1 = tickUnits.getCeilingTickUnit(getTickUnit());
1073: double unit1Width = lengthToJava2D(unit1.getSize(), dataArea, edge);
1074:
1075:
1076: double guess = (tickLabelWidth / unit1Width) * unit1.getSize();
1077:
1078: NumberTickUnit unit2
1079: = (NumberTickUnit) tickUnits.getCeilingTickUnit(guess);
1080: double unit2Width = lengthToJava2D(unit2.getSize(), dataArea, edge);
1081:
1082: tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit2);
1083: if (tickLabelWidth > unit2Width) {
1084: unit2 = (NumberTickUnit) tickUnits.getLargerTickUnit(unit2);
1085: }
1086:
1087: setTickUnit(unit2, false, false);
1088:
1089: }
1090:
1091:
1100: protected void selectVerticalAutoTickUnit(Graphics2D g2,
1101: Rectangle2D dataArea,
1102: RectangleEdge edge) {
1103:
1104: double tickLabelHeight = estimateMaximumTickLabelHeight(g2);
1105:
1106:
1107: TickUnitSource tickUnits = getStandardTickUnits();
1108: TickUnit unit1 = tickUnits.getCeilingTickUnit(getTickUnit());
1109: double unitHeight = lengthToJava2D(unit1.getSize(), dataArea, edge);
1110:
1111:
1112: double guess = (tickLabelHeight / unitHeight) * unit1.getSize();
1113:
1114: NumberTickUnit unit2
1115: = (NumberTickUnit) tickUnits.getCeilingTickUnit(guess);
1116: double unit2Height = lengthToJava2D(unit2.getSize(), dataArea, edge);
1117:
1118: tickLabelHeight = estimateMaximumTickLabelHeight(g2);
1119: if (tickLabelHeight > unit2Height) {
1120: unit2 = (NumberTickUnit) tickUnits.getLargerTickUnit(unit2);
1121: }
1122:
1123: setTickUnit(unit2, false, false);
1124:
1125: }
1126:
1127:
1139: public List refreshTicks(Graphics2D g2,
1140: AxisState state,
1141: Rectangle2D dataArea,
1142: RectangleEdge edge) {
1143:
1144: List result = new java.util.ArrayList();
1145: if (RectangleEdge.isTopOrBottom(edge)) {
1146: result = refreshTicksHorizontal(g2, dataArea, edge);
1147: }
1148: else if (RectangleEdge.isLeftOrRight(edge)) {
1149: result = refreshTicksVertical(g2, dataArea, edge);
1150: }
1151: return result;
1152:
1153: }
1154:
1155:
1165: protected List refreshTicksHorizontal(Graphics2D g2,
1166: Rectangle2D dataArea,
1167: RectangleEdge edge) {
1168:
1169: List result = new java.util.ArrayList();
1170:
1171: Font tickLabelFont = getTickLabelFont();
1172: g2.setFont(tickLabelFont);
1173:
1174: if (isAutoTickUnitSelection()) {
1175: selectAutoTickUnit(g2, dataArea, edge);
1176: }
1177:
1178: double size = getTickUnit().getSize();
1179: int count = calculateVisibleTickCount();
1180: double lowestTickValue = calculateLowestVisibleTickValue();
1181:
1182: if (count <= ValueAxis.MAXIMUM_TICK_COUNT) {
1183: for (int i = 0; i < count; i++) {
1184: double currentTickValue = lowestTickValue + (i * size);
1185: String tickLabel;
1186: NumberFormat formatter = getNumberFormatOverride();
1187: if (formatter != null) {
1188: tickLabel = formatter.format(currentTickValue);
1189: }
1190: else {
1191: tickLabel = getTickUnit().valueToString(currentTickValue);
1192: }
1193: TextAnchor anchor = null;
1194: TextAnchor rotationAnchor = null;
1195: double angle = 0.0;
1196: if (isVerticalTickLabels()) {
1197: anchor = TextAnchor.CENTER_RIGHT;
1198: rotationAnchor = TextAnchor.CENTER_RIGHT;
1199: if (edge == RectangleEdge.TOP) {
1200: angle = Math.PI / 2.0;
1201: }
1202: else {
1203: angle = -Math.PI / 2.0;
1204: }
1205: }
1206: else {
1207: if (edge == RectangleEdge.TOP) {
1208: anchor = TextAnchor.BOTTOM_CENTER;
1209: rotationAnchor = TextAnchor.BOTTOM_CENTER;
1210: }
1211: else {
1212: anchor = TextAnchor.TOP_CENTER;
1213: rotationAnchor = TextAnchor.TOP_CENTER;
1214: }
1215: }
1216:
1217: Tick tick = new NumberTick(new Double(currentTickValue),
1218: tickLabel, anchor, rotationAnchor, angle);
1219: result.add(tick);
1220: }
1221: }
1222: return result;
1223:
1224: }
1225:
1226:
1236: protected List refreshTicksVertical(Graphics2D g2,
1237: Rectangle2D dataArea,
1238: RectangleEdge edge) {
1239:
1240: List result = new java.util.ArrayList();
1241: result.clear();
1242:
1243: Font tickLabelFont = getTickLabelFont();
1244: g2.setFont(tickLabelFont);
1245: if (isAutoTickUnitSelection()) {
1246: selectAutoTickUnit(g2, dataArea, edge);
1247: }
1248:
1249: double size = getTickUnit().getSize();
1250: int count = calculateVisibleTickCount();
1251: double lowestTickValue = calculateLowestVisibleTickValue();
1252:
1253: if (count <= ValueAxis.MAXIMUM_TICK_COUNT) {
1254: for (int i = 0; i < count; i++) {
1255: double currentTickValue = lowestTickValue + (i * size);
1256: String tickLabel;
1257: NumberFormat formatter = getNumberFormatOverride();
1258: if (formatter != null) {
1259: tickLabel = formatter.format(currentTickValue);
1260: }
1261: else {
1262: tickLabel = getTickUnit().valueToString(currentTickValue);
1263: }
1264:
1265: TextAnchor anchor = null;
1266: TextAnchor rotationAnchor = null;
1267: double angle = 0.0;
1268: if (isVerticalTickLabels()) {
1269: if (edge == RectangleEdge.LEFT) {
1270: anchor = TextAnchor.BOTTOM_CENTER;
1271: rotationAnchor = TextAnchor.BOTTOM_CENTER;
1272: angle = -Math.PI / 2.0;
1273: }
1274: else {
1275: anchor = TextAnchor.BOTTOM_CENTER;
1276: rotationAnchor = TextAnchor.BOTTOM_CENTER;
1277: angle = Math.PI / 2.0;
1278: }
1279: }
1280: else {
1281: if (edge == RectangleEdge.LEFT) {
1282: anchor = TextAnchor.CENTER_RIGHT;
1283: rotationAnchor = TextAnchor.CENTER_RIGHT;
1284: }
1285: else {
1286: anchor = TextAnchor.CENTER_LEFT;
1287: rotationAnchor = TextAnchor.CENTER_LEFT;
1288: }
1289: }
1290:
1291: Tick tick = new NumberTick(new Double(currentTickValue),
1292: tickLabel, anchor, rotationAnchor, angle);
1293: result.add(tick);
1294: }
1295: }
1296: return result;
1297:
1298: }
1299:
1300:
1308: public Object clone() throws CloneNotSupportedException {
1309: NumberAxis clone = (NumberAxis) super.clone();
1310: if (this.numberFormatOverride != null) {
1311: clone.numberFormatOverride
1312: = (NumberFormat) this.numberFormatOverride.clone();
1313: }
1314: return clone;
1315: }
1316:
1317:
1324: public boolean equals(Object obj) {
1325: if (obj == this) {
1326: return true;
1327: }
1328: if (!(obj instanceof NumberAxis)) {
1329: return false;
1330: }
1331: if (!super.equals(obj)) {
1332: return false;
1333: }
1334: NumberAxis that = (NumberAxis) obj;
1335: if (this.autoRangeIncludesZero != that.autoRangeIncludesZero) {
1336: return false;
1337: }
1338: if (this.autoRangeStickyZero != that.autoRangeStickyZero) {
1339: return false;
1340: }
1341: if (!ObjectUtilities.equal(this.tickUnit, that.tickUnit)) {
1342: return false;
1343: }
1344: if (!ObjectUtilities.equal(this.numberFormatOverride,
1345: that.numberFormatOverride)) {
1346: return false;
1347: }
1348: if (!this.rangeType.equals(that.rangeType)) {
1349: return false;
1350: }
1351: return true;
1352: }
1353:
1354:
1359: public int hashCode() {
1360: if (getLabel() != null) {
1361: return getLabel().hashCode();
1362: }
1363: else {
1364: return 0;
1365: }
1366: }
1367:
1368: }