/* * DecimalNumberField.java * Copyright 2003 (C) Greg Bingleman <byngl@hotmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Created on January 13, 2003, 2:05 AM */ package pcgen.util; import javax.swing.JTextField; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.PlainDocument; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.DecimalFormat; import java.text.ParseException; /** * This text field handles decimal numbers. * It should be moved to gui.utils. * * @author Greg Bingleman <byngl@hotmail.com> * @version $Revision$ */ public class DecimalNumberField extends JTextField { private static final long serialVersionUID = 8756733358669554185L; private DecimalFormat doubleFormatter; private Toolkit toolkit; private boolean allowSign = false; private double lastVal; /** * Constructor for DecimalNumberField. * @param value double * @param columns int */ public DecimalNumberField(double value, int columns) { super(columns); toolkit = Toolkit.getDefaultToolkit(); doubleFormatter = new DecimalFormat(); doubleFormatter.setParseIntegerOnly(false); setValue(value); addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { lastVal = doubleFormatter.parse(getText()).floatValue(); } catch (ParseException p) { setText(doubleFormatter.format(lastVal)); toolkit.beep(); } } }); } /** * Sets the field's value. * Final as it's called from constructor. * @param value double */ public final void setValue(double value) { lastVal = value; setText(doubleFormatter.format(value)); } /** * Gets the value from the field. * @return double */ public double getValue() { double retVal; try { String text = getText(); if (text == null || text.trim().length()==0) { text = "0"; } retVal = doubleFormatter.parse(text).doubleValue(); lastVal = retVal; } catch (ParseException e) { retVal = lastVal; setText(doubleFormatter.format(lastVal)); toolkit.beep(); } return retVal; } /** * Creates the document model. * @return Document */ @Override protected Document createDefaultModel() { return new DecimalNumberDocument(); } /** */ private class DecimalNumberDocument extends PlainDocument { /** * Inserts text if legal according to the settings. * @param offs int * @param str String * @param a AttributeSet * @throws BadLocationException * @see Document#insertString(int, String, AttributeSet) */ @Override public void insertString(final int offs, final String str, final AttributeSet a) throws BadLocationException { final char[] source = str.toCharArray(); final char[] result = new char[source.length]; int j = 0; String curText = ""; try { curText = getText(0, getLength()); } catch (BadLocationException n) { //TODO: Should this really be ignored? } boolean foundPoint = (curText.indexOf('.') >= 0); final boolean foundSign = (curText.indexOf('-') >= 0); for (int i = 0; i < result.length; ++i) { final char ch = source[i]; if (!allowSign && (ch == '-')) { toolkit.beep(); } else if ((ch == '-') && ((i + offs) == 0)) { if (!foundSign) { result[j++] = ch; } else { toolkit.beep(); } } else { if (foundSign && ((i + offs) == 0)) { toolkit.beep(); } else if ((ch == '.') && (!foundPoint)) { foundPoint = true; result[j++] = ch; } else { if (Character.isDigit(ch)) { result[j++] = ch; } else { toolkit.beep(); } } } } super.insertString(offs, new String(result, 0, j), a); } } }