--- /dev/null
+package org.simantics.maps.sg;
+
+import java.util.Locale;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+class Formatting {
+
+ private static final transient double EPSILON = 0.01;
+
+ private static final transient double TRIM_THRESHOLD_MAX_VALUE = Math.pow(10, 4);
+
+ private static final transient String[] SI_UNIT_LARGE_PREFIXES = {
+ "k", "M", "G", "T", "P", "E", "Z", "Y"
+ };
+
+ public static enum FormatMode {
+ LIMIT_DIGITS,
+ LIMIT_DECIMALS,
+ }
+
+ public static String formatValue(double value, int max, boolean removeTrailingZeros, FormatMode formatMode) {
+ return formatValue(value, max, removeTrailingZeros, formatMode, TRIM_THRESHOLD_MAX_VALUE);
+ }
+
+ public static String formatValue(double value, int max, boolean removeTrailingZeros, FormatMode formatMode, double trimThresholdMaxValue) {
+ return formatValue(value, max, removeTrailingZeros, formatMode, trimThresholdMaxValue, true);
+ }
+
+ public static String formatValue(double value, int max, boolean removeTrailingZeros, FormatMode formatMode, double trimThresholdMaxValue, boolean trimLargeValues) {
+ //System.out.println("formatValue(" + value + ", " + max + ", " + removeTrailingZeros + ", " + formatMode + ", " + trimThresholdMaxValue + ", " + trimLargeValues + ")");
+ int allowedDecimals = max;
+ if (formatMode == FormatMode.LIMIT_DIGITS) {
+ int magnitude = (int) Math.ceil(Math.log10(Math.abs(value)));
+ //System.out.println("magnitude(" + value + "): " + magnitude);
+ allowedDecimals -= Math.abs(magnitude);
+ if (allowedDecimals < 0)
+ allowedDecimals = 0;
+ //System.out.println("allowedDecimals: " + allowedDecimals);
+ }
+
+ String valueStr = String.format(Locale.US, "%." + allowedDecimals + "f", value);
+ if (allowedDecimals > 0) {
+ if (removeTrailingZeros) {
+ for (int trunc = valueStr.length() - 1; trunc > 0; --trunc) {
+ char ch = valueStr.charAt(trunc);
+ if (ch == '.') {
+ valueStr = valueStr.substring(0, trunc);
+ break;
+ }
+ if (ch != '0') {
+ valueStr = valueStr.substring(0, trunc + 1);
+ break;
+ }
+ }
+ }
+ if (Math.abs(value) + EPSILON > trimThresholdMaxValue) {
+ // Cut anything beyond a possible decimal dot out since they
+ // should not show anyway. This is a complete hack that tries to
+ // circumvent floating-point inaccuracy problems.
+ int dotIndex = valueStr.lastIndexOf('.');
+ if (dotIndex > -1) {
+ valueStr = valueStr.substring(0, dotIndex);
+ }
+ }
+ }
+
+ if (valueStr.equals("-0"))
+ valueStr = "0";
+
+ if (trimLargeValues) {
+ double trimValue = value;
+ if (Math.abs(value) + EPSILON >= trimThresholdMaxValue) {
+ for (int i = 0; Math.abs(trimValue) + EPSILON >= trimThresholdMaxValue; ++i) {
+ double trim = trimValue / 1000;
+ if (Math.abs(trim) - EPSILON < trimThresholdMaxValue) {
+ valueStr = valueStr.substring(0, valueStr.length() - (i + 1) * 3);
+ valueStr += SI_UNIT_LARGE_PREFIXES[i];
+ break;
+ }
+ trimValue = trim;
+ }
+ }
+ }
+
+ //System.out.println("formatted result: " + valueStr);
+
+ return valueStr;
+ }
+
+}