@@ -33,25 +33,80 @@ public class AddressDocument extends PlainDocument {
3333 @ Override
3434 public void insertString (int offset , String s , AttributeSet a ) throws BadLocationException {
3535 if (s == null ) return ;
36+ if (s .isEmpty ()) return ;
3637
37- char [] cs = s .toCharArray ();
38- int n =cs .length ;
39- if (n ==0 ) return ;
40-
41- if ((offset >0 )&&(cs [0 ]=='#' )) {
42- super .remove (0 , offset );
43- offset =0 ;
38+ // Typing '#' at any point resets the field to just '#'
39+ if ("#" .equals (s )) {
40+ super .remove (0 , getLength ());
41+ super .insertString (0 , "#" , a );
42+ // Caret after '#'
43+ AddressField .this .setCaretPosition (1 );
44+ return ;
45+ }
46+
47+ // Compose the prospective new text
48+ String current = getText (0 , getLength ());
49+ StringBuilder sb = new StringBuilder (current );
50+ sb .insert (offset , s );
51+ String preText = sb .toString ();
52+
53+ // If we have any content, ensure it starts with '#'
54+ String newText = preText ;
55+ boolean addedHash = false ;
56+ if (!newText .isEmpty () && newText .charAt (0 ) != '#' ) {
57+ newText = "#" + newText ;
58+ addedHash = true ;
4459 }
4560
46- for (int i = 0 ; i < n ; i ++ ) {
47- char c =cs [i ];
48- if (Text .isASCIIDigit (c )) continue ;
49- if ((offset ==0 )&&(i ==0 )&&(c =='#' )) continue ;
50- return ; // not valid so exit function early
61+ // Validate: either "#" or "#" followed only by ASCII digits
62+ boolean ok = false ;
63+ if (newText .equals ("#" )) {
64+ ok = true ;
65+ } else if ((newText .length () > 1 ) && (newText .charAt (0 ) == '#' )) {
66+ ok = true ;
67+ for (int i = 1 ; i < newText .length (); i ++) {
68+ if (!Text .isASCIIDigit (newText .charAt (i ))) {
69+ ok = false ;
70+ break ;
71+ }
72+ }
5173 }
74+ if (!ok ) return ; // reject invalid edits
75+
76+ // Apply validated text
77+ super .remove (0 , getLength ());
78+ super .insertString (0 , newText , a );
5279
53- // Everything valid, so just insert as normal
54- super .insertString (offset , s , a );
80+ // Place caret where user expects it: after inserted text
81+ int caretPos = offset + s .length () + (addedHash ? 1 : 0 );
82+ if (caretPos > newText .length ()) caretPos = newText .length ();
83+ if (caretPos < 0 ) caretPos = 0 ;
84+ AddressField .this .setCaretPosition (caretPos );
85+ }
86+
87+ @ Override
88+ public void remove (int offs , int len ) throws BadLocationException {
89+ super .remove (offs , len );
90+
91+ String text = getText (0 , getLength ());
92+
93+ // Don't allow the field to become completely empty: reset to "#"
94+ if (text .isEmpty ()) {
95+ super .insertString (0 , "#" , null );
96+ AddressField .this .setCaretPosition (1 );
97+ return ;
98+ }
99+
100+ // Ensure first character is always '#'
101+ if (text .charAt (0 ) != '#' ) {
102+ text = "#" + text ;
103+ super .remove (0 , getLength ());
104+ super .insertString (0 , text , null );
105+ // Try to keep caret just after '#'
106+ int caretPos = 1 ;
107+ if (caretPos > text .length ()) caretPos = text .length ();
108+ AddressField .this .setCaretPosition (caretPos );
109+ }
55110 }
56111 }
57112}
0 commit comments