mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			434 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			434 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* DefaultFormatter.java --
 | |
| Copyright (C) 2005  Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package javax.swing.text;
 | |
| 
 | |
| import java.io.Serializable;
 | |
| import java.lang.reflect.Constructor;
 | |
| import java.text.ParseException;
 | |
| 
 | |
| import javax.swing.JFormattedTextField;
 | |
| 
 | |
| /**
 | |
|  * The <code>DefaultFormatter</code> is a concrete formatter for use in
 | |
|  * {@link JFormattedTextField}s.
 | |
|  *
 | |
|  * It can format arbitrary values by invoking
 | |
|  * their {@link Object#toString} method.
 | |
|  *
 | |
|  * In order to convert a String back to
 | |
|  * a value, the value class must provide a single argument constructor that
 | |
|  * takes a String object as argument value. If no such constructor is found,
 | |
|  * the String itself is passed back by #stringToValue.
 | |
|  *
 | |
|  * @author Roman Kennke (roman@kennke.org)
 | |
|  */
 | |
| public class DefaultFormatter extends JFormattedTextField.AbstractFormatter
 | |
|   implements Cloneable, Serializable
 | |
| {
 | |
| 
 | |
|   /**
 | |
|    * A {@link DocumentFilter} that intercepts modification of the
 | |
|    * JFormattedTextField's Document and commits the value depending
 | |
|    * on the value of the <code>commitsOnValidEdit</code> property.
 | |
|    *
 | |
|    */
 | |
|   // FIXME: Handle allowsInvalid and overwriteMode properties
 | |
|   private class FormatterDocumentFilter
 | |
|     extends DocumentFilter
 | |
|   {
 | |
|     /**
 | |
|      * Invoked when text is removed from a text component.
 | |
|      *
 | |
|      * @param bypass the FilterBypass to use to mutate the document
 | |
|      * @param offset the start position of the modification
 | |
|      * @param length the length of the removed text
 | |
|      *
 | |
|      * @throws BadLocationException if offset or lenght are invalid in
 | |
|      *     the Document
 | |
|      */
 | |
|     public void remove(DocumentFilter.FilterBypass bypass, int offset,
 | |
|                         int length)
 | |
|       throws BadLocationException
 | |
|     {
 | |
|       super.remove(bypass, offset, length);
 | |
|       checkValidInput();
 | |
|       commitIfAllowed();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Invoked when text is inserted into a text component.
 | |
|      *
 | |
|      * @param bypass the FilterBypass to use to mutate the document
 | |
|      * @param offset the start position of the modification
 | |
|      * @param text the inserted text
 | |
|      * @param attributes the attributes of the inserted text
 | |
|      *
 | |
|      * @throws BadLocationException if offset or lenght are invalid in
 | |
|      *     the Document
 | |
|      */
 | |
|     public void insertString(DocumentFilter.FilterBypass bypass, int offset,
 | |
|                               String text, AttributeSet attributes)
 | |
|       throws BadLocationException
 | |
|     {
 | |
|       if (overwriteMode == true)
 | |
|         replace(bypass, offset, text.length(), text, attributes);
 | |
|       else
 | |
|         super.insertString(bypass, offset, text, attributes);
 | |
|       checkValidInput();
 | |
|       commitIfAllowed();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Invoked when text is replaced in a text component.
 | |
|      *
 | |
|      * @param bypass the FilterBypass to use to mutate the document
 | |
|      * @param offset the start position of the modification
 | |
|      * @param length the length of the removed text
 | |
|      * @param text the inserted text
 | |
|      * @param attributes the attributes of the inserted text
 | |
|      *
 | |
|      * @throws BadLocationException if offset or lenght are invalid in
 | |
|      *     the Document
 | |
|      */
 | |
|     public void replace(DocumentFilter.FilterBypass bypass, int offset,
 | |
|                          int length, String text, AttributeSet attributes)
 | |
|       throws BadLocationException
 | |
|     {
 | |
|       super.replace(bypass, offset, length, text, attributes);
 | |
|       checkValidInput();
 | |
|       commitIfAllowed();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Commits the value to the JTextTextField if the property
 | |
|      * <code>commitsOnValidEdit</code> is set to <code>true</code>.
 | |
|      */
 | |
|     private void commitIfAllowed()
 | |
|     {
 | |
|       if (commitsOnValidEdit == true)
 | |
|         try
 | |
|           {
 | |
|             getFormattedTextField().commitEdit();
 | |
|           }
 | |
|         catch (ParseException ex)
 | |
|           {
 | |
|             // ignore invalid edits
 | |
|           }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks if the value in the input field is valid. If the
 | |
|      * property allowsInvalid is set to <code>false</code>, then
 | |
|      * the string in the input field is not allowed to be entered.
 | |
|      */
 | |
|     private void checkValidInput()
 | |
|     {
 | |
|       JFormattedTextField ftf = getFormattedTextField();
 | |
|       try
 | |
|         {
 | |
|           Object newval = stringToValue(ftf.getText());
 | |
|         }
 | |
|       catch (ParseException ex)
 | |
|         {
 | |
|           if (!allowsInvalid)
 | |
|             {
 | |
|               // roll back the input if invalid edits are not allowed
 | |
|               try
 | |
|                 {
 | |
|                   ftf.setText(valueToString(ftf.getValue()));
 | |
|                 }
 | |
|               catch (ParseException pe)
 | |
|                 {
 | |
|                   // if that happens, something serious must be wrong
 | |
|                   AssertionError ae;
 | |
|                   ae = new AssertionError("values must be parseable");
 | |
|                   ae.initCause(pe);
 | |
|                   throw ae;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /** The serialization UID (compatible with JDK1.5). */
 | |
|   private static final long serialVersionUID = -355018354457785329L;
 | |
| 
 | |
|   /**
 | |
|    * Indicates if the value should be committed after every
 | |
|    * valid modification of the Document.
 | |
|    */
 | |
|   boolean commitsOnValidEdit;
 | |
| 
 | |
|   /**
 | |
|    * If <code>true</code> newly inserted characters overwrite existing
 | |
|    * values, otherwise insertion is done the normal way.
 | |
|    */
 | |
|   boolean overwriteMode;
 | |
| 
 | |
|   /**
 | |
|    * If <code>true</code> invalid edits are allowed for a limited
 | |
|    * time.
 | |
|    */
 | |
|   boolean allowsInvalid;
 | |
| 
 | |
|   /**
 | |
|    * The class that is used for values.
 | |
|    */
 | |
|   Class valueClass;
 | |
| 
 | |
|   /**
 | |
|    * Creates a new instance of <code>DefaultFormatter</code>.
 | |
|    */
 | |
|   public DefaultFormatter()
 | |
|   {
 | |
|     commitsOnValidEdit = false;
 | |
|     overwriteMode = true;
 | |
|     allowsInvalid = true;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Installs the formatter on the specified {@link JFormattedTextField}.
 | |
|    *
 | |
|    * This method does the following things:
 | |
|    * <ul>
 | |
|    * <li>Display the value of #valueToString in the
 | |
|    *  <code>JFormattedTextField</code></li>
 | |
|    * <li>Install the Actions from #getActions on the <code>JTextField</code>
 | |
|    * </li>
 | |
|    * <li>Install the DocumentFilter returned by #getDocumentFilter</li>
 | |
|    * <li>Install the NavigationFilter returned by #getNavigationFilter</li>
 | |
|    * </ul>
 | |
|    *
 | |
|    * This method is typically not overridden by subclasses. Instead override
 | |
|    * one of the mentioned methods in order to customize behaviour.
 | |
|    *
 | |
|    * @param ftf the {@link JFormattedTextField} in which this formatter
 | |
|    *     is installed
 | |
|    */
 | |
|   public void install(JFormattedTextField ftf)
 | |
|   {
 | |
|     super.install(ftf);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns <code>true</code> if the value should be committed after
 | |
|    * each valid modification of the input field, <code>false</code> if
 | |
|    * it should never be committed by this formatter.
 | |
|    *
 | |
|    * @return the state of the <code>commitsOnValidEdit</code> property
 | |
|    *
 | |
|    * @see #setCommitsOnValidEdit
 | |
|    */
 | |
|   public boolean getCommitsOnValidEdit()
 | |
|   {
 | |
|     return commitsOnValidEdit;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the value of the <code>commitsOnValidEdit</code> property.
 | |
|    *
 | |
|    * @param commitsOnValidEdit the new state of the
 | |
|    *     <code>commitsOnValidEdit</code> property
 | |
|    *
 | |
|    * @see #getCommitsOnValidEdit
 | |
|    */
 | |
|   public void setCommitsOnValidEdit(boolean commitsOnValidEdit)
 | |
|   {
 | |
|     this.commitsOnValidEdit = commitsOnValidEdit;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the value of the <code>overwriteMode</code> property.
 | |
|    * If that is set to <code>true</code> then newly inserted characters
 | |
|    * overwrite existing values, otherwise the characters are inserted like
 | |
|    * normal. The default is <code>true</code>.
 | |
|    *
 | |
|    * @return the value of the <code>overwriteMode</code> property
 | |
|    */
 | |
|   public boolean getOverwriteMode()
 | |
|   {
 | |
|     return overwriteMode;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the value of the <code>overwriteMode</code> property.
 | |
|    *
 | |
|    * If that is set to <code>true</code> then newly inserted characters
 | |
|    * overwrite existing values, otherwise the characters are inserted like
 | |
|    * normal. The default is <code>true</code>.
 | |
|    *
 | |
|    * @param overwriteMode the new value for the <code>overwriteMode</code>
 | |
|    *     property
 | |
|    */
 | |
|   public void setOverwriteMode(boolean overwriteMode)
 | |
|   {
 | |
|     this.overwriteMode = overwriteMode;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns whether or not invalid edits are allowed or not. If invalid
 | |
|    * edits are allowed, the JFormattedTextField may temporarily contain invalid
 | |
|    * characters.
 | |
|    *
 | |
|    * @return the value of the allowsInvalid property
 | |
|    */
 | |
|   public boolean getAllowsInvalid()
 | |
|   {
 | |
|     return allowsInvalid;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the value of the <code>allowsInvalid</code> property.
 | |
|    *
 | |
|    * @param allowsInvalid the new value for the property
 | |
|    *
 | |
|    * @see #getAllowsInvalid()
 | |
|    */
 | |
|   public void setAllowsInvalid(boolean allowsInvalid)
 | |
|   {
 | |
|     this.allowsInvalid = allowsInvalid;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the class that is used for values. When Strings are converted
 | |
|    * back to values, this class is used to create new value objects.
 | |
|    *
 | |
|    * @return the class that is used for values
 | |
|    */
 | |
|   public Class<?> getValueClass()
 | |
|   {
 | |
|     return valueClass;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the class that is used for values.
 | |
|    *
 | |
|    * @param valueClass the class that is used for values
 | |
|    *
 | |
|    * @see #getValueClass()
 | |
|    */
 | |
|   public void setValueClass(Class<?> valueClass)
 | |
|   {
 | |
|     this.valueClass = valueClass;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Converts a String (from the JFormattedTextField input) to a value.
 | |
|    * In order to achieve this, the formatter tries to instantiate an object
 | |
|    * of the class returned by #getValueClass() using a single argument
 | |
|    * constructor that takes a String argument. If such a constructor cannot
 | |
|    * be found, the String itself is returned.
 | |
|    *
 | |
|    * @param string the string to convert
 | |
|    *
 | |
|    * @return the value for the string
 | |
|    *
 | |
|    * @throws ParseException if the string cannot be converted into
 | |
|    *     a value object (e.g. invalid input)
 | |
|    */
 | |
|   public Object stringToValue(String string)
 | |
|     throws ParseException
 | |
|   {
 | |
|     Object value = string;
 | |
|     Class valueClass = getValueClass();
 | |
|     if (valueClass == null)
 | |
|       {
 | |
|         JFormattedTextField jft = getFormattedTextField();
 | |
|         if (jft != null)
 | |
|           valueClass = jft.getValue().getClass();
 | |
|       }
 | |
|     if (valueClass != null)
 | |
|       try
 | |
|         {
 | |
|           Constructor constr = valueClass.getConstructor
 | |
|                                              (new Class[]{String.class});
 | |
|           value = constr.newInstance(new Object[]{ string });
 | |
|         }
 | |
|       catch (NoSuchMethodException ex)
 | |
|         {
 | |
|           // leave value as string
 | |
|         }
 | |
|       catch (Exception ex)
 | |
|         {
 | |
|           throw new ParseException(string, 0);
 | |
|         }
 | |
|     return value;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Converts a value object into a String. This is done by invoking the
 | |
|    * {@link Object#toString()} method on the value.
 | |
|    *
 | |
|    * @param value the value to be converted
 | |
|    *
 | |
|    * @return the string representation of the value
 | |
|    *
 | |
|    * @throws ParseException if the value cannot be converted
 | |
|    */
 | |
|   public String valueToString(Object value)
 | |
|     throws ParseException
 | |
|   {
 | |
|     if (value == null)
 | |
|       return "";
 | |
|     return value.toString();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates and returns a clone of this DefaultFormatter.
 | |
|    *
 | |
|    * @return a clone of this object
 | |
|    *
 | |
|    * @throws CloneNotSupportedException not thrown here
 | |
|    */
 | |
|   public Object clone()
 | |
|     throws CloneNotSupportedException
 | |
|   {
 | |
|     return super.clone();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the DocumentFilter that is used to restrict input.
 | |
|    *
 | |
|    * @return the DocumentFilter that is used to restrict input
 | |
|    */
 | |
|   protected DocumentFilter getDocumentFilter()
 | |
|   {
 | |
|     return new FormatterDocumentFilter();
 | |
|   }
 | |
| }
 |