001/* 002 * jDTAUS Banking Utilities 003 * Copyright (C) 2005 Christian Schulte 004 * <cs@schulte.it> 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License, or any later version. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 019 * 020 */ 021package org.jdtaus.banking.util.swing; 022 023import java.text.ParseException; 024import javax.swing.JFormattedTextField; 025import javax.swing.JFormattedTextField.AbstractFormatter; 026import javax.swing.text.AttributeSet; 027import javax.swing.text.BadLocationException; 028import javax.swing.text.DocumentFilter; 029import org.jdtaus.banking.AlphaNumericText27; 030import org.jdtaus.core.container.ContainerFactory; 031 032/** 033 * {@code JFormattedTextField} supporting the {@code AlphaNumericText27} type. 034 * <p>This textfield uses the {@link AlphaNumericText27} type for parsing and formatting. An empty string value is 035 * treated as {@code null}. The {@code normalizing} flag controls parsing. If {@code true} (default) the field's value 036 * is normalized using the {@link AlphaNumericText27#normalize(String)} method prior to parsing. The {@code validating} 037 * flag controls validation of values entered into the textfield. If {@code true} (default), a {@code DocumentFilter} is 038 * registered with the textfield disallowing invalid values, that is, values which are not {@code null} and not empty 039 * strings and for which the {@link AlphaNumericText27#parse(String)} method throws a {@code ParseException}.</p> 040 * 041 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 042 * @version $JDTAUS: AlphaNumericText27TextField.java 8864 2014-01-10 17:13:30Z schulte $ 043 */ 044public final class AlphaNumericText27TextField extends JFormattedTextField 045{ 046 047 /** Serial version UID for backwards compatibility with 1.1.x classes. */ 048 private static final long serialVersionUID = -8152767220100367519L; 049 050 /** 051 * Flag indicating if a normalizing parser is used. 052 * @serial 053 */ 054 private Boolean normalizing; 055 056 /** 057 * Flag indicating if validation is performed. 058 * @serial 059 */ 060 private Boolean validating; 061 062 /** Creates a new default {@code AlphaNumericText27TextField} instance. */ 063 public AlphaNumericText27TextField() 064 { 065 super(); 066 this.setColumns( AlphaNumericText27.MAX_LENGTH ); 067 this.setFormatterFactory( new AbstractFormatterFactory() 068 { 069 070 public AbstractFormatter getFormatter( final JFormattedTextField ftf ) 071 { 072 return new AbstractFormatter() 073 { 074 075 public Object stringToValue( final String text ) throws ParseException 076 { 077 Object value = null; 078 079 if ( text != null && text.trim().length() > 0 ) 080 { 081 value = AlphaNumericText27.parse( 082 isNormalizing() ? AlphaNumericText27.normalize( text ) : text ); 083 084 } 085 086 return value; 087 } 088 089 public String valueToString( final Object value ) throws ParseException 090 { 091 String ret = null; 092 093 if ( value instanceof AlphaNumericText27 ) 094 { 095 final AlphaNumericText27 txt = (AlphaNumericText27) value; 096 ret = txt.isEmpty() ? null : txt.format().trim(); 097 } 098 099 return ret; 100 } 101 102 protected DocumentFilter getDocumentFilter() 103 { 104 return new DocumentFilter() 105 { 106 107 public void insertString( final FilterBypass fb, final int o, String s, 108 final AttributeSet a ) throws BadLocationException 109 { 110 if ( isValidating() ) 111 { 112 if ( isNormalizing() ) 113 { 114 final char[] chars = s.toCharArray(); 115 for ( int i = chars.length - 1; i >= 0; i-- ) 116 { 117 chars[i] = Character.toUpperCase( chars[i] ); 118 } 119 s = String.valueOf( chars ); 120 } 121 122 final StringBuffer b = 123 new StringBuffer( fb.getDocument().getLength() + s.length() ); 124 125 b.append( fb.getDocument().getText( 0, fb.getDocument().getLength() ) ); 126 b.insert( o, s ); 127 128 try 129 { 130 AlphaNumericText27.parse( b.toString() ); 131 } 132 catch ( ParseException e ) 133 { 134 invalidEdit(); 135 return; 136 } 137 } 138 139 super.insertString( fb, o, s, a ); 140 } 141 142 public void replace( final FilterBypass fb, final int o, final int l, String s, 143 final AttributeSet a ) throws BadLocationException 144 { 145 if ( isValidating() ) 146 { 147 if ( isNormalizing() ) 148 { 149 final char[] chars = s.toCharArray(); 150 for ( int i = chars.length - 1; i >= 0; i-- ) 151 { 152 chars[i] = Character.toUpperCase( chars[i] ); 153 } 154 s = String.valueOf( chars ); 155 } 156 157 final StringBuffer b = new StringBuffer( 158 fb.getDocument().getText( 0, fb.getDocument().getLength() ) ); 159 160 b.delete( o, o + l ); 161 162 if ( s != null ) 163 { 164 b.insert( o, s ); 165 } 166 167 try 168 { 169 AlphaNumericText27.parse( b.toString() ); 170 } 171 catch ( ParseException e ) 172 { 173 invalidEdit(); 174 return; 175 } 176 } 177 178 super.replace( fb, o, l, s, a ); 179 } 180 181 }; 182 } 183 184 }; 185 } 186 187 } ); 188 } 189 190 /** 191 * Gets the last valid {@code AlphaNumericText27}. 192 * 193 * @return the last valid {@code AlphaNumericText27} or {@code null}. 194 */ 195 public AlphaNumericText27 getAlphaNumericText27() 196 { 197 return (AlphaNumericText27) this.getValue(); 198 } 199 200 /** 201 * Gets the flag indicating if a normalizing parser is used. 202 * 203 * @return {@code true} if a normalizing parser is used; {@code false} if a strict parser is used 204 * (defaults to {@code true}). 205 */ 206 public boolean isNormalizing() 207 { 208 if ( this.normalizing == null ) 209 { 210 this.normalizing = this.isDefaultNormalizing(); 211 } 212 213 return this.normalizing.booleanValue(); 214 } 215 216 /** 217 * Sets the flag indicating if a normalizing parser should be used. 218 * 219 * @param value {@code true} to use a normalizing parser; {@code false} to use a strict parser 220 * (defaults to {@code true}). 221 */ 222 public void setNormalizing( final boolean value ) 223 { 224 this.normalizing = Boolean.valueOf( value ); 225 } 226 227 /** 228 * Gets the flag indicating if validation is performed. 229 * 230 * @return {@code true} if the field's value is validated; {@code false} if no validation of the field's value is 231 * performed. 232 */ 233 public boolean isValidating() 234 { 235 if ( this.validating == null ) 236 { 237 this.validating = this.isDefaultValidating(); 238 } 239 240 return this.validating.booleanValue(); 241 } 242 243 /** 244 * Sets the flag indicating if validation should be performed. 245 * 246 * @param value {@code true} to validate the field's value; {@code false} to not validate the field's value. 247 */ 248 public void setValidating( boolean value ) 249 { 250 this.validating = Boolean.valueOf( value ); 251 } 252 253 //--Properties-------------------------------------------------------------- 254 255// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties 256 // This section is managed by jdtaus-container-mojo. 257 258 /** 259 * Gets the value of property <code>defaultValidating</code>. 260 * 261 * @return Default value of the flag indicating if validation should be performed. 262 */ 263 private java.lang.Boolean isDefaultValidating() 264 { 265 return (java.lang.Boolean) ContainerFactory.getContainer(). 266 getProperty( this, "defaultValidating" ); 267 268 } 269 270 /** 271 * Gets the value of property <code>defaultNormalizing</code>. 272 * 273 * @return Default value of the flag indicating if a normalizing parser should be used. 274 */ 275 private java.lang.Boolean isDefaultNormalizing() 276 { 277 return (java.lang.Boolean) ContainerFactory.getContainer(). 278 getProperty( this, "defaultNormalizing" ); 279 280 } 281 282// </editor-fold>//GEN-END:jdtausProperties 283 284 //--------------------------------------------------------------Properties-- 285}