/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Tiny Look and Feel *
* *
* (C) Copyright 2003 - 2007 Hans Bickel *
* *
* For licensing information and credits, please refer to the *
* comment in file de.muntjak.tinylookandfeel.TinyLookAndFeel *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package de.muntjak.tinylookandfeel.controlpanel;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
/**
* NumericTextField
*
* @version 1.0
* @author Hans Bickel
*/
public class NumericTextField extends JTextField {
private Vector listeners;
private ActionEvent actionEvent;
private int min, max, columns;
private boolean resistUpdate;
public NumericTextField(int columns, int value, int min, int max) {
super(columns);
this.columns = columns;
this.min = min;
this.max = max;
setHorizontalAlignment(JTextField.RIGHT);
setText("" + value);
addKeyListener(new ArrowKeyAction(this, min, max));
actionEvent = new ActionEvent(this, Event.ACTION_EVENT, "");
}
public int getValue() {
if(getText().length() == 0) return 0;
return Integer.parseInt(getText());
}
public void setValue(int newValue) {
if(resistUpdate) return;
setText(String.valueOf(newValue));
}
public void addActionListener(ActionListener l) {
if(listeners == null) {
listeners = new Vector();
}
if(listeners.contains(l)) return;
listeners.add(l);
}
public void removeActionListener(ActionListener l) {
if(listeners == null) return;
if(!listeners.contains(l)) return;
listeners.remove(l);
}
public void notifyActionListeners() {
if(listeners == null) return;
resistUpdate = true;
Iterator ii = listeners.iterator();
while(ii.hasNext()) {
((ActionListener)ii.next()).actionPerformed(actionEvent);
}
resistUpdate = false;
}
protected Document createDefaultModel() {
return new NumericDocument();
}
protected class NumericDocument extends PlainDocument {
NumericDocument() {
addDocumentListener(new KeyInputListener());
}
public void insertString(
int offs,
String str,
AttributeSet a) throws BadLocationException
{
if(str == null || str.length() == 0) return;
if(getLength() + str.length() > columns) return;
if(!checkInput(str)) {
Toolkit.getDefaultToolkit().beep();
return;
}
String text = getText(0, getLength());
if(offs == 0) {
text = str + text;
}
else if(offs >= text.length()) {
text += str;
}
else {
text = text.substring(0, offs) + str + text.substring(offs);
}
int val = Integer.parseInt(text);
boolean correct = false;
if(val < min) {
val = min;
correct = true;
}
else if(val > max) {
val = max;
correct = true;
}
if(correct) {
remove(0, getLength());
super.insertString(0, String.valueOf(val), a);
}
else {
super.insertString(offs, str, a);
}
}
private boolean checkInput(String s) {
for(int i = 0; i < s.length(); i++) {
if(!Character.isDigit(s.charAt(i))) {
return false;
}
}
return true;
}
}
class ArrowKeyAction extends KeyAdapter implements ActionListener {
private JTextField theField;
private javax.swing.Timer keyTimer;
private int step;
ArrowKeyAction(JTextField field, int min, int max) {
theField = field;
keyTimer = new javax.swing.Timer(20, this);
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == 38) { // up => decrease
step = 1;
if(e.getModifiers() == KeyEvent.SHIFT_MASK) {
step = 10;
}
changeVal();
keyTimer.setInitialDelay(300);
keyTimer.start();
}
else if(e.getKeyCode() == 40) { // up => increase
step = -1;
if(e.getModifiers() == KeyEvent.SHIFT_MASK) {
step = -10;
}
changeVal();
keyTimer.setInitialDelay(300);
keyTimer.start();
}
}
public void keyReleased(KeyEvent e) {
keyTimer.stop();
}
// the keyTimer action
public void actionPerformed(ActionEvent e) {
changeVal();
}
private void changeVal() {
int val = Integer.parseInt(theField.getText()) + step;
if(val > max) val = max;
else if(val < min) val = min;
// this should trigger insertUpdate()
theField.setText("" + val);
}
}
class KeyInputListener implements DocumentListener {
public void changedUpdate(DocumentEvent e) {
}
public void insertUpdate(DocumentEvent e) {
notifyActionListeners();
}
public void removeUpdate(DocumentEvent e) {
notifyActionListeners();
}
}
}