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 }