All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nu.zoom.swing.field.FloatField Maven / Gradle / Ivy

Go to download

This project contains some utility classes that have been used in various projects throughout the years.

There is a newer version: 1.3.1
Show newest version
/*
 * Copyright (C) 2004 Johan Maasing johan at zoom.nu Licensed under the Apache
 * License, Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package nu.zoom.swing.field;

import java.text.*;
import java.awt.Toolkit;
import javax.swing.*;
import javax.swing.text.*;

/**
 * This class implements a swing JTextField which only accepts float numbers. It
 * does so by checking anything entered in the field and at all times it must be
 * parsable as a float value. This means you can't enter plain text or other
 * symbols in the field. It has some utility methods to put and retrieve the
 * float value directly. 
* Default values for the field are approx. 11 columns width. The formatter used * is initialized to display max 6 integer numbers, max 6 fraction numbers and * min 1 fraction number. This will be noticeable by e.g. using * setValue(0.123456789f) ; where the field will truncate the value to * 0.123456. To change these default values you can retrieve the formatter by * the get/setFormatter methods.
* In the spirit of most of Swing this class is not thread safe. * * @author $Author: johan $ * @version $Revision: 1.2 $ */ @SuppressWarnings("serial") public class FloatField extends JTextField { protected DecimalFormat formatter; /** * Constructs a FloatField with the default values and initialized to 0.0. */ public FloatField() { super(11); setDocument(new TexCoordDocument()); formatter = new DecimalFormat(); formatter.setMaximumFractionDigits(6); formatter.setMinimumFractionDigits(1); formatter.setMaximumIntegerDigits(6); formatter.setDecimalSeparatorAlwaysShown(true); formatter.setGroupingUsed(false); setValue(0.0f); } /** * Constructs a FloatField with the default values and initialized with a * value. * * @param value * The intitial float value the field will display. */ public FloatField(float value) { super(11); setDocument(new TexCoordDocument()); formatter = new DecimalFormat(); formatter.setMaximumFractionDigits(6); formatter.setMinimumFractionDigits(1); formatter.setMaximumIntegerDigits(6); formatter.setDecimalSeparatorAlwaysShown(true); formatter.setGroupingUsed(false); setValue(value); } /** * Constructs a FloatField with the default values and initialized with a * value. * * @param value * The intitial float value the field will display. * @param enabled * Indicates if the field should initially be enabled for * editing. */ public FloatField(float value, boolean enabled) { super(11); setDocument(new TexCoordDocument()); formatter = new DecimalFormat(); formatter.setMaximumFractionDigits(6); formatter.setMinimumFractionDigits(1); formatter.setMaximumIntegerDigits(6); formatter.setDecimalSeparatorAlwaysShown(true); formatter.setGroupingUsed(false); setValue(value); setEnabled(enabled); } /** * Retrieves the float value displayed in the field. There is one case where * the field could actually be considered legal but still not contain a * float value, that is if the field have been emptied in which case an * exception will be thrown. * * @return The value currently in the field. * @throws ParseException * If the field does not contain a legal float value. */ public float getValue() throws ParseException { Number ret = formatter.parse(getText()); return ret.floatValue(); } /** * Set the value the field displays. * * @param value * The new value the field should display. */ public void setValue(float value) { String t = formatter.format(value); // This is the verbatim of the setText in JTextComponent try { Document doc = getDocument(); doc.remove(0, doc.getLength()); doc.insertString(0, t, null); } catch (BadLocationException e) { getToolkit().beep(); } } /** * Get a reference to the formatter the field uses to parse and format to * displayed number. * * @return The DecimalFormat object this field uses to format the output and * validate the input. */ public DecimalFormat getFormat() { return formatter; } /** * Set the formatter the field uses to parse and format numbers. * * @param format * The DecimalFormat the field should use in parsing and * formatting the value. */ public void setFormat(DecimalFormat format) { formatter = format; } /** * Overriden document to handle the validation of the value. */ class TexCoordDocument extends PlainDocument { ParsePosition ppos = new ParsePosition(0); TexCoordDocument() { super(); } public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { // Check special cases if ((str == null) || (str == "")) { // Empty string or null is special case. // They don't parse to a legal number but should be // allowed anyway to clear the text field int len = getLength(); try { remove(0, len); } catch (Exception exc) { System.err.println(exc.toString()); } return; } // Ordinary case, construct the proposed resulting string // and see if it parses to a number. // If the proposed result is not a number, beep the speaker // and ignore the change. String currentText = getText(0, getLength()); String beforeOffset = currentText.substring(0, offs); String afterOffset = currentText.substring(offs, currentText.length()); String proposedResult = beforeOffset + str + afterOffset; ppos.setIndex(0); formatter.parseObject(proposedResult, ppos); // Now check if the entire string could be parsed if (ppos.getIndex() == proposedResult.length()) { // Parsed OK super.insertString(offs, str, a); } else { // Parse failed Toolkit.getDefaultToolkit().beep(); } } public void remove(int offs, int len) throws BadLocationException { String currentText = getText(0, getLength()); String beforeOffset = currentText.substring(0, offs); String afterOffset = currentText.substring(len + offs, currentText.length()); String proposedResult = beforeOffset + afterOffset; if (proposedResult.length() == 0) { // Just empty the document super.remove(offs, len); } else { ppos.setIndex(0); formatter.parseObject(proposedResult, ppos); // Now check if the entire string could be parsed if (ppos.getIndex() == proposedResult.length()) { // Parsed OK super.remove(offs, len); } else { // Parse failed Toolkit.getDefaultToolkit().beep(); } } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy