package games.strategy.ui;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import games.strategy.util.ListenerList;
public class DoubleTextField extends JTextField {
private static final long serialVersionUID = -8698753345852617343L;
private double m_max = Double.MAX_VALUE;
private double m_min = Double.MIN_VALUE;
private String m_terr = null;
private final ListenerList<DoubleTextFieldChangeListener> m_listeners =
new ListenerList<>();
/** Creates new DoubleTextField. */
public DoubleTextField() {
super(10);
initTextField();
}
public DoubleTextField(final double min) {
this();
setMin(min);
}
public DoubleTextField(final double min, final double max) {
this();
setMin(min);
setMax(max);
}
private void initTextField() {
setDocument(new DoubleDocument());
setText(String.valueOf(m_min));
addFocusListener(new LostFocus());
}
public double getValue() {
return Double.parseDouble(getText());
}
private void checkValue() {
if (getText().trim().equals("-")) {
setText(String.valueOf(m_min));
}
try {
Double.parseDouble(getText());
} catch (final NumberFormatException e) {
setText(String.valueOf(m_min));
}
if (getValue() > m_max) {
setText(String.valueOf(m_max));
}
if (getValue() < m_min) {
setText(String.valueOf(m_min));
}
}
public void setValue(final double value) {
if (isGood(value)) {
setText(String.valueOf(value));
}
}
public void setMax(final double max) {
if (max < m_min) {
throw new IllegalArgumentException(
"Max cant be less than min. Current Min: " + m_min + ", Current Max: " + m_max + ", New Max: " + max);
}
m_max = max;
if (getValue() > m_max) {
setText(String.valueOf(max));
}
}
public void setTerr(final String terr) {
m_terr = terr;
}
public void setMin(final double min) {
if (min > m_max) {
throw new IllegalArgumentException(
"Min cant be greater than max. Current Max: " + m_max + ", Current Min: " + m_min + ", New Min: " + min);
}
m_min = min;
if (getValue() < m_min) {
setText(String.valueOf(min));
}
}
public double getMax() {
return m_max;
}
public String getTerr() {
return m_terr;
}
public double getMin() {
return m_min;
}
private boolean isGood(final double value) {
return value <= m_max && value >= m_min;
}
/**
* Make sure that no non numeric data is typed.
*/
private class DoubleDocument extends PlainDocument {
private static final long serialVersionUID = 64683753745223443L;
@Override
public void insertString(final int offs, final String str, final AttributeSet a) throws BadLocationException {
final String currentText = this.getText(0, getLength());
final String beforeOffset = currentText.substring(0, offs);
final String afterOffset = currentText.substring(offs, currentText.length());
final String proposedResult = beforeOffset + str + afterOffset;
// allow start of negative
try {
Double.parseDouble(proposedResult);
super.insertString(offs, str, a);
checkValue();
notifyListeners();
} catch (final NumberFormatException e) {
// if an error dont insert
// allow start of negative numbers
if (offs == 0) {
if (m_min < 0) {
if (str.equals("-")) {
super.insertString(offs, str, a);
}
}
}
}
}
@Override
public void remove(final int offs, final int len) throws BadLocationException {
super.remove(offs, len);
// if its a valid number weve changed
try {
Double.parseDouble(DoubleTextField.this.getText());
notifyListeners();
} catch (final NumberFormatException e) {
// ignore malformed input
}
}
}
public void addChangeListener(final DoubleTextFieldChangeListener listener) {
m_listeners.add(listener);
}
public void removeChangeListener(final DoubleTextFieldChangeListener listener) {
m_listeners.remove(listener);
}
private void notifyListeners() {
for (final DoubleTextFieldChangeListener listener : m_listeners) {
listener.changedValue(this);
}
}
private class LostFocus extends FocusAdapter {
@Override
public void focusLost(final FocusEvent e) {
// make sure the value is valid
checkValue();
}
}
}