001 package org.springframework.richclient.components;
002
003 import org.apache.commons.logging.Log;
004 import org.apache.commons.logging.LogFactory;
005 import org.springframework.richclient.form.binding.swing.text.TimeFormatter;
006
007 import javax.swing.*;
008 import javax.swing.text.BadLocationException;
009 import javax.swing.text.PlainDocument;
010 import javax.swing.text.AttributeSet;
011 import java.awt.event.FocusEvent;
012 import java.awt.event.FocusListener;
013
014 public class TimeTextField extends JFormattedTextField
015 {
016
017 Log log = LogFactory.getLog(TimeTextField.class);
018
019 private static final String INPUT_SEPARATORS = "[hHuU\\s\\.,+*-/]";
020
021 public TimeTextField()
022 {
023 super(new TimeFormatter());
024 this.setDocument(new TimeDocument());
025 setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT);
026 addFocusListener(new UpdateFocusListener());
027 }
028
029 private void updateText(String txt)
030 {
031 try
032 {
033 getDocument().remove(0, getText().length());
034 getDocument().insertString(0, txt, null);
035 }
036 catch (BadLocationException e)
037 {
038 log.error("Text out of boundaries. ", e);
039 }
040 }
041
042 protected void processFocusEvent(FocusEvent e)
043 {
044 super.processFocusEvent(e);
045 if (e.getID() == FocusEvent.FOCUS_GAINED)
046 {
047 setCaretPosition(0);
048 moveCaretPosition(getDocument().getLength());
049 }
050 }
051
052 class UpdateFocusListener implements FocusListener
053 {
054
055 public void focusGained(FocusEvent e)
056 {
057 }
058
059 public void focusLost(FocusEvent e)
060 {
061 try
062 {
063 commitEdit();
064 String valueToString = getFormatter().valueToString(getValue());
065 updateText(valueToString);
066 }
067 catch (Exception e1)
068 {
069 log.error("Invalid date format. ", e1);
070 }
071 }
072 }
073
074 class TimeDocument extends PlainDocument
075 {
076
077 public void replace(int offset, int length, String text, AttributeSet attrs)
078 throws BadLocationException
079 {
080 remove(offset, length);
081 insertString(offset, text, attrs);
082 }
083
084 public void remove(int offs, int len) throws BadLocationException
085 {
086 super.remove(offs, len);
087 }
088
089 public void insertString(int offset, String str, AttributeSet a) throws BadLocationException
090 {
091 if ((str = isValidString(offset, str)) != null)
092 super.insertString(offset, str, a);
093 }
094
095 private String isValidString(int offset, String str) throws BadLocationException
096 {
097 if (str == null)
098 return null;
099 str = str.replaceAll(INPUT_SEPARATORS, TimeFormatter.SEPARATOR_STRING); // set
100 // correct
101 // Separator
102
103 String s = getText(0, offset) + str;
104 if (offset < getLength())
105 s += getText(offset, getLength() - offset);
106
107 char[] strArray = s.toCharArray();
108 int sepPos = -1;
109 for (int i = 0; i < strArray.length; ++i) // check on only
110 // digits/one separator
111 {
112 if (!Character.isDigit(strArray[i]))
113 {
114 if (!(TimeFormatter.SEPARATOR == strArray[i]) || (sepPos != -1))
115 return null;
116
117 sepPos = i;
118 if ((sepPos > 2) || ((getLength() - sepPos) > 2)) // separator
119 // on a
120 // correct
121 // position
122 return null;
123 }
124 }
125
126 int length = sepPos == -1 ? s.length() : s.length() - 1;
127 if (length > 4) // correct number of digits
128 return null;
129
130 return str;
131 }
132 }
133 }