Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / javax / swing / text / DefaultFormatter.java
blob493699dacba3460c795470805e9cde8223ad359f
1 /* DefaultFormatter.java --
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package javax.swing.text;
40 import java.io.Serializable;
41 import java.lang.reflect.Constructor;
42 import java.text.ParseException;
44 import javax.swing.JFormattedTextField;
46 /**
47 * The <code>DefaultFormatter</code> is a concrete formatter for use in
48 * {@link JFormattedTextField}s.
50 * It can format arbitrary values by invoking
51 * their {@link Object#toString} method.
53 * In order to convert a String back to
54 * a value, the value class must provide a single argument constructor that
55 * takes a String object as argument value. If no such constructor is found,
56 * the String itself is passed back by #stringToValue.
58 * @author Roman Kennke (roman@kennke.org)
60 public class DefaultFormatter extends JFormattedTextField.AbstractFormatter
61 implements Cloneable, Serializable
64 /**
65 * A {@link DocumentFilter} that intercepts modification of the
66 * JFormattedTextField's Document and commits the value depending
67 * on the value of the <code>commitsOnValidEdit</code> property.
70 // FIXME: Handle allowsInvalid and overwriteMode properties
71 private class FormatterDocumentFilter
72 extends DocumentFilter
74 /**
75 * Invoked when text is removed from a text component.
77 * @param bypass the FilterBypass to use to mutate the document
78 * @param offset the start position of the modification
79 * @param length the length of the removed text
81 * @throws BadLocationException if offset or lenght are invalid in
82 * the Document
84 public void remove(DocumentFilter.FilterBypass bypass, int offset,
85 int length)
86 throws BadLocationException
88 super.remove(bypass, offset, length);
89 checkValidInput();
90 commitIfAllowed();
93 /**
94 * Invoked when text is inserted into a text component.
96 * @param bypass the FilterBypass to use to mutate the document
97 * @param offset the start position of the modification
98 * @param text the inserted text
99 * @param attributes the attributes of the inserted text
101 * @throws BadLocationException if offset or lenght are invalid in
102 * the Document
104 public void insertString(DocumentFilter.FilterBypass bypass, int offset,
105 String text, AttributeSet attributes)
106 throws BadLocationException
108 if (overwriteMode == true)
109 replace(bypass, offset, text.length(), text, attributes);
110 else
111 super.insertString(bypass, offset, text, attributes);
112 checkValidInput();
113 commitIfAllowed();
117 * Invoked when text is replaced in a text component.
119 * @param bypass the FilterBypass to use to mutate the document
120 * @param offset the start position of the modification
121 * @param length the length of the removed text
122 * @param text the inserted text
123 * @param attributes the attributes of the inserted text
125 * @throws BadLocationException if offset or lenght are invalid in
126 * the Document
128 public void replace(DocumentFilter.FilterBypass bypass, int offset,
129 int length, String text, AttributeSet attributes)
130 throws BadLocationException
132 super.replace(bypass, offset, length, text, attributes);
133 checkValidInput();
134 commitIfAllowed();
138 * Commits the value to the JTextTextField if the property
139 * <code>commitsOnValidEdit</code> is set to <code>true</code>.
141 private void commitIfAllowed()
143 if (commitsOnValidEdit == true)
146 getFormattedTextField().commitEdit();
148 catch (ParseException ex)
150 // ignore invalid edits
155 * Checks if the value in the input field is valid. If the
156 * property allowsInvalid is set to <code>false</code>, then
157 * the string in the input field is not allowed to be entered.
159 private void checkValidInput()
161 JFormattedTextField ftf = getFormattedTextField();
164 Object newval = stringToValue(ftf.getText());
166 catch (ParseException ex)
168 if (!allowsInvalid)
170 // roll back the input if invalid edits are not allowed
173 ftf.setText(valueToString(ftf.getValue()));
175 catch (ParseException pe)
177 // if that happens, something serious must be wrong
178 AssertionError ae;
179 ae = new AssertionError("values must be parseable");
180 ae.initCause(pe);
181 throw ae;
188 /** The serialization UID (compatible with JDK1.5). */
189 private static final long serialVersionUID = -355018354457785329L;
192 * Indicates if the value should be committed after every
193 * valid modification of the Document.
195 boolean commitsOnValidEdit;
198 * If <code>true</code> newly inserted characters overwrite existing
199 * values, otherwise insertion is done the normal way.
201 boolean overwriteMode;
204 * If <code>true</code> invalid edits are allowed for a limited
205 * time.
207 boolean allowsInvalid;
210 * The class that is used for values.
212 Class valueClass;
215 * Creates a new instance of <code>DefaultFormatter</code>.
217 public DefaultFormatter()
219 commitsOnValidEdit = true;
220 overwriteMode = true;
221 allowsInvalid = true;
222 valueClass = Object.class;
226 * Installs the formatter on the specified {@link JFormattedTextField}.
228 * This method does the following things:
229 * <ul>
230 * <li>Display the value of #valueToString in the
231 * <code>JFormattedTextField</code></li>
232 * <li>Install the Actions from #getActions on the <code>JTextField</code>
233 * </li>
234 * <li>Install the DocumentFilter returned by #getDocumentFilter</li>
235 * <li>Install the NavigationFilter returned by #getNavigationFilter</li>
236 * </ul>
238 * This method is typically not overridden by subclasses. Instead override
239 * one of the mentioned methods in order to customize behaviour.
241 * @param ftf the {@link JFormattedTextField} in which this formatter
242 * is installed
244 public void install(JFormattedTextField ftf)
246 super.install(ftf);
250 * Returns <code>true</code> if the value should be committed after
251 * each valid modification of the input field, <code>false</code> if
252 * it should never be committed by this formatter.
254 * @return the state of the <code>commitsOnValidEdit</code> property
256 * @see #setCommitsOnValidEdit
258 public boolean getCommitsOnValidEdit()
260 return commitsOnValidEdit;
264 * Sets the value of the <code>commitsOnValidEdit</code> property.
266 * @param commitsOnValidEdit the new state of the
267 * <code>commitsOnValidEdit</code> property
269 * @see #getCommitsOnValidEdit
271 public void setCommitsOnValidEdit(boolean commitsOnValidEdit)
273 this.commitsOnValidEdit = commitsOnValidEdit;
277 * Returns the value of the <code>overwriteMode</code> property.
278 * If that is set to <code>true</code> then newly inserted characters
279 * overwrite existing values, otherwise the characters are inserted like
280 * normal. The default is <code>true</code>.
282 * @return the value of the <code>overwriteMode</code> property
284 public boolean getOverwriteMode()
286 return overwriteMode;
290 * Sets the value of the <code>overwriteMode</code> property.
292 * If that is set to <code>true</code> then newly inserted characters
293 * overwrite existing values, otherwise the characters are inserted like
294 * normal. The default is <code>true</code>.
296 * @param overwriteMode the new value for the <code>overwriteMode</code>
297 * property
299 public void setOverwriteMode(boolean overwriteMode)
301 this.overwriteMode = overwriteMode;
305 * Returns whether or not invalid edits are allowed or not. If invalid
306 * edits are allowed, the JFormattedTextField may temporarily contain invalid
307 * characters.
309 * @return the value of the allowsInvalid property
311 public boolean getAllowsInvalid()
313 return allowsInvalid;
317 * Sets the value of the <code>allowsInvalid</code> property.
319 * @param allowsInvalid the new value for the property
321 * @see #getAllowsInvalid()
323 public void setAllowsInvalid(boolean allowsInvalid)
325 this.allowsInvalid = allowsInvalid;
329 * Returns the class that is used for values. When Strings are converted
330 * back to values, this class is used to create new value objects.
332 * @return the class that is used for values
334 public Class getValueClass()
336 return valueClass;
340 * Sets the class that is used for values.
342 * @param valueClass the class that is used for values
344 * @see #getValueClass()
346 public void setValueClass(Class valueClass)
348 this.valueClass = valueClass;
352 * Converts a String (from the JFormattedTextField input) to a value.
353 * In order to achieve this, the formatter tries to instantiate an object
354 * of the class returned by #getValueClass() using a single argument
355 * constructor that takes a String argument. If such a constructor cannot
356 * be found, the String itself is returned.
358 * @param string the string to convert
360 * @return the value for the string
362 * @throws ParseException if the string cannot be converted into
363 * a value object (e.g. invalid input)
365 public Object stringToValue(String string)
366 throws ParseException
368 Object value = string;
369 Class valueClass = getValueClass();
370 if (valueClass == null)
371 valueClass = getFormattedTextField().getValue().getClass();
372 if (valueClass != null)
375 Constructor constr = valueClass.getConstructor
376 (new Class[]{String.class});
377 value = constr.newInstance(new Object[]{ string });
379 catch (NoSuchMethodException ex)
381 // leave value as string
383 catch (Exception ex)
385 throw new ParseException(string, 0);
387 return value;
391 * Converts a value object into a String. This is done by invoking the
392 * {@link Object#toString()} method on the value.
394 * @param value the value to be converted
396 * @return the string representation of the value
398 * @throws ParseException if the value cannot be converted
400 public String valueToString(Object value)
401 throws ParseException
403 if (value == null)
404 return "";
405 return value.toString();
409 * Creates and returns a clone of this DefaultFormatter.
411 * @return a clone of this object
413 * @throws CloneNotSupportedException not thrown here
415 public Object clone()
416 throws CloneNotSupportedException
418 return super.clone();
422 * Returns the DocumentFilter that is used to restrict input.
424 * @return the DocumentFilter that is used to restrict input
426 protected DocumentFilter getDocumentFilter()
428 return new FormatterDocumentFilter();