package org.simantics.datatypes.literal; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; import org.simantics.common.format.Formatter; import org.simantics.databoard.Bindings; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.util.Bean; public class DecimalFormatFormatter extends Bean implements Formatter { public static final Binding BINDING = Bindings.getBindingUnchecked(DecimalFormatFormatter.class); public String formatString; private volatile DecimalFormat format; public DecimalFormatFormatter() { this("0.###############"); } public DecimalFormatFormatter(String formatString) { if (formatString == null) throw new NullPointerException("null formatString"); this.formatString = formatString; } public DecimalFormat getFormat() { if(format == null) { format = new java.text.DecimalFormat(formatString, DecimalFormatSymbols.getInstance(Locale.US)); } return format; } @Override public String format(Object object) { if (object instanceof String) return object.toString(); else if (object instanceof Number) { DecimalFormat format = getFormat(); // System.out.println("formatString: " + formatString); int integers = format.getMaximumIntegerDigits(); //System.out.println(" integers: " + integers); if (integers == Integer.MAX_VALUE) { // Parse number of integer digits from format string. integers = countIntegerDigits(formatString); } //System.out.println(" decimals: " + format.getMaximumFractionDigits()); //System.out.println(" integers: " + format.getMinimumIntegerDigits()); //System.out.println(" decimals: " + format.getMinimumFractionDigits()); String result = format.format(object); //System.out.println("result: " + result); int resultIntegers = countResultDigits(result); //System.out.println(" result integers: " + resultIntegers); if (resultIntegers > integers) { // Guard against format.getMaximumFractionDigits returning Integer.MAX_VALUE int decimals = Math.min(format.getMaximumFractionDigits(), 15); return getLimitString(integers, decimals); } return result; } else { return object != null ? object.toString() : ""; } } private int countIntegerDigits(String formatString) { int digits = 0; int len = formatString.length(); boolean escape = false; for (int i = 0; i < len; ++i) { char ch = formatString.charAt(i); if (ch == '.') break; else if (ch == '\'') escape = true; else if (!escape && (ch == '#' || ch == '0')) ++digits; } return digits; } private int countResultDigits(String formattedString) { int digits = 0; int len = formattedString.length(); for (int i = 0; i < len; ++i) { char ch = formattedString.charAt(i); if (ch == '.') break; else if (Character.isDigit(ch)) ++digits; } return digits; } private String getLimitString(int integers, int decimals) { StringBuilder b = new StringBuilder(integers + decimals + 1); for(int i=0;i