From 992e71aa71927dbb797d4ffa89e93b7927162b52 Mon Sep 17 00:00:00 2001
From: Tim Molter <tim.molter@gmail.com>
Date: Sat, 16 Feb 2013 20:16:26 +0100
Subject: [PATCH] more cleanup

---
 .../xchart/internal/chartpart/AxisTick.java   |  18 +-
 .../AxisTickCalculator.java}                  |   4 +-
 .../DateAxisTickCalculator.java}              |  13 +-
 .../DateFormatter.java                        |   2 +-
 .../DecimalAxisTickCalculator.java}           |  13 +-
 .../DecimalFormatter.java                     |   2 +-
 .../LogarithmicAxisTickCalculator.java        | 208 ++++++++++++++++++
 .../com/xeiam/xchart/style/StyleManager.java  |   4 +-
 .../xeiam/xchart/unit/ValueFormatterTest.java |   4 +-
 9 files changed, 239 insertions(+), 29 deletions(-)
 rename xchart/src/main/java/com/xeiam/xchart/internal/chartpart/{gridstep/GridStep.java => axistickcalculator/AxisTickCalculator.java} (92%)
 rename xchart/src/main/java/com/xeiam/xchart/internal/chartpart/{gridstep/DateGridStep.java => axistickcalculator/DateAxisTickCalculator.java} (93%)
 rename xchart/src/main/java/com/xeiam/xchart/internal/chartpart/{gridstep => axistickcalculator}/DateFormatter.java (98%)
 rename xchart/src/main/java/com/xeiam/xchart/internal/chartpart/{gridstep/DecimalGridStep.java => axistickcalculator/DecimalAxisTickCalculator.java} (94%)
 rename xchart/src/main/java/com/xeiam/xchart/internal/chartpart/{gridstep => axistickcalculator}/DecimalFormatter.java (98%)
 create mode 100644 xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/LogarithmicAxisTickCalculator.java

diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java
index 8e83c3c5..2fdc5157 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/AxisTick.java
@@ -21,9 +21,10 @@ import java.util.List;
 
 import com.xeiam.xchart.Chart;
 import com.xeiam.xchart.internal.chartpart.Axis.AxisType;
-import com.xeiam.xchart.internal.chartpart.gridstep.DateGridStep;
-import com.xeiam.xchart.internal.chartpart.gridstep.DecimalGridStep;
-import com.xeiam.xchart.internal.chartpart.gridstep.GridStep;
+import com.xeiam.xchart.internal.chartpart.axistickcalculator.AxisTickCalculator;
+import com.xeiam.xchart.internal.chartpart.axistickcalculator.DateAxisTickCalculator;
+import com.xeiam.xchart.internal.chartpart.axistickcalculator.DecimalAxisTickCalculator;
+import com.xeiam.xchart.internal.chartpart.axistickcalculator.LogarithmicAxisTickCalculator;
 
 /**
  * An axis tick
@@ -45,7 +46,7 @@ public class AxisTick implements ChartPart {
   /** the visibility state of axistick */
   private boolean isVisible = true; // default to true
 
-  GridStep gridStep = null;
+  AxisTickCalculator gridStep = null;
 
   /**
    * Constructor
@@ -81,22 +82,19 @@ public class AxisTick implements ChartPart {
       // System.out.println("workingspace= " + workingSpace);
     }
 
-    // ////////////////////////
-
     if (axis.getAxisType() == AxisType.Number) {
 
-      gridStep = new DecimalGridStep(axis.getDirection(), workingSpace, axis.getMin(), axis.getMax(), getChart().getStyleManager());
+      gridStep = new DecimalAxisTickCalculator(axis.getDirection(), workingSpace, axis.getMin(), axis.getMax(), getChart().getStyleManager());
 
     } else if (axis.getAxisType() == AxisType.Date) {
 
-      gridStep = new DateGridStep(axis.getDirection(), workingSpace, axis.getMin(), axis.getMax(), getChart().getStyleManager());
+      gridStep = new DateAxisTickCalculator(axis.getDirection(), workingSpace, axis.getMin(), axis.getMax(), getChart().getStyleManager());
 
     } else if (axis.getAxisType() == AxisType.Logarithmic) {
 
+      gridStep = new LogarithmicAxisTickCalculator(axis.getDirection(), workingSpace, axis.getMin(), axis.getMax(), getChart().getStyleManager());
     }
 
-    // /////////////////////////
-
     if (isVisible) {
 
       axisTickLabels.paint(g);
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/GridStep.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/AxisTickCalculator.java
similarity index 92%
rename from xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/GridStep.java
rename to xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/AxisTickCalculator.java
index f10ec2bf..8a924230 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/GridStep.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/AxisTickCalculator.java
@@ -19,14 +19,14 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-package com.xeiam.xchart.internal.chartpart.gridstep;
+package com.xeiam.xchart.internal.chartpart.axistickcalculator;
 
 import java.util.List;
 
 /**
  * @author timmolter
  */
-public interface GridStep {
+public interface AxisTickCalculator {
 
   public List<Integer> getTickLocations();
 
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DateGridStep.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateAxisTickCalculator.java
similarity index 93%
rename from xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DateGridStep.java
rename to xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateAxisTickCalculator.java
index d27af6eb..fd93c28c 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DateGridStep.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateAxisTickCalculator.java
@@ -19,7 +19,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-package com.xeiam.xchart.internal.chartpart.gridstep;
+package com.xeiam.xchart.internal.chartpart.axistickcalculator;
 
 import java.math.BigDecimal;
 import java.util.LinkedList;
@@ -30,9 +30,11 @@ import com.xeiam.xchart.internal.chartpart.AxisPair;
 import com.xeiam.xchart.style.StyleManager;
 
 /**
+ * This class encapsulates the logic to generate the axis tick mark and axis tick label data for rendering the axis ticks for date axes
+ * 
  * @author timmolter
  */
-public class DateGridStep implements GridStep {
+public class DateAxisTickCalculator implements AxisTickCalculator {
 
   /** the default tick mark step hint for x axis */
   private static final int DEFAULT_TICK_MARK_STEP_HINT_X = 74;
@@ -63,8 +65,9 @@ public class DateGridStep implements GridStep {
    * @param workingSpace
    * @param minValue
    * @param maxValue
+   * @param styleManager
    */
-  public DateGridStep(Direction axisDirection, int workingSpace, BigDecimal minValue, BigDecimal maxValue, StyleManager styleManager) {
+  public DateAxisTickCalculator(Direction axisDirection, int workingSpace, BigDecimal minValue, BigDecimal maxValue, StyleManager styleManager) {
 
     this.axisDirection = axisDirection;
     this.workingSpace = workingSpace;
@@ -72,10 +75,10 @@ public class DateGridStep implements GridStep {
     this.maxValue = maxValue;
     this.styleManager = styleManager;
 
-    go();
+    calculate();
   }
 
-  private void go() {
+  private void calculate() {
 
     // a check if all axis data are the exact same values
     if (minValue == maxValue) {
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DateFormatter.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateFormatter.java
similarity index 98%
rename from xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DateFormatter.java
rename to xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateFormatter.java
index 21fae0c6..448002e0 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DateFormatter.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DateFormatter.java
@@ -19,7 +19,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-package com.xeiam.xchart.internal.chartpart.gridstep;
+package com.xeiam.xchart.internal.chartpart.axistickcalculator;
 
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DecimalGridStep.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DecimalAxisTickCalculator.java
similarity index 94%
rename from xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DecimalGridStep.java
rename to xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DecimalAxisTickCalculator.java
index b1426418..f22f06ed 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DecimalGridStep.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DecimalAxisTickCalculator.java
@@ -19,7 +19,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-package com.xeiam.xchart.internal.chartpart.gridstep;
+package com.xeiam.xchart.internal.chartpart.axistickcalculator;
 
 import java.math.BigDecimal;
 import java.util.LinkedList;
@@ -30,11 +30,11 @@ import com.xeiam.xchart.internal.chartpart.AxisPair;
 import com.xeiam.xchart.style.StyleManager;
 
 /**
- * This class encapsulates the logic to generate the axis tick mark and axis tick label data for rendering the axis ticks for decimla axes
+ * This class encapsulates the logic to generate the axis tick mark and axis tick label data for rendering the axis ticks for decimal axes
  * 
  * @author timmolter
  */
-public class DecimalGridStep implements GridStep {
+public class DecimalAxisTickCalculator implements AxisTickCalculator {
 
   /** the default tick mark step hint for x axis */
   private static final int DEFAULT_TICK_MARK_STEP_HINT_X = 74;
@@ -65,8 +65,9 @@ public class DecimalGridStep implements GridStep {
    * @param workingSpace
    * @param minValue
    * @param maxValue
+   * @param styleManager
    */
-  public DecimalGridStep(Direction axisDirection, int workingSpace, BigDecimal minValue, BigDecimal maxValue, StyleManager styleManager) {
+  public DecimalAxisTickCalculator(Direction axisDirection, int workingSpace, BigDecimal minValue, BigDecimal maxValue, StyleManager styleManager) {
 
     this.axisDirection = axisDirection;
     this.workingSpace = workingSpace;
@@ -74,10 +75,10 @@ public class DecimalGridStep implements GridStep {
     this.maxValue = maxValue;
     this.styleManager = styleManager;
 
-    go();
+    calculate();
   }
 
-  private void go() {
+  private void calculate() {
 
     // a check if all axis data are the exact same values
     if (minValue == maxValue) {
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DecimalFormatter.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DecimalFormatter.java
similarity index 98%
rename from xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DecimalFormatter.java
rename to xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DecimalFormatter.java
index abf2d54d..27fb6d48 100644
--- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/gridstep/DecimalFormatter.java
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/DecimalFormatter.java
@@ -19,7 +19,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-package com.xeiam.xchart.internal.chartpart.gridstep;
+package com.xeiam.xchart.internal.chartpart.axistickcalculator;
 
 import java.math.BigDecimal;
 import java.text.DecimalFormat;
diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/LogarithmicAxisTickCalculator.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/LogarithmicAxisTickCalculator.java
new file mode 100644
index 00000000..7cd44ab0
--- /dev/null
+++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/axistickcalculator/LogarithmicAxisTickCalculator.java
@@ -0,0 +1,208 @@
+/**
+ * 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.util.LinkedList;
+import java.util.List;
+
+import com.xeiam.xchart.internal.chartpart.Axis.Direction;
+import com.xeiam.xchart.internal.chartpart.AxisPair;
+import com.xeiam.xchart.style.StyleManager;
+
+/**
+ * This class encapsulates the logic to generate the axis tick mark and axis tick label data for rendering the axis ticks for decimal axes
+ * 
+ * @author timmolter
+ */
+public class LogarithmicAxisTickCalculator implements AxisTickCalculator {
+
+  /** the default tick mark step hint for x axis */
+  private static final int DEFAULT_TICK_MARK_STEP_HINT_X = 74;
+
+  /** the default tick mark step hint for y axis */
+  private static final int DEFAULT_TICK_MARK_STEP_HINT_Y = 44;
+
+  /** the List of tick label position in pixels */
+  private List<Integer> tickLocations = new LinkedList<Integer>();;
+
+  /** the List of tick label values */
+  private List<String> tickLabels = new LinkedList<String>();
+
+  private final Direction axisDirection;
+
+  private final int workingSpace;
+
+  private final BigDecimal minValue;
+
+  private final BigDecimal maxValue;
+
+  private final StyleManager styleManager;
+
+  /**
+   * Constructor
+   * 
+   * @param axisDirection
+   * @param workingSpace
+   * @param minValue
+   * @param maxValue
+   * @param styleManager
+   */
+  public LogarithmicAxisTickCalculator(Direction axisDirection, int workingSpace, BigDecimal minValue, BigDecimal maxValue, StyleManager styleManager) {
+
+    this.axisDirection = axisDirection;
+    this.workingSpace = workingSpace;
+    this.minValue = minValue;
+    this.maxValue = maxValue;
+    this.styleManager = styleManager;
+
+    calculate();
+  }
+
+  private void calculate() {
+
+    // a check if all axis data are the exact same values
+    if (minValue == maxValue) {
+      tickLabels.add(styleManager.getDecimalFormatter().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
+    System.out.println("tickSpace= " + tickSpace);
+
+    // 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 = getGridStepForDecimal(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(styleManager.getDecimalFormatter().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);
+    }
+  }
+
+  /**
+   * Determine the grid step for the data set given the space in pixels allocated for the axis
+   * 
+   * @param tickSpace in plot space
+   * @return
+   */
+  private BigDecimal getGridStepForDecimal(int tickSpace) {
+
+    // 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);
+
+    // for very short plots, squeeze some more ticks in than normal
+    if (axisDirection == Direction.Y && tickSpace < 160) {
+      tickMarkSpaceHint = 25;
+    }
+
+    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;
+  }
+
+  /**
+   * 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;
+  }
+
+  private BigDecimal getFirstPosition(final BigDecimal min, BigDecimal gridStep) {
+
+    BigDecimal firstPosition;
+    if (min.remainder(gridStep).doubleValue() <= 0.0) {
+      firstPosition = min.subtract(min.remainder(gridStep));
+    } else {
+      firstPosition = min.subtract(min.remainder(gridStep)).add(gridStep);
+    }
+    return firstPosition;
+  }
+
+  @Override
+  public List<Integer> getTickLocations() {
+
+    return tickLocations;
+  }
+
+  @Override
+  public List<String> getTickLabels() {
+
+    return tickLabels;
+  }
+
+}
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 32b9701b..37ad7c29 100644
--- a/xchart/src/main/java/com/xeiam/xchart/style/StyleManager.java
+++ b/xchart/src/main/java/com/xeiam/xchart/style/StyleManager.java
@@ -25,8 +25,8 @@ import java.awt.Color;
 import java.awt.Font;
 import java.awt.Stroke;
 
-import com.xeiam.xchart.internal.chartpart.gridstep.DateFormatter;
-import com.xeiam.xchart.internal.chartpart.gridstep.DecimalFormatter;
+import com.xeiam.xchart.internal.chartpart.axistickcalculator.DateFormatter;
+import com.xeiam.xchart.internal.chartpart.axistickcalculator.DecimalFormatter;
 import com.xeiam.xchart.style.theme.Theme;
 import com.xeiam.xchart.style.theme.XChartTheme;
 
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 4edb9ce5..61321f15 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,8 @@ import java.util.TimeZone;
 
 import org.junit.Test;
 
-import com.xeiam.xchart.internal.chartpart.gridstep.DateFormatter;
-import com.xeiam.xchart.internal.chartpart.gridstep.DecimalFormatter;
+import com.xeiam.xchart.internal.chartpart.axistickcalculator.DateFormatter;
+import com.xeiam.xchart.internal.chartpart.axistickcalculator.DecimalFormatter;
 
 /**
  * @author timmolter
-- 
GitLab