This based on some code I found to handle specially formated fields.
It handles the rendering as well.
// declare a time field this way
final LimitedTimeField timeField = new LimitedTimeField("");
...
...
public class LimitedTimeField extends LimitedTimePatternField {
private Toolkit toolkit;
public LimitedTimeField(String value) {
super(PatternControl.getTimePattern());
toolkit = Toolkit.getDefaultToolkit();
adjustPreferredSize();
setValue(value);
setInputVerifier(new TimePassVerifier());
}
public String getFormattedValue() {
String strValue = getValue();
if (strValue.length() < 4) {return "";}
String retVal = strValue.substring(0, 2) + ":" + strValue.substring(2, 4);
return retVal;
}
protected static String removeTimeFormatting(String time){
String r1 = "";
for (int i = 0; i < time.length(); i ++){
if (time.charAt(i) != '_' && time.charAt(i) != ':'){r1 += time.charAt(i);}
}
return r1;
}
}
class TimePassVerifier extends InputVerifier{
private Toolkit toolkit;
public boolean verify(JComponent input){
toolkit = Toolkit.getDefaultToolkit();
LimitedTimeField dFld = (LimitedTimeField)input;
String strValue = LimitedTimeField.removeTimeFormatting(dFld.getText());
char[] c = strValue.toCharArray();
// If nothing has been entered just allow to leave focus
if(strValue.length() == 0) {return true;}
// Initialize the strValue variable again with time formatting in it,
strValue = dFld.getText();
if(c.length != 4) {
toolkit.beep();
return false;
}
for(int i = 0; i < c.length; i++) {
if(! Character.isDigit(c[i])){
toolkit.beep();
return false;
}
}
// Convert the time into hour, min, second set to "0" if invalid
int hour = 0;
int min = 0;
try {hour = Integer.parseInt(strValue.substring(0,3));}
catch(NumberFormatException e) {hour = 0;}
if(hour > 24) {
toolkit.beep();
return false;
}
try {min = Integer.parseInt(strValue.substring(3));}
catch(NumberFormatException e) {min = 0;}
if(min > 59) {
toolkit.beep();
return false;
}
return true;
}
}
//*********
public class LimitedTimePatternField extends JTextField implements DocumentListener, KeyListener, CaretListener {
protected LimitedTimeDocument doc;
protected int keyCode = 0;
protected int keyMods = 0;
protected boolean caretUpdateLock = false;
protected boolean dumbCaretUpdate = false;
private int KEY_CLEAR_FIELD = KeyEvent.VK_F2;
private String pattern = null;
int lenPattern = 0;
boolean ignoreKey = false;
public LimitedTimePatternField(String pat) {this(pat, LimitedTimeDocument.BLANK);}
public LimitedTimePatternField(String pat, char blk) {
doc = new LimitedTimeDocument(pat, blk);
doc.addDocumentListener(this);
addKeyListener(this);
addCaretListener(this);
setDocument(doc);
setInitialPosition();
this.pattern = pat;
this.lenPattern = pat.length();
}
public int getClearKey() {return KEY_CLEAR_FIELD;}
public void setClearKey(int keyVal) {KEY_CLEAR_FIELD = keyVal;}
public String getClearText() {return KeyEvent.getKeyText(getClearKey());}
public void adjustPreferredSize() {
if(pattern == null || lenPattern == 0) {return;}
char[] p = pattern.toCharArray();
char[] m = new char[p.length];
char[] t = doc.getBlankedPattern().toCharArray();
for(int mIndex = 0; mIndex < m.length; mIndex++) {
if(t[mIndex] == LimitedTimeDocument.BLANK) {m[mIndex] = (p[mIndex] == PatternControl.DIGIT_PATTERN) ? '8' : 'W' ;}
else {m[mIndex] = t[mIndex];}
}
String txtSave = getText();
setText(new String(m));
Dimension d = this.getPreferredSize();
Insets in = this.getInsets();
d.height += in.top + in.bottom;
d.width += in.left + in.right;
this.setPreferredSize(d);
setText(txtSave);
}
public void setText(String value) {
super.setText(value);
setInitialPosition();
}
public void setValue(String value) {setText(value);}
public String getValue() {
char[] t = getText().toCharArray();
char[] c = new char[t.length];
int cIndex = 0;
for(int tIndex = 0; tIndex < t.length; tIndex++) {
if(! doc.isFixed(tIndex)) {c[cIndex++] = t[tIndex];}
}
cIndex--;
while(cIndex >= 0) {
if(c[cIndex] != LimitedTimeDocument.BLANK) {break;}
cIndex--;
}
if(cIndex < 0) {return "";}
return (new String(c, 0, cIndex + 1)).replace(LimitedTimeDocument.BLANK, ' ');
}
private int forwardAdjustedCaret(int pos) {
if(pos < 0) {pos = 0;}
while(doc.isFixed(pos)) {pos++;}
if(pos > lenPattern) {pos = lenPattern;}
return pos;
}
private int backwardAdjustedCaret(int pos) {
if(pos < 0) {return forwardAdjustedCaret(0);}
if(pos > lenPattern) {pos = lenPattern;}
while(doc.isFixed(pos)) {pos--;}
if(pos <= 0) {return forwardAdjustedCaret(0);}
return pos;
}
private void clearField() {
setValue("");
setCaretPosition(forwardAdjustedCaret(0));
}
public void setInitialPosition() {
doc.clearLastAlteredPosition();
setCaretPosition(forwardAdjustedCaret(0));
}
public void keyTyped(KeyEvent event) {}
public void keyReleased(KeyEvent event) {}
public void keyPressed(KeyEvent event) {
if(event.isAltDown() && event.getKeyCode() != KeyEvent.VK_ALT) {ignoreKey = true;}
keyCode = event.getKeyCode();
keyMods = event.getModifiers();
int pos = getCaretPosition();
if(keyCode == KEY_CLEAR_FIELD) {
event.consume();
clearField();
}
else if(keyCode == KeyEvent.VK_BACK_SPACE) {
while(doc.isFixed(pos - 1)) {pos--;}
if(pos <= 0) {pos = forwardAdjustedCaret(0);}
dumbCaretUpdate = true;
setCaretPosition(pos);
dumbCaretUpdate = false;
}
else if(keyCode == KeyEvent.VK_LEFT) {
while(pos > lenPattern || doc.isFixed(pos - 1)) {pos--;}
if(pos <= 0) {pos = forwardAdjustedCaret(0);}
dumbCaretUpdate = true;
if((keyMods & InputEvent.SHIFT_MASK) != 0) {moveCaretPosition(pos);}
else {setCaretPosition(pos);}
dumbCaretUpdate = false;
}
}
protected void processInputMethodEvent(InputMethodEvent e) {
if(! ignoreKey) {super.processInputMethodEvent(e);}
ignoreKey = false;
}
public void changedUpdate(DocumentEvent event) {}
public void removeUpdate(DocumentEvent event) {}
public void insertUpdate(DocumentEvent event) {
if(keyCode == KeyEvent.VK_BACK_SPACE) {setCaretPosition(event.getOffset());}
else if(keyCode == KeyEvent.VK_DELETE) {setCaretPosition(event.getOffset());}
}
public void caretUpdate(CaretEvent e) {
if(doc.getLength() == 0) {return;}
if(caretUpdateLock) {return;}
caretUpdateLock = true;
if(keyCode == KeyEvent.VK_HOME) {
if((keyMods & InputEvent.SHIFT_MASK) != 0) {moveCaretPosition(forwardAdjustedCaret(0));}
else {setCaretPosition(forwardAdjustedCaret(0));}
keyCode = 0;
}
else if(keyCode == KeyEvent.VK_END) {
if((keyMods & InputEvent.SHIFT_MASK) != 0) {moveCaretPosition(backwardAdjustedCaret(lenPattern));}
else {setCaretPosition(backwardAdjustedCaret(lenPattern));}
keyCode = 0;
}
else if(keyCode == KeyEvent.VK_RIGHT) {
if((keyMods & InputEvent.SHIFT_MASK) != 0) {moveCaretPosition(forwardAdjustedCaret(e.getDot()));}
else {setCaretPosition(forwardAdjustedCaret(e.getDot()));}
keyCode = 0;
}
else if(! dumbCaretUpdate && doc.isFixed(e.getDot())) {
if(e.getDot() == e.getMark()) {setCaretPosition(forwardAdjustedCaret(e.getDot()));}
else {moveCaretPosition(forwardAdjustedCaret(e.getDot()));}
} else if(doc.getLastAlteredPosition() != -1) {
if(e.getDot() == e.getMark()) {setCaretPosition(forwardAdjustedCaret(doc.getLastAlteredPosition()));}
else {moveCaretPosition(forwardAdjustedCaret(doc.getLastAlteredPosition()));}
}
caretUpdateLock = false;
}
}
//**************
public class PatternControl {
public static final char DIGIT_PATTERN = '\u0011';
public static String getTimePattern() {
char[] pat = new char[5];
pat[0] = DIGIT_PATTERN;
pat[1] = DIGIT_PATTERN;
pat[2] = ':';
pat[3] = DIGIT_PATTERN;
pat[4] = DIGIT_PATTERN;
return new String(pat);
}
}
rykk
Sorry I am a very old guy and you cannot expect to much.
I have multiple editors that all use some of the various routines.
public class LimitedTimeDocument extends PlainDocument {
private Toolkit toolkit = Toolkit.getDefaultToolkit();
private String strPattern;
private String strBlankedPattern;
private char[] patt;
private int lenPattern;
private int lastPosition = -1;
public static char BLANK = '_';
public LimitedTimeDocument(String pat) {this(pat, BLANK);}
public LimitedTimeDocument(String pat, char blk) {
setPattern(pat, blk);
try {super.insertString(0, strBlankedPattern, null);}
catch(BadLocationException e) {}
}
public String getBlankedPattern() {return strBlankedPattern;}
public String getPattern() {return strPattern;}
public int getLastAlteredPosition() {return lastPosition;}
public void clearLastAlteredPosition() {lastPosition = -1;}
public void setPattern(String pat, char blk) {
BLANK = blk;
strPattern = pat;
strBlankedPattern = makeBlankedPattern();
patt = strPattern.toCharArray();
lenPattern = pat.length();
}
private String makeBlankedPattern() {
char[] rawPat = strPattern.toCharArray();
char[] blkPat = new char[rawPat.length];
for(int i = 0; i < rawPat.length; i++) {blkPat[i] = isEditablePattern(rawPat[i]) ? BLANK : rawPat[i];}
return new String(blkPat);
}
private boolean isEditablePattern(char c) {return (c == PatternControl.DIGIT_PATTERN || c == PatternControl.ALL_PATTERN || c == PatternControl.UC_ALL_PATTERN|| c == PatternControl.ALPHA_PATTERN || c == PatternControl.UC_ALPHA_PATTERN ||c == PatternControl.ALPHANUMERIC_PATTERN ||c == PatternControl.UC_ALPHANUMERIC_PATTERN ||c == PatternControl.ALPHANUMERIC_PATTERN);}
public boolean isFixed(int index) {
if(index < 0 || index >= lenPattern){return false;}
return (strBlankedPattern.charAt(index) != BLANK);
}
public void insertString(int offset, String str, AttributeSet a) throws BadLocationException {
int len = str.length();
if((offset + len) > lenPattern) {len = lenPattern - offset;}
if(offset > getLength() || offset >= lenPattern || len == 0) {return;}
char[] txtAdj = new char[lenPattern];
int idxAdj = 0;
char[] txtRaw = str.toCharArray();
int idxRaw = 0;
int idxPatt = offset;
char ch;
while(idxRaw < txtRaw.length && idxPatt < lenPattern) {
ch = patt[idxPatt];
if(isFixed(idxPatt)) {
txtAdj[idxAdj++] = ch;
idxPatt++;
}
else if(ch == PatternControl.DIGIT_PATTERN) {
if(Character.isDigit(txtRaw[idxRaw])) {
if(idxPatt==0){
if (txtRaw[idxRaw]=='0' || txtRaw[idxRaw]=='1'|| txtRaw[idxRaw]=='2') {
txtAdj[idxAdj++] = txtRaw[idxRaw];
idxPatt++;
}
else {toolkit.beep();}
}
//else if(idxPatt==1){
//if (txtRaw[idxRaw]=='0' || txtRaw[idxRaw]=='1' || txtRaw[idxRaw]=='2') {
//txtAdj[idxAdj++] = txtRaw[idxRaw];
//idxPatt++;
//}
//else {toolkit.beep();}
//}
else if(idxPatt==3){
if (txtRaw[idxRaw]<'6') {
txtAdj[idxAdj++] = txtRaw[idxRaw];
idxPatt++;
}
else {toolkit.beep();}
}
else {
txtAdj[idxAdj++] = txtRaw[idxRaw];
idxPatt++;
}
}
idxRaw++;
}
else if(ch == PatternControl.UC_ALL_PATTERN) {
txtAdj[idxAdj++] = Character.toUpperCase(txtRaw[idxRaw]);
idxPatt++;
idxRaw++;
}
else if(ch == PatternControl.UC_ALPHA_PATTERN) {
if(isAlpha(txtRaw[idxRaw])) {
txtAdj[idxAdj++] = Character.toUpperCase(txtRaw[idxRaw]);
idxPatt++;
}
idxRaw++;
}
else if(ch == PatternControl.ALPHA_PATTERN) {
if(isAlpha(txtRaw[idxRaw])) {
txtAdj[idxAdj++] = txtRaw[idxRaw];
idxPatt++;
}
idxRaw++;
}
else if(ch == PatternControl.ALL_PATTERN) {
txtAdj[idxAdj++] = txtRaw[idxRaw];
idxPatt++;
idxRaw++;
}
else if(ch == PatternControl.ALPHANUMERIC_PATTERN) {
if((isAlpha(txtRaw[idxRaw])) || (Character.isDigit(txtRaw[idxRaw]))) {
txtAdj[idxAdj++] = txtRaw[idxRaw];
idxPatt++;
}
idxRaw++;
}
else if((ch == PatternControl.UC_ALPHANUMERIC_PATTERN) || (ch == PatternControl.KEY_PATTERN)) {
if((isAlpha(txtRaw[idxRaw])) || (Character.isDigit(txtRaw[idxRaw]))) {
txtAdj[idxAdj++] = Character.toUpperCase(txtRaw[idxRaw]);
idxPatt++;
}
idxRaw++;
}
}
if(idxAdj > 0) {
super.remove(offset, idxAdj);
lastPosition = offset + idxAdj;
super.insertString(offset, (new String(txtAdj, 0, idxAdj)), a);
lastPosition = -1;
}
}
public void remove(int offs, int len) throws BadLocationException {
if((offs + len) > lenPattern) {len = lenPattern - offs;}
int lenDoc = getLength();
if(lenDoc == 0 || offs >= lenDoc || offs >= lenPattern || len <= 0) {return;}
super.remove(offs, len);
lastPosition = offs;
super.insertString(offs, strBlankedPattern.substring(offs, offs + len), null);
lastPosition = -1;
}
static boolean isAlpha(char c) {
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) {return false;}
return true;
}
}
rykk