KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jrobin > graph > ValueFormatter


1 /* ============================================================
2  * JRobin : Pure java implementation of RRDTool's functionality
3  * ============================================================
4  *
5  * Project Info: http://www.jrobin.org
6  * Project Lead: Sasa Markovic (saxon@jrobin.org)
7  *
8  * Developers: Sasa Markovic (saxon@jrobin.org)
9  * Arne Vandamme (cobralord@jrobin.org)
10  *
11  * (C) Copyright 2003, by Sasa Markovic.
12  *
13  * This library is free software; you can redistribute it and/or modify it under the terms
14  * of the GNU Lesser General Public License as published by the Free Software Foundation;
15  * either version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  * See the GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License along with this
22  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */

25 package org.jrobin.graph;
26
27 import java.util.Locale JavaDoc;
28 import java.text.NumberFormat JavaDoc;
29 import java.text.DecimalFormat JavaDoc;
30
31 /**
32  * <p>A <code>ValueFormatter</code> object is used to convert double values to a formatted string.
33  * The value can be scaled according to a specific base value (default: 1000) and an appropriate
34  * SI unit can be selected (k, M, G...).</p>
35  *
36  * @author Arne Vandamme (cobralord@jrobin.org)
37  * @author Sasa Markovic (saxon@jrobin.org)
38  */

39 class ValueFormatter
40 {
41     // ================================================================
42
// -- Members
43
// ================================================================
44
protected static final int NO_SCALE = -1;
45     protected static final double DEFAULT_BASE = 1000.0;
46     
47     private double base = DEFAULT_BASE;
48     private double[] scaleValues = new double[] {
49                                                     1e18, 1e15, 1e12, 1e9, 1e6, 1e3, 1e0, 1e-3, 1e-6, 1e-9, 1e-12, 1e-15
50                                                     };
51     protected static String JavaDoc[] PREFIXES = new String JavaDoc[] {
52                                                     "E", "P", "T", "G", "M", "k", " ", "m", "µ", "n", "p", "f"
53                                                     };
54                                             
55     private double value;
56     private DecimalFormat JavaDoc decFormat;
57     private int formattedStrLen;
58     
59     private double scaledValue;
60     private int scaleIndex = NO_SCALE; // Last used scale index
61
private int fixedIndex = NO_SCALE;
62     private String JavaDoc prefix;
63     
64     private boolean scale = false;
65     
66     
67     // ================================================================
68
// -- Constructors
69
// ================================================================
70
ValueFormatter() {
71     }
72     
73     /**
74      * Constructs a ValueFormatter object with a specific scaling base value, and a specific SI unit to use.
75      * @param base Double value of the scaling base.
76      * @param scaleIndex Index of the SI unit in the SI unit table called <code>PREFIXES</code>.
77      */

78     ValueFormatter( double base, int scaleIndex )
79     {
80         setBase( base );
81         this.fixedIndex = scaleIndex;
82     }
83     
84     
85     // ================================================================
86
// -- Protected methods
87
// ================================================================
88
/**
89      * Sets the value to format, the number of decimals the formatted string should have, and
90      * the entire string len of the formatted value. The formatted string will have whitespace
91      * prepended if the formatted string is shorter than the given length.
92      * @param value Double value that needs to be formatted.
93      * @param numDec Number of decimals that should be allowed in the formatted value.
94      * @param strLen Length of the complete formatted string.
95      */

96     void setFormat( double value, int numDec, int strLen )
97     {
98         this.value = value;
99         this.decFormat = getDecimalFormat( numDec );
100         this.formattedStrLen = strLen;
101     }
102     
103     /**
104      * Defines if the given value should be scaled using the set of SI units for a specific base value.
105      * @param normalScale True if normal scaling should be used, each value will be scaled with its own most
106      * appropriate SI unit.
107      * @param uniformScale True if uniform scaling should be used, each value will be scaled using the SI unit of the
108      * previously scaled value. Uniform scaling takes precendence over normal scaling.
109      */

110     void setScaling( boolean normalScale, boolean uniformScale )
111     {
112         if ( !uniformScale )
113             scaleIndex = NO_SCALE;
114         
115         if ( fixedIndex >= 0 ) {
116             scale = true;
117             scaleIndex = fixedIndex;
118         }
119         else {
120             scale = (normalScale || uniformScale);
121         }
122     }
123     
124     /**
125      * Formats the value with the given options and returns the result as a text string.
126      * @return String containing the formatted value.
127      */

128     String JavaDoc getFormattedValue()
129     {
130         String JavaDoc valueStr = "" + value;
131         
132         if ( !Double.isNaN(value) ) {
133             if ( scale ) {
134                 scaleValue( scaleIndex );
135                 valueStr = decFormat.format(scaledValue);
136             }
137             else
138                 valueStr = decFormat.format(value);
139         }
140         
141         // Fix the formatted string to the correct length
142
int diff = formattedStrLen - valueStr.length();
143         
144         StringBuffer JavaDoc preSpace = new StringBuffer JavaDoc("");
145         for (int i = 0; i < diff; i++)
146             preSpace.append(' ');
147             
148         valueStr = preSpace.append(valueStr).toString();
149         
150         return valueStr;
151     }
152     
153     /**
154      * Returns a more 'rounded' formatted value for use with grid steps.
155      * @return The scaled, rounded value as a <code>java.lang.String</code>.
156      */

157     String JavaDoc getScaledValue()
158     {
159         int tsv = scaleIndex;
160         scaleValue( tsv );
161         long intVal = new Double JavaDoc( scaledValue ).longValue();
162         
163         scaleIndex = tsv;
164         
165         if ( intVal == scaledValue )
166             return "" + intVal;
167         else
168             return "" + scaledValue;
169     }
170     
171     /**
172      * Sets the value of the scaling base, this base is used to determine when a scaled SI unit should be used.
173      * @param baseValue Double value of the scaling base.
174      */

175     void setBase( double baseValue )
176     {
177         if ( baseValue == this.base )
178             return;
179         
180         this.base = baseValue;
181         double tmp = 1;
182         for (int i = 1; i < 7; i++) {
183             tmp *= baseValue;
184             scaleValues[6 - i] = tmp;
185         }
186         tmp = 1;
187         for (int i = 7; i < scaleValues.length; i++) {
188             tmp *= baseValue;
189             scaleValues[i] = ( 1 / tmp );
190         }
191     }
192     
193     double getBase() {
194         return base;
195     }
196     
197     String JavaDoc getPrefix() {
198         return prefix;
199     }
200     
201     
202     // ================================================================
203
// -- Private methods
204
// ================================================================
205
/**
206      * Scales the given value based on the given options.
207      * @param scaleIndex Forced index of the SI unit in the <code>PREFIXES</code> table. <code>NO_SCALE</code> if not forced.
208      */

209     private void scaleValue( int scaleIndex )
210     {
211         double absValue = Math.abs(value);
212         if (scaleIndex == NO_SCALE)
213         {
214             this.prefix = " ";
215             this.scaledValue = value;
216         
217             for (int i = 0; i < scaleValues.length; i++)
218             {
219                 if (absValue >= scaleValues[i] && absValue < scaleValues[i] * base)
220                 {
221                     if ( scaleValues[i] != 1e-3 ) // Special case
222
{
223                         this.prefix = PREFIXES[i];
224                         this.scaledValue = value / scaleValues[i];
225                         this.scaleIndex = i;
226                         return;
227                     }
228                 }
229             }
230         }
231         else {
232             this.prefix = PREFIXES[scaleIndex];
233             this.scaledValue = value / scaleValues[scaleIndex];
234             this.scaleIndex = scaleIndex;
235         }
236     }
237     
238     /**
239      * Retrieves a <code>DecimalFormat</code> string to format the value, based on a given number of decimals that should
240      * be used.
241      * @param numDec Number of decimals to use in the formatted value.
242      * @return DecimalFormat to use for formatting.
243      */

244     private DecimalFormat JavaDoc getDecimalFormat( int numDec )
245     {
246         StringBuffer JavaDoc formatStr = new StringBuffer JavaDoc("###0"); // "#,##0", removed the 'grouping' separator
247
for(int i = 0; i < numDec; i++) {
248             if(i == 0) {
249                 formatStr.append('.');
250             }
251             formatStr.append('0');
252         }
253
254         NumberFormat JavaDoc nf = NumberFormat.getNumberInstance(Locale.ENGLISH);
255         DecimalFormat JavaDoc df = (DecimalFormat JavaDoc) nf;
256         df.applyPattern( formatStr.toString() );
257         
258         return df;
259     }
260 }
261
Popular Tags