root / import / ext3D / trunk / install-extension3d / IzPack / src / lib / com / izforge / izpack / panels / RuleInputField.java @ 15280
History | View | Annotate | Download (33 KB)
1 |
/*
|
---|---|
2 |
* $Id: RuleInputField.java,v 1.1 2006/06/14 07:29:07 cesar Exp $
|
3 |
* Copyright (C) 2002 Elmar Grom
|
4 |
*
|
5 |
* File : RuleInputField.java
|
6 |
* Description : A Java component that serves as a serial number
|
7 |
* input field with limited format verification.
|
8 |
* Author's email : elmar@grom.net
|
9 |
* Author's Website : http://www.izforge.com
|
10 |
*
|
11 |
* This program is free software; you can redistribute it and/or
|
12 |
* modify it under the terms of the GNU General Public License
|
13 |
* as published by the Free Software Foundation; either version 2
|
14 |
* of the License, or any later version.
|
15 |
*
|
16 |
* This program is distributed in the hope that it will be useful,
|
17 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19 |
* GNU General Public License for more details.
|
20 |
*
|
21 |
* You should have received a copy of the GNU General Public License
|
22 |
* along with this program; if not, write to the Free Software
|
23 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
24 |
*/
|
25 |
|
26 |
package com.izforge.izpack.panels; |
27 |
|
28 |
import java.awt.Toolkit; |
29 |
import java.awt.event.FocusEvent; |
30 |
import java.awt.event.FocusListener; |
31 |
import java.awt.event.KeyEvent; |
32 |
import java.awt.event.KeyListener; |
33 |
import java.util.StringTokenizer; |
34 |
import java.util.Vector; |
35 |
import java.util.Map; |
36 |
|
37 |
import javax.swing.JComponent; |
38 |
import javax.swing.JLabel; |
39 |
import javax.swing.JTextField; |
40 |
import javax.swing.event.CaretEvent; |
41 |
import javax.swing.event.CaretListener; |
42 |
|
43 |
import org.apache.regexp.RE; |
44 |
|
45 |
/*---------------------------------------------------------------------------*/
|
46 |
/**
|
47 |
* This class assists the user in entering serial numbers.
|
48 |
* <BR><BR>
|
49 |
* Serial numbers, license number, CD keys and the like are often lenghty
|
50 |
* alpha-numerical numbers. In many cases they are devided into multiple
|
51 |
* parts by dash or point separators. Entering these in a single text field
|
52 |
* can be a frustrating experience for the user. This class provides a way
|
53 |
* of presenting the user with an assembly of input fields that are arranged
|
54 |
* in the same way as the key, with the separators already in place.
|
55 |
* Immideate testing for format compliance if performed ans soon as each
|
56 |
* field is completed. In addition, the cursor is automatically advanced
|
57 |
* to make entering numbers as painless as possible.
|
58 |
* <br><br>
|
59 |
* <b>Formatting:</b>
|
60 |
*
|
61 |
* <ul>
|
62 |
* <li><code>N:X:Y </code>- numeric field, accepts digits only
|
63 |
* <li><code>H:X:Y </code>- hex field, accepts only hexadecimal digits
|
64 |
* <li><code>A:X:Y </code>- alpha field, accepts only letters, no digits
|
65 |
* <li><code>AN:X:Y</code>- alpha-numeric field, accepts digits and letters
|
66 |
* </ul>
|
67 |
* <b>Example:</b>
|
68 |
* <br><br>
|
69 |
* <code>"N:4:4 - H:6:6 - AN:3:3 x A:5:5"</code><br><br>
|
70 |
* This formatting string will produce a serial number field consisting of
|
71 |
* four separate input fields. The fisrt input field will accept four
|
72 |
* numeric digits, the second six hexa-decimal digits, the third three
|
73 |
* alpha-numeric digits and the fourth five letters. The first three input
|
74 |
* fields will be separated by '-' and the third and fourth by 'x'. The
|
75 |
* following snapshot was obtained with this setting:
|
76 |
* <br><br>
|
77 |
* <img src="doc-files/RuleInputField-1.gif"/>
|
78 |
*
|
79 |
* @version 0.0.1 / 10/19/02
|
80 |
* @author Elmar Grom
|
81 |
*/
|
82 |
/*---------------------------------------------------------------------------*/
|
83 |
public class RuleInputField extends JComponent implements KeyListener, |
84 |
FocusListener,
|
85 |
CaretListener,
|
86 |
ProcessingClient |
87 |
{ |
88 |
/** Used to specify the retsult format. This constant specifies to return
|
89 |
the contents of all fields concatenated into one long string, with
|
90 |
separation between each component. */
|
91 |
public static final int PLAIN_STRING = 1; |
92 |
/** Used to specify the retsult format. This constant specifies to return
|
93 |
the contents of all fields together with all separators as specified
|
94 |
in the field format concatenated into one long string. In this case
|
95 |
the resulting string looks just like the user saw it during data entry */
|
96 |
public static final int DISPLAY_FORMAT = 2; |
97 |
/** Used to specify the retsult format. This constant specifies to return
|
98 |
the contents of all fields concatenated into one long string, with
|
99 |
a special separator string inserted in between the individual
|
100 |
components. */
|
101 |
public static final int SPECIAL_SEPARATOR = 3; |
102 |
/** Used to specify the retsult format. This constant specifies to return
|
103 |
the contents of all fields in a somehow modified way. How the content
|
104 |
is modified depends on the operation performed by a encryption
|
105 |
service class. The class must be provided at object instatiation. */
|
106 |
public static final int ENCRYPTED = 4; |
107 |
/** Used internally to identify the default setting for the return format. */
|
108 |
private static int DEFAULT = DISPLAY_FORMAT; |
109 |
|
110 |
private Vector items = new Vector (); |
111 |
/** This <code>Vector</code> holds a reference to each input field, in the
|
112 |
order in which they appear on the screen. */
|
113 |
private Vector inputFields = new Vector (); |
114 |
private boolean hasParams = false; |
115 |
private Map validatorParams; |
116 |
private RuleTextField activeField;
|
117 |
private boolean backstep = false; |
118 |
private Toolkit toolkit; |
119 |
private String separator; |
120 |
private int resultFormat = DEFAULT; |
121 |
|
122 |
/** Holds an instance of the <code>Validator</code> if one was
|
123 |
specified and available */
|
124 |
private Validator validationService; |
125 |
/** Holds an instance of the <code>Processor</code> if one was specified
|
126 |
and available */
|
127 |
private Processor encryptionService;
|
128 |
|
129 |
/**
|
130 |
* @return true if this instance has any parameters to
|
131 |
* pass to the Validator instance.
|
132 |
*/
|
133 |
public boolean hasParams() |
134 |
{ |
135 |
return hasParams;
|
136 |
} |
137 |
|
138 |
/*--------------------------------------------------------------------------*/
|
139 |
/**
|
140 |
* Constructs a rule input field.
|
141 |
*
|
142 |
* @param format a string that specifies the formatting and to a
|
143 |
* limited degree the behavior of this field.
|
144 |
* @param preset a string that specifies preset values for specific
|
145 |
* sub-fields.
|
146 |
* @param separator a string to be used for separating the contents
|
147 |
* of individual fields in the string returned by
|
148 |
* <code>getText()</code>
|
149 |
* @param validator A string that specifies a class to perform
|
150 |
* validation services. The string must completely
|
151 |
* identify the class, so that it can be instantiated.
|
152 |
* The class must implement the <code>RuleValidator</code>
|
153 |
* interface. If an attempt to instantiate this class
|
154 |
* fails, no validation will be performed.
|
155 |
* @param validatorParams A <code>java.util.Map</code> containing name/
|
156 |
* value pairs, which will be forwarded to the validator.
|
157 |
* @param processor A string that specifies a class to perform
|
158 |
* processing services. The string must completely
|
159 |
* identify the class, so that it can be instantiated.
|
160 |
* The class must implement the <code>Processor</code>
|
161 |
* interface. If an attempt to instantiate this class
|
162 |
* fails, no processing will be performed. Instead,
|
163 |
* the text is returned in the default formatting.
|
164 |
* @param resultFormat specifies in which format the resulting text
|
165 |
* should be returned, wehn <code>getText()</code>
|
166 |
* is called. The following values are legal:<br>
|
167 |
* <ul>
|
168 |
* <li>PLAIN_STRING
|
169 |
* <li>DISPLAY_FORMAT
|
170 |
* <li>SPECIAL_SEPARATOR
|
171 |
* <li>ENCRYPTED
|
172 |
* </ul>
|
173 |
* @param toolkit needed to gain access to <code>beep()</code>
|
174 |
*/
|
175 |
/*--------------------------------------------------------------------------*/
|
176 |
public RuleInputField(
|
177 |
String format,
|
178 |
String preset,
|
179 |
String separator,
|
180 |
String validator,
|
181 |
Map validatorParams,
|
182 |
String processor,
|
183 |
int resultFormat,
|
184 |
Toolkit toolkit)
|
185 |
{ |
186 |
this(
|
187 |
format, |
188 |
preset, |
189 |
separator, |
190 |
validator, |
191 |
processor, |
192 |
resultFormat, |
193 |
toolkit); |
194 |
this.validatorParams = validatorParams;
|
195 |
this.hasParams = true; |
196 |
} |
197 |
|
198 |
/*--------------------------------------------------------------------------*/
|
199 |
/**
|
200 |
* Constructs a rule input field.
|
201 |
*
|
202 |
* @param format a string that specifies the formatting and to a
|
203 |
* limited degree the behavior of this field.
|
204 |
* @param preset a string that specifies preset values for specific
|
205 |
* sub-fields.
|
206 |
* @param separator a string to be used for separating the contents
|
207 |
* of individual fields in the string returned by
|
208 |
* <code>getText()</code>
|
209 |
* @param validator A string that specifies a class to perform
|
210 |
* validation services. The string must completely
|
211 |
* identify the class, so that it can be instantiated.
|
212 |
* The class must implement the <code>RuleValidator</code>
|
213 |
* interface. If an attempt to instantiate this class
|
214 |
* fails, no validation will be performed.
|
215 |
* @param processor A string that specifies a class to perform
|
216 |
* processing services. The string must completely
|
217 |
* identify the class, so that it can be instantiated.
|
218 |
* The class must implement the <code>Processor</code>
|
219 |
* interface. If an attempt to instantiate this class
|
220 |
* fails, no processing will be performed. Instead,
|
221 |
* the text is returned in the default formatting.
|
222 |
* @param resultFormat specifies in which format the resulting text
|
223 |
* should be returned, wehn <code>getText()</code>
|
224 |
* is called. The following values are legal:<br>
|
225 |
* <ul>
|
226 |
* <li>PLAIN_STRING
|
227 |
* <li>DISPLAY_FORMAT
|
228 |
* <li>SPECIAL_SEPARATOR
|
229 |
* <li>ENCRYPTED
|
230 |
* </ul>
|
231 |
* @param toolkit needed to gain access to <code>beep()</code>
|
232 |
*/
|
233 |
/*--------------------------------------------------------------------------*/
|
234 |
public RuleInputField (String format, |
235 |
String preset,
|
236 |
String separator,
|
237 |
String validator,
|
238 |
String processor,
|
239 |
int resultFormat,
|
240 |
Toolkit toolkit)
|
241 |
{ |
242 |
this.toolkit = toolkit;
|
243 |
this.separator = separator;
|
244 |
this.resultFormat = resultFormat;
|
245 |
|
246 |
com.izforge.izpack.gui.FlowLayout layout = new com.izforge.izpack.gui.FlowLayout ();
|
247 |
layout.setAlignment (com.izforge.izpack.gui.FlowLayout.LEFT); |
248 |
setLayout (layout); |
249 |
|
250 |
// ----------------------------------------------------
|
251 |
// attempt to create an instance of the Validator
|
252 |
// ----------------------------------------------------
|
253 |
try
|
254 |
{ |
255 |
validationService = (Validator)Class.forName (validator).newInstance (); |
256 |
} |
257 |
catch (Throwable exception) |
258 |
{ |
259 |
validationService = null;
|
260 |
} |
261 |
|
262 |
// ----------------------------------------------------
|
263 |
// attempt to create an instance of the Processor
|
264 |
// ----------------------------------------------------
|
265 |
try
|
266 |
{ |
267 |
encryptionService = (Processor)Class.forName (processor).newInstance ();
|
268 |
} |
269 |
catch (Throwable exception) |
270 |
{ |
271 |
encryptionService = null;
|
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 |
* Returns the number of sub-fields composing this <code>RuleInputField</code>.
|
293 |
*
|
294 |
* @return the number of sub-fields
|
295 |
*/
|
296 |
/*--------------------------------------------------------------------------*/
|
297 |
public int getNumFields () |
298 |
{ |
299 |
return (inputFields.size ());
|
300 |
} |
301 |
/*--------------------------------------------------------------------------*/
|
302 |
/**
|
303 |
* Returns the contents of the field indicated by <code>index</code>.
|
304 |
*
|
305 |
* @param index the index of the sub-field from which the contents
|
306 |
* is requested.
|
307 |
*
|
308 |
* @return the contents of the indicated sub-field.
|
309 |
*
|
310 |
* @exception IndexOutOfBoundsException if the index is out of bounds.
|
311 |
*/
|
312 |
/*--------------------------------------------------------------------------*/
|
313 |
public String getFieldContents (int index) throws IndexOutOfBoundsException |
314 |
{ |
315 |
if ((index < 0) || (index > (inputFields.size () - 1))) |
316 |
{ |
317 |
throw (new IndexOutOfBoundsException ()); |
318 |
} |
319 |
|
320 |
return (((JTextField)inputFields.elementAt (index)).getText ()); |
321 |
} |
322 |
/*--------------------------------------------------------------------------*/
|
323 |
/**
|
324 |
* Returns the validator parameters, if any. The caller should
|
325 |
* check for the existence of validator parameters via the
|
326 |
* <code>hasParams()</code> method prior to invoking this method.
|
327 |
* @return a java.util.Map containing the validator parameters.
|
328 |
*/
|
329 |
public Map getValidatorParams() |
330 |
{ |
331 |
return validatorParams;
|
332 |
} |
333 |
|
334 |
/*---------------------------------------------------------------------------*/
|
335 |
/**
|
336 |
* Returns the field contents, assembled acording to the encryption and
|
337 |
* separator rules.
|
338 |
*
|
339 |
* @return the field contents
|
340 |
*/
|
341 |
/*--------------------------------------------------------------------------*/
|
342 |
public String getText () |
343 |
{ |
344 |
Object item;
|
345 |
StringBuffer buffer = new StringBuffer (); |
346 |
int size = inputFields.size ();
|
347 |
|
348 |
// ----------------------------------------------------
|
349 |
// have the encryption service class perfrom the task
|
350 |
// of assembling an output string. If we have no instance
|
351 |
// of this class available set the formatting
|
352 |
// instruction to the default setting.
|
353 |
// ----------------------------------------------------
|
354 |
if (resultFormat == ENCRYPTED)
|
355 |
{ |
356 |
if (encryptionService != null) |
357 |
{ |
358 |
buffer.append (encryptionService.process (this));
|
359 |
} |
360 |
else
|
361 |
{ |
362 |
resultFormat = DEFAULT; |
363 |
} |
364 |
} |
365 |
|
366 |
// ----------------------------------------------------
|
367 |
// concatentate the field contents, with no separators
|
368 |
// in between.
|
369 |
// ----------------------------------------------------
|
370 |
else if (resultFormat == PLAIN_STRING) |
371 |
{ |
372 |
for (int i = 0; i < inputFields.size (); i++) |
373 |
{ |
374 |
buffer.append (((JTextField)inputFields.elementAt (i)).getText ());
|
375 |
} |
376 |
} |
377 |
|
378 |
// ----------------------------------------------------
|
379 |
// concatenate the field contents and setarators, as
|
380 |
// specified for the display of the field.
|
381 |
// ----------------------------------------------------
|
382 |
else if (resultFormat == DISPLAY_FORMAT) |
383 |
{ |
384 |
for (int i = 0; i < items.size (); i++) |
385 |
{ |
386 |
item = items.elementAt (i); |
387 |
if (item instanceof JTextField) |
388 |
{ |
389 |
buffer.append (((JTextField)item).getText ());
|
390 |
} |
391 |
else
|
392 |
{ |
393 |
buffer.append ((String)item);
|
394 |
} |
395 |
} |
396 |
} |
397 |
|
398 |
// ----------------------------------------------------
|
399 |
// concatenate the field contents and insert the
|
400 |
// separator string in between.
|
401 |
// ----------------------------------------------------
|
402 |
else if (resultFormat == SPECIAL_SEPARATOR) |
403 |
{ |
404 |
for (int i = 0; i < size; i++) |
405 |
{ |
406 |
buffer.append (((JTextField)inputFields.elementAt (i)).getText ());
|
407 |
|
408 |
if (i < (size - 1)) |
409 |
{ |
410 |
buffer.append (separator); |
411 |
} |
412 |
} |
413 |
} |
414 |
|
415 |
return (buffer.toString ());
|
416 |
} |
417 |
/*--------------------------------------------------------------------------*/
|
418 |
/**
|
419 |
* Creates the items that make up this field. Both separators and input
|
420 |
* fields are considered items. The items created are stored in
|
421 |
* <code>items</code>. In addition, all fields are stored in
|
422 |
* <code>inputFields</code>.
|
423 |
*
|
424 |
* @param format a string that specifies the layout of the input
|
425 |
* fields and separators.
|
426 |
*/
|
427 |
/*--------------------------------------------------------------------------*/
|
428 |
/*$
|
429 |
* @design
|
430 |
*
|
431 |
* I used a simple StringTokenizer to break the format string into
|
432 |
* individual tokens. The approach in building up the field is to consider
|
433 |
* each token a potential definition for an input field. Therefore I
|
434 |
* attempt to create an instance of FieldSpec from each token. FieldSpec
|
435 |
* analyzes the token and if it does not represent a valid specification
|
436 |
* for an input field throws an exception. If I catch an exception, I know
|
437 |
* the token does not represent a valid field specification. In this case
|
438 |
* I treat the token as a separator, even though this might not be what the
|
439 |
* user had intended. However, this approach allows me to implement robust
|
440 |
* behavior (no exception thrown) even though the user might have made a
|
441 |
* mistake in the definition. The mistake should become immediately obvious
|
442 |
* when testing the code, since a input field definition would show up as
|
443 |
* separator between two fields.
|
444 |
*--------------------------------------------------------------------------*/
|
445 |
private void createItems (String format) |
446 |
{ |
447 |
Object item;
|
448 |
JTextField field;
|
449 |
String token;
|
450 |
FieldSpec spec; |
451 |
StringTokenizer tokenizer = new StringTokenizer (format); |
452 |
|
453 |
while (tokenizer.hasMoreTokens ())
|
454 |
{ |
455 |
token = tokenizer.nextToken (); |
456 |
try
|
457 |
{ |
458 |
spec = new FieldSpec (token);
|
459 |
field = new RuleTextField (spec.getColumns (),
|
460 |
spec.getEditLength (), |
461 |
spec.getType (), |
462 |
spec.getUnlimitedEdit (), |
463 |
toolkit); |
464 |
|
465 |
// ------------------------------------------------
|
466 |
// if the previous item is also a field, insert a
|
467 |
// space as separator
|
468 |
// ------------------------------------------------
|
469 |
if (items.size () > 0) |
470 |
{ |
471 |
item = items.lastElement (); |
472 |
|
473 |
if (item instanceof JTextField) |
474 |
{ |
475 |
items.add (" ");
|
476 |
} |
477 |
} |
478 |
|
479 |
items.add (field); |
480 |
inputFields.add (field); |
481 |
field.addFocusListener (this);
|
482 |
field.addKeyListener (this);
|
483 |
field.addCaretListener (this);
|
484 |
} |
485 |
// --------------------------------------------------
|
486 |
// if we were not successful creating an input field,
|
487 |
// the token must be a separator or the definition
|
488 |
// has an error. Simply insert it as separator,
|
489 |
// when testing the installer the error should become
|
490 |
// obvious to the developer.
|
491 |
// --------------------------------------------------
|
492 |
catch (Throwable exception) |
493 |
{ |
494 |
if (items.size () == 0) |
495 |
{ |
496 |
items.add (token); |
497 |
} |
498 |
else
|
499 |
{ |
500 |
item = items.lastElement (); |
501 |
|
502 |
// ----------------------------------------------
|
503 |
// if the previous item is also a separator,
|
504 |
// simply concatenate the token with a space
|
505 |
// inserted in between, don't add it as new
|
506 |
// separator.
|
507 |
// ----------------------------------------------
|
508 |
if (item instanceof String) |
509 |
{ |
510 |
items.setElementAt (item + " " + token, (items.size () - 1)); |
511 |
} |
512 |
else
|
513 |
{ |
514 |
items.add (token); |
515 |
} |
516 |
} |
517 |
} |
518 |
} |
519 |
|
520 |
// ----------------------------------------------------
|
521 |
// add the fields and separators to the component
|
522 |
// ----------------------------------------------------
|
523 |
for (int i = 0; i < items.size (); i++) |
524 |
{ |
525 |
item = items.elementAt (i); |
526 |
|
527 |
if (item instanceof String) |
528 |
{ |
529 |
add (new JLabel ((String)item)); |
530 |
} |
531 |
else
|
532 |
{ |
533 |
add ((JTextField)item);
|
534 |
} |
535 |
} |
536 |
} |
537 |
/*--------------------------------------------------------------------------*/
|
538 |
/**
|
539 |
* Sets each field to a pre-defined value.
|
540 |
*
|
541 |
* @param data a <code>String</code> containing the preset values for
|
542 |
* each field. The format of the string is as follows:
|
543 |
* The content for the individuals fields must be separated
|
544 |
* by whitespace. Each data block is preceeded by the index
|
545 |
* of the field to set (counting starts at 0) followed by
|
546 |
* a colon ':'and after that the actual data for the field.
|
547 |
*/
|
548 |
/*--------------------------------------------------------------------------*/
|
549 |
private void setFields (String data) |
550 |
{ |
551 |
StringTokenizer tokenizer = new StringTokenizer (data); |
552 |
StringTokenizer tokenizer1 = null; |
553 |
String token;
|
554 |
String indexString;
|
555 |
String processorClass;
|
556 |
int index;
|
557 |
boolean process = false; |
558 |
String[] vals = null; |
559 |
int i = 0; |
560 |
|
561 |
vals = new String[tokenizer.countTokens()]; |
562 |
while (tokenizer.hasMoreTokens ())
|
563 |
{ |
564 |
token = tokenizer.nextToken (); |
565 |
indexString = token.substring (0, token.indexOf (':')); |
566 |
|
567 |
try
|
568 |
{ |
569 |
index = Integer.parseInt (indexString);
|
570 |
if (index < inputFields.size ())
|
571 |
{ |
572 |
String val = token.substring ((token.indexOf (':') + 1), token.length ()); |
573 |
String className = ""; |
574 |
if (val.indexOf(":")>-1){ |
575 |
className = val.substring(val.indexOf(":")+1); |
576 |
val = val.substring(0, val.indexOf(":")); |
577 |
} |
578 |
|
579 |
if (!className.equals("") && !process){ |
580 |
process = true;
|
581 |
} |
582 |
vals[i] = val; |
583 |
i++; |
584 |
((JTextField)inputFields.elementAt (index)).setText (val);
|
585 |
} |
586 |
}catch (Throwable exception) |
587 |
{ |
588 |
exception.printStackTrace(); |
589 |
} |
590 |
} |
591 |
|
592 |
if (process){
|
593 |
tokenizer = new StringTokenizer (data); |
594 |
while (tokenizer.hasMoreTokens ()){
|
595 |
token = tokenizer.nextToken (); |
596 |
indexString = token.substring (0, token.indexOf (':')); |
597 |
|
598 |
try{
|
599 |
index = Integer.parseInt (indexString);
|
600 |
if (index < inputFields.size ()){
|
601 |
String val = token.substring ((token.indexOf (':') + 1), token.length ()); |
602 |
String className = ""; |
603 |
String presult = ""; |
604 |
if (val.indexOf(":")>-1){ |
605 |
className = val.substring(val.indexOf(":")+1); |
606 |
val = val.substring(0, val.indexOf(":")); |
607 |
} |
608 |
|
609 |
if (!className.equals("")){ |
610 |
Processor p = (Processor) Class.forName(className).newInstance();
|
611 |
presult = p.process(this);
|
612 |
} |
613 |
String[] td = new RE("\\*").split(presult); |
614 |
((JTextField)inputFields.elementAt (index)).setText (td[index]);
|
615 |
} |
616 |
}catch (Throwable exception){ |
617 |
; |
618 |
} |
619 |
} |
620 |
} |
621 |
} |
622 |
|
623 |
/*--------------------------------------------------------------------------*/
|
624 |
/**
|
625 |
* This method validates the field content. Validating is performed through
|
626 |
* a user supplied service class that provides the validation rules.
|
627 |
*
|
628 |
* @return <code>true</code> if the validation passes or no implementation
|
629 |
* of a validation rule exists. Otherwise <code>false</code> is
|
630 |
* returned.
|
631 |
*/
|
632 |
/*--------------------------------------------------------------------------*/
|
633 |
public boolean validateContents () |
634 |
{ |
635 |
if (validationService != null) |
636 |
{ |
637 |
return (validationService.validate (this)); |
638 |
} |
639 |
else
|
640 |
{ |
641 |
return (true); |
642 |
} |
643 |
} |
644 |
|
645 |
/*---------------------------------------------------------------------------*
|
646 |
Implementation for KeyListener
|
647 |
*---------------------------------------------------------------------------*/
|
648 |
|
649 |
/*--------------------------------------------------------------------------*/
|
650 |
/**
|
651 |
* This method is invoked when a key has been typed. The event occurs when
|
652 |
* a key press is followed by a key release.
|
653 |
*
|
654 |
* @param event the key event forwarded by the system.
|
655 |
*/
|
656 |
/*--------------------------------------------------------------------------*/
|
657 |
public void keyTyped (KeyEvent event) |
658 |
{ |
659 |
} |
660 |
/*--------------------------------------------------------------------------*/
|
661 |
/**
|
662 |
* This method is invoked when a key has been pressed. This method verifies
|
663 |
* the condition of the input field in focus. Once the column count in the
|
664 |
* field has reached the specified maximum, the rule specified for the field
|
665 |
* in question is invoked. In case the test result is positive, focus is set
|
666 |
* to the next field. If hte test result is negative, the field content is
|
667 |
* marked and the caret set to the start of the field.
|
668 |
*
|
669 |
* @param event the key event forwarded by the system.
|
670 |
*/
|
671 |
/*--------------------------------------------------------------------------*/
|
672 |
public void keyPressed (KeyEvent event) |
673 |
{ |
674 |
if (event.getKeyCode () == KeyEvent.VK_BACK_SPACE) |
675 |
{ |
676 |
int caretPosition = activeField.getCaretPosition ();
|
677 |
|
678 |
if (caretPosition == 0) |
679 |
{ |
680 |
int activeIndex = inputFields.indexOf (activeField);
|
681 |
|
682 |
if (activeIndex > 0) |
683 |
{ |
684 |
activeIndex--; |
685 |
backstep = true;
|
686 |
activeField = (RuleTextField)inputFields.elementAt (activeIndex); |
687 |
activeField.grabFocus (); |
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 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 |
public void focusGained (FocusEvent event) |
720 |
{ |
721 |
activeField = (RuleTextField)event.getSource (); |
722 |
|
723 |
if (backstep)
|
724 |
{ |
725 |
activeField.setCaretPosition (activeField.getText ().length ()); |
726 |
backstep = false;
|
727 |
} |
728 |
else
|
729 |
{ |
730 |
activeField.selectAll (); |
731 |
} |
732 |
} |
733 |
/*--------------------------------------------------------------------------*/
|
734 |
/**
|
735 |
* Invoked when a component loses the keyboard focus. This method does
|
736 |
* nothing, we are only interested in 'focus gained' events.
|
737 |
*
|
738 |
* @param event the focus event forwardes by the sytem.
|
739 |
*/
|
740 |
/*--------------------------------------------------------------------------*/
|
741 |
public void focusLost (FocusEvent event) |
742 |
{ |
743 |
} |
744 |
|
745 |
/*---------------------------------------------------------------------------*
|
746 |
Implementation for CaretListener
|
747 |
*---------------------------------------------------------------------------*/
|
748 |
|
749 |
/*--------------------------------------------------------------------------*/
|
750 |
/**
|
751 |
* Called when the caret position is updated.
|
752 |
*
|
753 |
* @param event the caret event received from the text field
|
754 |
*/
|
755 |
/*--------------------------------------------------------------------------*/
|
756 |
public void caretUpdate (CaretEvent event) |
757 |
{ |
758 |
String text = activeField.getText ();
|
759 |
int fieldSize = activeField.getEditLength ();
|
760 |
int caretPosition = activeField.getCaretPosition ();
|
761 |
int selection = activeField.getSelectionEnd () - activeField.getSelectionStart ();
|
762 |
|
763 |
if ((!inputFields.lastElement ().equals (activeField)) && (!activeField.unlimitedEdit ()))
|
764 |
{ |
765 |
if ((text.length () == fieldSize) && (selection == 0) && (caretPosition == fieldSize) && !backstep) |
766 |
{ |
767 |
activeField.transferFocus (); |
768 |
} |
769 |
} |
770 |
} |
771 |
|
772 |
// ----------------------------------------------------------------------------
|
773 |
//
|
774 |
// ----------------------------------------------------------------------------
|
775 |
private static class FieldSpec |
776 |
{ |
777 |
private int MIN_TOKENS = 2; |
778 |
private int MAX_TOKENS = 3; |
779 |
|
780 |
private int type; |
781 |
private int columns; |
782 |
private int editLength; |
783 |
private boolean unlimitedEdit = false; |
784 |
|
785 |
public FieldSpec (String spec) throws Exception |
786 |
{ |
787 |
StringTokenizer tokenizer = new StringTokenizer (spec, ":"); |
788 |
|
789 |
if ((tokenizer.countTokens () >= MIN_TOKENS) && (tokenizer.countTokens () <= MAX_TOKENS))
|
790 |
{ |
791 |
String token = tokenizer.nextToken ().toUpperCase ();
|
792 |
// ------------------------------------------------
|
793 |
// test the first token for a valid type identifier
|
794 |
// if it's valid assign the token to the type.
|
795 |
// ------------------------------------------------
|
796 |
if (token.equals ("N")) |
797 |
{ |
798 |
type = RuleTextField.N; |
799 |
} |
800 |
else if (token.equals ("H")) |
801 |
{ |
802 |
type = RuleTextField.H; |
803 |
} |
804 |
else if (token.equals ("A")) |
805 |
{ |
806 |
type = RuleTextField.A; |
807 |
} |
808 |
else if (token.equals ("O")) |
809 |
{ |
810 |
type = RuleTextField.O; |
811 |
} |
812 |
else if (token.equals ("AN")) |
813 |
{ |
814 |
type = RuleTextField.AN; |
815 |
} |
816 |
else
|
817 |
{ |
818 |
throw (new Exception ()); |
819 |
} |
820 |
|
821 |
// ------------------------------------------------
|
822 |
// test for a valid integer to define the size
|
823 |
// of the field and assing to columns.
|
824 |
// ------------------------------------------------
|
825 |
try
|
826 |
{ |
827 |
token = tokenizer.nextToken (); |
828 |
columns = Integer.parseInt (token);
|
829 |
} |
830 |
catch (Throwable exception) |
831 |
{ |
832 |
throw (new Exception ()); |
833 |
} |
834 |
|
835 |
// ------------------------------------------------
|
836 |
// test for a valid integer to define the edit
|
837 |
// length and assign to editLength. If this fails
|
838 |
// test for identifier for unlimited edit length.
|
839 |
// If this works, set unlimitedEdit to true.
|
840 |
// ------------------------------------------------
|
841 |
try
|
842 |
{ |
843 |
token = tokenizer.nextToken ().toUpperCase (); |
844 |
editLength = Integer.parseInt (token);
|
845 |
} |
846 |
catch (Throwable exception) |
847 |
{ |
848 |
if (token.equals ("U")) |
849 |
{ |
850 |
unlimitedEdit = true;
|
851 |
} |
852 |
else
|
853 |
{ |
854 |
throw (new Exception ()); |
855 |
} |
856 |
} |
857 |
|
858 |
} |
859 |
else
|
860 |
{ |
861 |
throw (new Exception ()); |
862 |
} |
863 |
} |
864 |
|
865 |
public int getColumns () |
866 |
{ |
867 |
return (columns);
|
868 |
} |
869 |
|
870 |
public int getEditLength () |
871 |
{ |
872 |
return (editLength);
|
873 |
} |
874 |
|
875 |
public int getType () |
876 |
{ |
877 |
return (type);
|
878 |
} |
879 |
|
880 |
public boolean getUnlimitedEdit () |
881 |
{ |
882 |
return (unlimitedEdit);
|
883 |
} |
884 |
|
885 |
} |
886 |
// ----------------------------------------------------------------------------
|
887 |
|
888 |
} |
889 |
/*---------------------------------------------------------------------------*/
|