From c9d01c6f66df68945ac9798d1ffeb62911bf60ca Mon Sep 17 00:00:00 2001 From: Tim Molter Date: Fri, 10 May 2024 10:39:08 +0200 Subject: [PATCH] fix for issue #582 --- .../standalone/issues/TestForIssue582.java | 54 +++++++++++++++++++ .../main/java/org/knowm/xchart/XYChart.java | 2 +- .../chartpart/AxisTickCalculator_.java | 31 +++++++++-- 3 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 xchart-demo/src/main/java/org/knowm/xchart/standalone/issues/TestForIssue582.java diff --git a/xchart-demo/src/main/java/org/knowm/xchart/standalone/issues/TestForIssue582.java b/xchart-demo/src/main/java/org/knowm/xchart/standalone/issues/TestForIssue582.java new file mode 100644 index 00000000..a58df763 --- /dev/null +++ b/xchart-demo/src/main/java/org/knowm/xchart/standalone/issues/TestForIssue582.java @@ -0,0 +1,54 @@ +package org.knowm.xchart.standalone.issues; + +import org.knowm.xchart.SwingWrapper; +import org.knowm.xchart.XYChart; +import org.knowm.xchart.XYChartBuilder; + +import java.text.DecimalFormatSymbols; +import java.text.ParseException; +import java.util.Locale; + +public class TestForIssue582 { + + public static void main(String[] args) throws ParseException { + + XYChart chart = getXYChart(); + new SwingWrapper(chart).displayChart(); + } + + public static XYChart getXYChart() { + XYChart chart = new XYChartBuilder() + .width(720) + .height(480) + .title("Deadlock Example") + .xAxisTitle("Count") + .yAxisTitle("Value") + .build(); + + // If the decimal places in the pattern is fewer than the largest data value, the deadlock occurs. +// chart.getStyler().setDecimalPattern("#0.0000"); +// chart.getStyler().setDecimalPattern("#,###.00"); + +// chart.getStyler().setDecimalPattern("$ #0.00"); +// chart.getStyler().setDecimalPattern("$ #0.000"); + + chart.getStyler().setLocale(Locale.ITALIAN); + chart.getStyler().setDecimalPattern("#0.000"); + + double[] xValues = new double[]{1, 2, 3, 4, 5, 6, 7, 8}; + + // The only value here is 0.001 which is one decimal place below the pattern. + double[] yValues = new double[] { 0.0, 0.0, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0}; +// double[] yValues = new double[] { 0.0, 0.0, 0.0, 0.0, -0.001, 0.0, 0.0, 0.0}; +// double[] yValues = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; +// double[] yValues = new double[] { 0.0001, 0.0, 0.0, 0.0, -0.001, 0.0, 0.0, 0.0}; +// double[] yValues = new double[] { -0.0002, -0.0002, -0.0002, -0.0002, -0.001, -0.0002, -0.0002, -0.0002}; +// double[] yValues = new double[]{0.0002, 0.0002, 0.0002, 0.0002, 0.0001, 0.0002, 0.0002, 0.0002}; +// double[] yValues = new double[] { 20.0002, 20.0002, 20.0002, 20.0002, 20.001, 20.0002, 20.0002, 20.0002}; + + chart.addSeries("main", xValues, yValues); + + + return chart; + } +} diff --git a/xchart/src/main/java/org/knowm/xchart/XYChart.java b/xchart/src/main/java/org/knowm/xchart/XYChart.java index 91a13764..38dcf72a 100644 --- a/xchart/src/main/java/org/knowm/xchart/XYChart.java +++ b/xchart/src/main/java/org/knowm/xchart/XYChart.java @@ -39,7 +39,7 @@ public XYChart(int width, int height) { * * @param width * @param height - * @param theme - pass in a instance of Theme class, probably a custom Theme. + * @param theme - pass in an instance of Theme class, probably a custom Theme. */ public XYChart(int width, int height, Theme theme) { diff --git a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/AxisTickCalculator_.java b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/AxisTickCalculator_.java index a2ea1d03..ba440c0b 100644 --- a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/AxisTickCalculator_.java +++ b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/AxisTickCalculator_.java @@ -8,7 +8,7 @@ import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; -import java.text.Format; +import java.text.*; import java.util.*; import java.util.List; import java.util.stream.Collectors; @@ -161,6 +161,8 @@ public Format getAxisFormat() { protected void calculate() { + // System.out.println("calculate"); + // a check if all axis data are the exact same values if (minValue == maxValue) { tickLabels.add(getAxisFormat().format(BigDecimal.valueOf(maxValue).doubleValue())); @@ -186,7 +188,14 @@ protected void calculate() { return; } - // where the tick should begin in the working space in pixels + // this prevents an infinite loop when the axis number formatter "rounds" all axis ticks to the same value i.e. "#0.00" for 0.0, 0.0001, 0.0002 + // issue #582 + if(isNumberFormatChoppingDecimals(maxValue, minValue)){ + System.out.println("returning"); + return; + } + + // where the tick should begin in the working space in pixels double margin = Utils.getTickStartOffset( workingSpace, @@ -216,7 +225,7 @@ protected void calculate() { do { - // System.out.println("calculating ticks..."); +// System.out.println("calculating ticks..."); tickLabels.clear(); tickLocations.clear(); @@ -342,6 +351,7 @@ protected void calculate() { } } while (!areAllTickLabelsUnique(tickLabels) || !willLabelsFitInTickSpaceHint(tickLabels, gridStepInChartSpace)); + } private boolean areValuesEquallySpaced(List values) { @@ -452,4 +462,19 @@ private static double getAxisMaxValue( return 0; return dataMaxValue; } + + private boolean isNumberFormatChoppingDecimals(double axisMax, double axisMin){ + +// System.out.println("axisMax = " + axisMax); +// System.out.println("axisMin = " + axisMin); + String formattedMaxValue = getAxisFormat().format(axisMax); +// System.out.println("formattedMaxValue = " + formattedMaxValue); + String formattedMinValue = getAxisFormat().format(axisMin); +// System.out.println("formattedMinValue = " + formattedMinValue); + // if formatted number lost its decimals due to formatter + if(formattedMaxValue.equals(formattedMinValue)){ + return true; + } + return false; + } }