Statistics
| Revision:

root / trunk / libraries / libUIComponent / src / org / gvsig / gui / beans / swing / ValidatingTextField.java @ 17478

History | View | Annotate | Download (15.5 KB)

1
/*
2
 * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
3
 * for visualizing and manipulating spatial features with geometry and attributes.
4
 *
5
 * Copyright (C) 2003 Vivid Solutions
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License
9
 * as published by the Free Software Foundation; either version 2
10
 * of the License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
 *
21
 * For more information, contact:
22
 *
23
 * Vivid Solutions
24
 * Suite #1A
25
 * 2328 Government Street
26
 * Victoria BC  V8T 5G5
27
 * Canada
28
 *
29
 * (250)385-6040
30
 * www.vividsolutions.com
31
 */
32
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
33
 *
34
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
35
 *
36
 * This program is free software; you can redistribute it and/or
37
 * modify it under the terms of the GNU General Public License
38
 * as published by the Free Software Foundation; either version 2
39
 * of the License, or (at your option) any later version.
40
 *
41
 * This program is distributed in the hope that it will be useful,
42
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44
 * GNU General Public License for more details.
45
 *
46
 * You should have received a copy of the GNU General Public License
47
 * along with this program; if not, write to the Free Software
48
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
49
 *
50
 * For more information, contact:
51
 *
52
 *  Generalitat Valenciana
53
 *   Conselleria d'Infraestructures i Transport
54
 *   Av. Blasco Ib??ez, 50
55
 *   46010 VALENCIA
56
 *   SPAIN
57
 *
58
 *      +34 963862235
59
 *   gvsig@gva.es
60
 *      www.gvsig.gva.es
61
 *
62
 *    or
63
 *
64
 *   IVER T.I. S.A
65
 *   Salamanca 50
66
 *   46005 Valencia
67
 *   Spain
68
 *
69
 *   +34 963163400
70
 *   dac@iver.es
71
 */
72
package org.gvsig.gui.beans.swing;
73

    
74
import java.awt.event.FocusAdapter;
75
import java.awt.event.FocusEvent;
76

    
77
import javax.swing.JOptionPane;
78
import javax.swing.JTextField;
79
import javax.swing.text.AttributeSet;
80
import javax.swing.text.BadLocationException;
81
import javax.swing.text.PlainDocument;
82

    
83
import org.gvsig.gui.beans.Messages;
84

    
85

    
86
/**
87
 * Prevents the user from entering invalid data.
88
 */
89
public class ValidatingTextField extends JTextField {
90
                private static final long serialVersionUID = -3725027007216791855L;
91

    
92
                public static final Validator LONG_VALIDATOR = new ValidatingTextField.Validator() {
93
            public boolean isValid(String text) {
94
                try {
95
                    Long.parseLong(text.trim());
96

    
97
                    return true;
98
                } catch (NumberFormatException e) {
99
                    return false;
100
                }
101
            }
102
        };
103

    
104
    /**
105
     * Prevents the user from entering invalid integer.
106
     */
107
    public static final Validator INTEGER_VALIDATOR = new ValidatingTextField.Validator() {
108
            public boolean isValid(String text) {
109
                try {
110
                    Integer.parseInt(text.trim());
111

    
112
                    return true;
113
                } catch (NumberFormatException e) {
114
                    return false;
115
                }
116
            }
117
        };
118

    
119
    /**
120
     * Prevents the user from entering invalid double.
121
     */
122
    public static final Validator DOUBLE_VALIDATOR = new ValidatingTextField.Validator() {
123
            public boolean isValid(String text) {
124
                try {
125
                    //Add "0" so user can type "-" [Jon Aquino]
126
                    Double.parseDouble(text.trim() + "0");
127

    
128
                    return true;
129
                } catch (NumberFormatException e) {
130
                    return false;
131
                }
132
            }
133
        };
134

    
135
    /**
136
     * Cleaner that does nothing.
137
     */
138
    public static Cleaner DUMMY_CLEANER = new Cleaner() {
139
            public String clean(String text) {
140
                return text;
141
            }
142
        };
143

    
144
    /**
145
     * The validators allow the user to simply enter "+", "-", or ".". If the user
146
     * doesn't go any farther, this cleaner will set the text to 0, which is reasonable.
147
     */
148
    public static Cleaner NUMBER_CLEANER = new Cleaner() {
149
            public String clean(String text) {
150
                    if (text!=null) {
151
                            try {
152
                                    Double.parseDouble(text.trim());
153

    
154
                            } catch (NumberFormatException e) {
155
                                    return "0";
156
                            }
157
                    }
158
                    return text;
159

    
160
            }
161
        };
162
        
163
        
164
    /**
165
     * The validators allow the user to simply enter "+", "-", or ".". If the user
166
     * doesn't go any farther, this cleaner will set the text to 0, which is reasonable.
167
     */
168
    public static Cleaner NUMBER_CLEANER_2_DECIMALS = new Cleaner() {
169
            public String clean(String text) {
170
                    if (text!=null) {
171
                            try {
172
                                    System.out.println("text before "+text);
173
                                    double d = Double.parseDouble(text.trim());
174
                                    int integerPart = (int) d;
175
                                    double decimalPart = d - integerPart;
176
                                           text = integerPart + "." + (int) Math.round(decimalPart*100);
177
                                           System.out.println("text after "+text);
178
                            } catch (NumberFormatException e) {
179
                                    return "0";
180
                            }
181
                    }
182
                    
183
                    return text;
184
            }
185
        };
186
//        public static class NumberWithDefinedDecimalNumberCuntCleaner extends NumberCleaner {
187
//                private int decimalCount = 2;
188
//                public NumberWithDefinedDecimalNumberCuntCleaner(String textToAppend) {
189
//                            this(textToAppend, 2);
190
//                    }
191
//                    public NumberWithDefinedDecimalNumberCuntCleaner(String textToAppend, int decimalCount) {
192
//                        super(textToAppend);
193
//                        this.decimalCount = decimalCount;
194
//                    }
195
//                    
196
//                    @Override
197
//                    public String clean(String text) {
198
//                            String s = super.clean(text);
199
//                            if (s.indexOf(ch)
200
//                            
201
//                            return s;
202
//                    }
203
//        }
204

    
205
    /**
206
     * Validator that does nothing.
207
     */
208
    public static Validator DUMMY_VALIDATOR = new Validator() {
209
            public boolean isValid(String text) {
210
                return true;
211
            }
212
        };
213

    
214
    private Cleaner cleaner;
215

    
216
    /**
217
     * Validator that uses dummy cleaner.
218
     */
219
    public ValidatingTextField(String text, int columns,
220
        final Validator validator) {
221
        this(text, columns, LEFT, validator, DUMMY_CLEANER);
222
    }
223

    
224
    /**
225
     * Validator for text fields.
226
     */
227
    public ValidatingTextField(String text, int columns,
228
        int horizontalAlignment, final Validator validator,
229
        final Cleaner cleaner) {
230
        super(text, columns);
231
        this.cleaner = cleaner;
232
        setHorizontalAlignment(horizontalAlignment);
233
        installValidationBehavior(this, validator, cleaner);
234

    
235
        //Clean the text, mainly so that parties wishing to install a BlankCleaner
236
        //need only pass "" for the text. [Jon Aquino]
237
        setText(cleaner.clean(getText()));
238

    
239
        //Bonus: workaround for how GridBagLayout shrinks components to
240
        //minimum sizes if it can't accomodate their preferred sizes. [Jon Aquino]
241
        setMinimumSize(getPreferredSize());
242
    }
243

    
244
    //Hopefully this will let us add validation behaviour to combo boxes. [Jon Aquino]
245
    public static void installValidationBehavior(final JTextField textField,
246
        final Validator validator, final Cleaner cleaner) {
247
        textField.setDocument(new PlainDocument() {
248
          private static final long serialVersionUID = 7097829094600558963L;
249

    
250
                                                                public void insertString(int offs, String str, AttributeSet a)
251
                    throws BadLocationException {
252
                    String currentText = this.getText(0, getLength());
253
                    String beforeOffset = currentText.substring(0, offs);
254
                    String afterOffset = currentText.substring(offs,
255
                            currentText.length());
256
                    String proposedResult = beforeOffset + str + afterOffset;
257
                    if (validator.isValid(cleaner.clean(proposedResult))) {
258
                        super.insertString(offs, str, a);
259
                    }
260
                }
261

    
262
                public void remove(int offs, int len)
263
                    throws BadLocationException {
264
                    String currentText = this.getText(0, getLength());
265
                    String beforeOffset = currentText.substring(0, offs);
266
                    String afterOffset = currentText.substring(len + offs,
267
                            currentText.length());
268
                    String proposedResult = beforeOffset + afterOffset;
269
                    if (validator.isValid(cleaner.clean(proposedResult))) {
270
                        super.remove(offs, len);
271
                    }
272
                }
273
            });
274
        textField.addFocusListener(new FocusAdapter() {
275
                public void focusLost(FocusEvent e) {
276
                    textField.setText(cleaner.clean(textField.getText()));
277
                }
278
            });
279
    }
280

    
281
    public String getText() {
282
        //Focus may not be lost yet (e.g. when syncing with scrollbar) [Jon Aquino]
283
        return cleaner.clean(super.getText());
284
    }
285

    
286
    public double getDouble() {
287
        return Double.parseDouble(getText().trim());
288
    }
289

    
290
    public int getInteger() {
291
        return Integer.parseInt(getText().trim());
292
    }
293

    
294
    public static interface Validator {
295
        public boolean isValid(String text);
296
    }
297

    
298
    public static interface Cleaner {
299
        public String clean(String text);
300
    }
301

    
302
/**
303
 * Implements validator with a greater than threshold.
304
 */
305

    
306
    public static class GreaterThanValidator implements Validator {
307
        private double threshold;
308

    
309
        public GreaterThanValidator(double threshold) {
310
            this.threshold = threshold;
311
        }
312

    
313
        public boolean isValid(String text) {
314
            return Double.parseDouble(text.trim()) > threshold;
315
        }
316
    }
317
/**
318
 * Implements validator with a less than threshold.
319
 */
320

    
321
    public static class LessThanValidator implements Validator {
322
        private double threshold;
323

    
324
        public LessThanValidator(double threshold) {
325
            this.threshold = threshold;
326
        }
327

    
328
        public boolean isValid(String text) {
329
            return Double.parseDouble(text.trim()) < threshold;
330
        }
331
    }
332
/**
333
 * Implements validator with a greater than or equal to threshold.
334
 */
335

    
336
    public static class GreaterThanOrEqualValidator implements Validator {
337
        private double threshold;
338

    
339
        public GreaterThanOrEqualValidator(double threshold) {
340
            this.threshold = threshold;
341
        }
342

    
343
        public boolean isValid(String text) {
344
            return Double.parseDouble(text.trim()) >= threshold;
345
        }
346
    }
347
/**
348
 * Implements validator with a less than or equal to threshold.
349
 */
350

    
351
    public static class LessThanOrEqualValidator implements Validator {
352
        private double threshold;
353

    
354
        public LessThanOrEqualValidator(double threshold) {
355
            this.threshold = threshold;
356
        }
357

    
358
        public boolean isValid(String text) {
359
            return Double.parseDouble(text.trim()) <= threshold;
360
        }
361
    }
362

    
363
    /**
364
 * Implements cleaner which cleans up blank strings.
365
 */
366

    
367

    
368
    public static class BlankCleaner implements Cleaner {
369
        private String replacement;
370

    
371
        public BlankCleaner(String replacement) {
372
            this.replacement = replacement;
373
        }
374

    
375
        public String clean(String text) {
376
            return (text.trim().length() == 0) ? replacement : text;
377
        }
378
    }
379

    
380
    /**
381
     * Allow the user to start typing a number with "-" or "."
382
     * @author jaquino
383
     *
384
     * To change the template for this generated type comment go to
385
     * Window>Preferences>Java>Code Generation>Code and Comments
386
     */
387
    public static class NumberCleaner implements Cleaner {
388
        private String textToAppend;
389

    
390
        public NumberCleaner(String textToAppend) {
391
            this.textToAppend = textToAppend;
392
        }
393

    
394
        public String clean(String text) {
395
            if (text.trim().length() == 0) { return text; }
396
            try {
397
                Double.parseDouble(text);
398
                return text;
399
            }
400
            catch (NumberFormatException e) {
401
                return text + textToAppend;
402
            }
403
        }
404
    }
405
    
406
   
407

    
408
    public static class MinIntCleaner implements Cleaner {
409
        private int minimum;
410

    
411
        public MinIntCleaner(int minimum) {
412
            this.minimum = minimum;
413
        }
414

    
415
        public String clean(String text) {
416
                String s="";
417
                s=""+ Math.max(minimum, Integer.parseInt(text));
418
                return s;
419
        }
420
    }
421

    
422
/**
423
 * Extends CompositeValidator to validat that integers is within a set of boundary values.
424
 */
425
    public static class BoundedIntValidator extends CompositeValidator {
426
        public BoundedIntValidator(int min, int max) {
427
            super(new Validator[] {
428
                    INTEGER_VALIDATOR, new GreaterThanOrEqualValidator(min),
429
                    new LessThanOrEqualValidator(max)
430
                });
431
            assert (min < max);
432
        }
433
    }
434

    
435
    public static class BoundedDoubleValidator extends CompositeValidator {
436
        public BoundedDoubleValidator(double min, boolean includeMin,
437
            double max, boolean includeMax) {
438
            super(new Validator[] {
439
                    DOUBLE_VALIDATOR,
440
                    includeMin
441
                    ? (Validator) new GreaterThanOrEqualValidator(min)
442
                    : new GreaterThanValidator(min),
443
                    includeMax ? (Validator) new LessThanOrEqualValidator(max)
444
                               : new LessThanValidator(max)
445
                });
446
            assert (min < max);
447
        }
448
    }
449

    
450
    public static class MaxIntCleaner implements Cleaner {
451
        private int maximum;
452

    
453
        public MaxIntCleaner(int maximum) {
454
            this.maximum = maximum;
455
        }
456

    
457
        public String clean(String text) {
458
                String s="";
459
                s=""+ Math.min(maximum, Integer.parseInt(text));
460
                return s;
461
        }
462
    }
463
/**
464
 * Implements validator to check for more than one condition.
465
 */
466

    
467
    public static class CompositeValidator implements Validator {
468
        private Validator[] validators;
469

    
470
        public CompositeValidator(Validator[] validators) {
471
            this.validators = validators;
472
        }
473

    
474
        public boolean isValid(String text) {
475
            for (int i = 0; i < validators.length; i++) {
476
                if (!validators[i].isValid(text)) {
477
                    return false;
478
                }
479
            }
480

    
481
            return true;
482
        }
483
    }
484

    
485
    public static class CompositeCleaner implements Cleaner {
486
        private Cleaner[] cleaners;
487

    
488
        public CompositeCleaner(Cleaner[] cleaners) {
489
            this.cleaners = cleaners;
490
        }
491

    
492
        public String clean(String text) {
493
            String result = text;
494
            try{
495
                    for (int i = 0; i < cleaners.length; i++) {
496
                            result = cleaners[i].clean(result);
497
                    }
498
                }catch (NumberFormatException e) {
499
                                    JOptionPane.showMessageDialog(null, Messages.getText("numero_incorrecto"));
500
                   }
501

    
502

    
503
            return result;
504
        }
505
    }
506
}