1    package ca.janeg.project;
2    
3    import java.awt.BorderLayout;
4    import java.awt.Color;
5    import java.awt.Dimension;
6    import java.awt.Font;
7    import java.awt.event.WindowAdapter;
8    import java.awt.event.WindowEvent;
9    import java.text.DateFormat;
10   import java.text.ParseException;
11   import java.text.SimpleDateFormat;
12   
13   import javax.swing.BorderFactory;
14   import javax.swing.Box;
15   import javax.swing.BoxLayout;
16   import javax.swing.InputVerifier;
17   import javax.swing.JComponent;
18   import javax.swing.JFrame;
19   import javax.swing.JLabel;
20   import javax.swing.JPanel;
21   import javax.swing.JTextField;
22   import javax.swing.border.Border;
23   import javax.swing.border.TitledBorder;
24   
25   import ca.janeg.swing.Utils;
26   
27   /**
28    *  An example of validating user input fields using
29    *  <code>javax.swing.InputVerifier</code>.
30    * 
31    *  The verifiers are defined as inner classes.
32    * 
33    *  References:
34    *  <ul>      
35    *      <li><a href="http://www.javaworld.com/javaworld/jw-06-2001/jw-0622-traps.html?"> 
36    *      JavaWorld article by Michael Daconta</a></li>
37    *      <li><a href="http://developer.java.sun.com/developer/JDCTechTips/2001/tt1120.html">
38    *      JDC Tech Tip - VALIDATING NUMERICAL INPUT IN A JTEXTFIELD</a></li>
39    *
40    *  </ul>
41    *  @author Jane Griscti, jane@janeg.ca
42    */
43   public class FieldValidation {
44   
45       private final static DateFormat dateFormat = 
46                           new SimpleDateFormat( "MM/dd/yyyy" );
47       private final  Font font = new Font( null, 
48                                 Font.BOLD | Font.ITALIC,
49                                 12 );     
50       
51       private final JFrame frame          = new JFrame();                                         
52       private final JTextField name       = new JTextField( 25 );
53       private final JTextField age        = new JTextField( 3 );
54       private final JTextField birthday   = new JTextField( 10 );
55       private final JTextField status     = new JTextField( 30 );
56       
57       public FieldValidation(){
58           frame.setTitle( "Field Validation Example" );
59           
60           // assign a verifier to each input field     
61           age.setInputVerifier( new AgeVerifier() );
62           birthday.setInputVerifier( new BirthdayVerifier() );
63           name.setInputVerifier( new BlankFieldVerifier() );
64           
65           buildGUI();        
66       }
67       
68       /*
69        *  Build the example GUI.
70        */
71       private void buildGUI(){        
72   
73           JPanel mainPanel = new JPanel();
74           mainPanel.setLayout( new BoxLayout( mainPanel, BoxLayout.Y_AXIS ) );
75           mainPanel.setBorder( BorderFactory.createCompoundBorder(
76                                  BorderFactory.createEmptyBorder( 5,5,5,5 ),
77                                  mainPanel.getBorder() ) );
78                                  
79           mainPanel.add( buildInputPanel() );
80           mainPanel.add( buildStatusPanel() );
81            
82           frame.getContentPane().add( mainPanel, BorderLayout.CENTER );
83                   
84           frame.addWindowListener(new WindowAdapter() {
85               public void windowClosing(WindowEvent wevt) {
86                   System.exit(0);
87               }
88           });
89           
90           frame.setResizable( false );
91           frame.pack();
92           Utils.center( frame );
93           frame.setVisible( true );                                                 
94       }
95      
96       /*
97        *  Build the GUI input panel.
98        */
99       private JPanel buildInputPanel(){
100          JPanel panel = new JPanel();           
101                                         
102          Border border = BorderFactory.createTitledBorder( 
103                                  BorderFactory.createEtchedBorder(),
104                                  "Input",
105                                  TitledBorder.LEADING,
106                                  TitledBorder.TOP,
107                                  font,
108                                  Color.GRAY );
109          
110          panel.setLayout( new BoxLayout( panel, 
111                                          BoxLayout.Y_AXIS ) );
112          panel.setBorder( border );                                             
113          
114          panel.add( buildField( name, "Name:" ) );
115          panel.add( buildField( age, "Age:" ) );
116          panel.add( buildField( birthday, "Birthday:" ) );
117      
118          return panel;    
119      }
120      
121      /*
122       *  Build an input field to be displayed in the input panel.
123       */
124      private JPanel buildField( JComponent comp, String label ){        
125          
126          comp.setMinimumSize( comp.getPreferredSize() );
127          comp.setMaximumSize( comp.getPreferredSize() );        
128  
129          JPanel panel = new JPanel();
130          panel.setBorder( BorderFactory.createEmptyBorder( 2,2,2,2 ) );
131          
132          panel.setLayout( new BoxLayout( panel,
133                                          BoxLayout.X_AXIS ) );
134                                          
135          Box leftBox = new Box( BoxLayout.X_AXIS ); 
136          leftBox.setPreferredSize( new Dimension( 60, 20 ) );                                       
137          leftBox.add( new JLabel( label ) ); 
138   
139          Box rightBox = new Box( BoxLayout.X_AXIS );
140          rightBox.add( comp );
141                                                                                                              
142          panel.add( leftBox );
143          panel.add( rightBox );
144          panel.add( Box.createHorizontalGlue() );
145          
146          return panel;        
147      }
148      
149      /* 
150       *  Build the GUI status panel.
151       */
152      private JPanel buildStatusPanel(){
153          JPanel panel = new JPanel();
154          
155          Border border = BorderFactory.createTitledBorder( 
156                                  BorderFactory.createEtchedBorder(),
157                                  "Status",
158                                  TitledBorder.LEADING,
159                                  TitledBorder.TOP,
160                                  font,
161                                  Color.GRAY );        
162          panel.setBorder( border );
163                                 
164          status.setEditable( false );
165          status.setForeground( Color.BLUE );
166          status.setText( "Ready" );
167          panel.add( status );
168          return panel;
169      }
170      
171      /*
172       *  Checks to ensure a field is not blank.
173       *  
174       *  The 'shouldYieldFocus()' method produces
175       *  a 'beep' if the validation fails. It is inherited
176       *  by the other field verifiers.
177       */ 
178      private class BlankFieldVerifier extends InputVerifier {
179  
180          public boolean verify(JComponent comp) {
181              JTextField fld = (JTextField) comp;
182              String content = fld.getText();
183  
184              boolean isValid = true;
185              if (content.length() == 0) {
186                  status.setText("Field cannot be blank.");
187                  isValid = false;
188              }
189  
190              return isValid;
191          }
192  
193          public boolean shouldYieldFocus(JComponent input) {
194              boolean valid = super.shouldYieldFocus(input);
195  
196              if (!valid) {
197                  frame.getToolkit().beep();
198              }
199              return valid;
200          }
201  
202      }
203       
204      /*
205       *  Checks the age field to ensure it is not
206       *  empty and that it contains an integer value.
207       */
208      private class AgeVerifier extends BlankFieldVerifier {
209  
210          public boolean verify(JComponent comp) {
211  
212              JTextField fld = (JTextField) comp;
213              String content = fld.getText();
214  
215              boolean isValid = true;
216              
217              try {
218                  Integer.parseInt(content);
219              } catch (NumberFormatException nfe) {
220                  fld.setText("");
221                  status.setText("Age must be a number.");
222                  isValid = false;
223              }
224  
225              if (isValid) {
226                  status.setText("Age is valid.");
227              }
228              
229              return isValid;
230          }
231  
232      } 
233      
234      /* 
235       *  Checks the birthday field to ensure it is not blank
236       *  and it contains a valid date string. There is no
237       *  range checking on the date.
238       */
239      private class BirthdayVerifier extends BlankFieldVerifier {
240          public boolean verify(JComponent comp) {
241  
242              JTextField fld = (JTextField) comp;
243              String content = fld.getText();
244  
245              boolean isValid = true;
246              try {
247                  dateFormat.parse(content);
248              } catch (ParseException e) {
249                  fld.setText("");
250                  status.setText("Birthday must be mm/dd/yyyy.");
251                  isValid = false;
252              }
253  
254              if (isValid) {
255                  status.setText("Birthday is valid.");
256              }
257              return isValid;
258          }
259      }
260      
261      /**
262       *  Main entry point for the class.
263       */
264      public static void main(String[] args){
265          new FieldValidation();
266      }       
267      
268  }
269