diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/date/DateChart03.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/date/DateChart03.java index 74351cfac9e056101ef1197966c8bd61a4967f12..cf9160b8530cb084900fd778e1c868e6f8f2b982 100644 --- a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/date/DateChart03.java +++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/date/DateChart03.java @@ -61,8 +61,8 @@ public class DateChart03 implements ExampleChart { } catch (ParseException e) { e.printStackTrace(); } - System.out.println(date.getTime()); - System.out.println(date.toString()); + // System.out.println(date.getTime()); + // System.out.println(date.toString()); xData.add(date); yData.add(Math.random() * i); } diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart03.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart03.java index da94fc7a1c8fe32ba5c9c18b2d9fa6a6b331fc59..2a336a12cf9a173b33b5452f58fe6f3ff6a602e1 100644 --- a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart03.java +++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart03.java @@ -97,7 +97,7 @@ public class LineChart03 implements ExampleChart { chart.getStyleManager().setAxisTitleFont(new Font(Font.SANS_SERIF, Font.ITALIC, 18)); chart.getStyleManager().setAxisTickLabelsFont(new Font(Font.SERIF, Font.PLAIN, 11)); chart.getStyleManager().setDatePattern("dd-MMM"); - chart.getStyleManager().setNormalDecimalPattern("#0.000"); + chart.getStyleManager().setDecimalPattern("#0.000"); chart.getStyleManager().setLocale(Locale.GERMAN); Series series = chart.addSeries("Fake Data", xData, yData); diff --git a/xchart/src/main/java/com/xeiam/xchart/StyleManager.java b/xchart/src/main/java/com/xeiam/xchart/StyleManager.java index 8d20a5c6390e292a12a02a470b80c21d1b2e8906..07984c8efa14c7c6c3b8b240244451ad9aa7d8a5 100644 --- a/xchart/src/main/java/com/xeiam/xchart/StyleManager.java +++ b/xchart/src/main/java/com/xeiam/xchart/StyleManager.java @@ -141,8 +141,7 @@ public class StyleManager { private String datePattern; private Locale locale; private TimeZone timezone; - private String normalDecimalPattern; - private String scientificDecimalPattern; + private String decimalPattern; /** * Constructor @@ -227,8 +226,7 @@ public class StyleManager { datePattern = null; // if not null, this override pattern will be used locale = Locale.getDefault(); timezone = TimeZone.getDefault(); - normalDecimalPattern = "#.####"; - scientificDecimalPattern = "0.##E0"; + decimalPattern = null; } /** @@ -1099,28 +1097,14 @@ public class StyleManager { * * @param pattern - the pattern describing the decimal format */ - public void setNormalDecimalPattern(String normalDecimalPattern) { + public void setDecimalPattern(String normalDecimalPattern) { - this.normalDecimalPattern = normalDecimalPattern; + this.decimalPattern = normalDecimalPattern; } - public String getNormalDecimalPattern() { + public String getDecimalPattern() { - return normalDecimalPattern; + return decimalPattern; } - /** - * Set the scientific notation formatter for all tick labels - * - * @param pattern - the pattern describing the scientific notation format - */ - public void setScientificDecimalPattern(String scientificDecimalPattern) { - - this.scientificDecimalPattern = scientificDecimalPattern; - } - - public String getScientificDecimalPattern() { - - return scientificDecimalPattern; - } } diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickBarChartCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickBarChartCalculator.java index 9ece25998cc694f4b56eb1eee7c40aafc10b30ce..fa02636631695697c3a141cbd3f01394065b0c3b 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickBarChartCalculator.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickBarChartCalculator.java @@ -108,6 +108,8 @@ public class AxisTickBarChartCalculator extends AxisTickCalculator { NumberFormatter numberFormatter = null; DateFormatter dateFormatter = null; + String pattern = numberFormatter.getFormatPattern(minValue, maxValue); + if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Number) { numberFormatter = new NumberFormatter(styleManager); } @@ -118,7 +120,7 @@ public class AxisTickBarChartCalculator extends AxisTickCalculator { for (Object category : categories) { if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Number) { - tickLabels.add(numberFormatter.formatNumber((Double) category)); + tickLabels.add(numberFormatter.formatNumber((Double) category, pattern)); } else if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Date) { long span = (long) Math.abs(maxValue - minValue); // in data space @@ -139,6 +141,8 @@ public class AxisTickBarChartCalculator extends AxisTickCalculator { NumberFormatter numberFormatter = null; DateFormatter dateFormatter = null; + String pattern = numberFormatter.getFormatPattern(minValue, maxValue); + if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Number) { numberFormatter = new NumberFormatter(styleManager); } @@ -149,7 +153,7 @@ public class AxisTickBarChartCalculator extends AxisTickCalculator { for (double tickPosition = firstPosition; tickPosition <= maxValue; tickPosition = tickPosition + gridStep) { if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Number) { - tickLabels.add(numberFormatter.formatNumber(tickPosition)); + tickLabels.add(numberFormatter.formatNumber(tickPosition, pattern)); } else if (chartPainter.getAxisPair().getXAxis().getAxisType() == AxisType.Date) { long span = (long) Math.abs(maxValue - minValue); // in data space diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickLogarithmicCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickLogarithmicCalculator.java index 5fc5279a841b8f8053b0fc1845a93fcf99ef0382..c06cc803af91a3b6918c51eabcc63150aafe7a80 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickLogarithmicCalculator.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickLogarithmicCalculator.java @@ -46,9 +46,11 @@ public class AxisTickLogarithmicCalculator extends AxisTickCalculator { private void calculate() { + String pattern = numberFormatter.getFormatPattern(minValue, maxValue); + // a check if all axis data are the exact same values if (minValue == maxValue) { - tickLabels.add(numberFormatter.formatNumber(maxValue)); + tickLabels.add(numberFormatter.formatNumber(maxValue, pattern)); tickLocations.add(workingSpace / 2.0); return; } @@ -111,7 +113,7 @@ public class AxisTickLogarithmicCalculator extends AxisTickCalculator { // only add labels for the decades if (Math.abs(Math.log10(j) % 1) < 0.00000001) { - tickLabels.add(numberFormatter.formatNumber(j)); + tickLabels.add(numberFormatter.formatNumber(j, pattern)); } else { tickLabels.add(null); diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickNumericalCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickNumericalCalculator.java index 6a5d3f15585732d39123fe952f7142b3894f150e..2b4672b45c322edb4df852d14b9d1511037cd04b 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickNumericalCalculator.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTickNumericalCalculator.java @@ -48,9 +48,11 @@ public class AxisTickNumericalCalculator extends AxisTickCalculator { private void calculate() { + String pattern = numberFormatter.getFormatPattern(minValue, maxValue); + // a check if all axis data are the exact same values if (minValue == maxValue) { - tickLabels.add(numberFormatter.formatNumber(maxValue)); + tickLabels.add(numberFormatter.formatNumber(maxValue, pattern)); tickLocations.add(workingSpace / 2.0); return; } @@ -65,9 +67,9 @@ public class AxisTickNumericalCalculator extends AxisTickCalculator { BigDecimal firstPosition = BigDecimal.valueOf(getFirstPosition(gridStep.doubleValue())); // generate all tickLabels and tickLocations from the first to last position - for (BigDecimal tickPosition = firstPosition; tickPosition.compareTo(BigDecimal.valueOf(maxValue + gridStep.doubleValue() * 0.8)) <= 0; tickPosition = tickPosition.add(gridStep)) { + for (BigDecimal tickPosition = firstPosition; tickPosition.compareTo(BigDecimal.valueOf(maxValue + gridStep.doubleValue() * 0.2)) <= 0; tickPosition = tickPosition.add(gridStep)) { - tickLabels.add(numberFormatter.formatNumber(tickPosition.doubleValue())); + tickLabels.add(numberFormatter.formatNumber(tickPosition.doubleValue(), pattern)); // here we convert tickPosition finally to plot space, i.e. pixels double tickLabelPosition = margin + ((tickPosition.doubleValue() - minValue) / (maxValue - minValue) * tickSpace); tickLocations.add(tickLabelPosition); diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/DateFormatter.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/DateFormatter.java index db0dd73b601a5f8bb2a6879522bd91bc596cf3af..50bbb0d1d56eafa0ddc2126860b9f87e32685154 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/DateFormatter.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/DateFormatter.java @@ -88,6 +88,7 @@ public class DateFormatter { String datePattern; if (styleManager.getDatePattern() == null) { + // intelligently set date pattern if none is given if (timeUnit == MILLIS_SCALE) { datePattern = "ss.SSS"; diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/NumberFormatter.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/NumberFormatter.java index 7387214e9551d02e5b4ce1e143a7c9c3984fa4e1..087de22c89d798f26a05031a08eccac7116264e6 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/NumberFormatter.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/NumberFormatter.java @@ -35,32 +35,79 @@ public class NumberFormatter { this.styleManager = styleManager; } - /** - * Format a number value, if the override patterns are null, it uses defaults - * - * @param value - * @return - */ - public String formatNumber(double value) { + public String getFormatPattern(double min, double max) { - NumberFormat numberFormat = NumberFormat.getNumberInstance(styleManager.getLocale()); + System.out.println("min: " + min); + System.out.println("max: " + max); - double absoluteValue = Math.abs(value); + double difference = max - min; + int placeOfDifference = (int) Math.floor(Math.log(difference) / Math.log(10)) + 1; + int placeOfSmallest = (int) Math.floor(Math.log(Math.min(Math.abs(min), Math.abs(max))) / Math.log(10)) + 1; - if (absoluteValue < 10000.000001 && absoluteValue > .0009999999 || value == 0) { - - DecimalFormat normalFormat = (DecimalFormat) numberFormat; - normalFormat.applyPattern(styleManager.getNormalDecimalPattern()); - return normalFormat.format(value); + System.out.println("difference: " + difference); + System.out.println("placeOfDifference: " + placeOfDifference); + System.out.println("placeOfSmallest: " + placeOfSmallest); + if (placeOfDifference <= 4 && placeOfDifference >= -4) { + System.out.println("getNormalDecimalPattern"); + return getNormalDecimalPattern(placeOfSmallest, placeOfDifference); } else { + System.out.println("getScientificDecimalPattern"); + return getScientificDecimalPattern(placeOfSmallest, placeOfDifference); + } + } + + private String getNormalDecimalPattern(int placeOfMin, int placeOfDifference) { + + int maxNumPlaces = 15; + StringBuilder sb = new StringBuilder(); + for (int i = maxNumPlaces - 1; i >= -1 * maxNumPlaces; i--) { + + if (i < placeOfMin && i >= placeOfDifference - 2) { + sb.append("0"); + } + else { + sb.append("#"); + } + if (i % 3 == 0 && i > 0) { + sb.append(","); + } + if (i == 0) { + sb.append("."); + } + } + System.out.println(sb.toString()); + return sb.toString(); + } - DecimalFormat scientificFormat = (DecimalFormat) numberFormat; - scientificFormat.applyPattern(styleManager.getScientificDecimalPattern()); - return scientificFormat.format(value); + private String getScientificDecimalPattern(int placeOfMin, int placeOfDifference) { + StringBuilder sb = new StringBuilder(); + for (int i = placeOfMin; i >= 0; i--) { + sb.append("0"); + if (i == placeOfDifference) { + sb.append("."); + } } + sb.append("E0"); + System.out.println(sb.toString()); + return sb.toString(); + } + + /** + * Format a number value, if the override patterns are null, it uses defaults + * + * @param value + * @return + */ + public String formatNumber(double value, String pattern) { + + NumberFormat numberFormat = NumberFormat.getNumberInstance(styleManager.getLocale()); + + DecimalFormat normalFormat = (DecimalFormat) numberFormat; + normalFormat.applyPattern(styleManager.getDecimalPattern() == null ? pattern : styleManager.getDecimalPattern()); + return normalFormat.format(value); } } diff --git a/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest.java b/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest.java index 91397cfd0dd32c0f790072988d52f3fd36e1c5a6..bec784749e90d2b1387f99343f49046b4863753f 100644 --- a/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest.java +++ b/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest.java @@ -44,10 +44,10 @@ public class NumberFormatterTest { assertThat(stringValue, equalTo("1")); stringValue = numberFormatter.formatNumber(1000); - assertThat(stringValue, equalTo("1000")); + assertThat(stringValue, equalTo("1,000")); stringValue = numberFormatter.formatNumber(9999); - assertThat(stringValue, equalTo("9999")); + assertThat(stringValue, equalTo("9,999")); stringValue = numberFormatter.formatNumber(20000); assertThat(stringValue, equalTo("2E4")); @@ -84,10 +84,13 @@ public class NumberFormatterTest { stringValue = numberFormatter.formatNumber(0.01); assertThat(stringValue, equalTo("0,01")); + stringValue = numberFormatter.formatNumber(10000); + assertThat(stringValue, equalTo("10.000")); + stringValue = numberFormatter.formatNumber(200.23); assertThat(stringValue, equalTo("200,23")); - styleManager.setNormalDecimalPattern("#.#"); + styleManager.setDecimalPattern("#.#"); stringValue = numberFormatter.formatNumber(200.23); assertThat(stringValue, equalTo("200,2")); diff --git a/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest2.java b/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest2.java new file mode 100644 index 0000000000000000000000000000000000000000..0f6853aa20951b5de95d9afbc34e52fdbf7800d9 --- /dev/null +++ b/xchart/src/test/java/com/xeiam/xchart/NumberFormatterTest2.java @@ -0,0 +1,41 @@ +/** + * Copyright 2011 - 2014 Xeiam LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.xeiam.xchart; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.Test; + +import com.xeiam.xchart.internal.chartpart.NumberFormatter; + +/** + * @author timmolter + */ +public class NumberFormatterTest2 { + + @Test + public void testNumberFormatting() { + + StyleManager styleManager = new StyleManager(); + NumberFormatter numberFormatter = new NumberFormatter(styleManager); + + String pattern = numberFormatter.getFormatPattern(1000000, 1000010); + System.out.println(pattern); + assertThat(pattern, equalTo("00000.00E0")); + } + +}