/* | 
|
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. | 
|
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|
 * | 
|
 * This code is free software; you can redistribute it and/or modify it | 
|
 * under the terms of the GNU General Public License version 2 only, as | 
|
 * published by the Free Software Foundation.  Oracle designates this | 
|
 * particular file as subject to the "Classpath" exception as provided | 
|
 * by Oracle in the LICENSE file that accompanied this code. | 
|
 * | 
|
 * This code 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 | 
|
 * version 2 for more details (a copy is included in the LICENSE file that | 
|
 * accompanied this code). | 
|
 * | 
|
 * You should have received a copy of the GNU General Public License version | 
|
 * 2 along with this work; if not, write to the Free Software Foundation, | 
|
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|
 * | 
|
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|
 * or visit www.oracle.com if you need additional information or have any | 
|
 * questions. | 
|
*/  | 
|
package javax.swing;  | 
|
import sun.swing.SwingUtilities2;  | 
|
import java.awt.*;  | 
|
import java.awt.event.*;  | 
|
import java.beans.*;  | 
|
import javax.swing.text.*;  | 
|
import javax.swing.plaf.*;  | 
|
import javax.swing.event.*;  | 
|
import javax.accessibility.*;  | 
|
import java.io.ObjectOutputStream;  | 
|
import java.io.ObjectInputStream;  | 
|
import java.io.IOException;  | 
|
import java.io.Serializable;  | 
|
/** | 
|
 * <code>JTextField</code> is a lightweight component that allows the editing | 
|
 * of a single line of text. | 
|
 * For information on and examples of using text fields, | 
|
 * see | 
|
 * <a href="https://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html">How to Use Text Fields</a> | 
|
 * in <em>The Java Tutorial.</em> | 
|
 * | 
|
 * <p> | 
|
 * <code>JTextField</code> is intended to be source-compatible | 
|
 * with <code>java.awt.TextField</code> where it is reasonable to do so.  This | 
|
 * component has capabilities not found in the <code>java.awt.TextField</code> | 
|
 * class.  The superclass should be consulted for additional capabilities. | 
|
 * <p> | 
|
 * <code>JTextField</code> has a method to establish the string used as the | 
|
 * command string for the action event that gets fired.  The | 
|
 * <code>java.awt.TextField</code> used the text of the field as the command | 
|
 * string for the <code>ActionEvent</code>. | 
|
 * <code>JTextField</code> will use the command | 
|
 * string set with the <code>setActionCommand</code> method if not <code>null</code>, | 
|
 * otherwise it will use the text of the field as a compatibility with | 
|
 * <code>java.awt.TextField</code>. | 
|
 * <p> | 
|
 * The method <code>setEchoChar</code> and <code>getEchoChar</code> | 
|
 * are not provided directly to avoid a new implementation of a | 
|
 * pluggable look-and-feel inadvertently exposing password characters. | 
|
 * To provide password-like services a separate class <code>JPasswordField</code> | 
|
 * extends <code>JTextField</code> to provide this service with an independently | 
|
 * pluggable look-and-feel. | 
|
 * <p> | 
|
 * The <code>java.awt.TextField</code> could be monitored for changes by adding | 
|
 * a <code>TextListener</code> for <code>TextEvent</code>'s. | 
|
 * In the <code>JTextComponent</code> based | 
|
 * components, changes are broadcasted from the model via a | 
|
 * <code>DocumentEvent</code> to <code>DocumentListeners</code>. | 
|
 * The <code>DocumentEvent</code> gives | 
|
 * the location of the change and the kind of change if desired. | 
|
 * The code fragment might look something like: | 
|
 * <pre><code> | 
|
 *     DocumentListener myListener = ??; | 
|
 *     JTextField myArea = ??; | 
|
 *     myArea.getDocument().addDocumentListener(myListener); | 
|
 * </code></pre> | 
|
 * <p> | 
|
 * The horizontal alignment of <code>JTextField</code> can be set to be left | 
|
 * justified, leading justified, centered, right justified or trailing justified. | 
|
 * Right/trailing justification is useful if the required size | 
|
 * of the field text is smaller than the size allocated to it. | 
|
 * This is determined by the <code>setHorizontalAlignment</code> | 
|
 * and <code>getHorizontalAlignment</code> methods.  The default | 
|
 * is to be leading justified. | 
|
 * <p> | 
|
 * How the text field consumes VK_ENTER events depends | 
|
 * on whether the text field has any action listeners. | 
|
 * If so, then VK_ENTER results in the listeners | 
|
 * getting an ActionEvent, | 
|
 * and the VK_ENTER event is consumed. | 
|
 * This is compatible with how AWT text fields handle VK_ENTER events. | 
|
 * If the text field has no action listeners, then as of v 1.3 the VK_ENTER | 
|
 * event is not consumed.  Instead, the bindings of ancestor components | 
|
 * are processed, which enables the default button feature of | 
|
 * JFC/Swing to work. | 
|
 * <p> | 
|
 * Customized fields can easily be created by extending the model and | 
|
 * changing the default model provided.  For example, the following piece | 
|
 * of code will create a field that holds only upper case characters.  It | 
|
 * will work even if text is pasted into from the clipboard or it is altered via | 
|
 * programmatic changes. | 
|
 * <pre><code> | 
|
 | 
|
 public class UpperCaseField extends JTextField { | 
|
  | 
|
     public UpperCaseField(int cols) { | 
|
         super(cols); | 
|
     } | 
|
  | 
|
     protected Document createDefaultModel() { | 
|
         return new UpperCaseDocument(); | 
|
     } | 
|
  | 
|
     static class UpperCaseDocument extends PlainDocument { | 
|
  | 
|
         public void insertString(int offs, String str, AttributeSet a) | 
|
             throws BadLocationException { | 
|
  | 
|
             if (str == null) { | 
|
                 return; | 
|
             } | 
|
             char[] upper = str.toCharArray(); | 
|
             for (int i = 0; i < upper.length; i++) { | 
|
                 upper[i] = Character.toUpperCase(upper[i]); | 
|
             } | 
|
             super.insertString(offs, new String(upper), a); | 
|
         } | 
|
     } | 
|
 } | 
|
 | 
|
 * </code></pre> | 
|
 * <p> | 
|
 * <strong>Warning:</strong> Swing is not thread safe. For more | 
|
 * information see <a | 
|
 * href="package-summary.html#threading">Swing's Threading | 
|
 * Policy</a>. | 
|
 * <p> | 
|
 * <strong>Warning:</strong> | 
|
 * Serialized objects of this class will not be compatible with | 
|
 * future Swing releases. The current serialization support is | 
|
 * appropriate for short term storage or RMI between applications running | 
|
 * the same version of Swing.  As of 1.4, support for long term storage | 
|
 * of all JavaBeans™ | 
|
 * has been added to the <code>java.beans</code> package. | 
|
 * Please see {@link java.beans.XMLEncoder}. | 
|
 * | 
|
 * @beaninfo | 
|
 *   attribute: isContainer false | 
|
 * description: A component which allows for the editing of a single line of text. | 
|
 * | 
|
 * @author  Timothy Prinzing | 
|
 * @see #setActionCommand | 
|
 * @see JPasswordField | 
|
 * @see #addActionListener | 
|
*/  | 
|
public class JTextField extends JTextComponent implements SwingConstants {  | 
|
    /** | 
|
     * Constructs a new <code>TextField</code>.  A default model is created, | 
|
     * the initial string is <code>null</code>, | 
|
     * and the number of columns is set to 0. | 
|
*/  | 
|
    public JTextField() { | 
|
this(null, null, 0);  | 
|
}  | 
|
    /** | 
|
     * Constructs a new <code>TextField</code> initialized with the | 
|
     * specified text. A default model is created and the number of | 
|
     * columns is 0. | 
|
     * | 
|
     * @param text the text to be displayed, or <code>null</code> | 
|
*/  | 
|
public JTextField(String text) {  | 
|
this(null, text, 0);  | 
|
}  | 
|
    /** | 
|
     * Constructs a new empty <code>TextField</code> with the specified | 
|
     * number of columns. | 
|
     * A default model is created and the initial string is set to | 
|
     * <code>null</code>. | 
|
     * | 
|
     * @param columns  the number of columns to use to calculate | 
|
     *   the preferred width; if columns is set to zero, the | 
|
     *   preferred width will be whatever naturally results from | 
|
     *   the component implementation | 
|
*/  | 
|
    public JTextField(int columns) { | 
|
this(null, null, columns);  | 
|
}  | 
|
    /** | 
|
     * Constructs a new <code>TextField</code> initialized with the | 
|
     * specified text and columns.  A default model is created. | 
|
     * | 
|
     * @param text the text to be displayed, or <code>null</code> | 
|
     * @param columns  the number of columns to use to calculate | 
|
     *   the preferred width; if columns is set to zero, the | 
|
     *   preferred width will be whatever naturally results from | 
|
     *   the component implementation | 
|
*/  | 
|
public JTextField(String text, int columns) {  | 
|
this(null, text, columns);  | 
|
}  | 
|
    /** | 
|
     * Constructs a new <code>JTextField</code> that uses the given text | 
|
     * storage model and the given number of columns. | 
|
     * This is the constructor through which the other constructors feed. | 
|
     * If the document is <code>null</code>, a default model is created. | 
|
     * | 
|
     * @param doc  the text storage to use; if this is <code>null</code>, | 
|
     *          a default will be provided by calling the | 
|
     *          <code>createDefaultModel</code> method | 
|
     * @param text  the initial string to display, or <code>null</code> | 
|
     * @param columns  the number of columns to use to calculate | 
|
     *   the preferred width >= 0; if <code>columns</code> | 
|
     *   is set to zero, the preferred width will be whatever | 
|
     *   naturally results from the component implementation | 
|
     * @exception IllegalArgumentException if <code>columns</code> < 0 | 
|
*/  | 
|
public JTextField(Document doc, String text, int columns) {  | 
|
if (columns < 0) {  | 
|
throw new IllegalArgumentException("columns less than zero.");  | 
|
}  | 
|
visibility = new DefaultBoundedRangeModel();  | 
|
visibility.addChangeListener(new ScrollRepainter());  | 
|
this.columns = columns;  | 
|
        if (doc == null) { | 
|
doc = createDefaultModel();  | 
|
}  | 
|
setDocument(doc);  | 
|
if (text != null) {  | 
|
setText(text);  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Gets the class ID for a UI. | 
|
     * | 
|
     * @return the string "TextFieldUI" | 
|
     * @see JComponent#getUIClassID | 
|
     * @see UIDefaults#getUI | 
|
*/  | 
|
public String getUIClassID() {  | 
|
return uiClassID;  | 
|
}  | 
|
    /** | 
|
     * Associates the editor with a text document. | 
|
     * The currently registered factory is used to build a view for | 
|
     * the document, which gets displayed by the editor after revalidation. | 
|
     * A PropertyChange event ("document") is propagated to each listener. | 
|
     * | 
|
     * @param doc  the document to display/edit | 
|
     * @see #getDocument | 
|
     * @beaninfo | 
|
     *  description: the text document model | 
|
     *        bound: true | 
|
     *       expert: true | 
|
*/  | 
|
public void setDocument(Document doc) {  | 
|
if (doc != null) {  | 
|
doc.putProperty("filterNewlines", Boolean.TRUE);  | 
|
}  | 
|
super.setDocument(doc);  | 
|
}  | 
|
    /** | 
|
     * Calls to <code>revalidate</code> that come from within the | 
|
     * textfield itself will | 
|
     * be handled by validating the textfield, unless the textfield | 
|
     * is contained within a <code>JViewport</code>, | 
|
     * in which case this returns false. | 
|
     * | 
|
     * @return if the parent of this textfield is a <code>JViewPort</code> | 
|
     *          return false, otherwise return true | 
|
     * | 
|
     * @see JComponent#revalidate | 
|
     * @see JComponent#isValidateRoot | 
|
     * @see java.awt.Container#isValidateRoot | 
|
*/  | 
|
@Override  | 
|
    public boolean isValidateRoot() { | 
|
return !(SwingUtilities.getUnwrappedParent(this) instanceof JViewport);  | 
|
}  | 
|
    /** | 
|
     * Returns the horizontal alignment of the text. | 
|
     * Valid keys are: | 
|
     * <ul> | 
|
     * <li><code>JTextField.LEFT</code> | 
|
     * <li><code>JTextField.CENTER</code> | 
|
     * <li><code>JTextField.RIGHT</code> | 
|
     * <li><code>JTextField.LEADING</code> | 
|
     * <li><code>JTextField.TRAILING</code> | 
|
     * </ul> | 
|
     * | 
|
     * @return the horizontal alignment | 
|
*/  | 
|
    public int getHorizontalAlignment() { | 
|
return horizontalAlignment;  | 
|
}  | 
|
    /** | 
|
     * Sets the horizontal alignment of the text. | 
|
     * Valid keys are: | 
|
     * <ul> | 
|
     * <li><code>JTextField.LEFT</code> | 
|
     * <li><code>JTextField.CENTER</code> | 
|
     * <li><code>JTextField.RIGHT</code> | 
|
     * <li><code>JTextField.LEADING</code> | 
|
     * <li><code>JTextField.TRAILING</code> | 
|
     * </ul> | 
|
     * <code>invalidate</code> and <code>repaint</code> are called when the | 
|
     * alignment is set, | 
|
     * and a <code>PropertyChange</code> event ("horizontalAlignment") is fired. | 
|
     * | 
|
     * @param alignment the alignment | 
|
     * @exception IllegalArgumentException if <code>alignment</code> | 
|
     *  is not a valid key | 
|
     * @beaninfo | 
|
     *   preferred: true | 
|
     *       bound: true | 
|
     * description: Set the field alignment to LEFT, CENTER, RIGHT, | 
|
     *              LEADING (the default) or TRAILING | 
|
     *        enum: LEFT JTextField.LEFT CENTER JTextField.CENTER RIGHT JTextField.RIGHT | 
|
     *              LEADING JTextField.LEADING TRAILING JTextField.TRAILING | 
|
*/  | 
|
     public void setHorizontalAlignment(int alignment) { | 
|
if (alignment == horizontalAlignment) return;  | 
|
int oldValue = horizontalAlignment;  | 
|
if ((alignment == LEFT) || (alignment == CENTER) ||  | 
|
(alignment == RIGHT)|| (alignment == LEADING) ||  | 
|
(alignment == TRAILING)) {  | 
|
horizontalAlignment = alignment;  | 
|
        } else { | 
|
throw new IllegalArgumentException("horizontalAlignment");  | 
|
}  | 
|
firePropertyChange("horizontalAlignment", oldValue, horizontalAlignment);  | 
|
invalidate();  | 
|
repaint();  | 
|
}  | 
|
    /** | 
|
     * Creates the default implementation of the model | 
|
     * to be used at construction if one isn't explicitly | 
|
     * given.  An instance of <code>PlainDocument</code> is returned. | 
|
     * | 
|
     * @return the default model implementation | 
|
*/  | 
|
protected Document createDefaultModel() {  | 
|
return new PlainDocument();  | 
|
}  | 
|
    /** | 
|
     * Returns the number of columns in this <code>TextField</code>. | 
|
     * | 
|
     * @return the number of columns >= 0 | 
|
*/  | 
|
    public int getColumns() { | 
|
return columns;  | 
|
}  | 
|
    /** | 
|
     * Sets the number of columns in this <code>TextField</code>, | 
|
     * and then invalidate the layout. | 
|
     * | 
|
     * @param columns the number of columns >= 0 | 
|
     * @exception IllegalArgumentException if <code>columns</code> | 
|
     *          is less than 0 | 
|
     * @beaninfo | 
|
     * description: the number of columns preferred for display | 
|
*/  | 
|
    public void setColumns(int columns) { | 
|
int oldVal = this.columns;  | 
|
if (columns < 0) {  | 
|
throw new IllegalArgumentException("columns less than zero.");  | 
|
}  | 
|
if (columns != oldVal) {  | 
|
this.columns = columns;  | 
|
invalidate();  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Returns the column width. | 
|
     * The meaning of what a column is can be considered a fairly weak | 
|
     * notion for some fonts.  This method is used to define the width | 
|
     * of a column.  By default this is defined to be the width of the | 
|
     * character <em>m</em> for the font used.  This method can be | 
|
     * redefined to be some alternative amount | 
|
     * | 
|
     * @return the column width >= 1 | 
|
*/  | 
|
    protected int getColumnWidth() { | 
|
        if (columnWidth == 0) { | 
|
FontMetrics metrics = getFontMetrics(getFont());  | 
|
columnWidth = metrics.charWidth('m');  | 
|
}  | 
|
return columnWidth;  | 
|
}  | 
|
    /** | 
|
     * Returns the preferred size <code>Dimensions</code> needed for this | 
|
     * <code>TextField</code>.  If a non-zero number of columns has been | 
|
     * set, the width is set to the columns multiplied by | 
|
     * the column width. | 
|
     * | 
|
     * @return the dimension of this textfield | 
|
*/  | 
|
public Dimension getPreferredSize() {  | 
|
Dimension size = super.getPreferredSize();  | 
|
if (columns != 0) {  | 
|
Insets insets = getInsets();  | 
|
size.width = columns * getColumnWidth() +  | 
|
insets.left + insets.right;  | 
|
}  | 
|
return size;  | 
|
}  | 
|
    /** | 
|
     * Sets the current font.  This removes cached row height and column | 
|
     * width so the new font will be reflected. | 
|
     * <code>revalidate</code> is called after setting the font. | 
|
     * | 
|
     * @param f the new font | 
|
*/  | 
|
public void setFont(Font f) {  | 
|
super.setFont(f);  | 
|
columnWidth = 0;  | 
|
}  | 
|
    /** | 
|
     * Adds the specified action listener to receive | 
|
     * action events from this textfield. | 
|
     * | 
|
     * @param l the action listener to be added | 
|
*/  | 
|
public synchronized void addActionListener(ActionListener l) {  | 
|
listenerList.add(ActionListener.class, l);  | 
|
}  | 
|
    /** | 
|
     * Removes the specified action listener so that it no longer | 
|
     * receives action events from this textfield. | 
|
     * | 
|
     * @param l the action listener to be removed | 
|
*/  | 
|
public synchronized void removeActionListener(ActionListener l) {  | 
|
if ((l != null) && (getAction() == l)) {  | 
|
setAction(null);  | 
|
        } else { | 
|
listenerList.remove(ActionListener.class, l);  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Returns an array of all the <code>ActionListener</code>s added | 
|
     * to this JTextField with addActionListener(). | 
|
     * | 
|
     * @return all of the <code>ActionListener</code>s added or an empty | 
|
     *         array if no listeners have been added | 
|
     * @since 1.4 | 
|
*/  | 
|
public synchronized ActionListener[] getActionListeners() {  | 
|
return listenerList.getListeners(ActionListener.class);  | 
|
}  | 
|
    /** | 
|
     * Notifies all listeners that have registered interest for | 
|
     * notification on this event type.  The event instance | 
|
     * is lazily created. | 
|
     * The listener list is processed in last to | 
|
     * first order. | 
|
     * @see EventListenerList | 
|
*/  | 
|
    protected void fireActionPerformed() { | 
|
        // Guaranteed to return a non-null array | 
|
Object[] listeners = listenerList.getListenerList();  | 
|
int modifiers = 0;  | 
|
AWTEvent currentEvent = EventQueue.getCurrentEvent();  | 
|
if (currentEvent instanceof InputEvent) {  | 
|
modifiers = ((InputEvent)currentEvent).getModifiers();  | 
|
} else if (currentEvent instanceof ActionEvent) {  | 
|
modifiers = ((ActionEvent)currentEvent).getModifiers();  | 
|
}  | 
|
ActionEvent e =  | 
|
new ActionEvent(this, ActionEvent.ACTION_PERFORMED,  | 
|
(command != null) ? command : getText(),  | 
|
EventQueue.getMostRecentEventTime(), modifiers);  | 
|
// Process the listeners last to first, notifying  | 
|
        // those that are interested in this event | 
|
for (int i = listeners.length-2; i>=0; i-=2) {  | 
|
if (listeners[i]==ActionListener.class) {  | 
|
((ActionListener)listeners[i+1]).actionPerformed(e);  | 
|
}  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Sets the command string used for action events. | 
|
     * | 
|
     * @param command the command string | 
|
*/  | 
|
public void setActionCommand(String command) {  | 
|
this.command = command;  | 
|
}  | 
|
private Action action;  | 
|
private PropertyChangeListener actionPropertyChangeListener;  | 
|
    /** | 
|
     * Sets the <code>Action</code> for the <code>ActionEvent</code> source. | 
|
     * The new <code>Action</code> replaces | 
|
     * any previously set <code>Action</code> but does not affect | 
|
     * <code>ActionListeners</code> independently | 
|
     * added with <code>addActionListener</code>. | 
|
     * If the <code>Action</code> is already a registered | 
|
     * <code>ActionListener</code> | 
|
     * for the <code>ActionEvent</code> source, it is not re-registered. | 
|
     * <p> | 
|
     * Setting the <code>Action</code> results in immediately changing | 
|
     * all the properties described in <a href="Action.html#buttonActions"> | 
|
     * Swing Components Supporting <code>Action</code></a>. | 
|
     * Subsequently, the textfield's properties are automatically updated | 
|
     * as the <code>Action</code>'s properties change. | 
|
     * <p> | 
|
     * This method uses three other methods to set | 
|
     * and help track the <code>Action</code>'s property values. | 
|
     * It uses the <code>configurePropertiesFromAction</code> method | 
|
     * to immediately change the textfield's properties. | 
|
     * To track changes in the <code>Action</code>'s property values, | 
|
     * this method registers the <code>PropertyChangeListener</code> | 
|
     * returned by <code>createActionPropertyChangeListener</code>. The | 
|
     * default {@code PropertyChangeListener} invokes the | 
|
     * {@code actionPropertyChanged} method when a property in the | 
|
     * {@code Action} changes. | 
|
     * | 
|
     * @param a the <code>Action</code> for the <code>JTextField</code>, | 
|
     *          or <code>null</code> | 
|
     * @since 1.3 | 
|
     * @see Action | 
|
     * @see #getAction | 
|
     * @see #configurePropertiesFromAction | 
|
     * @see #createActionPropertyChangeListener | 
|
     * @see #actionPropertyChanged | 
|
     * @beaninfo | 
|
     *        bound: true | 
|
     *    attribute: visualUpdate true | 
|
     *  description: the Action instance connected with this ActionEvent source | 
|
*/  | 
|
public void setAction(Action a) {  | 
|
Action oldValue = getAction();  | 
|
if (action==null || !action.equals(a)) {  | 
|
action = a;  | 
|
if (oldValue!=null) {  | 
|
removeActionListener(oldValue);  | 
|
oldValue.removePropertyChangeListener(actionPropertyChangeListener);  | 
|
actionPropertyChangeListener = null;  | 
|
}  | 
|
configurePropertiesFromAction(action);  | 
|
if (action!=null) {  | 
|
                // Don't add if it is already a listener | 
|
if (!isListener(ActionListener.class, action)) {  | 
|
addActionListener(action);  | 
|
}  | 
|
                // Reverse linkage: | 
|
actionPropertyChangeListener = createActionPropertyChangeListener(action);  | 
|
action.addPropertyChangeListener(actionPropertyChangeListener);  | 
|
}  | 
|
firePropertyChange("action", oldValue, action);  | 
|
}  | 
|
}  | 
|
private boolean isListener(Class c, ActionListener a) {  | 
|
boolean isListener = false;  | 
|
Object[] listeners = listenerList.getListenerList();  | 
|
for (int i = listeners.length-2; i>=0; i-=2) {  | 
|
if (listeners[i]==c && listeners[i+1]==a) {  | 
|
isListener=true;  | 
|
}  | 
|
}  | 
|
return isListener;  | 
|
}  | 
|
    /** | 
|
     * Returns the currently set <code>Action</code> for this | 
|
     * <code>ActionEvent</code> source, or <code>null</code> | 
|
     * if no <code>Action</code> is set. | 
|
     * | 
|
     * @return the <code>Action</code> for this <code>ActionEvent</code> source, | 
|
     *          or <code>null</code> | 
|
     * @since 1.3 | 
|
     * @see Action | 
|
     * @see #setAction | 
|
*/  | 
|
public Action getAction() {  | 
|
return action;  | 
|
}  | 
|
    /** | 
|
     * Sets the properties on this textfield to match those in the specified | 
|
     * <code>Action</code>.  Refer to <a href="Action.html#buttonActions"> | 
|
     * Swing Components Supporting <code>Action</code></a> for more | 
|
     * details as to which properties this sets. | 
|
     * | 
|
     * @param a the <code>Action</code> from which to get the properties, | 
|
     *          or <code>null</code> | 
|
     * @since 1.3 | 
|
     * @see Action | 
|
     * @see #setAction | 
|
*/  | 
|
protected void configurePropertiesFromAction(Action a) {  | 
|
AbstractAction.setEnabledFromAction(this, a);  | 
|
AbstractAction.setToolTipTextFromAction(this, a);  | 
|
setActionCommandFromAction(a);  | 
|
}  | 
|
    /** | 
|
     * Updates the textfield's state in response to property changes in | 
|
     * associated action. This method is invoked from the | 
|
     * {@code PropertyChangeListener} returned from | 
|
     * {@code createActionPropertyChangeListener}. Subclasses do not normally | 
|
     * need to invoke this. Subclasses that support additional {@code Action} | 
|
     * properties should override this and | 
|
     * {@code configurePropertiesFromAction}. | 
|
     * <p> | 
|
     * Refer to the table at <a href="Action.html#buttonActions"> | 
|
     * Swing Components Supporting <code>Action</code></a> for a list of | 
|
     * the properties this method sets. | 
|
     * | 
|
     * @param action the <code>Action</code> associated with this textfield | 
|
     * @param propertyName the name of the property that changed | 
|
     * @since 1.6 | 
|
     * @see Action | 
|
     * @see #configurePropertiesFromAction | 
|
*/  | 
|
protected void actionPropertyChanged(Action action, String propertyName) {  | 
|
if (propertyName == Action.ACTION_COMMAND_KEY) {  | 
|
setActionCommandFromAction(action);  | 
|
} else if (propertyName == "enabled") {  | 
|
AbstractAction.setEnabledFromAction(this, action);  | 
|
} else if (propertyName == Action.SHORT_DESCRIPTION) {  | 
|
AbstractAction.setToolTipTextFromAction(this, action);  | 
|
}  | 
|
}  | 
|
private void setActionCommandFromAction(Action action) {  | 
|
setActionCommand((action == null) ? null :  | 
|
(String)action.getValue(Action.ACTION_COMMAND_KEY));  | 
|
}  | 
|
    /** | 
|
     * Creates and returns a <code>PropertyChangeListener</code> that is | 
|
     * responsible for listening for changes from the specified | 
|
     * <code>Action</code> and updating the appropriate properties. | 
|
     * <p> | 
|
     * <b>Warning:</b> If you subclass this do not create an anonymous | 
|
     * inner class.  If you do the lifetime of the textfield will be tied to | 
|
     * that of the <code>Action</code>. | 
|
     * | 
|
     * @param a the textfield's action | 
|
     * @since 1.3 | 
|
     * @see Action | 
|
     * @see #setAction | 
|
*/  | 
|
protected PropertyChangeListener createActionPropertyChangeListener(Action a) {  | 
|
return new TextFieldActionPropertyChangeListener(this, a);  | 
|
}  | 
|
private static class TextFieldActionPropertyChangeListener extends  | 
|
ActionPropertyChangeListener<JTextField> {  | 
|
TextFieldActionPropertyChangeListener(JTextField tf, Action a) {  | 
|
super(tf, a);  | 
|
}  | 
|
protected void actionPropertyChanged(JTextField textField,  | 
|
Action action,  | 
|
PropertyChangeEvent e) {  | 
|
if (AbstractAction.shouldReconfigure(e)) {  | 
|
textField.configurePropertiesFromAction(action);  | 
|
            } else { | 
|
textField.actionPropertyChanged(action, e.getPropertyName());  | 
|
}  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Fetches the command list for the editor.  This is | 
|
     * the list of commands supported by the plugged-in UI | 
|
     * augmented by the collection of commands that the | 
|
     * editor itself supports.  These are useful for binding | 
|
     * to events, such as in a keymap. | 
|
     * | 
|
     * @return the command list | 
|
*/  | 
|
public Action[] getActions() {  | 
|
return TextAction.augmentList(super.getActions(), defaultActions);  | 
|
}  | 
|
    /** | 
|
     * Processes action events occurring on this textfield by | 
|
     * dispatching them to any registered <code>ActionListener</code> objects. | 
|
     * This is normally called by the controller registered with | 
|
     * textfield. | 
|
*/  | 
|
    public void postActionEvent() { | 
|
fireActionPerformed();  | 
|
}  | 
|
// --- Scrolling support -----------------------------------  | 
|
    /** | 
|
     * Gets the visibility of the text field.  This can | 
|
     * be adjusted to change the location of the visible | 
|
     * area if the size of the field is greater than | 
|
     * the area that was allocated to the field. | 
|
     * | 
|
     * <p> | 
|
     * The fields look-and-feel implementation manages | 
|
     * the values of the minimum, maximum, and extent | 
|
     * properties on the <code>BoundedRangeModel</code>. | 
|
     * | 
|
     * @return the visibility | 
|
     * @see BoundedRangeModel | 
|
*/  | 
|
public BoundedRangeModel getHorizontalVisibility() {  | 
|
return visibility;  | 
|
}  | 
|
    /** | 
|
     * Gets the scroll offset, in pixels. | 
|
     * | 
|
     * @return the offset >= 0 | 
|
*/  | 
|
    public int getScrollOffset() { | 
|
return visibility.getValue();  | 
|
}  | 
|
    /** | 
|
     * Sets the scroll offset, in pixels. | 
|
     * | 
|
     * @param scrollOffset the offset >= 0 | 
|
*/  | 
|
    public void setScrollOffset(int scrollOffset) { | 
|
visibility.setValue(scrollOffset);  | 
|
}  | 
|
    /** | 
|
     * Scrolls the field left or right. | 
|
     * | 
|
     * @param r the region to scroll | 
|
*/  | 
|
public void scrollRectToVisible(Rectangle r) {  | 
|
        // convert to coordinate system of the bounded range | 
|
Insets i = getInsets();  | 
|
int x0 = r.x + visibility.getValue() - i.left;  | 
|
int x1 = x0 + r.width;  | 
|
if (x0 < visibility.getValue()) {  | 
|
            // Scroll to the left | 
|
visibility.setValue(x0);  | 
|
} else if(x1 > visibility.getValue() + visibility.getExtent()) {  | 
|
            // Scroll to the right | 
|
visibility.setValue(x1 - visibility.getExtent());  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Returns true if the receiver has an <code>ActionListener</code> | 
|
     * installed. | 
|
*/  | 
|
    boolean hasActionListener() { | 
|
        // Guaranteed to return a non-null array | 
|
Object[] listeners = listenerList.getListenerList();  | 
|
// Process the listeners last to first, notifying  | 
|
        // those that are interested in this event | 
|
for (int i = listeners.length-2; i>=0; i-=2) {  | 
|
if (listeners[i]==ActionListener.class) {  | 
|
return true;  | 
|
}  | 
|
}  | 
|
return false;  | 
|
}  | 
|
// --- variables -------------------------------------------  | 
|
    /** | 
|
     * Name of the action to send notification that the | 
|
     * contents of the field have been accepted.  Typically | 
|
     * this is bound to a carriage-return. | 
|
*/  | 
|
public static final String notifyAction = "notify-field-accept";  | 
|
private BoundedRangeModel visibility;  | 
|
private int horizontalAlignment = LEADING;  | 
|
private int columns;  | 
|
private int columnWidth;  | 
|
private String command;  | 
|
private static final Action[] defaultActions = {  | 
|
new NotifyAction()  | 
|
};  | 
|
    /** | 
|
     * @see #getUIClassID | 
|
     * @see #readObject | 
|
*/  | 
|
private static final String uiClassID = "TextFieldUI";  | 
|
// --- Action implementations -----------------------------------  | 
|
    // Note that JFormattedTextField.CommitAction extends this | 
|
static class NotifyAction extends TextAction {  | 
|
        NotifyAction() { | 
|
super(notifyAction);  | 
|
}  | 
|
public void actionPerformed(ActionEvent e) {  | 
|
JTextComponent target = getFocusedComponent();  | 
|
if (target instanceof JTextField) {  | 
|
JTextField field = (JTextField) target;  | 
|
field.postActionEvent();  | 
|
}  | 
|
}  | 
|
        public boolean isEnabled() { | 
|
JTextComponent target = getFocusedComponent();  | 
|
if (target instanceof JTextField) {  | 
|
return ((JTextField)target).hasActionListener();  | 
|
}  | 
|
return false;  | 
|
}  | 
|
}  | 
|
class ScrollRepainter implements ChangeListener, Serializable {  | 
|
public void stateChanged(ChangeEvent e) {  | 
|
repaint();  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * See <code>readObject</code> and <code>writeObject</code> in | 
|
     * <code>JComponent</code> for more | 
|
     * information about serialization in Swing. | 
|
*/  | 
|
private void writeObject(ObjectOutputStream s) throws IOException {  | 
|
s.defaultWriteObject();  | 
|
if (getUIClassID().equals(uiClassID)) {  | 
|
byte count = JComponent.getWriteObjCounter(this);  | 
|
JComponent.setWriteObjCounter(this, --count);  | 
|
if (count == 0 && ui != null) {  | 
|
ui.installUI(this);  | 
|
}  | 
|
}  | 
|
}  | 
|
    /** | 
|
     * Returns a string representation of this <code>JTextField</code>. | 
|
     * This method is intended to be used only for debugging purposes, | 
|
     * and the content and format of the returned string may vary between | 
|
     * implementations. The returned string may be empty but may not | 
|
     * be <code>null</code>. | 
|
     * | 
|
     * @return  a string representation of this <code>JTextField</code> | 
|
*/  | 
|
protected String paramString() {  | 
|
String horizontalAlignmentString;  | 
|
if (horizontalAlignment == LEFT) {  | 
|
horizontalAlignmentString = "LEFT";  | 
|
} else if (horizontalAlignment == CENTER) {  | 
|
horizontalAlignmentString = "CENTER";  | 
|
} else if (horizontalAlignment == RIGHT) {  | 
|
horizontalAlignmentString = "RIGHT";  | 
|
} else if (horizontalAlignment == LEADING) {  | 
|
horizontalAlignmentString = "LEADING";  | 
|
} else if (horizontalAlignment == TRAILING) {  | 
|
horizontalAlignmentString = "TRAILING";  | 
|
} else horizontalAlignmentString = "";  | 
|
String commandString = (command != null ?  | 
|
command : "");  | 
|
return super.paramString() +  | 
|
",columns=" + columns +  | 
|
",columnWidth=" + columnWidth +  | 
|
",command=" + commandString +  | 
|
",horizontalAlignment=" + horizontalAlignmentString;  | 
|
}  | 
|
/////////////////  | 
|
// Accessibility support  | 
|
////////////////  | 
|
    /** | 
|
     * Gets the <code>AccessibleContext</code> associated with this | 
|
     * <code>JTextField</code>. For <code>JTextFields</code>, | 
|
     * the <code>AccessibleContext</code> takes the form of an | 
|
     * <code>AccessibleJTextField</code>. | 
|
     * A new <code>AccessibleJTextField</code> instance is created | 
|
     * if necessary. | 
|
     * | 
|
     * @return an <code>AccessibleJTextField</code> that serves as the | 
|
     *         <code>AccessibleContext</code> of this <code>JTextField</code> | 
|
*/  | 
|
public AccessibleContext getAccessibleContext() {  | 
|
        if (accessibleContext == null) { | 
|
accessibleContext = new AccessibleJTextField();  | 
|
}  | 
|
return accessibleContext;  | 
|
}  | 
|
    /** | 
|
     * This class implements accessibility support for the | 
|
     * <code>JTextField</code> class.  It provides an implementation of the | 
|
     * Java Accessibility API appropriate to text field user-interface | 
|
     * elements. | 
|
     * <p> | 
|
     * <strong>Warning:</strong> | 
|
     * Serialized objects of this class will not be compatible with | 
|
     * future Swing releases. The current serialization support is | 
|
     * appropriate for short term storage or RMI between applications running | 
|
     * the same version of Swing.  As of 1.4, support for long term storage | 
|
     * of all JavaBeans™ | 
|
     * has been added to the <code>java.beans</code> package. | 
|
     * Please see {@link java.beans.XMLEncoder}. | 
|
*/  | 
|
    protected class AccessibleJTextField extends AccessibleJTextComponent { | 
|
        /** | 
|
         * Gets the state set of this object. | 
|
         * | 
|
         * @return an instance of AccessibleStateSet describing the states | 
|
         * of the object | 
|
         * @see AccessibleState | 
|
*/  | 
|
public AccessibleStateSet getAccessibleStateSet() {  | 
|
AccessibleStateSet states = super.getAccessibleStateSet();  | 
|
states.add(AccessibleState.SINGLE_LINE);  | 
|
return states;  | 
|
}  | 
|
}  | 
|
}  |