Statistics
| Revision:

svn-gvsig-desktop / trunk / applications / appgvSIG / src / com / iver / cit / gvsig / gui / ValidatingTextField.java @ 3718

History | View | Annotate | Download (13.6 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 com.iver.cit.gvsig.gui;
73

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

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

    
82
import com.vividsolutions.jts.util.Assert;
83

    
84

    
85
/**
86
 * Prevents the user from entering invalid data.
87
 */
88
public class ValidatingTextField extends JTextField {
89
    public static final Validator LONG_VALIDATOR = new ValidatingTextField.Validator() {
90
            public boolean isValid(String text) {
91
                try {
92
                    Long.parseLong(text.trim());
93

    
94
                    return true;
95
                } catch (NumberFormatException e) {
96
                    return false;
97
                }
98
            }
99
        };
100

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

    
109
                    return true;
110
                } catch (NumberFormatException e) {
111
                    return false;
112
                }
113
            }
114
        };
115

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

    
125
                    return true;
126
                } catch (NumberFormatException e) {
127
                    return false;
128
                }
129
            }
130
        };
131

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

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

    
150
                    return text;
151
                } catch (NumberFormatException e) {
152
                    return "0";
153
                }
154
            }
155
        };
156

    
157
    /**
158
     * Validator that does nothing.
159
     */
160
    public static Validator DUMMY_VALIDATOR = new Validator() {
161
            public boolean isValid(String text) {
162
                return true;
163
            }
164
        };
165

    
166
    private Cleaner cleaner;
167

    
168
    /**
169
     * Validator that uses dummy cleaner.
170
     */
171
    public ValidatingTextField(String text, int columns,
172
        final Validator validator) {
173
        this(text, columns, LEFT, validator, DUMMY_CLEANER);
174
    }
175

    
176
    /**
177
     * Validator for text fields.
178
     */
179
    public ValidatingTextField(String text, int columns,
180
        int horizontalAlignment, final Validator validator,
181
        final Cleaner cleaner) {
182
        super(text, columns);
183
        this.cleaner = cleaner;
184
        setHorizontalAlignment(horizontalAlignment);
185
        installValidationBehavior(this, validator, cleaner);
186

    
187
        //Clean the text, mainly so that parties wishing to install a BlankCleaner
188
        //need only pass "" for the text. [Jon Aquino]
189
        setText(cleaner.clean(getText()));
190

    
191
        //Bonus: workaround for how GridBagLayout shrinks components to
192
        //minimum sizes if it can't accomodate their preferred sizes. [Jon Aquino]
193
        setMinimumSize(getPreferredSize());
194
    }
195

    
196
    //Hopefully this will let us add validation behaviour to combo boxes. [Jon Aquino]
197
    public static void installValidationBehavior(final JTextField textField,
198
        final Validator validator, final Cleaner cleaner) {
199
        textField.setDocument(new PlainDocument() {
200
                public void insertString(int offs, String str, AttributeSet a)
201
                    throws BadLocationException {
202
                    String currentText = this.getText(0, getLength());
203
                    String beforeOffset = currentText.substring(0, offs);
204
                    String afterOffset = currentText.substring(offs,
205
                            currentText.length());
206
                    String proposedResult = beforeOffset + str + afterOffset;
207
                    if (validator.isValid(cleaner.clean(proposedResult))) {
208
                        super.insertString(offs, str, a);
209
                    }
210
                }
211

    
212
                public void remove(int offs, int len)
213
                    throws BadLocationException {
214
                    String currentText = this.getText(0, getLength());
215
                    String beforeOffset = currentText.substring(0, offs);
216
                    String afterOffset = currentText.substring(len + offs,
217
                            currentText.length());
218
                    String proposedResult = beforeOffset + afterOffset;
219
                    if (validator.isValid(cleaner.clean(proposedResult))) {
220
                        super.remove(offs, len);
221
                    }
222
                }
223
            });
224
        textField.addFocusListener(new FocusAdapter() {
225
                public void focusLost(FocusEvent e) {
226
                    textField.setText(cleaner.clean(textField.getText()));
227
                }
228
            });
229
    }
230

    
231
    public String getText() {
232
        //Focus may not be lost yet (e.g. when syncing with scrollbar) [Jon Aquino]
233
        return cleaner.clean(super.getText());
234
    }
235

    
236
    public double getDouble() {
237
        return Double.parseDouble(getText().trim());
238
    }
239

    
240
    public int getInteger() {
241
        return Integer.parseInt(getText().trim());
242
    }
243

    
244
    public static interface Validator {
245
        public boolean isValid(String text);
246
    }
247

    
248
    public static interface Cleaner {
249
        public String clean(String text);
250
    }
251

    
252
/**
253
 * Implements validator with a greater than threshold.
254
 */
255

    
256
    public static class GreaterThanValidator implements Validator {
257
        private double threshold;
258

    
259
        public GreaterThanValidator(double threshold) {
260
            this.threshold = threshold;
261
        }
262

    
263
        public boolean isValid(String text) {
264
            return Double.parseDouble(text.trim()) > threshold;
265
        }
266
    }
267
/**
268
 * Implements validator with a less than threshold.
269
 */
270

    
271
    public static class LessThanValidator implements Validator {
272
        private double threshold;
273

    
274
        public LessThanValidator(double threshold) {
275
            this.threshold = threshold;
276
        }
277

    
278
        public boolean isValid(String text) {
279
            return Double.parseDouble(text.trim()) < threshold;
280
        }
281
    }
282
/**
283
 * Implements validator with a greater than or equal to threshold.
284
 */
285

    
286
    public static class GreaterThanOrEqualValidator implements Validator {
287
        private double threshold;
288

    
289
        public GreaterThanOrEqualValidator(double threshold) {
290
            this.threshold = threshold;
291
        }
292

    
293
        public boolean isValid(String text) {
294
            return Double.parseDouble(text.trim()) >= threshold;
295
        }
296
    }
297
/**
298
 * Implements validator with a less than or equal to threshold.
299
 */
300

    
301
    public static class LessThanOrEqualValidator implements Validator {
302
        private double threshold;
303

    
304
        public LessThanOrEqualValidator(double threshold) {
305
            this.threshold = threshold;
306
        }
307

    
308
        public boolean isValid(String text) {
309
            return Double.parseDouble(text.trim()) <= threshold;
310
        }
311
    }
312
    
313
    /**
314
 * Implements cleaner which cleans up blank strings.
315
 */
316

    
317

    
318
    public static class BlankCleaner implements Cleaner {
319
        private String replacement;
320

    
321
        public BlankCleaner(String replacement) {
322
            this.replacement = replacement;
323
        }
324

    
325
        public String clean(String text) {
326
            return (text.trim().length() == 0) ? replacement : text;
327
        }
328
    }
329
    
330
    /**
331
     * Allow the user to start typing a number with "-" or "."
332
     * @author jaquino
333
     *
334
     * To change the template for this generated type comment go to
335
     * Window>Preferences>Java>Code Generation>Code and Comments
336
     */
337
    public static class NumberCleaner implements Cleaner {
338
        private String textToAppend;
339

    
340
        public NumberCleaner(String textToAppend) {
341
            this.textToAppend = textToAppend;
342
        }
343

    
344
        public String clean(String text) {
345
            if (text.trim().length() == 0) { return text; }
346
            try {
347
                Double.parseDouble(text);
348
                return text;
349
            }
350
            catch (NumberFormatException e) {
351
                return text + textToAppend;
352
            }
353
        }
354
    }    
355

    
356
    public static class MinIntCleaner implements Cleaner {
357
        private int minimum;
358

    
359
        public MinIntCleaner(int minimum) {
360
            this.minimum = minimum;
361
        }
362

    
363
        public String clean(String text) {
364
            return "" + Math.max(minimum, Integer.parseInt(text));
365
        }
366
    }
367

    
368
/**
369
 * Extends CompositeValidator to validat that integers is within a set of boundary values.
370
 */
371
    public static class BoundedIntValidator extends CompositeValidator {
372
        public BoundedIntValidator(int min, int max) {
373
            super(new Validator[] {
374
                    INTEGER_VALIDATOR, new GreaterThanOrEqualValidator(min),
375
                    new LessThanOrEqualValidator(max)
376
                });
377
            Assert.isTrue(min < max);
378
        }
379
    }
380

    
381
    public static class BoundedDoubleValidator extends CompositeValidator {
382
        public BoundedDoubleValidator(double min, boolean includeMin,
383
            double max, boolean includeMax) {
384
            super(new Validator[] {
385
                    DOUBLE_VALIDATOR,
386
                    includeMin
387
                    ? (Validator) new GreaterThanOrEqualValidator(min)
388
                    : new GreaterThanValidator(min),
389
                    includeMax ? (Validator) new LessThanOrEqualValidator(max)
390
                               : new LessThanValidator(max)
391
                });
392
            Assert.isTrue(min < max);
393
        }
394
    }
395

    
396
    public static class MaxIntCleaner implements Cleaner {
397
        private int maximum;
398

    
399
        public MaxIntCleaner(int maximum) {
400
            this.maximum = maximum;
401
        }
402

    
403
        public String clean(String text) {
404
            return "" + Math.min(maximum, Integer.parseInt(text));
405
        }
406
    }
407
/**
408
 * Implements validator to check for more than one condition.
409
 */
410

    
411
    public static class CompositeValidator implements Validator {
412
        private Validator[] validators;
413

    
414
        public CompositeValidator(Validator[] validators) {
415
            this.validators = validators;
416
        }
417

    
418
        public boolean isValid(String text) {
419
            for (int i = 0; i < validators.length; i++) {
420
                if (!validators[i].isValid(text)) {
421
                    return false;
422
                }
423
            }
424

    
425
            return true;
426
        }
427
    }
428

    
429
    public static class CompositeCleaner implements Cleaner {
430
        private Cleaner[] cleaners;
431

    
432
        public CompositeCleaner(Cleaner[] cleaners) {
433
            this.cleaners = cleaners;
434
        }
435

    
436
        public String clean(String text) {
437
            String result = text;
438
            for (int i = 0; i < cleaners.length; i++) {
439
                result = cleaners[i].clean(result);
440
            }
441

    
442
            return result;
443
        }
444
    }
445
}