From c92fe4cea95b44bce75dde486654fa5843f125c2 Mon Sep 17 00:00:00 2001
From: Tim Molter <tim.molter@gmail.com>
Date: Sun, 17 Feb 2013 21:54:18 +0100
Subject: [PATCH] another rearrange
---
.../com/xeiam/xchart/demo/XChartDemo.java | 4 -
.../DateChart01.java} | 27 ++--
.../xchart/demo/charts/line/LineChart09.java | 6 +-
.../AxisTickCalculator.java | 104 +++++++++----
.../DateAxisTickCalculator.java | 144 +++++++++++-------
.../axistickcalculator/DateFormatter.java | 127 ---------------
.../NumberAxisTickCalculator.java | 30 ++++
.../axistickcalculator/NumberFormatter.java | 108 -------------
.../com/xeiam/xchart/style/StyleManager.java | 91 +++++++++--
.../xeiam/xchart/unit/ValueFormatterTest.java | 71 ++++-----
10 files changed, 324 insertions(+), 388 deletions(-)
rename xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/{line/LineChart04.java => date/DateChart01.java} (73%)
delete mode 100644 xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateFormatter.java
delete mode 100644 xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/NumberFormatter.java
diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/XChartDemo.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/XChartDemo.java
index 6c15a09a..f906f95a 100644
--- a/xchart-demo/src/main/java/com/xeiam/xchart/demo/XChartDemo.java
+++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/XChartDemo.java
@@ -33,7 +33,6 @@ import com.xeiam.xchart.demo.charts.area.AreaChart01;
import com.xeiam.xchart.demo.charts.line.LineChart01;
import com.xeiam.xchart.demo.charts.line.LineChart02;
import com.xeiam.xchart.demo.charts.line.LineChart03;
-import com.xeiam.xchart.demo.charts.line.LineChart04;
import com.xeiam.xchart.demo.charts.line.LineChart05;
import com.xeiam.xchart.demo.charts.line.LineChart06;
import com.xeiam.xchart.demo.charts.line.LineChart07;
@@ -140,9 +139,6 @@ public class XChartDemo extends JPanel implements TreeSelectionListener {
chart = new DefaultMutableTreeNode(new ChartInfo("LineChart03 - Multiple curves on one Chart", new LineChart03().getChart()));
category.add(chart);
- chart = new DefaultMutableTreeNode(new ChartInfo("LineChart04 - Date Axis", new LineChart04().getChart()));
- category.add(chart);
-
chart = new DefaultMutableTreeNode(new ChartInfo("LineChart05 - Vertical and horizontal lines", new LineChart05().getChart()));
category.add(chart);
diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart04.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/date/DateChart01.java
similarity index 73%
rename from xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart04.java
rename to xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/date/DateChart01.java
index fa954642..f1234c92 100644
--- a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart04.java
+++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/date/DateChart01.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.xeiam.xchart.demo.charts.line;
+package com.xeiam.xchart.demo.charts.date;
import java.text.DateFormat;
import java.text.ParseException;
@@ -25,22 +25,15 @@ import java.util.TimeZone;
import com.xeiam.xchart.Chart;
import com.xeiam.xchart.SwingWrapper;
+import com.xeiam.xchart.demo.charts.line.ExampleChart;
import com.xeiam.xchart.style.Series;
import com.xeiam.xchart.style.StyleManager.LegendPosition;
-/**
- * Date Axis
- * <p>
- * Demonstrates the following:
- * <ul>
- * <li>Date-tyoe X Axis Data
- * <li>Placing legend inside northwest corner of plot area
- */
-public class LineChart04 implements ExampleChart {
+public class DateChart01 implements ExampleChart {
public static void main(String[] args) {
- ExampleChart exampleChart = new LineChart04();
+ ExampleChart exampleChart = new DateChart01();
Chart chart = exampleChart.getChart();
new SwingWrapper(chart).displayChart();
}
@@ -55,12 +48,12 @@ public class LineChart04 implements ExampleChart {
Collection<Date> xData = new ArrayList<Date>();
Collection<Number> yData = new ArrayList<Number>();
- DateFormat sdf = new SimpleDateFormat("yyyy.MM.dd.HH");
+ DateFormat sdf = new SimpleDateFormat("ss:S");
Date date = null;
for (int i = 1; i <= 10; i++) {
try {
- date = sdf.parse("2012.12.22." + (10 + i));
+ date = sdf.parse("31:" + (100 * i));
} catch (ParseException e) {
e.printStackTrace();
}
@@ -69,15 +62,13 @@ public class LineChart04 implements ExampleChart {
}
// Customize Chart
- chart.setChartTitle("LineChart04");
- chart.setXAxisTitle("time of day");
- chart.setYAxisTitle("gigawatts");
- chart.getStyleManager().getDateFormatter().setTimezone(TimeZone.getTimeZone("UTC"));
+ chart.setChartTitle("DateChart01");
+ chart.getStyleManager().setTimezone(TimeZone.getTimeZone("UTC"));
chart.getStyleManager().setLegendPosition(LegendPosition.InsideNW);
Series series = chart.addDateSeries("value", xData, yData);
return chart;
- }
+ }
}
diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart09.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart09.java
index 39348ac9..c91f5353 100644
--- a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart09.java
+++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/line/LineChart09.java
@@ -81,9 +81,9 @@ public class LineChart09 implements ExampleChart {
chart.getStyleManager().setLegendFont(new Font(Font.SERIF, Font.PLAIN, 18));
chart.getStyleManager().setAxisTitleFont(new Font(Font.SANS_SERIF, Font.ITALIC, 18));
chart.getStyleManager().setAxisTickLabelsFont(new Font(Font.SERIF, Font.PLAIN, 11));
- chart.getStyleManager().getDateFormatter().setDatePattern("dd-MMM");
- chart.getStyleManager().getDecimalFormatter().setNormalDecimalPattern("#.000");
- chart.getStyleManager().getDateFormatter().setLocale(Locale.GERMAN);
+ chart.getStyleManager().setDatePattern("dd-MMM");
+ chart.getStyleManager().setNormalDecimalPattern("#.000");
+ chart.getStyleManager().setLocale(Locale.GERMAN);
Series series = chart.addDateSeries("Fake Data", xData, yData);
series.setLineColor(SeriesColor.BLUE);
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/AxisTickCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/AxisTickCalculator.java
index 35bf74aa..efacecbd 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/AxisTickCalculator.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/AxisTickCalculator.java
@@ -22,12 +22,13 @@
package com.xeiam.xchart.internal.chartpart.axistickcalculator;
import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
import java.util.LinkedList;
import java.util.List;
import com.xeiam.xchart.internal.chartpart.Axis.AxisType;
import com.xeiam.xchart.internal.chartpart.Axis.Direction;
-import com.xeiam.xchart.internal.chartpart.AxisPair;
import com.xeiam.xchart.style.StyleManager;
/**
@@ -65,43 +66,90 @@ public abstract class AxisTickCalculator {
this.maxValue = maxValue;
this.styleManager = styleManager;
- calculate();
}
- private void calculate() {
-
- // a check if all axis data are the exact same values
- if (minValue == maxValue) {
- if (getAxisType() == AxisType.Number) {
- tickLabels.add(styleManager.getDecimalFormatter().formatNumber(maxValue));
- } else if (getAxisType() == AxisType.Date) {
- tickLabels.add(styleManager.getDateFormatter().formatDateValue(maxValue, maxValue, maxValue));
+ BigDecimal getGridStepDecimal(double gridStepHint) {
+
+ // gridStepHint --> significand * 10 ** exponent
+ // e.g. 724.1 --> 7.241 * 10 ** 2
+ double significand = gridStepHint;
+ int exponent = 0;
+ if (significand == 0) {
+ exponent = 1;
+ } else if (significand < 1) {
+ while (significand < 1) {
+ significand *= 10.0;
+ exponent--;
+ }
+ } else {
+ while (significand >= 10) {
+ significand /= 10.0;
+ exponent++;
}
- tickLocations.add((int) (workingSpace / 2.0));
- return;
}
- // tick space - a percentage of the working space available for ticks, i.e. 95%
- int tickSpace = AxisPair.getTickSpace(workingSpace); // in plot space
+ // calculate the grid step with hint.
+ BigDecimal gridStep;
+ if (significand > 7.5) {
+ // gridStep = 10.0 * 10 ** exponent
+ gridStep = BigDecimal.TEN.multiply(pow(10, exponent));
+ } else if (significand > 3.5) {
+ // gridStep = 5.0 * 10 ** exponent
+ gridStep = new BigDecimal(new Double(5).toString()).multiply(pow(10, exponent));
+ } else if (significand > 1.5) {
+ // gridStep = 2.0 * 10 ** exponent
+ gridStep = new BigDecimal(new Double(2).toString()).multiply(pow(10, exponent));
+ } else {
+ // gridStep = 1.0 * 10 ** exponent
+ gridStep = pow(10, exponent);
+ }
+ return gridStep;
+ }
- // where the tick should begin in the working space in pixels
- int margin = AxisPair.getTickStartOffset(workingSpace, tickSpace); // in plot space BigDecimal gridStep = getGridStepForDecimal(tickSpace);
+ /**
+ * Calculates the value of the first argument raised to the power of the second argument.
+ *
+ * @param base the base
+ * @param exponent the exponent
+ * @return the value <tt>a<sup>b</sup></tt> in <tt>BigDecimal</tt>
+ */
+ private BigDecimal pow(double base, int exponent) {
+
+ BigDecimal value;
+ if (exponent > 0) {
+ value = new BigDecimal(new Double(base).toString()).pow(exponent);
+ } else {
+ value = BigDecimal.ONE.divide(new BigDecimal(new Double(base).toString()).pow(-exponent));
+ }
+ return value;
+ }
- BigDecimal gridStep = getGridStep(tickSpace);
- BigDecimal firstPosition = getFirstPosition(minValue, gridStep);
+ /**
+ * Format a number value, if the override patterns are null, it uses defaults
+ *
+ * @param value
+ * @return
+ */
+ public String formatNumber(BigDecimal value) {
- // generate all tickLabels and tickLocations from the first to last position
- for (BigDecimal tickPosition = firstPosition; tickPosition.compareTo(maxValue) <= 0; tickPosition = tickPosition.add(gridStep)) {
+ NumberFormat numberFormat = NumberFormat.getNumberInstance(styleManager.getLocale());
+
+ BigDecimal absoluteValue = value.abs();
+
+ if (absoluteValue.compareTo(new BigDecimal("10000.000001")) == -1 && absoluteValue.compareTo(new BigDecimal(".0009999999")) == 1 || BigDecimal.ZERO.compareTo(value) == 0) {
+
+ DecimalFormat normalFormat = (DecimalFormat) numberFormat;
+ normalFormat.applyPattern(styleManager.getNormalDecimalPattern());
+ return normalFormat.format(value);
+
+ } else {
+
+ DecimalFormat scientificFormat = (DecimalFormat) numberFormat;
+ scientificFormat.applyPattern(styleManager.getScientificDecimalPattern());
+ return scientificFormat.format(value);
- if (getAxisType() == AxisType.Number) {
- tickLabels.add(styleManager.getDecimalFormatter().formatNumber(tickPosition));
- } else if (getAxisType() == AxisType.Date) {
- tickLabels.add(styleManager.getDateFormatter().formatDateValue(tickPosition, minValue, maxValue));
- }
- // here we convert tickPosition finally to plot space, i.e. pixels
- int tickLabelPosition = (int) (margin + ((tickPosition.subtract(minValue)).doubleValue() / (maxValue.subtract(minValue)).doubleValue() * tickSpace));
- tickLocations.add(tickLabelPosition);
}
+
}
public List<Integer> getTickLocations() {
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateAxisTickCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateAxisTickCalculator.java
index b007ff60..58ef2836 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateAxisTickCalculator.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateAxisTickCalculator.java
@@ -22,9 +22,12 @@
package com.xeiam.xchart.internal.chartpart.axistickcalculator;
import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.concurrent.TimeUnit;
import com.xeiam.xchart.internal.chartpart.Axis.AxisType;
import com.xeiam.xchart.internal.chartpart.Axis.Direction;
+import com.xeiam.xchart.internal.chartpart.AxisPair;
import com.xeiam.xchart.style.StyleManager;
/**
@@ -34,6 +37,14 @@ import com.xeiam.xchart.style.StyleManager;
*/
public class DateAxisTickCalculator extends AxisTickCalculator {
+ public static final long SEC_SCALE = TimeUnit.SECONDS.toMillis(1L);
+ public static final long MIN_SCALE = TimeUnit.MINUTES.toMillis(1L);
+ public static final long HOUR_SCALE = TimeUnit.HOURS.toMillis(1L);
+ public static final long DAY_SCALE = TimeUnit.DAYS.toMillis(1L);
+ public static final long WEEK_SCALE = TimeUnit.DAYS.toMillis(1L) * 7;
+ public static final long MONTH_SCALE = TimeUnit.DAYS.toMillis(1L) * 31;
+ public static final long YEAR_SCALE = TimeUnit.DAYS.toMillis(1L) * 365;
+
/**
* Constructor
*
@@ -46,7 +57,35 @@ public class DateAxisTickCalculator extends AxisTickCalculator {
public DateAxisTickCalculator(Direction axisDirection, int workingSpace, BigDecimal minValue, BigDecimal maxValue, StyleManager styleManager) {
super(axisDirection, workingSpace, minValue, maxValue, styleManager);
+ calculate();
+ }
+
+ private void calculate() {
+
+ // a check if all axis data are the exact same values
+ if (minValue == maxValue) {
+ tickLabels.add(formatDateValue(maxValue, maxValue, maxValue));
+ tickLocations.add((int) (workingSpace / 2.0));
+ return;
+ }
+
+ // tick space - a percentage of the working space available for ticks, i.e. 95%
+ int tickSpace = AxisPair.getTickSpace(workingSpace); // in plot space
+
+ // where the tick should begin in the working space in pixels
+ int margin = AxisPair.getTickStartOffset(workingSpace, tickSpace); // in plot space BigDecimal gridStep = getGridStepForDecimal(tickSpace);
+
+ BigDecimal gridStep = getGridStep(tickSpace);
+ BigDecimal firstPosition = getFirstPosition(minValue, gridStep);
+
+ // generate all tickLabels and tickLocations from the first to last position
+ for (BigDecimal tickPosition = firstPosition; tickPosition.compareTo(maxValue) <= 0; tickPosition = tickPosition.add(gridStep)) {
+ tickLabels.add(formatDateValue(tickPosition, minValue, maxValue));
+ // here we convert tickPosition finally to plot space, i.e. pixels
+ int tickLabelPosition = (int) (margin + ((tickPosition.subtract(minValue)).doubleValue() / (maxValue.subtract(minValue)).doubleValue() * tickSpace));
+ tickLocations.add(tickLabelPosition);
+ }
}
/**
@@ -61,67 +100,21 @@ public class DateAxisTickCalculator extends AxisTickCalculator {
// the span of the data
double span = Math.abs(maxValue.subtract(minValue).doubleValue()); // in data space
- int tickMarkSpaceHint = (axisDirection == Direction.X ? DEFAULT_TICK_MARK_STEP_HINT_X : DEFAULT_TICK_MARK_STEP_HINT_Y);
+ double gridStepHint = span / tickSpace * DEFAULT_TICK_MARK_STEP_HINT_X;
- // for very short plots, squeeze some more ticks in than normal
- if (axisDirection == Direction.Y && tickSpace < 160) {
- tickMarkSpaceHint = 25;
- }
+ BigDecimal gridStep;
+ if (span < SEC_SCALE) {
+ // decimal
+ gridStep = getGridStepDecimal(gridStepHint);
- double gridStepHint = span / tickSpace * tickMarkSpaceHint;
-
- // gridStepHint --> significand * 10 ** exponent
- // e.g. 724.1 --> 7.241 * 10 ** 2
- double significand = gridStepHint;
- int exponent = 0;
- if (significand == 0) {
- exponent = 1;
- } else if (significand < 1) {
- while (significand < 1) {
- significand *= 10.0;
- exponent--;
- }
} else {
- while (significand >= 10) {
- significand /= 10.0;
- exponent++;
- }
- }
- // calculate the grid step with hint.
- BigDecimal gridStep;
- if (significand > 7.5) {
- // gridStep = 10.0 * 10 ** exponent
- gridStep = BigDecimal.TEN.multiply(pow(10, exponent));
- } else if (significand > 3.5) {
- // gridStep = 5.0 * 10 ** exponent
- gridStep = new BigDecimal(new Double(5).toString()).multiply(pow(10, exponent));
- } else if (significand > 1.5) {
- // gridStep = 2.0 * 10 ** exponent
- gridStep = new BigDecimal(new Double(2).toString()).multiply(pow(10, exponent));
- } else {
- // gridStep = 1.0 * 10 ** exponent
- gridStep = pow(10, exponent);
- }
- return gridStep;
- }
+ // date
+ gridStep = getGridStepDecimal(gridStepHint);
- /**
- * Calculates the value of the first argument raised to the power of the second argument.
- *
- * @param base the base
- * @param exponent the exponent
- * @return the value <tt>a<sup>b</sup></tt> in <tt>BigDecimal</tt>
- */
- private BigDecimal pow(double base, int exponent) {
-
- BigDecimal value;
- if (exponent > 0) {
- value = new BigDecimal(new Double(base).toString()).pow(exponent);
- } else {
- value = BigDecimal.ONE.divide(new BigDecimal(new Double(base).toString()).pow(-exponent));
}
- return value;
+
+ return gridStep;
}
@Override
@@ -136,6 +129,47 @@ public class DateAxisTickCalculator extends AxisTickCalculator {
return firstPosition;
}
+ /**
+ * Format a date value
+ *
+ * @param value
+ * @param min
+ * @param max
+ * @return
+ */
+ public String formatDateValue(BigDecimal value, BigDecimal min, BigDecimal max) {
+
+ String datePattern;
+ // TODO check if min and max are the same, then calculate this differently
+
+ // intelligently set date pattern if none is given
+ long diff = max.subtract(min).longValue();
+
+ if (diff < SEC_SCALE) {
+ datePattern = "ss:S";
+ } else if (diff < MIN_SCALE) {
+ datePattern = "mm:ss";
+ } else if (diff < HOUR_SCALE) {
+ datePattern = "HH:mm";
+ } else if (diff < DAY_SCALE) {
+ datePattern = "EEE HH:mm";
+ } else if (diff < WEEK_SCALE) {
+ datePattern = "EEE";
+ } else if (diff < MONTH_SCALE) {
+ datePattern = "MMM-dd";
+ } else if (diff < YEAR_SCALE) {
+ datePattern = "yyyy:MMM";
+ } else {
+ datePattern = "yyyy";
+ }
+
+ SimpleDateFormat simpleDateformat = new SimpleDateFormat(datePattern, styleManager.getLocale());
+ simpleDateformat.setTimeZone(styleManager.getTimezone());
+ simpleDateformat.applyPattern(datePattern);
+
+ return simpleDateformat.format(value.longValueExact());
+ }
+
@Override
public AxisType getAxisType() {
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateFormatter.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateFormatter.java
deleted file mode 100644
index 448002e0..00000000
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateFormatter.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- * Copyright (C) 2013 Xeiam LLC http://xeiam.com
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package com.xeiam.xchart.internal.chartpart.axistickcalculator;
-
-import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.util.concurrent.TimeUnit;
-
-/**
- * @author timmolter
- */
-public class DateFormatter {
-
- private String datePattern;
- private Locale locale;
- private TimeZone timezone;
-
- private static final long SEC_SCALE = TimeUnit.SECONDS.toMillis(1L);
- private static final long MIN_SCALE = TimeUnit.MINUTES.toMillis(1L);
- private static final long HOUR_SCALE = TimeUnit.HOURS.toMillis(1L);
- private static final long DAY_SCALE = TimeUnit.DAYS.toMillis(1L);
- private static final long WEEK_SCALE = TimeUnit.DAYS.toMillis(1L) * 7;
- private static final long MONTH_SCALE = TimeUnit.DAYS.toMillis(1L) * 31;
- private static final long YEAR_SCALE = TimeUnit.DAYS.toMillis(1L) * 365;
-
- /**
- * Constructor
- */
- public DateFormatter() {
-
- datePattern = "HHmmss";
- locale = Locale.getDefault();
- timezone = TimeZone.getDefault();
- }
-
- /**
- * Format a date value
- *
- * @param value
- * @param min
- * @param max
- * @return
- */
- public String formatDateValue(BigDecimal value, BigDecimal min, BigDecimal max) {
-
- // TODO check if min and max are the same, then calculate this differently
-
- // intelligently set date pattern if none is given
- long diff = max.subtract(min).longValue();
-
- if (diff < SEC_SCALE) {
- datePattern = "ss:S";
- } else if (diff < MIN_SCALE) {
- datePattern = "mm:ss";
- } else if (diff < HOUR_SCALE) {
- datePattern = "HH:mm";
- } else if (diff < DAY_SCALE) {
- datePattern = "EEE HH:mm";
- } else if (diff < WEEK_SCALE) {
- datePattern = "EEE";
- } else if (diff < MONTH_SCALE) {
- datePattern = "MMM-dd";
- } else if (diff < YEAR_SCALE) {
- datePattern = "yyyy:MMM";
- } else {
- datePattern = "yyyy";
- }
-
- SimpleDateFormat simpleDateformat = new SimpleDateFormat(datePattern, locale);
- simpleDateformat.setTimeZone(timezone);
- simpleDateformat.applyPattern(datePattern);
- return simpleDateformat.format(value.longValueExact());
-
- }
-
- /**
- * Set the String formatter for Data x-axis
- *
- * @param pattern - the pattern describing the date and time format
- */
- public void setDatePattern(String datePattern) {
-
- this.datePattern = datePattern;
- }
-
- /**
- * Set the locale to use for rendering the chart
- *
- * @param locale - the locale to use when formatting Strings and dates for the axis tick labels
- */
- public void setLocale(Locale locale) {
-
- this.locale = locale;
- }
-
- /**
- * Set the timezone to use for formatting Date axis tick labels
- *
- * @param timezone the timezone to use when formatting date data
- */
- public void setTimezone(TimeZone timezone) {
-
- this.timezone = timezone;
- }
-
-}
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/NumberAxisTickCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/NumberAxisTickCalculator.java
index 936eba15..7f286d4d 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/NumberAxisTickCalculator.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/NumberAxisTickCalculator.java
@@ -25,6 +25,7 @@ import java.math.BigDecimal;
import com.xeiam.xchart.internal.chartpart.Axis.AxisType;
import com.xeiam.xchart.internal.chartpart.Axis.Direction;
+import com.xeiam.xchart.internal.chartpart.AxisPair;
import com.xeiam.xchart.style.StyleManager;
/**
@@ -46,6 +47,35 @@ public class NumberAxisTickCalculator extends AxisTickCalculator {
public NumberAxisTickCalculator(Direction axisDirection, int workingSpace, BigDecimal minValue, BigDecimal maxValue, StyleManager styleManager) {
super(axisDirection, workingSpace, minValue, maxValue, styleManager);
+ calculate();
+ }
+
+ private void calculate() {
+
+ // a check if all axis data are the exact same values
+ if (minValue == maxValue) {
+ tickLabels.add(formatNumber(maxValue));
+ tickLocations.add((int) (workingSpace / 2.0));
+ return;
+ }
+
+ // tick space - a percentage of the working space available for ticks, i.e. 95%
+ int tickSpace = AxisPair.getTickSpace(workingSpace); // in plot space
+
+ // where the tick should begin in the working space in pixels
+ int margin = AxisPair.getTickStartOffset(workingSpace, tickSpace); // in plot space BigDecimal gridStep = getGridStepForDecimal(tickSpace);
+
+ BigDecimal gridStep = getGridStep(tickSpace);
+ BigDecimal firstPosition = getFirstPosition(minValue, gridStep);
+
+ // generate all tickLabels and tickLocations from the first to last position
+ for (BigDecimal tickPosition = firstPosition; tickPosition.compareTo(maxValue) <= 0; tickPosition = tickPosition.add(gridStep)) {
+
+ tickLabels.add(formatNumber(tickPosition));
+ // here we convert tickPosition finally to plot space, i.e. pixels
+ int tickLabelPosition = (int) (margin + ((tickPosition.subtract(minValue)).doubleValue() / (maxValue.subtract(minValue)).doubleValue() * tickSpace));
+ tickLocations.add(tickLabelPosition);
+ }
}
/**
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/NumberFormatter.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/NumberFormatter.java
deleted file mode 100644
index 594fa777..00000000
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/NumberFormatter.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * Copyright (C) 2013 Xeiam LLC http://xeiam.com
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-package com.xeiam.xchart.internal.chartpart.axistickcalculator;
-
-import java.math.BigDecimal;
-import java.text.DecimalFormat;
-import java.text.NumberFormat;
-import java.util.Locale;
-
-/**
- * @author timmolter
- */
-public class NumberFormatter {
-
- private String normalDecimalPattern;
- private String scientificDecimalPattern;
- // TODO move to parent class??
- private Locale locale;
-
- /**
- * Constructor
- */
- public NumberFormatter() {
-
- normalDecimalPattern = "#.####";
- scientificDecimalPattern = "0.##E0";
- locale = Locale.getDefault();
-
- }
-
- /**
- * Format a number value, if the override patterns are null, it uses defaults
- *
- * @param value
- * @return
- */
- public String formatNumber(BigDecimal value) {
-
- NumberFormat numberFormat = NumberFormat.getNumberInstance(locale);
-
- BigDecimal absoluteValue = value.abs();
-
- if (absoluteValue.compareTo(new BigDecimal("10000.000001")) == -1 && absoluteValue.compareTo(new BigDecimal(".0009999999")) == 1 || BigDecimal.ZERO.compareTo(value) == 0) {
-
- DecimalFormat normalFormat = (DecimalFormat) numberFormat;
- normalFormat.applyPattern(normalDecimalPattern);
- return normalFormat.format(value);
-
- } else {
-
- DecimalFormat scientificFormat = (DecimalFormat) numberFormat;
- scientificFormat.applyPattern(scientificDecimalPattern);
- return scientificFormat.format(value);
-
- }
-
- }
-
- /**
- * Set the decimal formatter for all tick labels
- *
- * @param pattern - the pattern describing the decimal format
- */
- public void setNormalDecimalPattern(String normalDecimalPattern) {
-
- this.normalDecimalPattern = normalDecimalPattern;
- }
-
- /**
- * 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;
- }
-
- /**
- * Set the locale to use for rendering the chart
- *
- * @param locale - the locale to use when formatting Strings and dates for the axis tick labels
- */
- public void setLocale(Locale locale) {
-
- this.locale = locale;
- }
-
-}
diff --git a/xchart/src/main/java/com/xeiam/xchart/style/StyleManager.java b/xchart/src/main/java/com/xeiam/xchart/style/StyleManager.java
index 244f8344..00507e5f 100644
--- a/xchart/src/main/java/com/xeiam/xchart/style/StyleManager.java
+++ b/xchart/src/main/java/com/xeiam/xchart/style/StyleManager.java
@@ -24,9 +24,9 @@ package com.xeiam.xchart.style;
import java.awt.Color;
import java.awt.Font;
import java.awt.Stroke;
+import java.util.Locale;
+import java.util.TimeZone;
-import com.xeiam.xchart.internal.chartpart.axistickcalculator.DateFormatter;
-import com.xeiam.xchart.internal.chartpart.axistickcalculator.NumberFormatter;
import com.xeiam.xchart.style.theme.Theme;
import com.xeiam.xchart.style.theme.XChartTheme;
@@ -97,9 +97,11 @@ public class StyleManager {
private Color errorBarsColor;
// Formatting ////////////////////////////////
-
- private NumberFormatter decimalFormatter;
- private DateFormatter dateFormatter;
+ private String datePattern;
+ private Locale locale;
+ private TimeZone timezone;
+ private String normalDecimalPattern;
+ private String scientificDecimalPattern;
/**
* Constructor
@@ -160,8 +162,11 @@ public class StyleManager {
errorBarsColor = theme.getErrorBarsColor();
// Formatting ////////////////////////////////
- decimalFormatter = new NumberFormatter();
- dateFormatter = new DateFormatter();
+ datePattern = "HHmmss";
+ locale = Locale.getDefault();
+ timezone = TimeZone.getDefault();
+ normalDecimalPattern = "#.####";
+ scientificDecimalPattern = "0.##E0";
}
/**
@@ -755,14 +760,78 @@ public class StyleManager {
// Formatting ////////////////////////////////
- public NumberFormatter getDecimalFormatter() {
+ /**
+ * Set the String formatter for Data x-axis
+ *
+ * @param pattern - the pattern describing the date and time format
+ */
+ public void setDatePattern(String datePattern) {
+
+ this.datePattern = datePattern;
+ }
+
+ public String getDatePattern() {
+
+ return datePattern;
+ }
+
+ /**
+ * Set the locale to use for rendering the chart
+ *
+ * @param locale - the locale to use when formatting Strings and dates for the axis tick labels
+ */
+ public void setLocale(Locale locale) {
+
+ this.locale = locale;
+ }
- return decimalFormatter;
+ public Locale getLocale() {
+
+ return locale;
}
- public DateFormatter getDateFormatter() {
+ /**
+ * Set the timezone to use for formatting Date axis tick labels
+ *
+ * @param timezone the timezone to use when formatting date data
+ */
+ public void setTimezone(TimeZone timezone) {
- return dateFormatter;
+ this.timezone = timezone;
}
+ public TimeZone getTimezone() {
+
+ return timezone;
+ }
+
+ /**
+ * Set the decimal formatter for all tick labels
+ *
+ * @param pattern - the pattern describing the decimal format
+ */
+ public void setNormalDecimalPattern(String normalDecimalPattern) {
+
+ this.normalDecimalPattern = normalDecimalPattern;
+ }
+
+ public String getNormalDecimalPattern() {
+
+ return normalDecimalPattern;
+ }
+
+ /**
+ * 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/test/java/com/xeiam/xchart/unit/ValueFormatterTest.java b/xchart/src/test/java/com/xeiam/xchart/unit/ValueFormatterTest.java
index ac59498f..5a27d906 100644
--- a/xchart/src/test/java/com/xeiam/xchart/unit/ValueFormatterTest.java
+++ b/xchart/src/test/java/com/xeiam/xchart/unit/ValueFormatterTest.java
@@ -30,8 +30,9 @@ import java.util.TimeZone;
import org.junit.Test;
-import com.xeiam.xchart.internal.chartpart.axistickcalculator.DateFormatter;
-import com.xeiam.xchart.internal.chartpart.axistickcalculator.NumberFormatter;
+import com.xeiam.xchart.internal.chartpart.Axis.Direction;
+import com.xeiam.xchart.internal.chartpart.axistickcalculator.DateAxisTickCalculator;
+import com.xeiam.xchart.style.StyleManager;
/**
* @author timmolter
@@ -43,59 +44,60 @@ public class ValueFormatterTest {
@Test
public void testNumberFormatting() {
- NumberFormatter axisTickLabelFormatter = new NumberFormatter();
+ StyleManager styleManager = new StyleManager();
+ DateAxisTickCalculator dateAxisTickCalculator = new DateAxisTickCalculator(Direction.X, 1000, new BigDecimal(10), new BigDecimal(90), styleManager);
// big
- axisTickLabelFormatter.setLocale(locale);
+ styleManager.setLocale(locale);
BigDecimal value = new BigDecimal("1");
- String stringValue = axisTickLabelFormatter.formatNumber(value);
+ String stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("1"));
value = new BigDecimal(1000L);
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("1000"));
value = new BigDecimal("9999");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("9999"));
value = new BigDecimal(20000L);
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("2E4"));
value = new BigDecimal("200.23");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("200.23"));
// small
value = new BigDecimal("0.01");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("0.01"));
value = new BigDecimal("0.001");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("0.001"));
value = new BigDecimal("0.0012");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("0.0012"));
value = new BigDecimal("0.0001");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("1E-4"));
value = new BigDecimal(".00012");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("1.2E-4"));
value = new BigDecimal("0.0");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("0"));
value = new BigDecimal("0");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("0"));
// other case
@@ -111,24 +113,24 @@ public class ValueFormatterTest {
// assertThat(stringValue, equalTo("0.01"));
// non-default
- axisTickLabelFormatter.setLocale(Locale.GERMANY);
+ styleManager.setLocale(Locale.GERMANY);
value = new BigDecimal("0.01");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("0,01"));
value = new BigDecimal("200.23");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("200,23"));
- axisTickLabelFormatter.setNormalDecimalPattern("#.#");
+ styleManager.setNormalDecimalPattern("#.#");
value = new BigDecimal("200.23");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("200,2"));
- axisTickLabelFormatter.setScientificDecimalPattern("0.#E0");
+ styleManager.setScientificDecimalPattern("0.#E0");
value = new BigDecimal("2009764.23");
- stringValue = axisTickLabelFormatter.formatNumber(value);
+ stringValue = dateAxisTickCalculator.formatNumber(value);
assertThat(stringValue, equalTo("2E6"));
}
@@ -136,67 +138,68 @@ public class ValueFormatterTest {
@Test
public void testDateFormatting() {
- DateFormatter axisTickLabelFormatter = new DateFormatter();
+ StyleManager styleManager = new StyleManager();
+ DateAxisTickCalculator dateAxisTickCalculator = new DateAxisTickCalculator(Direction.X, 1000, new BigDecimal(10), new BigDecimal(90), styleManager);
TimeZone timeZone = TimeZone.getTimeZone("UTC");
- axisTickLabelFormatter.setLocale(locale);
- axisTickLabelFormatter.setTimezone(timeZone);
+ styleManager.setLocale(locale);
+ styleManager.setTimezone(timeZone);
// ms
BigDecimal value = new BigDecimal(1358108105531L);
BigDecimal min = new BigDecimal(1358108105100L);
BigDecimal max = new BigDecimal(1358108105900L);
- String stringValue = axisTickLabelFormatter.formatDateValue(value, min, max);
+ String stringValue = dateAxisTickCalculator.formatDateValue(value, min, max);
assertThat(stringValue, equalTo("05:531"));
// sec
value = new BigDecimal(1358108105000L);
min = new BigDecimal(1358108101000L);
max = new BigDecimal(1358108109000L);
- stringValue = axisTickLabelFormatter.formatDateValue(value, min, max);
+ stringValue = dateAxisTickCalculator.formatDateValue(value, min, max);
assertThat(stringValue, equalTo("15:05"));
// min
value = new BigDecimal(1358111750000L);
min = new BigDecimal(1358111690000L);
max = new BigDecimal(1358111870000L);
- stringValue = axisTickLabelFormatter.formatDateValue(value, min, max);
+ stringValue = dateAxisTickCalculator.formatDateValue(value, min, max);
assertThat(stringValue, equalTo("21:15"));
// hour
value = new BigDecimal(1358111870000L);
min = new BigDecimal(1358101070000L);
max = new BigDecimal(1358115470000L);
- stringValue = axisTickLabelFormatter.formatDateValue(value, min, max);
+ stringValue = dateAxisTickCalculator.formatDateValue(value, min, max);
assertThat(stringValue, equalTo("Sun 21:17"));
// day
value = new BigDecimal(1358112317000L);
min = new BigDecimal(1357939517000L);
max = new BigDecimal(1358285117000L);
- stringValue = axisTickLabelFormatter.formatDateValue(value, min, max);
+ stringValue = dateAxisTickCalculator.formatDateValue(value, min, max);
assertThat(stringValue, equalTo("Sun"));
// week
value = new BigDecimal(1358112317000L);
min = new BigDecimal(1357075517000L);
max = new BigDecimal(1359149117000L);
- stringValue = axisTickLabelFormatter.formatDateValue(value, min, max);
+ stringValue = dateAxisTickCalculator.formatDateValue(value, min, max);
assertThat(stringValue, equalTo("Jan-13"));
// month
value = new BigDecimal(1358112838000L);
min = new BigDecimal(1354397638000L);
max = new BigDecimal(1361223238000L);
- stringValue = axisTickLabelFormatter.formatDateValue(value, min, max);
+ stringValue = dateAxisTickCalculator.formatDateValue(value, min, max);
assertThat(stringValue, equalTo("2013:Jan"));
// year
value = new BigDecimal(1358113402000L);
min = new BigDecimal(1263419002000L);
max = new BigDecimal(1421185402000L);
- stringValue = axisTickLabelFormatter.formatDateValue(value, min, max);
+ stringValue = dateAxisTickCalculator.formatDateValue(value, min, max);
assertThat(stringValue, equalTo("2013"));
}
--
GitLab