001/* ----------------------------------------------------------------------------
002   The Kiwi Toolkit - A Java Class Library
003   Copyright (C) 1998-2004 Mark A. Lindner
004
005   This library is free software; you can redistribute it and/or
006   modify it under the terms of the GNU General Public License as
007   published by the Free Software Foundation; either version 2 of the
008   License, or (at your option) any later version.
009
010   This library is distributed in the hope that it will be useful,
011   but WITHOUT ANY WARRANTY; without even the implied warranty of
012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013   General Public License for more details.
014
015   You should have received a copy of the GNU General Public License
016   along with this library; if not, write to the Free Software
017   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018   02111-1307, USA.
019 
020   The author may be contacted at: mark_a_lindner@yahoo.com
021   ----------------------------------------------------------------------------
022   $Log: NumericField.java,v $
023   Revision 1.13  2004/05/12 18:50:22  markl
024   comment block updates
025
026   Revision 1.12  2004/03/16 06:43:39  markl
027   LocaleManager method change
028
029   Revision 1.11  2003/01/19 09:50:53  markl
030   Javadoc & comment header updates.
031
032   Revision 1.10  2001/03/20 00:54:52  markl
033   Fixed deprecated calls.
034
035   Revision 1.9  2001/03/12 09:27:59  markl
036   Source code and Javadoc cleanup.
037
038   Revision 1.8  1999/10/05 02:55:26  markl
039   Added screenshot
040
041   Revision 1.7  1999/07/29 06:45:19  markl
042   Changes to support length constraints.
043
044   Revision 1.6  1999/07/26 08:51:36  markl
045   Added getGrouping() and setGrouping() methods.
046
047   Revision 1.5  1999/07/25 13:40:54  markl
048   Minor enhancements and bug fixes.
049
050   Revision 1.4  1999/07/19 09:46:35  markl
051   More validation fixes.
052
053   Revision 1.3  1999/07/12 08:51:18  markl
054   Broke out common functionality.
055
056   Revision 1.2  1999/07/09 04:37:54  markl
057   Broke up into two classes.
058
059   Revision 1.1  1999/06/28 08:18:47  markl
060   Initial revision
061   ----------------------------------------------------------------------------
062*/
063
064package kiwi.ui;
065
066import java.awt.*;
067import java.awt.event.*;
068import java.text.*;
069import javax.swing.*;
070
071import kiwi.text.*;
072import kiwi.util.*;
073
074/** A subclass of <code>DataField</code> for the input and display of
075 * specialized data values, such as currency amounts, percentages, and decimal
076 * values.
077 *
078 * <p><center>
079 * <img src="snapshot/NumericField.gif"><br>
080 * <i>An example NumericField.</i>
081 * </center>
082 *
083 * @author Mark Lindner
084 */
085
086public class NumericField extends DataField
087  {
088  private static LocaleManager lm = LocaleManager.getDefault();
089  private int type, decimals = 2;
090  private double value = 0.0, maxValue, minValue;
091  private boolean hasMaxValue = false, hasMinValue = false, grouping = true;
092
093  /** Construct a new <code>NumericField</code> of the specified width and
094   * a default type of <code>DECIMAL_FORMAT</code>.
095   *
096   * @param width The width of the field.
097   */
098  
099  public NumericField(int width)
100    {
101    this(width, DECIMAL_FORMAT);
102    }
103
104  /** Construct a new <code>NumericField</code> of the specified width, for the
105   * specified value type.
106   *
107   * @param width The width of the field.
108   * @param type A validation type; one of the format constants defined in the
109   * <code>FormatConstants</code> class.
110   * @see kiwi.text.FormatConstants
111   *
112   */
113  
114  public NumericField(int width, int type)
115    {
116    super(width);
117    
118    setType(type);
119    setHorizontalAlignment(SwingConstants.RIGHT);
120    setFont(KiwiUtils.boldFont);
121    }
122
123  /** Set the numeric value to be displayed by this field. The value is
124   * formatted as a string, according to the rules of the current locale,
125   * and displayed in the field. Invalid input flagging is automatically
126   * turned off.
127   *
128   * @param value The value.
129   */
130  
131  public synchronized void setValue(double value)
132    {
133    this.value = value;
134    String s = "?";
135
136    switch(type)
137      {
138      case CURRENCY_FORMAT:
139        s = lm.formatCurrency(value, decimals, grouping);
140        break;
141
142      case PERCENTAGE_FORMAT:
143        s = lm.formatPercentage(value, decimals, grouping);
144        break;
145
146      case INTEGER_FORMAT:
147        s = lm.formatInteger((long)value, grouping);
148        break;
149        
150      case DECIMAL_FORMAT:
151      default:
152        s = lm.formatDecimal(value, decimals, grouping);
153        break;
154      }
155
156    setText(s);
157    invalid = false;
158    paintInvalid(invalid);
159    }
160
161  /** Set the numeric value to be displayed by this field.
162   *
163   * @param value The value. This value is cast internally to a double.
164   */
165
166  public void setValue(float value)
167    {
168    setValue((double)value);
169    }
170
171  /** Set the numeric value to be displayed by this field.
172   *
173   * @param value The value. This value is cast internally to a double.
174   */
175  
176  public void setValue(int value)
177    {
178    setValue((double)value);
179    }
180
181  /** Set the numeric value to be displayed by this field.
182   *
183   * @param value The value. This value is cast internally to a double.
184   */
185  
186  public void setValue(long value)
187    {
188    setValue((double)value);
189    }
190
191  /** Set the numeric value to be displayed by this field.
192   *
193   * @param value The value. This value is cast internally to a double.
194   */
195  
196  public void setValue(short value)
197    {
198    setValue((double)value);
199    }
200  
201  /** Set the validation type for this field.
202   *
203   * @param type A validation type; one of the format constants defined in the
204   * <code>FormatConstants</code> class.
205   * @see kiwi.text.FormatConstants
206   */
207
208  public void setType(int type)
209    {
210    this.type = type;
211
212    if(type == INTEGER_FORMAT)
213      setDecimals(0);
214    else
215      setDecimals(2);
216    
217    validateInput();
218    }
219
220  /** Get the validation type for this field.
221   *
222   * @return The validation type.
223   */
224  
225  public int getType()
226    {
227    return(type);
228    }
229  
230  /** Get the value from the field. The value returned is the value that
231   * was parsed by the last call to <code>validateInput()</code>.
232   *
233   * @return The parsed value, or 0.0 if the last call to
234   * <code>validateInput()</code> resulted in a parsing error, or if there was
235   * no previous call to <code>validateInput()</code>.
236   * @see #validateInput
237   */
238  
239  public synchronized double getValue()
240    {
241    String text = getText().trim();
242
243    try
244      {
245      switch(type)
246        {
247        case CURRENCY_FORMAT:
248          value = lm.parseCurrency(text);
249          break;
250
251        case PERCENTAGE_FORMAT:
252          value = lm.parsePercentage(text);
253          break;
254
255        case INTEGER_FORMAT:
256          value = (double)lm.parseInteger(text);
257          break;
258
259        case DECIMAL_FORMAT:
260        default:
261          value = lm.parseDecimal(text);
262          break;
263        }
264
265      if(hasMinValue && (value < minValue))
266        invalid = true;
267
268      if(hasMaxValue && (value > maxValue))
269        invalid = true;
270      }
271    catch(ParseException ex)
272      {
273      invalid = true;
274      }
275
276    return(value);
277    }
278
279  /** Validate the input in this field.
280   *
281   * @return <code>true</code> if the field contains valid input, and
282   * <code>false</code> otherwise.
283   */
284  
285  protected boolean checkInput()
286    {
287    invalid = false;
288
289    double v = getValue();
290
291    if(!invalid)
292      setValue(v);
293
294    paintInvalid(invalid);
295
296    return(!invalid);
297    }
298
299  /** Set the number of decimals to display to the right of the radix. The
300   * default is 2.
301   *
302   * @param decimals The new decimal count.
303   */
304  
305  public void setDecimals(int decimals)
306    {
307    if(decimals < 0)
308      decimals = 0;
309    
310    this.decimals = decimals;
311    }
312
313  /** Get the number of decimals being displayed to the right of the radix.
314   *
315   * @return The decimal count.
316   */
317
318  public int getDecimals()
319    {
320    return(decimals);
321    }
322
323  /** Set a maximum value constraint. If a value is entered that is greater
324   * than the maximum value, the input will not validate.
325   *
326   * @param value The new maximum value.
327   */
328  
329  public void setMaxValue(double value)
330    {
331    maxValue = value;
332    hasMaxValue = true;
333    }
334
335  /** Set a maximum value constraint. If a value is entered that is greater
336   * than the maximum value, the input will not validate.
337   *
338   * @since Kiwi 1.3
339   *
340   * @param value The new maximum value.
341   */
342  
343  public void setMaxValue(int value)
344    {
345    setMaxValue((double)value);
346    }
347  
348  /** Clear the maximum value constraint.
349   */
350
351  public void clearMaxValue()
352    {
353    hasMaxValue = false;
354    }
355
356  /** Set a minimum value constraint. If a value is entered that is less than
357   * the minimum value, the input will not validate.
358   *
359   * @param value The new minimum value.
360   */
361  
362  public void setMinValue(double value)
363    {
364    minValue = value;
365    hasMinValue = true;
366    }
367
368  /** Set a minimum value constraint. If a value is entered that is less than
369   * the minimum value, the input will not validate.
370   *
371   * @since Kiwi 1.3
372   *
373   * @param value The new minimum value.
374   */
375  
376  public void setMinValue(int value)
377    {
378    setMinValue((double)value);
379    }
380  
381  /** Clear the minimum value constraint.
382   */
383  
384  public void clearMinValue()
385    {
386    hasMinValue = false;
387    }
388
389  /** Set the grouping mode for this numeric field. If grouping is turned
390   * off, values will be formatted without grouping characters separating the
391   * thousands. The default mode is on.
392   *
393   * @param grouping A flag specifying whether grouping should be on
394   * (<code>true</code>) or off (<code>false</code>).
395   */
396   
397  public void setGrouping(boolean grouping)
398    {
399    this.grouping = grouping;
400    }
401
402  /** Get the grouping mode for this numeric field.
403   *
404   * @return The current grouping mode.
405   */
406    
407  public boolean getGrouping()
408    {
409    return(grouping);
410    }
411
412  }
413
414/* end of source file */