JAL-3261 tidy up get/set properties in Cache, Javadoc, tests
[jalview.git] / src / jalview / util / Format.java
index d85013c..0f12eb8 100755 (executable)
@@ -1,19 +1,22 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
- * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
  * Jalview is free software: you can redistribute it and/or
  * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
- * 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
  * Jalview is distributed in the hope that it will be useful, but 
  * WITHOUT ANY WARRANTY; without even the implied warranty 
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
  * PURPOSE.  See the GNU General Public License for more details.
  * 
- * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 /**
  * A class for formatting numbers that follows printf conventions.
  */
 package jalview.util;
 
+import java.util.Arrays;
+
 /**
- * DOCUMENT ME!
+ * A utility class that provides a variety of formatting methods.
+ * 
+ * Principle method {@code format} formats the number following printf
+ * conventions. Main limitation: Can only handle one format parameter at a time
+ * Use multiple Format objects to format more than one number
  * 
- * @author $author$
- * @version $Revision$
+ * @author unknown
  */
 public class Format
 {
@@ -51,14 +59,64 @@ public class Format
 
   private char fmt; // one of cdeEfgGiosxXos
 
+  private final String formatString;
+
   /**
-   * Creates a new Format object.
+   * Creates a new Format object given a format descriptor, which follows printf
+   * conventions The string has a prefix, a format code and a suffix. The prefix
+   * and suffix become part of the formatted output. The format code directs the
+   * formatting of the (single) parameter to be formatted. The code has the
+   * following structure
+   * <ul>
+   * <li>a % (required)
+   * <li>a modifier (optional)
+   * <dl>
+   * <dt>+
+   * <dd>forces display of + for positive numbers
+   * <dt>0
+   * <dd>show leading zeroes
+   * <dt>-
+   * <dd>align left in the field
+   * <dt>space
+   * <dd>prepend a space in front of positive numbers
+   * <dt>#
+   * <dd>use "alternate" format. Add 0 or 0x for octal or hexadecimal numbers.
+   * Don't suppress trailing zeroes in general floating point format.
+   * </dl>
+   * <li>an integer denoting field width (optional)
+   * <li>a period followed by an integer denoting precision (optional)
+   * <li>a format descriptor (required)
+   * <dl>
+   * <dt>f
+   * <dd>floating point number in fixed format
+   * <dt>e, E
+   * <dd>floating point number in exponential notation (scientific format). The
+   * E format results in an uppercase E for the exponent (1.14130E+003), the e
+   * format in a lowercase e.
+   * <dt>g, G
+   * <dd>floating point number in general format (fixed format for small
+   * numbers, exponential format for large numbers). Trailing zeroes are
+   * suppressed. The G format results in an uppercase E for the exponent (if
+   * any), the g format in a lowercase e.
+   * <dt>d, i
+   * <dd>integer in decimal
+   * <dt>x
+   * <dd>integer in hexadecimal
+   * <dt>o
+   * <dd>integer in octal
+   * <dt>s
+   * <dd>string
+   * <dt>c
+   * <dd>character
+   * </dl>
+   * </ul>
    * 
    * @param s
-   *          DOCUMENT ME!
+   *          the format descriptor
    */
-  public Format(String s)
+  public Format(final String s)
   {
+    formatString = s;
     width = 0;
     precision = -1;
     pre = "";
@@ -206,63 +264,11 @@ public class Format
   }
 
   /**
-   * Formats the number following printf conventions. Main limitation: Can only
-   * handle one format parameter at a time Use multiple Format objects to format
-   * more than one number
-   * 
-   * @param s
-   *          the format string following printf conventions The string has a
-   *          prefix, a format code and a suffix. The prefix and suffix become
-   *          part of the formatted output. The format code directs the
-   *          formatting of the (single) parameter to be formatted. The code has
-   *          the following structure
-   *          <ul>
-   *          <li>a % (required)
-   *          <li>a modifier (optional)
-   *          <dl>
-   *          <dt>+
-   *          <dd>forces display of + for positive numbers
-   *          <dt>0
-   *          <dd>show leading zeroes
-   *          <dt>-
-   *          <dd>align left in the field
-   *          <dt>space
-   *          <dd>prepend a space in front of positive numbers
-   *          <dt>#
-   *          <dd>use "alternate" format. Add 0 or 0x for octal or hexadecimal
-   *          numbers. Don't suppress trailing zeroes in general floating point
-   *          format.
-   *          </dl>
-   *          <li>an integer denoting field width (optional)
-   *          <li>a period followed by an integer denoting precision (optional)
-   *          <li>a format descriptor (required)
-   *          <dl>
-   *          <dt>f
-   *          <dd>floating point number in fixed format
-   *          <dt>e, E
-   *          <dd>floating point number in exponential notation (scientific
-   *          format). The E format results in an uppercase E for the exponent
-   *          (1.14130E+003), the e format in a lowercase e.
-   *          <dt>g, G
-   *          <dd>floating point number in general format (fixed format for
-   *          small numbers, exponential format for large numbers). Trailing
-   *          zeroes are suppressed. The G format results in an uppercase E for
-   *          the exponent (if any), the g format in a lowercase e.
-   *          <dt>d, i
-   *          <dd>integer in decimal
-   *          <dt>x
-   *          <dd>integer in hexadecimal
-   *          <dt>o
-   *          <dd>integer in octal
-   *          <dt>s
-   *          <dd>string
-   *          <dt>c
-   *          <dd>character
-   *          </dl>
-   *          </ul>
-   * @exception IllegalArgumentException
-   *              if bad format
+   * Returns a 6 character string consisting of the hex values of the colour's
+   * rgb values (left padded with zeroes if necessary)
    * 
+   * @param color
+   * @return
    */
   public static String getHexString(java.awt.Color color)
   {
@@ -619,7 +625,7 @@ public class Format
   /**
    * Formats a character into a string (like sprintf in C)
    * 
-   * @param x
+   * @param debounceTrap
    *          the value to format
    * @return the formatted string
    */
@@ -638,7 +644,7 @@ public class Format
   /**
    * Formats a string into a larger string (like sprintf in C)
    * 
-   * @param x
+   * @param debounceTrap
    *          the value to format
    * @return the formatted string
    */
@@ -658,30 +664,22 @@ public class Format
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns a string consisting of n repeats of character c
    * 
    * @param c
-   *          DOCUMENT ME!
    * @param n
-   *          DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
-  private static String repeat(char c, int n)
+  static String repeat(char c, int n)
   {
     if (n <= 0)
     {
       return "";
     }
-
-    StringBuffer s = new StringBuffer(n);
-
-    for (int i = 0; i < n; i++)
-    {
-      s.append(c);
-    }
-
-    return s.toString();
+    char[] chars = new char[n];
+    Arrays.fill(chars, c);
+    return new String(chars);
   }
 
   /**
@@ -790,8 +788,8 @@ public class Format
     {
       w = width;
     }
-    else if (((fmt == 'd') || (fmt == 'i') || (fmt == 'x') || (fmt == 'X') || (fmt == 'o'))
-            && (precision > 0))
+    else if (((fmt == 'd') || (fmt == 'i') || (fmt == 'x') || (fmt == 'X')
+            || (fmt == 'o')) && (precision > 0))
     {
       w = precision;
     }
@@ -833,7 +831,8 @@ public class Format
     double factor = 1;
     String leading_zeroes = "";
 
-    for (int i = 1; (i <= precision) && (factor <= 0x7FFFFFFFFFFFFFFFL); i++)
+    for (int i = 1; (i <= precision)
+            && (factor <= 0x7FFFFFFFFFFFFFFFL); i++)
     {
       factor *= 10;
       leading_zeroes = leading_zeroes + "0";
@@ -884,21 +883,18 @@ public class Format
     String f = "";
     int e = 0;
     double dd = d;
-    double factor = 1;
 
     if (d != 0)
     {
       while (dd > 10)
       {
         e++;
-        factor /= 10;
         dd = dd / 10;
       }
 
       while (dd < 1)
       {
         e--;
-        factor *= 10;
         dd = dd * 10;
       }
     }
@@ -908,8 +904,7 @@ public class Format
       return fixed_format(d);
     }
 
-    d = d * factor;
-    f = f + fixed_format(d);
+    f = f + fixed_format(dd);
 
     if ((fmt == 'e') || (fmt == 'g'))
     {
@@ -935,4 +930,55 @@ public class Format
 
     return f + p.substring(p.length() - 3, p.length());
   }
+
+  @Override
+  public String toString()
+  {
+    return formatString;
+  }
+
+  /**
+   * Bespoke method to format percentage float value to the specified number of
+   * decimal places. Avoids use of general-purpose format parsers as a
+   * processing hotspot.
+   * 
+   * @param sb
+   * @param value
+   * @param dp
+   */
+  public static void appendPercentage(StringBuilder sb, float value, int dp)
+  {
+    /*
+     * rounding first
+     */
+    double d = value;
+    long factor = 1L;
+    for (int i = 0; i < dp; i++)
+    {
+      factor *= 10;
+    }
+    d *= factor;
+    d += 0.5;
+
+    /*
+     * integer part
+     */
+    value = (float) (d / factor);
+    sb.append((long) value);
+
+    /*
+     * decimal places
+     */
+    if (dp > 0)
+    {
+      sb.append(".");
+      while (dp > 0)
+      {
+        value = value - (int) value;
+        value *= 10;
+        sb.append((int) value);
+        dp--;
+      }
+    }
+  }
 }