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();
 | 
						|
  }
 | 
						|
}
 |