KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > izforge > izpack > panels > RuleInputField


1 /*
2  * IzPack - Copyright 2001-2007 Julien Ponge, All Rights Reserved.
3  *
4  * http://www.izforge.com/izpack/
5  * http://developer.berlios.de/projects/izpack/
6  *
7  * Copyright 2002 Elmar Grom
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */

21
22 package com.izforge.izpack.panels;
23
24 import java.awt.Toolkit JavaDoc;
25 import java.awt.event.FocusEvent JavaDoc;
26 import java.awt.event.FocusListener JavaDoc;
27 import java.awt.event.KeyEvent JavaDoc;
28 import java.awt.event.KeyListener JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.StringTokenizer JavaDoc;
31 import java.util.Vector JavaDoc;
32
33 import javax.swing.JComponent JavaDoc;
34 import javax.swing.JLabel JavaDoc;
35 import javax.swing.JTextField JavaDoc;
36 import javax.swing.event.CaretEvent JavaDoc;
37 import javax.swing.event.CaretListener JavaDoc;
38
39 import org.apache.regexp.RE;
40
41 import com.izforge.izpack.installer.InstallData;
42 import com.izforge.izpack.util.Debug;
43 import com.izforge.izpack.util.VariableSubstitutor;
44
45 /*---------------------------------------------------------------------------*/
46 /**
47  * This class assists the user in entering serial numbers. <BR>
48  * <BR>
49  * Serial numbers, license number, CD keys and the like are often lenghty alpha-numerical numbers.
50  * In many cases they are devided into multiple parts by dash or point separators. Entering these in
51  * a single text field can be a frustrating experience for the user. This class provides a way of
52  * presenting the user with an assembly of input fields that are arranged in the same way as the
53  * key, with the separators already in place. Immideate testing for format compliance if performed
54  * ans soon as each field is completed. In addition, the cursor is automatically advanced to make
55  * entering numbers as painless as possible. <br>
56  * <br>
57  * <b>Formatting:</b>
58  *
59  * <ul>
60  * <li><code>N:X:Y </code>- numeric field, accepts digits only
61  * <li><code>H:X:Y </code>- hex field, accepts only hexadecimal digits
62  * <li><code>A:X:Y </code>- alpha field, accepts only letters, no digits
63  * <li><code>AN:X:Y</code>- alpha-numeric field, accepts digits and letters
64  * </ul>
65  * <b>Example:</b> <br>
66  * <br>
67  * <code>"N:4:4 - H:6:6 - AN:3:3 x A:5:5"</code><br>
68  * <br>
69  * This formatting string will produce a serial number field consisting of four separate input
70  * fields. The fisrt input field will accept four numeric digits, the second six hexa-decimal
71  * digits, the third three alpha-numeric digits and the fourth five letters. The first three input
72  * fields will be separated by '-' and the third and fourth by 'x'. The following snapshot was
73  * obtained with this setting: <br>
74  * <br>
75  * <img SRC="doc-files/RuleInputField-1.gif"/>
76  *
77  * @version 0.0.1 / 10/19/02
78  * @author Elmar Grom
79  */

80 /*---------------------------------------------------------------------------*/
81 public class RuleInputField extends JComponent JavaDoc implements KeyListener JavaDoc, FocusListener JavaDoc,
82         CaretListener JavaDoc, ProcessingClient
83 {
84
85     /**
86      *
87      */

88     private static final long serialVersionUID = 3832616275124958257L;
89
90     /**
91      * Used to specify the retsult format. This constant specifies to return the contents of all
92      * fields concatenated into one long string, with separation between each component.
93      */

94     public static final int PLAIN_STRING = 1;
95
96     /**
97      * Used to specify the retsult format. This constant specifies to return the contents of all
98      * fields together with all separators as specified in the field format concatenated into one
99      * long string. In this case the resulting string looks just like the user saw it during data
100      * entry
101      */

102     public static final int DISPLAY_FORMAT = 2;
103
104     /**
105      * Used to specify the retsult format. This constant specifies to return the contents of all
106      * fields concatenated into one long string, with a special separator string inserted in between
107      * the individual components.
108      */

109     public static final int SPECIAL_SEPARATOR = 3;
110
111     /**
112      * Used to specify the retsult format. This constant specifies to return the contents of all
113      * fields in a somehow modified way. How the content is modified depends on the operation
114      * performed by a encryption service class. The class must be provided at object instatiation.
115      */

116     public static final int ENCRYPTED = 4;
117
118     /** Used internally to identify the default setting for the return format. */
119     private static int DEFAULT = DISPLAY_FORMAT;
120
121     private Vector JavaDoc items = new Vector JavaDoc();
122
123     /**
124      * This <code>Vector</code> holds a reference to each input field, in the order in which they
125      * appear on the screen.
126      */

127     private Vector JavaDoc inputFields = new Vector JavaDoc();
128
129     private boolean hasParams = false;
130
131     private Map JavaDoc validatorParams;
132
133     private RuleTextField activeField;
134
135     private boolean backstep = false;
136
137     private Toolkit JavaDoc toolkit;
138
139     private String JavaDoc separator;
140
141     private int resultFormat = DEFAULT;
142
143     private InstallData idata = null;
144
145     /**
146      * Holds an instance of the <code>Validator</code> if one was specified and available
147      */

148     private Validator validationService;
149
150     /**
151      * Holds an instance of the <code>Processor</code> if one was specified and available
152      */

153     private Processor encryptionService;
154
155     /**
156      * @return true if this instance has any parameters to pass to the Validator instance.
157      */

158     public boolean hasParams()
159     {
160         return hasParams;
161     }
162
163     /*--------------------------------------------------------------------------*/
164     /**
165      * Constructs a rule input field.
166      *
167      * @param format a string that specifies the formatting and to a limited degree the behavior of
168      * this field.
169      * @param preset a string that specifies preset values for specific sub-fields.
170      * @param separator a string to be used for separating the contents of individual fields in the
171      * string returned by <code>getText()</code>
172      * @param validator A string that specifies a class to perform validation services. The string
173      * must completely identify the class, so that it can be instantiated. The class must implement
174      * the <code>RuleValidator</code> interface. If an attempt to instantiate this class fails, no
175      * validation will be performed.
176      * @param validatorParams A <code>java.util.Map</code> containing name/ value pairs, which
177      * will be forwarded to the validator.
178      * @param processor A string that specifies a class to perform processing services. The string
179      * must completely identify the class, so that it can be instantiated. The class must implement
180      * the <code>Processor</code> interface. If an attempt to instantiate this class fails, no
181      * processing will be performed. Instead, the text is returned in the default formatting.
182      * @param resultFormat specifies in which format the resulting text should be returned, wehn
183      * <code>getText()</code> is called. The following values are legal:<br>
184      * <ul>
185      * <li>PLAIN_STRING
186      * <li>DISPLAY_FORMAT
187      * <li>SPECIAL_SEPARATOR
188      * <li>ENCRYPTED
189      * </ul>
190      * @param toolkit needed to gain access to <code>beep()</code>
191      */

192     /*--------------------------------------------------------------------------*/
193     public RuleInputField(String JavaDoc format, String JavaDoc preset, String JavaDoc separator, String JavaDoc validator,
194             Map JavaDoc validatorParams, String JavaDoc processor, int resultFormat, Toolkit JavaDoc toolkit,
195             InstallData idata)
196     {
197         this(format, preset, separator, validator, processor, resultFormat, toolkit, idata);
198         this.validatorParams = validatorParams;
199         this.hasParams = true;
200     }
201
202     /*--------------------------------------------------------------------------*/
203     /**
204      * Constructs a rule input field.
205      *
206      * @param format a string that specifies the formatting and to a limited degree the behavior of
207      * this field.
208      * @param preset a string that specifies preset values for specific sub-fields.
209      * @param separator a string to be used for separating the contents of individual fields in the
210      * string returned by <code>getText()</code>
211      * @param validator A string that specifies a class to perform validation services. The string
212      * must completely identify the class, so that it can be instantiated. The class must implement
213      * the <code>RuleValidator</code> interface. If an attempt to instantiate this class fails, no
214      * validation will be performed.
215      * @param processor A string that specifies a class to perform processing services. The string
216      * must completely identify the class, so that it can be instantiated. The class must implement
217      * the <code>Processor</code> interface. If an attempt to instantiate this class fails, no
218      * processing will be performed. Instead, the text is returned in the default formatting.
219      * @param resultFormat specifies in which format the resulting text should be returned, wehn
220      * <code>getText()</code> is called. The following values are legal:<br>
221      * <ul>
222      * <li>PLAIN_STRING
223      * <li>DISPLAY_FORMAT
224      * <li>SPECIAL_SEPARATOR
225      * <li>ENCRYPTED
226      * </ul>
227      * @param toolkit needed to gain access to <code>beep()</code>
228      */

229     /*--------------------------------------------------------------------------*/
230     public RuleInputField(String JavaDoc format, String JavaDoc preset, String JavaDoc separator, String JavaDoc validator,
231             String JavaDoc processor, int resultFormat, Toolkit JavaDoc toolkit, InstallData idata)
232     {
233         this.toolkit = toolkit;
234         this.separator = separator;
235         this.resultFormat = resultFormat;
236         this.idata = idata;
237
238         com.izforge.izpack.gui.FlowLayout layout = new com.izforge.izpack.gui.FlowLayout();
239         layout.setAlignment(com.izforge.izpack.gui.FlowLayout.LEFT);
240         setLayout(layout);
241
242         // ----------------------------------------------------
243
// attempt to create an instance of the Validator
244
// ----------------------------------------------------
245
try
246         {
247             if (validator != null)
248             {
249                 validationService = (Validator) Class.forName(validator).newInstance();
250             }
251         }
252         catch (Throwable JavaDoc exception)
253         {
254             validationService = null;
255             Debug.trace(exception);
256         }
257
258         // ----------------------------------------------------
259
// attempt to create an instance of the Processor
260
// ----------------------------------------------------
261
try
262         {
263             if (processor != null)
264             {
265                 encryptionService = (Processor) Class.forName(processor).newInstance();
266             }
267         }
268         catch (Throwable JavaDoc exception)
269         {
270             encryptionService = null;
271             Debug.trace(exception);
272         }
273
274         // ----------------------------------------------------
275
// create the fields and field separators
276
// ----------------------------------------------------
277
createItems(format);
278
279         if ((preset != null) && (preset.length() > 0))
280         {
281             setFields(preset);
282         }
283
284         // ----------------------------------------------------
285
// set the focus to the first field
286
// ----------------------------------------------------
287
activeField = (RuleTextField) inputFields.elementAt(0);
288         activeField.grabFocus();
289     }
290
291     /*--------------------------------------------------------------------------*/
292     /**
293      * Returns the number of sub-fields composing this <code>RuleInputField</code>.
294      *
295      * @return the number of sub-fields
296      */

297     /*--------------------------------------------------------------------------*/
298     public int getNumFields()
299     {
300         return (inputFields.size());
301     }
302
303     /*--------------------------------------------------------------------------*/
304     /**
305      * Returns the contents of the field indicated by <code>index</code>.
306      *
307      * @param index the index of the sub-field from which the contents is requested.
308      *
309      * @return the contents of the indicated sub-field.
310      *
311      * @exception IndexOutOfBoundsException if the index is out of bounds.
312      */

313     /*--------------------------------------------------------------------------*/
314     public String JavaDoc getFieldContents(int index) throws IndexOutOfBoundsException JavaDoc
315     {
316         if ((index < 0) || (index > (inputFields.size() - 1))) { throw (new IndexOutOfBoundsException JavaDoc()); }
317
318         return (((JTextField JavaDoc) inputFields.elementAt(index)).getText());
319     }
320
321     /*--------------------------------------------------------------------------*/
322     /**
323      * Returns the validator parameters, if any. The caller should check for the existence of
324      * validator parameters via the <code>hasParams()</code> method prior to invoking this method.
325      *
326      * @return a java.util.Map containing the validator parameters.
327      */

328     public Map JavaDoc getValidatorParams()
329     {
330         return validatorParams;
331     }
332
333     /*---------------------------------------------------------------------------*/
334     /**
335      * Returns the field contents, assembled acording to the encryption and separator rules.
336      *
337      * @return the field contents
338      */

339     /*--------------------------------------------------------------------------*/
340     public String JavaDoc getText()
341     {
342         Object JavaDoc item;
343         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
344         int size = inputFields.size();
345
346         // ----------------------------------------------------
347
// have the encryption service class perfrom the task
348
// of assembling an output string. If we have no instance
349
// of this class available set the formatting
350
// instruction to the default setting.
351
// ----------------------------------------------------
352
if (resultFormat == ENCRYPTED)
353         {
354             if (encryptionService != null)
355             {
356                 buffer.append(encryptionService.process(this));
357             }
358             else
359             {
360                 resultFormat = DEFAULT;
361             }
362         }
363
364         // ----------------------------------------------------
365
// concatentate the field contents, with no separators
366
// in between.
367
// ----------------------------------------------------
368
else if (resultFormat == PLAIN_STRING)
369         {
370             for (int i = 0; i < inputFields.size(); i++)
371             {
372                 buffer.append(((JTextField JavaDoc) inputFields.elementAt(i)).getText());
373             }
374         }
375
376         // ----------------------------------------------------
377
// concatenate the field contents and setarators, as
378
// specified for the display of the field.
379
// ----------------------------------------------------
380
else if (resultFormat == DISPLAY_FORMAT)
381         {
382             for (int i = 0; i < items.size(); i++)
383             {
384                 item = items.elementAt(i);
385                 if (item instanceof JTextField JavaDoc)
386                 {
387                     buffer.append(((JTextField JavaDoc) item).getText());
388                 }
389                 else
390                 {
391                     buffer.append((String JavaDoc) item);
392                 }
393             }
394         }
395
396         // ----------------------------------------------------
397
// concatenate the field contents and insert the
398
// separator string in between.
399
// ----------------------------------------------------
400
else if (resultFormat == SPECIAL_SEPARATOR)
401         {
402             for (int i = 0; i < size; i++)
403             {
404                 buffer.append(((JTextField JavaDoc) inputFields.elementAt(i)).getText());
405
406                 if (i < (size - 1))
407                 {
408                     buffer.append(separator);
409                 }
410             }
411         }
412
413         return (buffer.toString());
414     }
415
416     /*--------------------------------------------------------------------------*/
417     /**
418      * Creates the items that make up this field. Both separators and input fields are considered
419      * items. The items created are stored in <code>items</code>. In addition, all fields are
420      * stored in <code>inputFields</code>.
421      *
422      * @param format a string that specifies the layout of the input fields and separators.
423      */

424     /*--------------------------------------------------------------------------*/
425     /*
426      * $ @design
427      *
428      * I used a simple StringTokenizer to break the format string into individual tokens. The
429      * approach in building up the field is to consider each token a potential definition for an
430      * input field. Therefore I attempt to create an instance of FieldSpec from each token.
431      * FieldSpec analyzes the token and if it does not represent a valid specification for an input
432      * field throws an exception. If I catch an exception, I know the token does not represent a
433      * valid field specification. In this case I treat the token as a separator, even though this
434      * might not be what the user had intended. However, this approach allows me to implement robust
435      * behavior (no exception thrown) even though the user might have made a mistake in the
436      * definition. The mistake should become immediately obvious when testing the code, since a
437      * input field definition would show up as separator between two fields.
438      * --------------------------------------------------------------------------
439      */

440     private void createItems(String JavaDoc format)
441     {
442         Object JavaDoc item;
443         JTextField JavaDoc field;
444         String JavaDoc token;
445         FieldSpec spec;
446         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(format);
447
448         while (tokenizer.hasMoreTokens())
449         {
450             token = tokenizer.nextToken();
451             try
452             {
453                 spec = new FieldSpec(token);
454                 field = new RuleTextField(spec.getColumns(), spec.getEditLength(), spec.getType(),
455                         spec.getUnlimitedEdit(), toolkit);
456
457                 // ------------------------------------------------
458
// if the previous item is also a field, insert a
459
// space as separator
460
// ------------------------------------------------
461
if (items.size() > 0)
462                 {
463                     item = items.lastElement();
464
465                     if (item instanceof JTextField JavaDoc)
466                     {
467                         items.add(" ");
468                     }
469                 }
470
471                 items.add(field);
472                 inputFields.add(field);
473                 field.addFocusListener(this);
474                 field.addKeyListener(this);
475                 field.addCaretListener(this);
476             }
477             // --------------------------------------------------
478
// if we were not successful creating an input field,
479
// the token must be a separator or the definition
480
// has an error. Simply insert it as separator,
481
// when testing the installer the error should become
482
// obvious to the developer.
483
// --------------------------------------------------
484
catch (Throwable JavaDoc exception)
485             {
486                 if (items.size() == 0)
487                 {
488                     items.add(token);
489                 }
490                 else
491                 {
492                     item = items.lastElement();
493
494                     // ----------------------------------------------
495
// if the previous item is also a separator,
496
// simply concatenate the token with a space
497
// inserted in between, don't add it as new
498
// separator.
499
// ----------------------------------------------
500
if (item instanceof String JavaDoc)
501                     {
502                         items.setElementAt(item + " " + token, (items.size() - 1));
503                     }
504                     else
505                     {
506                         items.add(token);
507                     }
508                 }
509             }
510         }
511
512         // ----------------------------------------------------
513
// add the fields and separators to the component
514
// ----------------------------------------------------
515
for (int i = 0; i < items.size(); i++)
516         {
517             item = items.elementAt(i);
518
519             if (item instanceof String JavaDoc)
520             {
521                 add(new JLabel JavaDoc((String JavaDoc) item));
522             }
523             else
524             {
525                 add((JTextField JavaDoc) item);
526             }
527         }
528     }
529
530     /*--------------------------------------------------------------------------*/
531     /**
532      * Sets each field to a pre-defined value.
533      *
534      * @param data a <code>String</code> containing the preset values for each field. The format
535      * of the string is as follows: The content for the individuals fields must be separated by
536      * whitespace. Each data block is preceeded by the index of the field to set (counting starts at
537      * 0) followed by a colon ':'and after that the actual data for the field.
538      */

539     /*--------------------------------------------------------------------------*/
540     private void setFields(String JavaDoc data)
541     {
542         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(data);
543         String JavaDoc token;
544         String JavaDoc indexString;
545         int index;
546         boolean process = false;
547         String JavaDoc[] vals = null;
548         int i = 0;
549
550         vals = new String JavaDoc[tokenizer.countTokens()];
551         while (tokenizer.hasMoreTokens())
552         {
553             token = tokenizer.nextToken();
554             indexString = token.substring(0, token.indexOf(':'));
555
556             try
557             {
558                 index = Integer.parseInt(indexString);
559                 if (index < inputFields.size())
560                 {
561                     String JavaDoc val = token.substring((token.indexOf(':') + 1), token.length());
562                     String JavaDoc className = "";
563                     if (val.indexOf(":") > -1)
564                     {
565                         className = val.substring(val.indexOf(":") + 1);
566                         val = val.substring(0, val.indexOf(":"));
567                     }
568
569                     if (!"".equals(className) && !process)
570                     {
571                         process = true;
572                     }
573                     VariableSubstitutor vs = new VariableSubstitutor(idata.getVariables());
574                     val = vs.substitute(val, null);
575                     vals[i] = val;
576                     i++;
577                     ((JTextField JavaDoc) inputFields.elementAt(index)).setText(val);
578                 }
579             }
580             catch (Throwable JavaDoc exception)
581             {
582                 exception.printStackTrace();
583             }
584         }
585
586         if (process)
587         {
588             tokenizer = new StringTokenizer JavaDoc(data);
589             while (tokenizer.hasMoreTokens())
590             {
591                 token = tokenizer.nextToken();
592                 indexString = token.substring(0, token.indexOf(':'));
593
594                 try
595                 {
596                     index = Integer.parseInt(indexString);
597                     if (index < inputFields.size())
598                     {
599                         String JavaDoc val = token.substring((token.indexOf(':') + 1), token.length());
600                         String JavaDoc className = "";
601                         String JavaDoc presult = "";
602                         if (val.indexOf(":") > -1)
603                         {
604                             className = val.substring(val.indexOf(":") + 1);
605                             val = val.substring(0, val.indexOf(":"));
606                         }
607
608                         if (!"".equals(className))
609                         {
610                             Processor p = (Processor) Class.forName(className).newInstance();
611                             presult = p.process(this);
612                         }
613                         String JavaDoc[] td = new RE("\\*").split(presult);
614                         ((JTextField JavaDoc) inputFields.elementAt(index)).setText(td[index]);
615                     }
616                 }
617                 catch (Throwable JavaDoc exception)
618                 {}
619             }
620         }
621     }
622
623     /*--------------------------------------------------------------------------*/
624     /**
625      * This method validates the field content. Validating is performed through a user supplied
626      * service class that provides the validation rules.
627      *
628      * @return <code>true</code> if the validation passes or no implementation of a validation
629      * rule exists. Otherwise <code>false</code> is returned.
630      */

631     /*--------------------------------------------------------------------------*/
632     public boolean validateContents()
633     {
634         if (validationService != null)
635         {
636             return (validationService.validate(this));
637         }
638         else
639         {
640             return (true);
641         }
642     }
643
644     /*---------------------------------------------------------------------------*
645      Implementation for KeyListener
646      *---------------------------------------------------------------------------*/

647
648     /*--------------------------------------------------------------------------*/
649     /**
650      * This method is invoked when a key has been typed. The event occurs when a key press is
651      * followed by a key release.
652      *
653      * @param event the key event forwarded by the system.
654      */

655     /*--------------------------------------------------------------------------*/
656     public void keyTyped(KeyEvent JavaDoc event)
657     {
658     }
659
660     /*--------------------------------------------------------------------------*/
661     /**
662      * This method is invoked when a key has been pressed. This method verifies the condition of the
663      * input field in focus. Once the column count in the field has reached the specified maximum,
664      * the rule specified for the field in question is invoked. In case the test result is positive,
665      * focus is set to the next field. If hte test result is negative, the field content is marked
666      * and the caret set to the start of the field.
667      *
668      * @param event the key event forwarded by the system.
669      */

670     /*--------------------------------------------------------------------------*/
671     public void keyPressed(KeyEvent JavaDoc event)
672     {
673         if (event.getKeyCode() == KeyEvent.VK_BACK_SPACE)
674         {
675             int caretPosition = activeField.getCaretPosition();
676
677             if (caretPosition == 0)
678             {
679                 int activeIndex = inputFields.indexOf(activeField);
680
681                 if (activeIndex > 0)
682                 {
683                     activeIndex--;
684                     backstep = true;
685                     activeField = (RuleTextField) inputFields.elementAt(activeIndex);
686                     activeField.grabFocus();
687                 }
688             }
689         }
690     }
691
692     /*--------------------------------------------------------------------------*/
693     /**
694      * This method is invoked when a key has been released.
695      *
696      * @param event the key event forwarded by the system.
697      */

698     /*--------------------------------------------------------------------------*/
699     public void keyReleased(KeyEvent JavaDoc event)
700     {
701     }
702
703     /*---------------------------------------------------------------------------*
704      Implementation for FocusListener
705      *---------------------------------------------------------------------------*/

706
707     /*--------------------------------------------------------------------------*/
708     /**
709      * Invoked when a component gains the keyboard focus.
710      *
711      * @param event the focus event forwardes by the sytem.
712      */

713     /*--------------------------------------------------------------------------*/
714     /*
715      * $ @design <- keep this tag in place and don't write on this line!
716      *
717      * Enter design related documentation here.
718      * --------------------------------------------------------------------------
719      */

720     public void focusGained(FocusEvent JavaDoc event)
721     {
722         activeField = (RuleTextField) event.getSource();
723
724         if (backstep)
725         {
726             activeField.setCaretPosition(activeField.getText().length());
727             backstep = false;
728         }
729         else
730         {
731             activeField.selectAll();
732         }
733     }
734
735     /*--------------------------------------------------------------------------*/
736     /**
737      * Invoked when a component loses the keyboard focus. This method does nothing, we are only
738      * interested in 'focus gained' events.
739      *
740      * @param event the focus event forwardes by the sytem.
741      */

742     /*--------------------------------------------------------------------------*/
743     public void focusLost(FocusEvent JavaDoc event)
744     {
745     }
746
747     /*---------------------------------------------------------------------------*
748      Implementation for CaretListener
749      *---------------------------------------------------------------------------*/

750
751     /*--------------------------------------------------------------------------*/
752     /**
753      * Called when the caret position is updated.
754      *
755      * @param event the caret event received from the text field
756      */

757     /*--------------------------------------------------------------------------*/
758     public void caretUpdate(CaretEvent JavaDoc event)
759     {
760         if (activeField != null)
761         {
762             String JavaDoc text = activeField.getText();
763             int fieldSize = activeField.getEditLength();
764             int caretPosition = activeField.getCaretPosition();
765             int selection = activeField.getSelectionEnd() - activeField.getSelectionStart();
766
767             if ((!inputFields.lastElement().equals(activeField)) && (!activeField.unlimitedEdit()))
768             {
769                 if ((text.length() == fieldSize) && (selection == 0)
770                         && (caretPosition == fieldSize) && !backstep)
771                 {
772                     activeField.transferFocus();
773                 }
774             }
775         }
776     }
777
778     // ----------------------------------------------------------------------------
779
//
780
// ----------------------------------------------------------------------------
781
private static class FieldSpec
782     {
783
784         private int MIN_TOKENS = 2;
785
786         private int MAX_TOKENS = 3;
787
788         private int type;
789
790         private int columns;
791
792         private int editLength;
793
794         private boolean unlimitedEdit = false;
795
796         public FieldSpec(String JavaDoc spec) throws Exception JavaDoc
797         {
798             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(spec, ":");
799
800             if ((tokenizer.countTokens() >= MIN_TOKENS) && (tokenizer.countTokens() <= MAX_TOKENS))
801             {
802                 String JavaDoc token = tokenizer.nextToken().toUpperCase();
803                 // ------------------------------------------------
804
// test the first token for a valid type identifier
805
// if it's valid assign the token to the type.
806
// ------------------------------------------------
807
if ("N".equals(token))
808                 {
809                     type = RuleTextField.N;
810                 }
811                 else if ("H".equals(token))
812                 {
813                     type = RuleTextField.H;
814                 }
815                 else if ("A".equals(token))
816                 {
817                     type = RuleTextField.A;
818                 }
819                 else if ("O".equals(token))
820                 {
821                     type = RuleTextField.O;
822                 }
823                 else if ("AN".equals(token))
824                 {
825                     type = RuleTextField.AN;
826                 }
827                 else
828                 {
829                     throw (new Exception JavaDoc());
830                 }
831
832                 // ------------------------------------------------
833
// test for a valid integer to define the size
834
// of the field and assing to columns.
835
// ------------------------------------------------
836
try
837                 {
838                     token = tokenizer.nextToken();
839                     columns = Integer.parseInt(token);
840                 }
841                 catch (Throwable JavaDoc exception)
842                 {
843                     throw (new Exception JavaDoc());
844                 }
845
846                 // ------------------------------------------------
847
// test for a valid integer to define the edit
848
// length and assign to editLength. If this fails
849
// test for identifier for unlimited edit length.
850
// If this works, set unlimitedEdit to true.
851
// ------------------------------------------------
852
try
853                 {
854                     token = tokenizer.nextToken().toUpperCase();
855                     editLength = Integer.parseInt(token);
856                 }
857                 catch (Throwable JavaDoc exception)
858                 {
859                     if ("U".equals(token))
860                     {
861                         unlimitedEdit = true;
862                     }
863                     else
864                     {
865                         throw (new Exception JavaDoc());
866                     }
867                 }
868
869             }
870             else
871             {
872                 throw (new Exception JavaDoc());
873             }
874         }
875
876         public int getColumns()
877         {
878             return (columns);
879         }
880
881         public int getEditLength()
882         {
883             return (editLength);
884         }
885
886         public int getType()
887         {
888             return (type);
889         }
890
891         public boolean getUnlimitedEdit()
892         {
893             return (unlimitedEdit);
894         }
895
896     }
897     // ----------------------------------------------------------------------------
898

899 }
900 /*---------------------------------------------------------------------------*/
901
Popular Tags