Statistics
| Revision:

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

History | View | Annotate | Download (14 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 junit.framework.Assert;
84

    
85
import org.gvsig.gui.beans.Messages;
86

    
87

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

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

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

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

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

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

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

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

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

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

    
162
    /**
163
     * Validator that does nothing.
164
     */
165
    public static Validator DUMMY_VALIDATOR = new Validator() {
166
            public boolean isValid(String text) {
167
                return true;
168
            }
169
        };
170

    
171
    private Cleaner cleaner;
172

    
173
    /**
174
     * Validator that uses dummy cleaner.
175
     */
176
    public ValidatingTextField(String text, int columns,
177
        final Validator validator) {
178
        this(text, columns, LEFT, validator, DUMMY_CLEANER);
179
    }
180

    
181
    /**
182
     * Validator for text fields.
183
     */
184
    public ValidatingTextField(String text, int columns,
185
        int horizontalAlignment, final Validator validator,
186
        final Cleaner cleaner) {
187
        super(text, columns);
188
        this.cleaner = cleaner;
189
        setHorizontalAlignment(horizontalAlignment);
190
        installValidationBehavior(this, validator, cleaner);
191

    
192
        //Clean the text, mainly so that parties wishing to install a BlankCleaner
193
        //need only pass "" for the text. [Jon Aquino]
194
        setText(cleaner.clean(getText()));
195

    
196
        //Bonus: workaround for how GridBagLayout shrinks components to
197
        //minimum sizes if it can't accomodate their preferred sizes. [Jon Aquino]
198
        setMinimumSize(getPreferredSize());
199
    }
200

    
201
    //Hopefully this will let us add validation behaviour to combo boxes. [Jon Aquino]
202
    public static void installValidationBehavior(final JTextField textField,
203
        final Validator validator, final Cleaner cleaner) {
204
        textField.setDocument(new PlainDocument() {
205
          private static final long serialVersionUID = 7097829094600558963L;
206

    
207
                                                                public void insertString(int offs, String str, AttributeSet a)
208
                    throws BadLocationException {
209
                    String currentText = this.getText(0, getLength());
210
                    String beforeOffset = currentText.substring(0, offs);
211
                    String afterOffset = currentText.substring(offs,
212
                            currentText.length());
213
                    String proposedResult = beforeOffset + str + afterOffset;
214
                    if (validator.isValid(cleaner.clean(proposedResult))) {
215
                        super.insertString(offs, str, a);
216
                    }
217
                }
218

    
219
                public void remove(int offs, int len)
220
                    throws BadLocationException {
221
                    String currentText = this.getText(0, getLength());
222
                    String beforeOffset = currentText.substring(0, offs);
223
                    String afterOffset = currentText.substring(len + offs,
224
                            currentText.length());
225
                    String proposedResult = beforeOffset + afterOffset;
226
                    if (validator.isValid(cleaner.clean(proposedResult))) {
227
                        super.remove(offs, len);
228
                    }
229
                }
230
            });
231
        textField.addFocusListener(new FocusAdapter() {
232
                public void focusLost(FocusEvent e) {
233
                    textField.setText(cleaner.clean(textField.getText()));
234
                }
235
            });
236
    }
237

    
238
    public String getText() {
239
        //Focus may not be lost yet (e.g. when syncing with scrollbar) [Jon Aquino]
240
        return cleaner.clean(super.getText());
241
    }
242

    
243
    public double getDouble() {
244
        return Double.parseDouble(getText().trim());
245
    }
246

    
247
    public int getInteger() {
248
        return Integer.parseInt(getText().trim());
249
    }
250

    
251
    public static interface Validator {
252
        public boolean isValid(String text);
253
    }
254

    
255
    public static interface Cleaner {
256
        public String clean(String text);
257
    }
258

    
259
/**
260
 * Implements validator with a greater than threshold.
261
 */
262

    
263
    public static class GreaterThanValidator implements Validator {
264
        private double threshold;
265

    
266
        public GreaterThanValidator(double threshold) {
267
            this.threshold = threshold;
268
        }
269

    
270
        public boolean isValid(String text) {
271
            return Double.parseDouble(text.trim()) > threshold;
272
        }
273
    }
274
/**
275
 * Implements validator with a less than threshold.
276
 */
277

    
278
    public static class LessThanValidator implements Validator {
279
        private double threshold;
280

    
281
        public LessThanValidator(double threshold) {
282
            this.threshold = threshold;
283
        }
284

    
285
        public boolean isValid(String text) {
286
            return Double.parseDouble(text.trim()) < threshold;
287
        }
288
    }
289
/**
290
 * Implements validator with a greater than or equal to threshold.
291
 */
292

    
293
    public static class GreaterThanOrEqualValidator implements Validator {
294
        private double threshold;
295

    
296
        public GreaterThanOrEqualValidator(double threshold) {
297
            this.threshold = threshold;
298
        }
299

    
300
        public boolean isValid(String text) {
301
            return Double.parseDouble(text.trim()) >= threshold;
302
        }
303
    }
304
/**
305
 * Implements validator with a less than or equal to threshold.
306
 */
307

    
308
    public static class LessThanOrEqualValidator implements Validator {
309
        private double threshold;
310

    
311
        public LessThanOrEqualValidator(double threshold) {
312
            this.threshold = threshold;
313
        }
314

    
315
        public boolean isValid(String text) {
316
            return Double.parseDouble(text.trim()) <= threshold;
317
        }
318
    }
319

    
320
    /**
321
 * Implements cleaner which cleans up blank strings.
322
 */
323

    
324

    
325
    public static class BlankCleaner implements Cleaner {
326
        private String replacement;
327

    
328
        public BlankCleaner(String replacement) {
329
            this.replacement = replacement;
330
        }
331

    
332
        public String clean(String text) {
333
            return (text.trim().length() == 0) ? replacement : text;
334
        }
335
    }
336

    
337
    /**
338
     * Allow the user to start typing a number with "-" or "."
339
     * @author jaquino
340
     *
341
     * To change the template for this generated type comment go to
342
     * Window>Preferences>Java>Code Generation>Code and Comments
343
     */
344
    public static class NumberCleaner implements Cleaner {
345
        private String textToAppend;
346

    
347
        public NumberCleaner(String textToAppend) {
348
            this.textToAppend = textToAppend;
349
        }
350

    
351
        public String clean(String text) {
352
            if (text.trim().length() == 0) { return text; }
353
            try {
354
                Double.parseDouble(text);
355
                return text;
356
            }
357
            catch (NumberFormatException e) {
358
                return text + textToAppend;
359
            }
360
        }
361
    }
362

    
363
    public static class MinIntCleaner implements Cleaner {
364
        private int minimum;
365

    
366
        public MinIntCleaner(int minimum) {
367
            this.minimum = minimum;
368
        }
369

    
370
        public String clean(String text) {
371
                String s="";
372
                s=""+ Math.max(minimum, Integer.parseInt(text));
373
                return s;
374
        }
375
    }
376

    
377
/**
378
 * Extends CompositeValidator to validat that integers is within a set of boundary values.
379
 */
380
    public static class BoundedIntValidator extends CompositeValidator {
381
        public BoundedIntValidator(int min, int max) {
382
            super(new Validator[] {
383
                    INTEGER_VALIDATOR, new GreaterThanOrEqualValidator(min),
384
                    new LessThanOrEqualValidator(max)
385
                });
386
            Assert.assertTrue(min < max);
387
        }
388
    }
389

    
390
    public static class BoundedDoubleValidator extends CompositeValidator {
391
        public BoundedDoubleValidator(double min, boolean includeMin,
392
            double max, boolean includeMax) {
393
            super(new Validator[] {
394
                    DOUBLE_VALIDATOR,
395
                    includeMin
396
                    ? (Validator) new GreaterThanOrEqualValidator(min)
397
                    : new GreaterThanValidator(min),
398
                    includeMax ? (Validator) new LessThanOrEqualValidator(max)
399
                               : new LessThanValidator(max)
400
                });
401
            Assert.assertTrue(min < max);
402
        }
403
    }
404

    
405
    public static class MaxIntCleaner implements Cleaner {
406
        private int maximum;
407

    
408
        public MaxIntCleaner(int maximum) {
409
            this.maximum = maximum;
410
        }
411

    
412
        public String clean(String text) {
413
                String s="";
414
                s=""+ Math.min(maximum, Integer.parseInt(text));
415
                return s;
416
        }
417
    }
418
/**
419
 * Implements validator to check for more than one condition.
420
 */
421

    
422
    public static class CompositeValidator implements Validator {
423
        private Validator[] validators;
424

    
425
        public CompositeValidator(Validator[] validators) {
426
            this.validators = validators;
427
        }
428

    
429
        public boolean isValid(String text) {
430
            for (int i = 0; i < validators.length; i++) {
431
                if (!validators[i].isValid(text)) {
432
                    return false;
433
                }
434
            }
435

    
436
            return true;
437
        }
438
    }
439

    
440
    public static class CompositeCleaner implements Cleaner {
441
        private Cleaner[] cleaners;
442

    
443
        public CompositeCleaner(Cleaner[] cleaners) {
444
            this.cleaners = cleaners;
445
        }
446

    
447
        public String clean(String text) {
448
            String result = text;
449
            try{
450
                    for (int i = 0; i < cleaners.length; i++) {
451
                            result = cleaners[i].clean(result);
452
                    }
453
                }catch (NumberFormatException e) {
454
                                    JOptionPane.showMessageDialog(null, Messages.getText("numero_incorrecto"));
455
                   }
456

    
457

    
458
            return result;
459
        }
460
    }
461
}