nu.zoom.swing.field.FloatField Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of base Show documentation
Show all versions of base Show documentation
This project contains some utility classes that have been used in various projects throughout the years.
/*
* 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