ui/src/main/java/ucar/util/prefs/ui/Field.java
private static String formatDouble( double d, int min_sigFigs, int fixed_decimals) {
    String s = java.lang.Double.toString( d);

    if (java.lang.Double.isNaN(d)) return s;

    // extract the sign
    String sign;
    String unsigned;
    if ( s.startsWith( "-" ) || s.startsWith( "+" ) ) {
      sign = s.substring( 0, 1 );
      unsigned = s.substring( 1 );
    } else {
      sign = "";
      unsigned = s;
    }

    // deal with exponential notation
    String mantissa;
    String exponent;
    int eInd = unsigned.indexOf( 'E' );
    if ( eInd == -1 )
      eInd = unsigned.indexOf( 'e' );
    if ( eInd == -1 ) {
      mantissa = unsigned;
      exponent = "";
    } else {
      mantissa = unsigned.substring( 0, eInd );
      exponent = unsigned.substring( eInd );
    }

    // deal with decimal point
    StringBuffer number, fraction;
    int dotInd = mantissa.indexOf( '.' );
    if ( dotInd == -1 ) {
      number = new StringBuffer( mantissa );
      fraction = new StringBuffer( "" );
    } else {
      number = new StringBuffer( mantissa.substring( 0, dotInd ) );
      fraction = new StringBuffer( mantissa.substring( dotInd + 1 ) );
    }

    // number of significant figures
    int numFigs = number.length();
    int fracFigs = fraction.length();

    // can do either fixed_decimals or min_sigFigs
    if (fixed_decimals != -1) {
      if (fixed_decimals == 0) {
        fraction.setLength( 0 );
      } else if (fixed_decimals > fracFigs) {
        int want = fixed_decimals - fracFigs;
        for (int i=0; i<want; i++)
          fraction.append("0");
      } else if (fixed_decimals < fracFigs) {
        int chop = fracFigs - fixed_decimals;   // LOOK should round !!
        fraction.setLength( fraction.length() - chop );
      }
      fracFigs = fixed_decimals;

    } else {
            // Don't count leading zeros in the fraction, if no number
      if ( ( numFigs == 0 || number.toString().equals( "0" ) ) && fracFigs > 0 ) {
        numFigs = 0;
        number = new StringBuffer( "" );
        for ( int i = 0; i < fraction.length(); ++i ) {
          if ( fraction.charAt( i ) != '0' )
            break;
          --fracFigs;
        }
      }
        // Don't count trailing zeroes in the number if no fraction
      if ( ( fracFigs == 0) && numFigs > 0 ) {
        for ( int i=number.length()-1; i > 0; i-- ) {
          if ( number.charAt( i ) != '0' )
            break;
          --numFigs;
        }
      }
        // deal with min sig figures
      int sigFigs = numFigs + fracFigs;
      if (sigFigs > min_sigFigs) {
          // Want fewer figures in the fraction; chop (should round? )
        int chop = Math.min(sigFigs - min_sigFigs, fracFigs);
        fraction.setLength( fraction.length() - chop );
        fracFigs -= chop;
      }
    }


    /*int sigFigs = numFigs + fracFigs;
    if (sigFigs > max_sigFigs) {

      if (numFigs >= max_sigFigs) {  // enough sig figs in just the number part
        fraction.setLength( 0 );
        for ( int i=max_sigFigs; i<numFigs; ++i )
          number.setCharAt( i, '0' );  // should round?
      } else {

        // Want fewer figures in the fraction; chop (should round? )
        int chop = sigFigs - max_sigFigs;
        fraction.setLength( fraction.length() - chop );
      }
    }


    /* may want a fixed decimal place
    if (dec_places != -1) {

      if (dec_places == 0) {
        fraction.setLength( 0 );
        fracFigs = 0;
      } else if (dec_places > fracFigs) {
        int want = dec_places - fracFigs;
        for (int i=0; i<want; i++)
          fraction.append("0");
      } else if (dec_places < fracFigs) {
        int chop = fracFigs - dec_places;
        fraction.setLength( fraction.length() - chop );
        fracFigs = dec_places;
      }

    } */

    if ( fraction.length() == 0 )
      return sign + number + exponent;
    else
      return sign + number + "." + fraction + exponent;
  }

}
private static String formatDouble( double d, int min_sigFigs, int fixed_decimals) {
    String s = java.lang.Double.toString( d);

    if (java.lang.Double.isNaN(d)) return s;

    // extract the sign
    String sign;
    String unsigned;
    if ( s.startsWith( "-" ) || s.startsWith( "+" ) ) {
      sign = s.substring( 0, 1 );
      unsigned = s.substring( 1 );
    } else {
      sign = "";
      unsigned = s;
    }

    // deal with exponential notation
    String mantissa;
    String exponent;
    int eInd = unsigned.indexOf( 'E' );
    if ( eInd == -1 )
      eInd = unsigned.indexOf( 'e' );
    if ( eInd == -1 ) {
      mantissa = unsigned;
      exponent = "";
    } else {
      mantissa = unsigned.substring( 0, eInd );
      exponent = unsigned.substring( eInd );
    }

    // deal with decimal point
    StringBuffer number, fraction;
    int dotInd = mantissa.indexOf( '.' );
    if ( dotInd == -1 ) {
      number = new StringBuffer( mantissa );
      fraction = new StringBuffer( "" );
    } else {
      number = new StringBuffer( mantissa.substring( 0, dotInd ) );
      fraction = new StringBuffer( mantissa.substring( dotInd + 1 ) );
    }

    // number of significant figures
    int numFigs = number.length();
    int fracFigs = fraction.length();

    // can do either fixed_decimals or min_sigFigs
    if (fixed_decimals != -1) {
      if (fixed_decimals == 0) {
        fraction.setLength( 0 );
      } else if (fixed_decimals > fracFigs) {
        int want = fixed_decimals - fracFigs;
        for (int i=0; i<want; i++)
          fraction.append("0");
      } else if (fixed_decimals < fracFigs) {
        int chop = fracFigs - fixed_decimals;   // LOOK should round !!
        fraction.setLength( fraction.length() - chop );
      }
      fracFigs = fixed_decimals;

    } else {
            // Don't count leading zeros in the fraction, if no number
      if ( ( numFigs == 0 || number.toString().equals( "0" ) ) && fracFigs > 0 ) {
        numFigs = 0;
        number = new StringBuffer( "" );
        for ( int i = 0; i < fraction.length(); ++i ) {
          if ( fraction.charAt( i ) != '0' )
            break;
          --fracFigs;
        }
      }
        // Don't count trailing zeroes in the number if no fraction
      if ( ( fracFigs == 0) && numFigs > 0 ) {
        for ( int i=number.length()-1; i > 0; i-- ) {
          if ( number.charAt( i ) != '0' )
            break;
          --numFigs;
        }
      }
        // deal with min sig figures
      int sigFigs = numFigs + fracFigs;
      if (sigFigs > min_sigFigs) {
          // Want fewer figures in the fraction; chop (should round? )
        int chop = Math.min(sigFigs - min_sigFigs, fracFigs);
        fraction.setLength( fraction.length() - chop );
        fracFigs -= chop;
      }
    }


    /*int sigFigs = numFigs + fracFigs;
    if (sigFigs > max_sigFigs) {

      if (numFigs >= max_sigFigs) {  // enough sig figs in just the number part
        fraction.setLength( 0 );
        for ( int i=max_sigFigs; i<numFigs; ++i )
          number.setCharAt( i, '0' );  // should round?
      } else {

        // Want fewer figures in the fraction; chop (should round? )
        int chop = sigFigs - max_sigFigs;
        fraction.setLength( fraction.length() - chop );
      }
    }


    /* may want a fixed decimal place
    if (dec_places != -1) {

      if (dec_places == 0) {
        fraction.setLength( 0 );
        fracFigs = 0;
      } else if (dec_places > fracFigs) {
        int want = dec_places - fracFigs;
        for (int i=0; i<want; i++)
          fraction.append("0");
      } else if (dec_places < fracFigs) {
        int chop = fracFigs - dec_places;
        fraction.setLength( fraction.length() - chop );
        fracFigs = dec_places;
      }

    } */

    if ( fraction.length() == 0 )
      return sign + number + exponent;
    else
      return sign + number + "." + fraction + exponent;
  }

}
/* This dorks with Double.toString():

From Double.toString() (m = magnitude of the number):

If m is greater than or equal to 10^-3 but less than 10^7, then it is represented as the
integer part of m, in decimal form with no leading zeroes, followed by '.' (.),
followed by one or more decimal digits representing the fractional part of m.

If m is less than 10^-3 or greater than 10^7, then it is represented in scientific notation.
Let n be the unique integer such that 10n<=m<10n+1; then let a be the mathematically exact
quotient of m and 10n so that 1<=a<10. The magnitude is then represented as the integer part
of a, as a single decimal digit, followed by '.' (.), followed by decimal digits representing
the fractional part of a, followed by the letter 'E' (E), followed by a representation of n
as a decimal integer, as produced by the method Integer.toString(int).

How many digits must be printed for the fractional part of m or a? There must be
at least one digit to represent the fractional part, and beyond that as many,
but only as many, more digits as are needed to uniquely distinguish the argument
value from adjacent values of type double. That is, suppose that x is the exact
mathematical value represented by the decimal representation produced by this method
for a finite nonzero argument d. Then d must be the double value nearest to x; or if
two double values are equally close to x, then d must be one of them and the least
significant bit of the significand of d must be 0.