Home » openjdk-7 » javax » swing » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   package javax.swing;
   26   
   27   import sun.swing.SwingUtilities2;
   28   
   29   import java.awt;
   30   import java.awt.event;
   31   import java.beans;
   32   import javax.swing.text;
   33   import javax.swing.plaf;
   34   import javax.swing.event;
   35   import javax.accessibility;
   36   
   37   import java.io.ObjectOutputStream;
   38   import java.io.ObjectInputStream;
   39   import java.io.IOException;
   40   import java.io.Serializable;
   41   
   42   /**
   43    * <code>JTextField</code> is a lightweight component that allows the editing
   44    * of a single line of text.
   45    * For information on and examples of using text fields,
   46    * see
   47    * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/textfield.html">How to Use Text Fields</a>
   48    * in <em>The Java Tutorial.</em>
   49    *
   50    * <p>
   51    * <code>JTextField</code> is intended to be source-compatible
   52    * with <code>java.awt.TextField</code> where it is reasonable to do so.  This
   53    * component has capabilities not found in the <code>java.awt.TextField</code>
   54    * class.  The superclass should be consulted for additional capabilities.
   55    * <p>
   56    * <code>JTextField</code> has a method to establish the string used as the
   57    * command string for the action event that gets fired.  The
   58    * <code>java.awt.TextField</code> used the text of the field as the command
   59    * string for the <code>ActionEvent</code>.
   60    * <code>JTextField</code> will use the command
   61    * string set with the <code>setActionCommand</code> method if not <code>null</code>,
   62    * otherwise it will use the text of the field as a compatibility with
   63    * <code>java.awt.TextField</code>.
   64    * <p>
   65    * The method <code>setEchoChar</code> and <code>getEchoChar</code>
   66    * are not provided directly to avoid a new implementation of a
   67    * pluggable look-and-feel inadvertently exposing password characters.
   68    * To provide password-like services a separate class <code>JPasswordField</code>
   69    * extends <code>JTextField</code> to provide this service with an independently
   70    * pluggable look-and-feel.
   71    * <p>
   72    * The <code>java.awt.TextField</code> could be monitored for changes by adding
   73    * a <code>TextListener</code> for <code>TextEvent</code>'s.
   74    * In the <code>JTextComponent</code> based
   75    * components, changes are broadcasted from the model via a
   76    * <code>DocumentEvent</code> to <code>DocumentListeners</code>.
   77    * The <code>DocumentEvent</code> gives
   78    * the location of the change and the kind of change if desired.
   79    * The code fragment might look something like:
   80    * <pre><code>
   81    * &nbsp;   DocumentListener myListener = ??;
   82    * &nbsp;   JTextField myArea = ??;
   83    * &nbsp;   myArea.getDocument().addDocumentListener(myListener);
   84    * </code></pre>
   85    * <p>
   86    * The horizontal alignment of <code>JTextField</code> can be set to be left
   87    * justified, leading justified, centered, right justified or trailing justified.
   88    * Right/trailing justification is useful if the required size
   89    * of the field text is smaller than the size allocated to it.
   90    * This is determined by the <code>setHorizontalAlignment</code>
   91    * and <code>getHorizontalAlignment</code> methods.  The default
   92    * is to be leading justified.
   93    * <p>
   94    * How the text field consumes VK_ENTER events depends
   95    * on whether the text field has any action listeners.
   96    * If so, then VK_ENTER results in the listeners
   97    * getting an ActionEvent,
   98    * and the VK_ENTER event is consumed.
   99    * This is compatible with how AWT text fields handle VK_ENTER events.
  100    * If the text field has no action listeners, then as of v 1.3 the VK_ENTER
  101    * event is not consumed.  Instead, the bindings of ancestor components
  102    * are processed, which enables the default button feature of
  103    * JFC/Swing to work.
  104    * <p>
  105    * Customized fields can easily be created by extending the model and
  106    * changing the default model provided.  For example, the following piece
  107    * of code will create a field that holds only upper case characters.  It
  108    * will work even if text is pasted into from the clipboard or it is altered via
  109    * programmatic changes.
  110    * <pre><code>
  111   
  112   &nbsp;public class UpperCaseField extends JTextField {
  113   &nbsp;
  114   &nbsp;    public UpperCaseField(int cols) {
  115   &nbsp;        super(cols);
  116   &nbsp;    }
  117   &nbsp;
  118   &nbsp;    protected Document createDefaultModel() {
  119   &nbsp;        return new UpperCaseDocument();
  120   &nbsp;    }
  121   &nbsp;
  122   &nbsp;    static class UpperCaseDocument extends PlainDocument {
  123   &nbsp;
  124   &nbsp;        public void insertString(int offs, String str, AttributeSet a)
  125   &nbsp;            throws BadLocationException {
  126   &nbsp;
  127   &nbsp;            if (str == null) {
  128   &nbsp;                return;
  129   &nbsp;            }
  130   &nbsp;            char[] upper = str.toCharArray();
  131   &nbsp;            for (int i = 0; i < upper.length; i++) {
  132   &nbsp;                upper[i] = Character.toUpperCase(upper[i]);
  133   &nbsp;            }
  134   &nbsp;            super.insertString(offs, new String(upper), a);
  135   &nbsp;        }
  136   &nbsp;    }
  137   &nbsp;}
  138   
  139    * </code></pre>
  140    * <p>
  141    * <strong>Warning:</strong> Swing is not thread safe. For more
  142    * information see <a
  143    * href="package-summary.html#threading">Swing's Threading
  144    * Policy</a>.
  145    * <p>
  146    * <strong>Warning:</strong>
  147    * Serialized objects of this class will not be compatible with
  148    * future Swing releases. The current serialization support is
  149    * appropriate for short term storage or RMI between applications running
  150    * the same version of Swing.  As of 1.4, support for long term storage
  151    * of all JavaBeans<sup><font size="-2">TM</font></sup>
  152    * has been added to the <code>java.beans</code> package.
  153    * Please see {@link java.beans.XMLEncoder}.
  154    *
  155    * @beaninfo
  156    *   attribute: isContainer false
  157    * description: A component which allows for the editing of a single line of text.
  158    *
  159    * @author  Timothy Prinzing
  160    * @see #setActionCommand
  161    * @see JPasswordField
  162    * @see #addActionListener
  163    */
  164   public class JTextField extends JTextComponent implements SwingConstants {
  165   
  166       /**
  167        * Constructs a new <code>TextField</code>.  A default model is created,
  168        * the initial string is <code>null</code>,
  169        * and the number of columns is set to 0.
  170        */
  171       public JTextField() {
  172           this(null, null, 0);
  173       }
  174   
  175       /**
  176        * Constructs a new <code>TextField</code> initialized with the
  177        * specified text. A default model is created and the number of
  178        * columns is 0.
  179        *
  180        * @param text the text to be displayed, or <code>null</code>
  181        */
  182       public JTextField(String text) {
  183           this(null, text, 0);
  184       }
  185   
  186       /**
  187        * Constructs a new empty <code>TextField</code> with the specified
  188        * number of columns.
  189        * A default model is created and the initial string is set to
  190        * <code>null</code>.
  191        *
  192        * @param columns  the number of columns to use to calculate
  193        *   the preferred width; if columns is set to zero, the
  194        *   preferred width will be whatever naturally results from
  195        *   the component implementation
  196        */
  197       public JTextField(int columns) {
  198           this(null, null, columns);
  199       }
  200   
  201       /**
  202        * Constructs a new <code>TextField</code> initialized with the
  203        * specified text and columns.  A default model is created.
  204        *
  205        * @param text the text to be displayed, or <code>null</code>
  206        * @param columns  the number of columns to use to calculate
  207        *   the preferred width; if columns is set to zero, the
  208        *   preferred width will be whatever naturally results from
  209        *   the component implementation
  210        */
  211       public JTextField(String text, int columns) {
  212           this(null, text, columns);
  213       }
  214   
  215       /**
  216        * Constructs a new <code>JTextField</code> that uses the given text
  217        * storage model and the given number of columns.
  218        * This is the constructor through which the other constructors feed.
  219        * If the document is <code>null</code>, a default model is created.
  220        *
  221        * @param doc  the text storage to use; if this is <code>null</code>,
  222        *          a default will be provided by calling the
  223        *          <code>createDefaultModel</code> method
  224        * @param text  the initial string to display, or <code>null</code>
  225        * @param columns  the number of columns to use to calculate
  226        *   the preferred width >= 0; if <code>columns</code>
  227        *   is set to zero, the preferred width will be whatever
  228        *   naturally results from the component implementation
  229        * @exception IllegalArgumentException if <code>columns</code> < 0
  230        */
  231       public JTextField(Document doc, String text, int columns) {
  232           if (columns < 0) {
  233               throw new IllegalArgumentException("columns less than zero.");
  234           }
  235           visibility = new DefaultBoundedRangeModel();
  236           visibility.addChangeListener(new ScrollRepainter());
  237           this.columns = columns;
  238           if (doc == null) {
  239               doc = createDefaultModel();
  240           }
  241           setDocument(doc);
  242           if (text != null) {
  243               setText(text);
  244           }
  245       }
  246   
  247       /**
  248        * Gets the class ID for a UI.
  249        *
  250        * @return the string "TextFieldUI"
  251        * @see JComponent#getUIClassID
  252        * @see UIDefaults#getUI
  253        */
  254       public String getUIClassID() {
  255           return uiClassID;
  256       }
  257   
  258   
  259       /**
  260        * Associates the editor with a text document.
  261        * The currently registered factory is used to build a view for
  262        * the document, which gets displayed by the editor after revalidation.
  263        * A PropertyChange event ("document") is propagated to each listener.
  264        *
  265        * @param doc  the document to display/edit
  266        * @see #getDocument
  267        * @beaninfo
  268        *  description: the text document model
  269        *        bound: true
  270        *       expert: true
  271        */
  272       public void setDocument(Document doc) {
  273           if (doc != null) {
  274               doc.putProperty("filterNewlines", Boolean.TRUE);
  275           }
  276           super.setDocument(doc);
  277       }
  278   
  279       /**
  280        * Calls to <code>revalidate</code> that come from within the
  281        * textfield itself will
  282        * be handled by validating the textfield, unless the textfield
  283        * is contained within a <code>JViewport</code>,
  284        * in which case this returns false.
  285        *
  286        * @return if the parent of this textfield is a <code>JViewPort</code>
  287        *          return false, otherwise return true
  288        *
  289        * @see JComponent#revalidate
  290        * @see JComponent#isValidateRoot
  291        * @see java.awt.Container#isValidateRoot
  292        */
  293       @Override
  294       public boolean isValidateRoot() {
  295           return !(SwingUtilities.getUnwrappedParent(this) instanceof JViewport);
  296       }
  297   
  298   
  299       /**
  300        * Returns the horizontal alignment of the text.
  301        * Valid keys are:
  302        * <ul>
  303        * <li><code>JTextField.LEFT</code>
  304        * <li><code>JTextField.CENTER</code>
  305        * <li><code>JTextField.RIGHT</code>
  306        * <li><code>JTextField.LEADING</code>
  307        * <li><code>JTextField.TRAILING</code>
  308        * </ul>
  309        *
  310        * @return the horizontal alignment
  311        */
  312       public int getHorizontalAlignment() {
  313           return horizontalAlignment;
  314       }
  315   
  316       /**
  317        * Sets the horizontal alignment of the text.
  318        * Valid keys are:
  319        * <ul>
  320        * <li><code>JTextField.LEFT</code>
  321        * <li><code>JTextField.CENTER</code>
  322        * <li><code>JTextField.RIGHT</code>
  323        * <li><code>JTextField.LEADING</code>
  324        * <li><code>JTextField.TRAILING</code>
  325        * </ul>
  326        * <code>invalidate</code> and <code>repaint</code> are called when the
  327        * alignment is set,
  328        * and a <code>PropertyChange</code> event ("horizontalAlignment") is fired.
  329        *
  330        * @param alignment the alignment
  331        * @exception IllegalArgumentException if <code>alignment</code>
  332        *  is not a valid key
  333        * @beaninfo
  334        *   preferred: true
  335        *       bound: true
  336        * description: Set the field alignment to LEFT, CENTER, RIGHT,
  337        *              LEADING (the default) or TRAILING
  338        *        enum: LEFT JTextField.LEFT CENTER JTextField.CENTER RIGHT JTextField.RIGHT
  339        *              LEADING JTextField.LEADING TRAILING JTextField.TRAILING
  340        */
  341        public void setHorizontalAlignment(int alignment) {
  342           if (alignment == horizontalAlignment) return;
  343           int oldValue = horizontalAlignment;
  344           if ((alignment == LEFT) || (alignment == CENTER) ||
  345               (alignment == RIGHT)|| (alignment == LEADING) ||
  346               (alignment == TRAILING)) {
  347               horizontalAlignment = alignment;
  348           } else {
  349               throw new IllegalArgumentException("horizontalAlignment");
  350           }
  351           firePropertyChange("horizontalAlignment", oldValue, horizontalAlignment);
  352           invalidate();
  353           repaint();
  354       }
  355   
  356       /**
  357        * Creates the default implementation of the model
  358        * to be used at construction if one isn't explicitly
  359        * given.  An instance of <code>PlainDocument</code> is returned.
  360        *
  361        * @return the default model implementation
  362        */
  363       protected Document createDefaultModel() {
  364           return new PlainDocument();
  365       }
  366   
  367       /**
  368        * Returns the number of columns in this <code>TextField</code>.
  369        *
  370        * @return the number of columns >= 0
  371        */
  372       public int getColumns() {
  373           return columns;
  374       }
  375   
  376       /**
  377        * Sets the number of columns in this <code>TextField</code>,
  378        * and then invalidate the layout.
  379        *
  380        * @param columns the number of columns >= 0
  381        * @exception IllegalArgumentException if <code>columns</code>
  382        *          is less than 0
  383        * @beaninfo
  384        * description: the number of columns preferred for display
  385        */
  386       public void setColumns(int columns) {
  387           int oldVal = this.columns;
  388           if (columns < 0) {
  389               throw new IllegalArgumentException("columns less than zero.");
  390           }
  391           if (columns != oldVal) {
  392               this.columns = columns;
  393               invalidate();
  394           }
  395       }
  396   
  397       /**
  398        * Returns the column width.
  399        * The meaning of what a column is can be considered a fairly weak
  400        * notion for some fonts.  This method is used to define the width
  401        * of a column.  By default this is defined to be the width of the
  402        * character <em>m</em> for the font used.  This method can be
  403        * redefined to be some alternative amount
  404        *
  405        * @return the column width >= 1
  406        */
  407       protected int getColumnWidth() {
  408           if (columnWidth == 0) {
  409               FontMetrics metrics = getFontMetrics(getFont());
  410               columnWidth = metrics.charWidth('m');
  411           }
  412           return columnWidth;
  413       }
  414   
  415       /**
  416        * Returns the preferred size <code>Dimensions</code> needed for this
  417        * <code>TextField</code>.  If a non-zero number of columns has been
  418        * set, the width is set to the columns multiplied by
  419        * the column width.
  420        *
  421        * @return the dimension of this textfield
  422        */
  423       public Dimension getPreferredSize() {
  424           Dimension size = super.getPreferredSize();
  425           if (columns != 0) {
  426               Insets insets = getInsets();
  427               size.width = columns * getColumnWidth() +
  428                   insets.left + insets.right;
  429           }
  430           return size;
  431       }
  432   
  433       /**
  434        * Sets the current font.  This removes cached row height and column
  435        * width so the new font will be reflected.
  436        * <code>revalidate</code> is called after setting the font.
  437        *
  438        * @param f the new font
  439        */
  440       public void setFont(Font f) {
  441           super.setFont(f);
  442           columnWidth = 0;
  443       }
  444   
  445       /**
  446        * Adds the specified action listener to receive
  447        * action events from this textfield.
  448        *
  449        * @param l the action listener to be added
  450        */
  451       public synchronized void addActionListener(ActionListener l) {
  452           listenerList.add(ActionListener.class, l);
  453       }
  454   
  455       /**
  456        * Removes the specified action listener so that it no longer
  457        * receives action events from this textfield.
  458        *
  459        * @param l the action listener to be removed
  460        */
  461       public synchronized void removeActionListener(ActionListener l) {
  462           if ((l != null) && (getAction() == l)) {
  463               setAction(null);
  464           } else {
  465               listenerList.remove(ActionListener.class, l);
  466           }
  467       }
  468   
  469       /**
  470        * Returns an array of all the <code>ActionListener</code>s added
  471        * to this JTextField with addActionListener().
  472        *
  473        * @return all of the <code>ActionListener</code>s added or an empty
  474        *         array if no listeners have been added
  475        * @since 1.4
  476        */
  477       public synchronized ActionListener[] getActionListeners() {
  478           return listenerList.getListeners(ActionListener.class);
  479       }
  480   
  481       /**
  482        * Notifies all listeners that have registered interest for
  483        * notification on this event type.  The event instance
  484        * is lazily created.
  485        * The listener list is processed in last to
  486        * first order.
  487        * @see EventListenerList
  488        */
  489       protected void fireActionPerformed() {
  490           // Guaranteed to return a non-null array
  491           Object[] listeners = listenerList.getListenerList();
  492           int modifiers = 0;
  493           AWTEvent currentEvent = EventQueue.getCurrentEvent();
  494           if (currentEvent instanceof InputEvent) {
  495               modifiers = ((InputEvent)currentEvent).getModifiers();
  496           } else if (currentEvent instanceof ActionEvent) {
  497               modifiers = ((ActionEvent)currentEvent).getModifiers();
  498           }
  499           ActionEvent e =
  500               new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
  501                               (command != null) ? command : getText(),
  502                               EventQueue.getMostRecentEventTime(), modifiers);
  503   
  504           // Process the listeners last to first, notifying
  505           // those that are interested in this event
  506           for (int i = listeners.length-2; i>=0; i-=2) {
  507               if (listeners[i]==ActionListener.class) {
  508                   ((ActionListener)listeners[i+1]).actionPerformed(e);
  509               }
  510           }
  511       }
  512   
  513       /**
  514        * Sets the command string used for action events.
  515        *
  516        * @param command the command string
  517        */
  518       public void setActionCommand(String command) {
  519           this.command = command;
  520       }
  521   
  522       private Action action;
  523       private PropertyChangeListener actionPropertyChangeListener;
  524   
  525       /**
  526        * Sets the <code>Action</code> for the <code>ActionEvent</code> source.
  527        * The new <code>Action</code> replaces
  528        * any previously set <code>Action</code> but does not affect
  529        * <code>ActionListeners</code> independently
  530        * added with <code>addActionListener</code>.
  531        * If the <code>Action</code> is already a registered
  532        * <code>ActionListener</code>
  533        * for the <code>ActionEvent</code> source, it is not re-registered.
  534        * <p>
  535        * Setting the <code>Action</code> results in immediately changing
  536        * all the properties described in <a href="Action.html#buttonActions">
  537        * Swing Components Supporting <code>Action</code></a>.
  538        * Subsequently, the textfield's properties are automatically updated
  539        * as the <code>Action</code>'s properties change.
  540        * <p>
  541        * This method uses three other methods to set
  542        * and help track the <code>Action</code>'s property values.
  543        * It uses the <code>configurePropertiesFromAction</code> method
  544        * to immediately change the textfield's properties.
  545        * To track changes in the <code>Action</code>'s property values,
  546        * this method registers the <code>PropertyChangeListener</code>
  547        * returned by <code>createActionPropertyChangeListener</code>. The
  548        * default {@code PropertyChangeListener} invokes the
  549        * {@code actionPropertyChanged} method when a property in the
  550        * {@code Action} changes.
  551        *
  552        * @param a the <code>Action</code> for the <code>JTextField</code>,
  553        *          or <code>null</code>
  554        * @since 1.3
  555        * @see Action
  556        * @see #getAction
  557        * @see #configurePropertiesFromAction
  558        * @see #createActionPropertyChangeListener
  559        * @see #actionPropertyChanged
  560        * @beaninfo
  561        *        bound: true
  562        *    attribute: visualUpdate true
  563        *  description: the Action instance connected with this ActionEvent source
  564        */
  565       public void setAction(Action a) {
  566           Action oldValue = getAction();
  567           if (action==null || !action.equals(a)) {
  568               action = a;
  569               if (oldValue!=null) {
  570                   removeActionListener(oldValue);
  571                   oldValue.removePropertyChangeListener(actionPropertyChangeListener);
  572                   actionPropertyChangeListener = null;
  573               }
  574               configurePropertiesFromAction(action);
  575               if (action!=null) {
  576                   // Don't add if it is already a listener
  577                   if (!isListener(ActionListener.class, action)) {
  578                       addActionListener(action);
  579                   }
  580                   // Reverse linkage:
  581                   actionPropertyChangeListener = createActionPropertyChangeListener(action);
  582                   action.addPropertyChangeListener(actionPropertyChangeListener);
  583               }
  584               firePropertyChange("action", oldValue, action);
  585           }
  586       }
  587   
  588       private boolean isListener(Class c, ActionListener a) {
  589           boolean isListener = false;
  590           Object[] listeners = listenerList.getListenerList();
  591           for (int i = listeners.length-2; i>=0; i-=2) {
  592               if (listeners[i]==c && listeners[i+1]==a) {
  593                       isListener=true;
  594               }
  595           }
  596           return isListener;
  597       }
  598   
  599       /**
  600        * Returns the currently set <code>Action</code> for this
  601        * <code>ActionEvent</code> source, or <code>null</code>
  602        * if no <code>Action</code> is set.
  603        *
  604        * @return the <code>Action</code> for this <code>ActionEvent</code> source,
  605        *          or <code>null</code>
  606        * @since 1.3
  607        * @see Action
  608        * @see #setAction
  609        */
  610       public Action getAction() {
  611           return action;
  612       }
  613   
  614       /**
  615        * Sets the properties on this textfield to match those in the specified
  616        * <code>Action</code>.  Refer to <a href="Action.html#buttonActions">
  617        * Swing Components Supporting <code>Action</code></a> for more
  618        * details as to which properties this sets.
  619        *
  620        * @param a the <code>Action</code> from which to get the properties,
  621        *          or <code>null</code>
  622        * @since 1.3
  623        * @see Action
  624        * @see #setAction
  625        */
  626       protected void configurePropertiesFromAction(Action a) {
  627           AbstractAction.setEnabledFromAction(this, a);
  628           AbstractAction.setToolTipTextFromAction(this, a);
  629           setActionCommandFromAction(a);
  630       }
  631   
  632       /**
  633        * Updates the textfield's state in response to property changes in
  634        * associated action. This method is invoked from the
  635        * {@code PropertyChangeListener} returned from
  636        * {@code createActionPropertyChangeListener}. Subclasses do not normally
  637        * need to invoke this. Subclasses that support additional {@code Action}
  638        * properties should override this and
  639        * {@code configurePropertiesFromAction}.
  640        * <p>
  641        * Refer to the table at <a href="Action.html#buttonActions">
  642        * Swing Components Supporting <code>Action</code></a> for a list of
  643        * the properties this method sets.
  644        *
  645        * @param action the <code>Action</code> associated with this textfield
  646        * @param propertyName the name of the property that changed
  647        * @since 1.6
  648        * @see Action
  649        * @see #configurePropertiesFromAction
  650        */
  651       protected void actionPropertyChanged(Action action, String propertyName) {
  652           if (propertyName == Action.ACTION_COMMAND_KEY) {
  653               setActionCommandFromAction(action);
  654           } else if (propertyName == "enabled") {
  655               AbstractAction.setEnabledFromAction(this, action);
  656           } else if (propertyName == Action.SHORT_DESCRIPTION) {
  657               AbstractAction.setToolTipTextFromAction(this, action);
  658           }
  659       }
  660   
  661       private void setActionCommandFromAction(Action action) {
  662           setActionCommand((action == null) ? null :
  663                            (String)action.getValue(Action.ACTION_COMMAND_KEY));
  664       }
  665   
  666       /**
  667        * Creates and returns a <code>PropertyChangeListener</code> that is
  668        * responsible for listening for changes from the specified
  669        * <code>Action</code> and updating the appropriate properties.
  670        * <p>
  671        * <b>Warning:</b> If you subclass this do not create an anonymous
  672        * inner class.  If you do the lifetime of the textfield will be tied to
  673        * that of the <code>Action</code>.
  674        *
  675        * @param a the textfield's action
  676        * @since 1.3
  677        * @see Action
  678        * @see #setAction
  679        */
  680       protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
  681           return new TextFieldActionPropertyChangeListener(this, a);
  682       }
  683   
  684       private static class TextFieldActionPropertyChangeListener extends
  685                            ActionPropertyChangeListener<JTextField> {
  686           TextFieldActionPropertyChangeListener(JTextField tf, Action a) {
  687               super(tf, a);
  688           }
  689   
  690           protected void actionPropertyChanged(JTextField textField,
  691                                                Action action,
  692                                                PropertyChangeEvent e) {
  693               if (AbstractAction.shouldReconfigure(e)) {
  694                   textField.configurePropertiesFromAction(action);
  695               } else {
  696                   textField.actionPropertyChanged(action, e.getPropertyName());
  697               }
  698           }
  699       }
  700   
  701       /**
  702        * Fetches the command list for the editor.  This is
  703        * the list of commands supported by the plugged-in UI
  704        * augmented by the collection of commands that the
  705        * editor itself supports.  These are useful for binding
  706        * to events, such as in a keymap.
  707        *
  708        * @return the command list
  709        */
  710       public Action[] getActions() {
  711           return TextAction.augmentList(super.getActions(), defaultActions);
  712       }
  713   
  714       /**
  715        * Processes action events occurring on this textfield by
  716        * dispatching them to any registered <code>ActionListener</code> objects.
  717        * This is normally called by the controller registered with
  718        * textfield.
  719        */
  720       public void postActionEvent() {
  721           fireActionPerformed();
  722       }
  723   
  724       // --- Scrolling support -----------------------------------
  725   
  726       /**
  727        * Gets the visibility of the text field.  This can
  728        * be adjusted to change the location of the visible
  729        * area if the size of the field is greater than
  730        * the area that was allocated to the field.
  731        *
  732        * <p>
  733        * The fields look-and-feel implementation manages
  734        * the values of the minimum, maximum, and extent
  735        * properties on the <code>BoundedRangeModel</code>.
  736        *
  737        * @return the visibility
  738        * @see BoundedRangeModel
  739        */
  740       public BoundedRangeModel getHorizontalVisibility() {
  741           return visibility;
  742       }
  743   
  744       /**
  745        * Gets the scroll offset, in pixels.
  746        *
  747        * @return the offset >= 0
  748        */
  749       public int getScrollOffset() {
  750           return visibility.getValue();
  751       }
  752   
  753       /**
  754        * Sets the scroll offset, in pixels.
  755        *
  756        * @param scrollOffset the offset >= 0
  757        */
  758       public void setScrollOffset(int scrollOffset) {
  759           visibility.setValue(scrollOffset);
  760       }
  761   
  762       /**
  763        * Scrolls the field left or right.
  764        *
  765        * @param r the region to scroll
  766        */
  767       public void scrollRectToVisible(Rectangle r) {
  768           // convert to coordinate system of the bounded range
  769           Insets i = getInsets();
  770           int x0 = r.x + visibility.getValue() - i.left;
  771           int x1 = x0 + r.width;
  772           if (x0 < visibility.getValue()) {
  773               // Scroll to the left
  774               visibility.setValue(x0);
  775           } else if(x1 > visibility.getValue() + visibility.getExtent()) {
  776               // Scroll to the right
  777               visibility.setValue(x1 - visibility.getExtent());
  778           }
  779       }
  780   
  781       /**
  782        * Returns true if the receiver has an <code>ActionListener</code>
  783        * installed.
  784        */
  785       boolean hasActionListener() {
  786           // Guaranteed to return a non-null array
  787           Object[] listeners = listenerList.getListenerList();
  788           // Process the listeners last to first, notifying
  789           // those that are interested in this event
  790           for (int i = listeners.length-2; i>=0; i-=2) {
  791               if (listeners[i]==ActionListener.class) {
  792                   return true;
  793               }
  794           }
  795           return false;
  796       }
  797   
  798       // --- variables -------------------------------------------
  799   
  800       /**
  801        * Name of the action to send notification that the
  802        * contents of the field have been accepted.  Typically
  803        * this is bound to a carriage-return.
  804        */
  805       public static final String notifyAction = "notify-field-accept";
  806   
  807       private BoundedRangeModel visibility;
  808       private int horizontalAlignment = LEADING;
  809       private int columns;
  810       private int columnWidth;
  811       private String command;
  812   
  813       private static final Action[] defaultActions = {
  814           new NotifyAction()
  815       };
  816   
  817       /**
  818        * @see #getUIClassID
  819        * @see #readObject
  820        */
  821       private static final String uiClassID = "TextFieldUI";
  822   
  823       // --- Action implementations -----------------------------------
  824   
  825       // Note that JFormattedTextField.CommitAction extends this
  826       static class NotifyAction extends TextAction {
  827   
  828           NotifyAction() {
  829               super(notifyAction);
  830           }
  831   
  832           public void actionPerformed(ActionEvent e) {
  833               JTextComponent target = getFocusedComponent();
  834               if (target instanceof JTextField) {
  835                   JTextField field = (JTextField) target;
  836                   field.postActionEvent();
  837               }
  838           }
  839   
  840           public boolean isEnabled() {
  841               JTextComponent target = getFocusedComponent();
  842               if (target instanceof JTextField) {
  843                   return ((JTextField)target).hasActionListener();
  844               }
  845               return false;
  846           }
  847       }
  848   
  849       class ScrollRepainter implements ChangeListener, Serializable {
  850   
  851           public void stateChanged(ChangeEvent e) {
  852               repaint();
  853           }
  854   
  855       }
  856   
  857   
  858       /**
  859        * See <code>readObject</code> and <code>writeObject</code> in
  860        * <code>JComponent</code> for more
  861        * information about serialization in Swing.
  862        */
  863       private void writeObject(ObjectOutputStream s) throws IOException {
  864           s.defaultWriteObject();
  865           if (getUIClassID().equals(uiClassID)) {
  866               byte count = JComponent.getWriteObjCounter(this);
  867               JComponent.setWriteObjCounter(this, --count);
  868               if (count == 0 && ui != null) {
  869                   ui.installUI(this);
  870               }
  871           }
  872       }
  873   
  874   
  875       /**
  876        * Returns a string representation of this <code>JTextField</code>.
  877        * This method is intended to be used only for debugging purposes,
  878        * and the content and format of the returned string may vary between
  879        * implementations. The returned string may be empty but may not
  880        * be <code>null</code>.
  881        *
  882        * @return  a string representation of this <code>JTextField</code>
  883        */
  884       protected String paramString() {
  885           String horizontalAlignmentString;
  886           if (horizontalAlignment == LEFT) {
  887               horizontalAlignmentString = "LEFT";
  888           } else if (horizontalAlignment == CENTER) {
  889               horizontalAlignmentString = "CENTER";
  890           } else if (horizontalAlignment == RIGHT) {
  891               horizontalAlignmentString = "RIGHT";
  892           } else if (horizontalAlignment == LEADING) {
  893               horizontalAlignmentString = "LEADING";
  894           } else if (horizontalAlignment == TRAILING) {
  895               horizontalAlignmentString = "TRAILING";
  896           } else horizontalAlignmentString = "";
  897           String commandString = (command != null ?
  898                                   command : "");
  899   
  900           return super.paramString() +
  901           ",columns=" + columns +
  902           ",columnWidth=" + columnWidth +
  903           ",command=" + commandString +
  904           ",horizontalAlignment=" + horizontalAlignmentString;
  905       }
  906   
  907   
  908   /////////////////
  909   // Accessibility support
  910   ////////////////
  911   
  912   
  913       /**
  914        * Gets the <code>AccessibleContext</code> associated with this
  915        * <code>JTextField</code>. For <code>JTextFields</code>,
  916        * the <code>AccessibleContext</code> takes the form of an
  917        * <code>AccessibleJTextField</code>.
  918        * A new <code>AccessibleJTextField</code> instance is created
  919        * if necessary.
  920        *
  921        * @return an <code>AccessibleJTextField</code> that serves as the
  922        *         <code>AccessibleContext</code> of this <code>JTextField</code>
  923        */
  924       public AccessibleContext getAccessibleContext() {
  925           if (accessibleContext == null) {
  926               accessibleContext = new AccessibleJTextField();
  927           }
  928           return accessibleContext;
  929       }
  930   
  931       /**
  932        * This class implements accessibility support for the
  933        * <code>JTextField</code> class.  It provides an implementation of the
  934        * Java Accessibility API appropriate to text field user-interface
  935        * elements.
  936        * <p>
  937        * <strong>Warning:</strong>
  938        * Serialized objects of this class will not be compatible with
  939        * future Swing releases. The current serialization support is
  940        * appropriate for short term storage or RMI between applications running
  941        * the same version of Swing.  As of 1.4, support for long term storage
  942        * of all JavaBeans<sup><font size="-2">TM</font></sup>
  943        * has been added to the <code>java.beans</code> package.
  944        * Please see {@link java.beans.XMLEncoder}.
  945        */
  946       protected class AccessibleJTextField extends AccessibleJTextComponent {
  947   
  948           /**
  949            * Gets the state set of this object.
  950            *
  951            * @return an instance of AccessibleStateSet describing the states
  952            * of the object
  953            * @see AccessibleState
  954            */
  955           public AccessibleStateSet getAccessibleStateSet() {
  956               AccessibleStateSet states = super.getAccessibleStateSet();
  957               states.add(AccessibleState.SINGLE_LINE);
  958               return states;
  959           }
  960       }
  961   }

Home » openjdk-7 » javax » swing » [javadoc | source]