package org.limewire.ui.swing.components;
import java.awt.Toolkit;
import javax.swing.JTextField;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
/**
* A JTextField component that only accepts integer values as input. Any other
* input will not be added and a system beep will be issued. Additionally,
* a min and max number can be set.
*/
public class NumericTextField extends JTextField {
/**
* Create a Textfield with a specified number of columns displayed.
*/
public NumericTextField(int columns) {
this(columns, 0, Integer.MAX_VALUE);
}
/**
* Create a Textfield with a specified number of columns displayed,
* and minimum and maximum integer values which will be accepted.
*/
public NumericTextField(int columns, int minValue, int maxValue) {
super(columns);
addIntegerWithMaxValueFilter(minValue, maxValue);
}
/**
* @return the value of the field as an int. If field is empty, or the field text
* cannot be retrieved as an int for any other reason, return the specified default value
*/
public int getValue(int defaultValue) {
try {
return Integer.parseInt(getText());
} catch (NumberFormatException e) {
setValue(defaultValue);
return defaultValue;
}
}
/**
* Given an int, set the content of the text field.
*
* @param value set on the field
*/
public void setValue(int value) {
setText(String.valueOf(value));
}
private void addIntegerWithMaxValueFilter(int minValue, int maxValue) {
((AbstractDocument) this.getDocument()).setDocumentFilter(new NumericDocumentFilter(minValue, maxValue));
}
class NumericDocumentFilter extends DocumentFilter {
private final int maxValue;
private final int minValue;
NumericDocumentFilter(int minValue, int maxValue) {
this.minValue = minValue;
this.maxValue = maxValue;
}
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
throws BadLocationException {
if (string == null)
return;
if (isValidValue(string, offset, 0)) {
super.insertString(fb, offset, string, attr);
} else {
Toolkit.getDefaultToolkit().beep();
}
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
if (text == null)
return;
if (isValidValue(text, offset, length)) {
super.replace(fb, offset, length, text, attrs);
} else {
Toolkit.getDefaultToolkit().beep();
}
}
private boolean isStringNumeric(String string) {
try {
Integer.parseInt(string);
} catch (NumberFormatException e) {
return false;
}
return true;
}
private boolean isValidValue(String text, int offset, int length) {
String currentValue = getText();
String newValue = currentValue.substring(0, offset) + text + currentValue.substring(offset+length);
if (isStringNumeric(newValue) &&
Integer.parseInt(newValue) >= minValue &&
Integer.parseInt(newValue) <= maxValue) {
return true;
}
return false;
}
}
}