svn-gvsig-desktop / trunk / applications / appgvSIG / src / com / iver / cit / gvsig / gui / ValidatingTextField.java @ 3718
History | View | Annotate | Download (13.6 KB)
1 | 312 | fernando | /*
|
---|---|---|---|
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 | 1103 | fjp | /* 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 | 312 | fernando | 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 | } |