< prev index next >

src/java.desktop/share/classes/javax/swing/JTextField.java

Print this page




  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://docs.oracle.com/javase/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 


 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&trade;
 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  * @since 1.2
 164  */
 165 @SuppressWarnings("serial") // Same-version serialization only
 166 public class JTextField extends JTextComponent implements SwingConstants {
 167 
 168     /**
 169      * Constructs a new <code>TextField</code>.  A default model is created,
 170      * the initial string is <code>null</code>,
 171      * and the number of columns is set to 0.
 172      */
 173     public JTextField() {
 174         this(null, null, 0);
 175     }
 176 
 177     /**
 178      * Constructs a new <code>TextField</code> initialized with the
 179      * specified text. A default model is created and the number of
 180      * columns is 0.
 181      *
 182      * @param text the text to be displayed, or <code>null</code>
 183      */
 184     public JTextField(String text) {
 185         this(null, text, 0);
 186     }
 187 
 188     /**
 189      * Constructs a new empty <code>TextField</code> with the specified
 190      * number of columns.
 191      * A default model is created and the initial string is set to
 192      * <code>null</code>.
 193      *
 194      * @param columns  the number of columns to use to calculate
 195      *   the preferred width; if columns is set to zero, the
 196      *   preferred width will be whatever naturally results from
 197      *   the component implementation
 198      */
 199     public JTextField(int columns) {
 200         this(null, null, columns);
 201     }
 202 
 203     /**
 204      * Constructs a new <code>TextField</code> initialized with the
 205      * specified text and columns.  A default model is created.
 206      *
 207      * @param text the text to be displayed, or <code>null</code>
 208      * @param columns  the number of columns to use to calculate
 209      *   the preferred width; if columns is set to zero, the
 210      *   preferred width will be whatever naturally results from
 211      *   the component implementation
 212      */
 213     public JTextField(String text, int columns) {
 214         this(null, text, columns);
 215     }
 216 
 217     /**
 218      * Constructs a new <code>JTextField</code> that uses the given text
 219      * storage model and the given number of columns.
 220      * This is the constructor through which the other constructors feed.
 221      * If the document is <code>null</code>, a default model is created.
 222      *
 223      * @param doc  the text storage to use; if this is <code>null</code>,
 224      *          a default will be provided by calling the
 225      *          <code>createDefaultModel</code> method
 226      * @param text  the initial string to display, or <code>null</code>
 227      * @param columns  the number of columns to use to calculate
 228      *   the preferred width &gt;= 0; if <code>columns</code>
 229      *   is set to zero, the preferred width will be whatever
 230      *   naturally results from the component implementation
 231      * @exception IllegalArgumentException if <code>columns</code> &lt; 0
 232      */
 233     public JTextField(Document doc, String text, int columns) {
 234         if (columns < 0) {
 235             throw new IllegalArgumentException("columns less than zero.");
 236         }
 237         visibility = new DefaultBoundedRangeModel();
 238         visibility.addChangeListener(new ScrollRepainter());
 239         this.columns = columns;
 240         if (doc == null) {
 241             doc = createDefaultModel();
 242         }
 243         setDocument(doc);
 244         if (text != null) {
 245             setText(text);
 246         }
 247     }
 248 
 249     /**
 250      * Gets the class ID for a UI.
 251      *


 262      * Associates the editor with a text document.
 263      * The currently registered factory is used to build a view for
 264      * the document, which gets displayed by the editor after revalidation.
 265      * A PropertyChange event ("document") is propagated to each listener.
 266      *
 267      * @param doc  the document to display/edit
 268      * @see #getDocument
 269      * @beaninfo
 270      *  description: the text document model
 271      *        bound: true
 272      *       expert: true
 273      */
 274     public void setDocument(Document doc) {
 275         if (doc != null) {
 276             doc.putProperty("filterNewlines", Boolean.TRUE);
 277         }
 278         super.setDocument(doc);
 279     }
 280 
 281     /**
 282      * Calls to <code>revalidate</code> that come from within the
 283      * textfield itself will
 284      * be handled by validating the textfield, unless the textfield
 285      * is contained within a <code>JViewport</code>,
 286      * in which case this returns false.
 287      *
 288      * @return if the parent of this textfield is a <code>JViewPort</code>
 289      *          return false, otherwise return true
 290      *
 291      * @see JComponent#revalidate
 292      * @see JComponent#isValidateRoot
 293      * @see java.awt.Container#isValidateRoot
 294      */
 295     @Override
 296     public boolean isValidateRoot() {
 297         return !(SwingUtilities.getUnwrappedParent(this) instanceof JViewport);
 298     }
 299 
 300 
 301     /**
 302      * Returns the horizontal alignment of the text.
 303      * Valid keys are:
 304      * <ul>
 305      * <li><code>JTextField.LEFT</code>
 306      * <li><code>JTextField.CENTER</code>
 307      * <li><code>JTextField.RIGHT</code>
 308      * <li><code>JTextField.LEADING</code>
 309      * <li><code>JTextField.TRAILING</code>
 310      * </ul>
 311      *
 312      * @return the horizontal alignment
 313      */
 314     public int getHorizontalAlignment() {
 315         return horizontalAlignment;
 316     }
 317 
 318     /**
 319      * Sets the horizontal alignment of the text.
 320      * Valid keys are:
 321      * <ul>
 322      * <li><code>JTextField.LEFT</code>
 323      * <li><code>JTextField.CENTER</code>
 324      * <li><code>JTextField.RIGHT</code>
 325      * <li><code>JTextField.LEADING</code>
 326      * <li><code>JTextField.TRAILING</code>
 327      * </ul>
 328      * <code>invalidate</code> and <code>repaint</code> are called when the
 329      * alignment is set,
 330      * and a <code>PropertyChange</code> event ("horizontalAlignment") is fired.
 331      *
 332      * @param alignment the alignment
 333      * @exception IllegalArgumentException if <code>alignment</code>
 334      *  is not a valid key
 335      * @beaninfo
 336      *   preferred: true
 337      *       bound: true
 338      * description: Set the field alignment to LEFT, CENTER, RIGHT,
 339      *              LEADING (the default) or TRAILING
 340      *        enum: LEFT JTextField.LEFT CENTER JTextField.CENTER RIGHT JTextField.RIGHT
 341      *              LEADING JTextField.LEADING TRAILING JTextField.TRAILING
 342      */
 343      public void setHorizontalAlignment(int alignment) {
 344         if (alignment == horizontalAlignment) return;
 345         int oldValue = horizontalAlignment;
 346         if ((alignment == LEFT) || (alignment == CENTER) ||
 347             (alignment == RIGHT)|| (alignment == LEADING) ||
 348             (alignment == TRAILING)) {
 349             horizontalAlignment = alignment;
 350         } else {
 351             throw new IllegalArgumentException("horizontalAlignment");
 352         }
 353         firePropertyChange("horizontalAlignment", oldValue, horizontalAlignment);
 354         invalidate();
 355         repaint();
 356     }
 357 
 358     /**
 359      * Creates the default implementation of the model
 360      * to be used at construction if one isn't explicitly
 361      * given.  An instance of <code>PlainDocument</code> is returned.
 362      *
 363      * @return the default model implementation
 364      */
 365     protected Document createDefaultModel() {
 366         return new PlainDocument();
 367     }
 368 
 369     /**
 370      * Returns the number of columns in this <code>TextField</code>.
 371      *
 372      * @return the number of columns &gt;= 0
 373      */
 374     public int getColumns() {
 375         return columns;
 376     }
 377 
 378     /**
 379      * Sets the number of columns in this <code>TextField</code>,
 380      * and then invalidate the layout.
 381      *
 382      * @param columns the number of columns &gt;= 0
 383      * @exception IllegalArgumentException if <code>columns</code>
 384      *          is less than 0
 385      * @beaninfo
 386      * description: the number of columns preferred for display
 387      */
 388     public void setColumns(int columns) {
 389         int oldVal = this.columns;
 390         if (columns < 0) {
 391             throw new IllegalArgumentException("columns less than zero.");
 392         }
 393         if (columns != oldVal) {
 394             this.columns = columns;
 395             invalidate();
 396         }
 397     }
 398 
 399     /**
 400      * Returns the column width.
 401      * The meaning of what a column is can be considered a fairly weak
 402      * notion for some fonts.  This method is used to define the width
 403      * of a column.  By default this is defined to be the width of the
 404      * character <em>m</em> for the font used.  This method can be
 405      * redefined to be some alternative amount
 406      *
 407      * @return the column width &gt;= 1
 408      */
 409     protected int getColumnWidth() {
 410         if (columnWidth == 0) {
 411             FontMetrics metrics = getFontMetrics(getFont());
 412             columnWidth = metrics.charWidth('m');
 413         }
 414         return columnWidth;
 415     }
 416 
 417     /**
 418      * Returns the preferred size <code>Dimensions</code> needed for this
 419      * <code>TextField</code>.  If a non-zero number of columns has been
 420      * set, the width is set to the columns multiplied by
 421      * the column width.
 422      *
 423      * @return the dimension of this textfield
 424      */
 425     public Dimension getPreferredSize() {
 426         Dimension size = super.getPreferredSize();
 427         if (columns != 0) {
 428             Insets insets = getInsets();
 429             size.width = columns * getColumnWidth() +
 430                 insets.left + insets.right;
 431         }
 432         return size;
 433     }
 434 
 435     /**
 436      * Sets the current font.  This removes cached row height and column
 437      * width so the new font will be reflected.
 438      * <code>revalidate</code> is called after setting the font.
 439      *
 440      * @param f the new font
 441      */
 442     public void setFont(Font f) {
 443         super.setFont(f);
 444         columnWidth = 0;
 445     }
 446 
 447     /**
 448      * Adds the specified action listener to receive
 449      * action events from this textfield.
 450      *
 451      * @param l the action listener to be added
 452      */
 453     public synchronized void addActionListener(ActionListener l) {
 454         listenerList.add(ActionListener.class, l);
 455     }
 456 
 457     /**
 458      * Removes the specified action listener so that it no longer
 459      * receives action events from this textfield.
 460      *
 461      * @param l the action listener to be removed
 462      */
 463     public synchronized void removeActionListener(ActionListener l) {
 464         if ((l != null) && (getAction() == l)) {
 465             setAction(null);
 466         } else {
 467             listenerList.remove(ActionListener.class, l);
 468         }
 469     }
 470 
 471     /**
 472      * Returns an array of all the <code>ActionListener</code>s added
 473      * to this JTextField with addActionListener().
 474      *
 475      * @return all of the <code>ActionListener</code>s added or an empty
 476      *         array if no listeners have been added
 477      * @since 1.4
 478      */
 479     public synchronized ActionListener[] getActionListeners() {
 480         return listenerList.getListeners(ActionListener.class);
 481     }
 482 
 483     /**
 484      * Notifies all listeners that have registered interest for
 485      * notification on this event type.  The event instance
 486      * is lazily created.
 487      * The listener list is processed in last to
 488      * first order.
 489      * @see EventListenerList
 490      */
 491     protected void fireActionPerformed() {
 492         // Guaranteed to return a non-null array
 493         Object[] listeners = listenerList.getListenerList();
 494         int modifiers = 0;
 495         AWTEvent currentEvent = EventQueue.getCurrentEvent();


 508         for (int i = listeners.length-2; i>=0; i-=2) {
 509             if (listeners[i]==ActionListener.class) {
 510                 ((ActionListener)listeners[i+1]).actionPerformed(e);
 511             }
 512         }
 513     }
 514 
 515     /**
 516      * Sets the command string used for action events.
 517      *
 518      * @param command the command string
 519      */
 520     public void setActionCommand(String command) {
 521         this.command = command;
 522     }
 523 
 524     private Action action;
 525     private PropertyChangeListener actionPropertyChangeListener;
 526 
 527     /**
 528      * Sets the <code>Action</code> for the <code>ActionEvent</code> source.
 529      * The new <code>Action</code> replaces
 530      * any previously set <code>Action</code> but does not affect
 531      * <code>ActionListeners</code> independently
 532      * added with <code>addActionListener</code>.
 533      * If the <code>Action</code> is already a registered
 534      * <code>ActionListener</code>
 535      * for the <code>ActionEvent</code> source, it is not re-registered.
 536      * <p>
 537      * Setting the <code>Action</code> results in immediately changing
 538      * all the properties described in <a href="Action.html#buttonActions">
 539      * Swing Components Supporting <code>Action</code></a>.
 540      * Subsequently, the textfield's properties are automatically updated
 541      * as the <code>Action</code>'s properties change.
 542      * <p>
 543      * This method uses three other methods to set
 544      * and help track the <code>Action</code>'s property values.
 545      * It uses the <code>configurePropertiesFromAction</code> method
 546      * to immediately change the textfield's properties.
 547      * To track changes in the <code>Action</code>'s property values,
 548      * this method registers the <code>PropertyChangeListener</code>
 549      * returned by <code>createActionPropertyChangeListener</code>. The
 550      * default {@code PropertyChangeListener} invokes the
 551      * {@code actionPropertyChanged} method when a property in the
 552      * {@code Action} changes.
 553      *
 554      * @param a the <code>Action</code> for the <code>JTextField</code>,
 555      *          or <code>null</code>
 556      * @since 1.3
 557      * @see Action
 558      * @see #getAction
 559      * @see #configurePropertiesFromAction
 560      * @see #createActionPropertyChangeListener
 561      * @see #actionPropertyChanged
 562      * @beaninfo
 563      *        bound: true
 564      *    attribute: visualUpdate true
 565      *  description: the Action instance connected with this ActionEvent source
 566      */
 567     public void setAction(Action a) {
 568         Action oldValue = getAction();
 569         if (action==null || !action.equals(a)) {
 570             action = a;
 571             if (oldValue!=null) {
 572                 removeActionListener(oldValue);
 573                 oldValue.removePropertyChangeListener(actionPropertyChangeListener);
 574                 actionPropertyChangeListener = null;
 575             }


 582                 // Reverse linkage:
 583                 actionPropertyChangeListener = createActionPropertyChangeListener(action);
 584                 action.addPropertyChangeListener(actionPropertyChangeListener);
 585             }
 586             firePropertyChange("action", oldValue, action);
 587         }
 588     }
 589 
 590     private boolean isListener(Class<?> c, ActionListener a) {
 591         boolean isListener = false;
 592         Object[] listeners = listenerList.getListenerList();
 593         for (int i = listeners.length-2; i>=0; i-=2) {
 594             if (listeners[i]==c && listeners[i+1]==a) {
 595                     isListener=true;
 596             }
 597         }
 598         return isListener;
 599     }
 600 
 601     /**
 602      * Returns the currently set <code>Action</code> for this
 603      * <code>ActionEvent</code> source, or <code>null</code>
 604      * if no <code>Action</code> is set.
 605      *
 606      * @return the <code>Action</code> for this <code>ActionEvent</code> source,
 607      *          or <code>null</code>
 608      * @since 1.3
 609      * @see Action
 610      * @see #setAction
 611      */
 612     public Action getAction() {
 613         return action;
 614     }
 615 
 616     /**
 617      * Sets the properties on this textfield to match those in the specified
 618      * <code>Action</code>.  Refer to <a href="Action.html#buttonActions">
 619      * Swing Components Supporting <code>Action</code></a> for more
 620      * details as to which properties this sets.
 621      *
 622      * @param a the <code>Action</code> from which to get the properties,
 623      *          or <code>null</code>
 624      * @since 1.3
 625      * @see Action
 626      * @see #setAction
 627      */
 628     protected void configurePropertiesFromAction(Action a) {
 629         AbstractAction.setEnabledFromAction(this, a);
 630         AbstractAction.setToolTipTextFromAction(this, a);
 631         setActionCommandFromAction(a);
 632     }
 633 
 634     /**
 635      * Updates the textfield's state in response to property changes in
 636      * associated action. This method is invoked from the
 637      * {@code PropertyChangeListener} returned from
 638      * {@code createActionPropertyChangeListener}. Subclasses do not normally
 639      * need to invoke this. Subclasses that support additional {@code Action}
 640      * properties should override this and
 641      * {@code configurePropertiesFromAction}.
 642      * <p>
 643      * Refer to the table at <a href="Action.html#buttonActions">
 644      * Swing Components Supporting <code>Action</code></a> for a list of
 645      * the properties this method sets.
 646      *
 647      * @param action the <code>Action</code> associated with this textfield
 648      * @param propertyName the name of the property that changed
 649      * @since 1.6
 650      * @see Action
 651      * @see #configurePropertiesFromAction
 652      */
 653     protected void actionPropertyChanged(Action action, String propertyName) {
 654         if (propertyName == Action.ACTION_COMMAND_KEY) {
 655             setActionCommandFromAction(action);
 656         } else if (propertyName == "enabled") {
 657             AbstractAction.setEnabledFromAction(this, action);
 658         } else if (propertyName == Action.SHORT_DESCRIPTION) {
 659             AbstractAction.setToolTipTextFromAction(this, action);
 660         }
 661     }
 662 
 663     private void setActionCommandFromAction(Action action) {
 664         setActionCommand((action == null) ? null :
 665                          (String)action.getValue(Action.ACTION_COMMAND_KEY));
 666     }
 667 
 668     /**
 669      * Creates and returns a <code>PropertyChangeListener</code> that is
 670      * responsible for listening for changes from the specified
 671      * <code>Action</code> and updating the appropriate properties.
 672      * <p>
 673      * <b>Warning:</b> If you subclass this do not create an anonymous
 674      * inner class.  If you do the lifetime of the textfield will be tied to
 675      * that of the <code>Action</code>.
 676      *
 677      * @param a the textfield's action
 678      * @return a {@code PropertyChangeListener} that is responsible for
 679      *         listening for changes from the specified {@code Action} and
 680      *         updating the appropriate properties
 681      * @since 1.3
 682      * @see Action
 683      * @see #setAction
 684      */
 685     protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
 686         return new TextFieldActionPropertyChangeListener(this, a);
 687     }
 688 
 689     private static class TextFieldActionPropertyChangeListener extends
 690                          ActionPropertyChangeListener<JTextField> {
 691         TextFieldActionPropertyChangeListener(JTextField tf, Action a) {
 692             super(tf, a);
 693         }
 694 
 695         protected void actionPropertyChanged(JTextField textField,


 701                 textField.actionPropertyChanged(action, e.getPropertyName());
 702             }
 703         }
 704     }
 705 
 706     /**
 707      * Fetches the command list for the editor.  This is
 708      * the list of commands supported by the plugged-in UI
 709      * augmented by the collection of commands that the
 710      * editor itself supports.  These are useful for binding
 711      * to events, such as in a keymap.
 712      *
 713      * @return the command list
 714      */
 715     public Action[] getActions() {
 716         return TextAction.augmentList(super.getActions(), defaultActions);
 717     }
 718 
 719     /**
 720      * Processes action events occurring on this textfield by
 721      * dispatching them to any registered <code>ActionListener</code> objects.
 722      * This is normally called by the controller registered with
 723      * textfield.
 724      */
 725     public void postActionEvent() {
 726         fireActionPerformed();
 727     }
 728 
 729     // --- Scrolling support -----------------------------------
 730 
 731     /**
 732      * Gets the visibility of the text field.  This can
 733      * be adjusted to change the location of the visible
 734      * area if the size of the field is greater than
 735      * the area that was allocated to the field.
 736      *
 737      * <p>
 738      * The fields look-and-feel implementation manages
 739      * the values of the minimum, maximum, and extent
 740      * properties on the <code>BoundedRangeModel</code>.
 741      *
 742      * @return the visibility
 743      * @see BoundedRangeModel
 744      */
 745     public BoundedRangeModel getHorizontalVisibility() {
 746         return visibility;
 747     }
 748 
 749     /**
 750      * Gets the scroll offset, in pixels.
 751      *
 752      * @return the offset &gt;= 0
 753      */
 754     public int getScrollOffset() {
 755         return visibility.getValue();
 756     }
 757 
 758     /**
 759      * Sets the scroll offset, in pixels.
 760      *


 767     /**
 768      * Scrolls the field left or right.
 769      *
 770      * @param r the region to scroll
 771      */
 772     public void scrollRectToVisible(Rectangle r) {
 773         // convert to coordinate system of the bounded range
 774         Insets i = getInsets();
 775         int x0 = r.x + visibility.getValue() - i.left;
 776         int x1 = x0 + r.width;
 777         if (x0 < visibility.getValue()) {
 778             // Scroll to the left
 779             visibility.setValue(x0);
 780         } else if(x1 > visibility.getValue() + visibility.getExtent()) {
 781             // Scroll to the right
 782             visibility.setValue(x1 - visibility.getExtent());
 783         }
 784     }
 785 
 786     /**
 787      * Returns true if the receiver has an <code>ActionListener</code>
 788      * installed.
 789      */
 790     boolean hasActionListener() {
 791         // Guaranteed to return a non-null array
 792         Object[] listeners = listenerList.getListenerList();
 793         // Process the listeners last to first, notifying
 794         // those that are interested in this event
 795         for (int i = listeners.length-2; i>=0; i-=2) {
 796             if (listeners[i]==ActionListener.class) {
 797                 return true;
 798             }
 799         }
 800         return false;
 801     }
 802 
 803     // --- variables -------------------------------------------
 804 
 805     /**
 806      * Name of the action to send notification that the
 807      * contents of the field have been accepted.  Typically


 844 
 845         public boolean isEnabled() {
 846             JTextComponent target = getFocusedComponent();
 847             if (target instanceof JTextField) {
 848                 return ((JTextField)target).hasActionListener();
 849             }
 850             return false;
 851         }
 852     }
 853 
 854     class ScrollRepainter implements ChangeListener, Serializable {
 855 
 856         public void stateChanged(ChangeEvent e) {
 857             repaint();
 858         }
 859 
 860     }
 861 
 862 
 863     /**
 864      * See <code>readObject</code> and <code>writeObject</code> in
 865      * <code>JComponent</code> for more
 866      * information about serialization in Swing.
 867      */
 868     private void writeObject(ObjectOutputStream s) throws IOException {
 869         s.defaultWriteObject();
 870         if (getUIClassID().equals(uiClassID)) {
 871             byte count = JComponent.getWriteObjCounter(this);
 872             JComponent.setWriteObjCounter(this, --count);
 873             if (count == 0 && ui != null) {
 874                 ui.installUI(this);
 875             }
 876         }
 877     }
 878 
 879 
 880     /**
 881      * Returns a string representation of this <code>JTextField</code>.
 882      * This method is intended to be used only for debugging purposes,
 883      * and the content and format of the returned string may vary between
 884      * implementations. The returned string may be empty but may not
 885      * be <code>null</code>.
 886      *
 887      * @return  a string representation of this <code>JTextField</code>
 888      */
 889     protected String paramString() {
 890         String horizontalAlignmentString;
 891         if (horizontalAlignment == LEFT) {
 892             horizontalAlignmentString = "LEFT";
 893         } else if (horizontalAlignment == CENTER) {
 894             horizontalAlignmentString = "CENTER";
 895         } else if (horizontalAlignment == RIGHT) {
 896             horizontalAlignmentString = "RIGHT";
 897         } else if (horizontalAlignment == LEADING) {
 898             horizontalAlignmentString = "LEADING";
 899         } else if (horizontalAlignment == TRAILING) {
 900             horizontalAlignmentString = "TRAILING";
 901         } else horizontalAlignmentString = "";
 902         String commandString = (command != null ?
 903                                 command : "");
 904 
 905         return super.paramString() +
 906         ",columns=" + columns +
 907         ",columnWidth=" + columnWidth +
 908         ",command=" + commandString +
 909         ",horizontalAlignment=" + horizontalAlignmentString;
 910     }
 911 
 912 
 913 /////////////////
 914 // Accessibility support
 915 ////////////////
 916 
 917 
 918     /**
 919      * Gets the <code>AccessibleContext</code> associated with this
 920      * <code>JTextField</code>. For <code>JTextFields</code>,
 921      * the <code>AccessibleContext</code> takes the form of an
 922      * <code>AccessibleJTextField</code>.
 923      * A new <code>AccessibleJTextField</code> instance is created
 924      * if necessary.
 925      *
 926      * @return an <code>AccessibleJTextField</code> that serves as the
 927      *         <code>AccessibleContext</code> of this <code>JTextField</code>
 928      */
 929     public AccessibleContext getAccessibleContext() {
 930         if (accessibleContext == null) {
 931             accessibleContext = new AccessibleJTextField();
 932         }
 933         return accessibleContext;
 934     }
 935 
 936     /**
 937      * This class implements accessibility support for the
 938      * <code>JTextField</code> class.  It provides an implementation of the
 939      * Java Accessibility API appropriate to text field user-interface
 940      * elements.
 941      * <p>
 942      * <strong>Warning:</strong>
 943      * Serialized objects of this class will not be compatible with
 944      * future Swing releases. The current serialization support is
 945      * appropriate for short term storage or RMI between applications running
 946      * the same version of Swing.  As of 1.4, support for long term storage
 947      * of all JavaBeans&trade;
 948      * has been added to the <code>java.beans</code> package.
 949      * Please see {@link java.beans.XMLEncoder}.
 950      */
 951     @SuppressWarnings("serial") // Same-version serialization only
 952     protected class AccessibleJTextField extends AccessibleJTextComponent {
 953 
 954         /**
 955          * Gets the state set of this object.
 956          *
 957          * @return an instance of AccessibleStateSet describing the states
 958          * of the object
 959          * @see AccessibleState
 960          */
 961         public AccessibleStateSet getAccessibleStateSet() {
 962             AccessibleStateSet states = super.getAccessibleStateSet();
 963             states.add(AccessibleState.SINGLE_LINE);
 964             return states;
 965         }
 966     }
 967 }


  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} 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://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html">How to Use Text Fields</a>
  48  * in <em>The Java Tutorial.</em>
  49  *
  50  * <p>
  51  * {@code JTextField} is intended to be source-compatible
  52  * with {@code java.awt.TextField} where it is reasonable to do so.  This
  53  * component has capabilities not found in the {@code java.awt.TextField}
  54  * class.  The superclass should be consulted for additional capabilities.
  55  * <p>
  56  * {@code JTextField} 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} used the text of the field as the command
  59  * string for the {@code ActionEvent}.
  60  * {@code JTextField} will use the command
  61  * string set with the {@code setActionCommand} method if not {@code null},
  62  * otherwise it will use the text of the field as a compatibility with
  63  * {@code java.awt.TextField}.
  64  * <p>
  65  * The method {@code setEchoChar} and {@code getEchoChar}
  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}
  69  * extends {@code JTextField} to provide this service with an independently
  70  * pluggable look-and-feel.
  71  * <p>
  72  * The {@code java.awt.TextField} could be monitored for changes by adding
  73  * a {@code TextListener} for {@code TextEvent}'s.
  74  * In the {@code JTextComponent} based
  75  * components, changes are broadcasted from the model via a
  76  * {@code DocumentEvent} to {@code DocumentListeners}.
  77  * The {@code DocumentEvent} 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} 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}
  91  * and {@code getHorizontalAlignment} 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 


 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&trade;
 152  * has been added to the {@code java.beans} 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  * @since 1.2
 164  */
 165 @SuppressWarnings("serial") // Same-version serialization only
 166 public class JTextField extends JTextComponent implements SwingConstants {
 167 
 168     /**
 169      * Constructs a new {@code TextField}.  A default model is created,
 170      * the initial string is {@code null},
 171      * and the number of columns is set to 0.
 172      */
 173     public JTextField() {
 174         this(null, null, 0);
 175     }
 176 
 177     /**
 178      * Constructs a new {@code TextField} initialized with the
 179      * specified text. A default model is created and the number of
 180      * columns is 0.
 181      *
 182      * @param text the text to be displayed, or {@code null}
 183      */
 184     public JTextField(String text) {
 185         this(null, text, 0);
 186     }
 187 
 188     /**
 189      * Constructs a new empty {@code TextField} with the specified
 190      * number of columns.
 191      * A default model is created and the initial string is set to
 192      * {@code null}.
 193      *
 194      * @param columns  the number of columns to use to calculate
 195      *   the preferred width; if columns is set to zero, the
 196      *   preferred width will be whatever naturally results from
 197      *   the component implementation
 198      */
 199     public JTextField(int columns) {
 200         this(null, null, columns);
 201     }
 202 
 203     /**
 204      * Constructs a new {@code TextField} initialized with the
 205      * specified text and columns.  A default model is created.
 206      *
 207      * @param text the text to be displayed, or {@code null}
 208      * @param columns  the number of columns to use to calculate
 209      *   the preferred width; if columns is set to zero, the
 210      *   preferred width will be whatever naturally results from
 211      *   the component implementation
 212      */
 213     public JTextField(String text, int columns) {
 214         this(null, text, columns);
 215     }
 216 
 217     /**
 218      * Constructs a new {@code JTextField} that uses the given text
 219      * storage model and the given number of columns.
 220      * This is the constructor through which the other constructors feed.
 221      * If the document is {@code null}, a default model is created.
 222      *
 223      * @param doc  the text storage to use; if this is {@code null},
 224      *          a default will be provided by calling the
 225      *          {@code createDefaultModel} method
 226      * @param text  the initial string to display, or {@code null}
 227      * @param columns  the number of columns to use to calculate
 228      *   the preferred width &gt;= 0; if {@code columns}
 229      *   is set to zero, the preferred width will be whatever
 230      *   naturally results from the component implementation
 231      * @exception IllegalArgumentException if {@code columns < 0}
 232      */
 233     public JTextField(Document doc, String text, int columns) {
 234         if (columns < 0) {
 235             throw new IllegalArgumentException("columns less than zero.");
 236         }
 237         visibility = new DefaultBoundedRangeModel();
 238         visibility.addChangeListener(new ScrollRepainter());
 239         this.columns = columns;
 240         if (doc == null) {
 241             doc = createDefaultModel();
 242         }
 243         setDocument(doc);
 244         if (text != null) {
 245             setText(text);
 246         }
 247     }
 248 
 249     /**
 250      * Gets the class ID for a UI.
 251      *


 262      * Associates the editor with a text document.
 263      * The currently registered factory is used to build a view for
 264      * the document, which gets displayed by the editor after revalidation.
 265      * A PropertyChange event ("document") is propagated to each listener.
 266      *
 267      * @param doc  the document to display/edit
 268      * @see #getDocument
 269      * @beaninfo
 270      *  description: the text document model
 271      *        bound: true
 272      *       expert: true
 273      */
 274     public void setDocument(Document doc) {
 275         if (doc != null) {
 276             doc.putProperty("filterNewlines", Boolean.TRUE);
 277         }
 278         super.setDocument(doc);
 279     }
 280 
 281     /**
 282      * Calls to {@code revalidate} that come from within the
 283      * textfield itself will
 284      * be handled by validating the textfield, unless the textfield
 285      * is contained within a {@code JViewport},
 286      * in which case this returns false.
 287      *
 288      * @return if the parent of this textfield is a {@code JViewPort}
 289      *          return false, otherwise return true
 290      *
 291      * @see JComponent#revalidate
 292      * @see JComponent#isValidateRoot
 293      * @see java.awt.Container#isValidateRoot
 294      */
 295     @Override
 296     public boolean isValidateRoot() {
 297         return !(SwingUtilities.getUnwrappedParent(this) instanceof JViewport);
 298     }
 299 
 300 
 301     /**
 302      * Returns the horizontal alignment of the text.
 303      * Valid keys are:
 304      * <ul>
 305      * <li>{@code JTextField.LEFT}
 306      * <li>{@code JTextField.CENTER}
 307      * <li>{@code JTextField.RIGHT}
 308      * <li>{@code JTextField.LEADING}
 309      * <li>{@code JTextField.TRAILING}
 310      * </ul>
 311      *
 312      * @return the horizontal alignment
 313      */
 314     public int getHorizontalAlignment() {
 315         return horizontalAlignment;
 316     }
 317 
 318     /**
 319      * Sets the horizontal alignment of the text.
 320      * Valid keys are:
 321      * <ul>
 322      * <li>{@code JTextField.LEFT}
 323      * <li>{@code JTextField.CENTER}
 324      * <li>{@code JTextField.RIGHT}
 325      * <li>{@code JTextField.LEADING}
 326      * <li>{@code JTextField.TRAILING}
 327      * </ul>
 328      * {@code invalidate} and {@code repaint} are called when the
 329      * alignment is set,
 330      * and a {@code PropertyChange} event ("horizontalAlignment") is fired.
 331      *
 332      * @param alignment the alignment
 333      * @exception IllegalArgumentException if {@code alignment}
 334      *  is not a valid key
 335      * @beaninfo
 336      *   preferred: true
 337      *       bound: true
 338      * description: Set the field alignment to LEFT, CENTER, RIGHT,
 339      *              LEADING (the default) or TRAILING
 340      *        enum: LEFT JTextField.LEFT CENTER JTextField.CENTER RIGHT JTextField.RIGHT
 341      *              LEADING JTextField.LEADING TRAILING JTextField.TRAILING
 342      */
 343      public void setHorizontalAlignment(int alignment) {
 344         if (alignment == horizontalAlignment) return;
 345         int oldValue = horizontalAlignment;
 346         if ((alignment == LEFT) || (alignment == CENTER) ||
 347             (alignment == RIGHT)|| (alignment == LEADING) ||
 348             (alignment == TRAILING)) {
 349             horizontalAlignment = alignment;
 350         } else {
 351             throw new IllegalArgumentException("horizontalAlignment");
 352         }
 353         firePropertyChange("horizontalAlignment", oldValue, horizontalAlignment);
 354         invalidate();
 355         repaint();
 356     }
 357 
 358     /**
 359      * Creates the default implementation of the model
 360      * to be used at construction if one isn't explicitly
 361      * given.  An instance of {@code PlainDocument} is returned.
 362      *
 363      * @return the default model implementation
 364      */
 365     protected Document createDefaultModel() {
 366         return new PlainDocument();
 367     }
 368 
 369     /**
 370      * Returns the number of columns in this {@code TextField}.
 371      *
 372      * @return the number of columns &gt;= 0
 373      */
 374     public int getColumns() {
 375         return columns;
 376     }
 377 
 378     /**
 379      * Sets the number of columns in this {@code TextField},
 380      * and then invalidate the layout.
 381      *
 382      * @param columns the number of columns &gt;= 0
 383      * @exception IllegalArgumentException if {@code columns}
 384      *          is less than 0
 385      * @beaninfo
 386      * description: the number of columns preferred for display
 387      */
 388     public void setColumns(int columns) {
 389         int oldVal = this.columns;
 390         if (columns < 0) {
 391             throw new IllegalArgumentException("columns less than zero.");
 392         }
 393         if (columns != oldVal) {
 394             this.columns = columns;
 395             invalidate();
 396         }
 397     }
 398 
 399     /**
 400      * Returns the column width.
 401      * The meaning of what a column is can be considered a fairly weak
 402      * notion for some fonts.  This method is used to define the width
 403      * of a column.  By default this is defined to be the width of the
 404      * character <em>m</em> for the font used.  This method can be
 405      * redefined to be some alternative amount
 406      *
 407      * @return the column width &gt;= 1
 408      */
 409     protected int getColumnWidth() {
 410         if (columnWidth == 0) {
 411             FontMetrics metrics = getFontMetrics(getFont());
 412             columnWidth = metrics.charWidth('m');
 413         }
 414         return columnWidth;
 415     }
 416 
 417     /**
 418      * Returns the preferred size {@code Dimensions} needed for this
 419      * {@code TextField}.  If a non-zero number of columns has been
 420      * set, the width is set to the columns multiplied by
 421      * the column width.
 422      *
 423      * @return the dimension of this textfield
 424      */
 425     public Dimension getPreferredSize() {
 426         Dimension size = super.getPreferredSize();
 427         if (columns != 0) {
 428             Insets insets = getInsets();
 429             size.width = columns * getColumnWidth() +
 430                 insets.left + insets.right;
 431         }
 432         return size;
 433     }
 434 
 435     /**
 436      * Sets the current font.  This removes cached row height and column
 437      * width so the new font will be reflected.
 438      * {@code revalidate} is called after setting the font.
 439      *
 440      * @param f the new font
 441      */
 442     public void setFont(Font f) {
 443         super.setFont(f);
 444         columnWidth = 0;
 445     }
 446 
 447     /**
 448      * Adds the specified action listener to receive
 449      * action events from this textfield.
 450      *
 451      * @param l the action listener to be added
 452      */
 453     public synchronized void addActionListener(ActionListener l) {
 454         listenerList.add(ActionListener.class, l);
 455     }
 456 
 457     /**
 458      * Removes the specified action listener so that it no longer
 459      * receives action events from this textfield.
 460      *
 461      * @param l the action listener to be removed
 462      */
 463     public synchronized void removeActionListener(ActionListener l) {
 464         if ((l != null) && (getAction() == l)) {
 465             setAction(null);
 466         } else {
 467             listenerList.remove(ActionListener.class, l);
 468         }
 469     }
 470 
 471     /**
 472      * Returns an array of all the {@code ActionListener}s added
 473      * to this JTextField with addActionListener().
 474      *
 475      * @return all of the {@code ActionListener}s added or an empty
 476      *         array if no listeners have been added
 477      * @since 1.4
 478      */
 479     public synchronized ActionListener[] getActionListeners() {
 480         return listenerList.getListeners(ActionListener.class);
 481     }
 482 
 483     /**
 484      * Notifies all listeners that have registered interest for
 485      * notification on this event type.  The event instance
 486      * is lazily created.
 487      * The listener list is processed in last to
 488      * first order.
 489      * @see EventListenerList
 490      */
 491     protected void fireActionPerformed() {
 492         // Guaranteed to return a non-null array
 493         Object[] listeners = listenerList.getListenerList();
 494         int modifiers = 0;
 495         AWTEvent currentEvent = EventQueue.getCurrentEvent();


 508         for (int i = listeners.length-2; i>=0; i-=2) {
 509             if (listeners[i]==ActionListener.class) {
 510                 ((ActionListener)listeners[i+1]).actionPerformed(e);
 511             }
 512         }
 513     }
 514 
 515     /**
 516      * Sets the command string used for action events.
 517      *
 518      * @param command the command string
 519      */
 520     public void setActionCommand(String command) {
 521         this.command = command;
 522     }
 523 
 524     private Action action;
 525     private PropertyChangeListener actionPropertyChangeListener;
 526 
 527     /**
 528      * Sets the {@code Action} for the {@code ActionEvent} source.
 529      * The new {@code Action} replaces
 530      * any previously set {@code Action} but does not affect
 531      * {@code ActionListeners} independently
 532      * added with {@code addActionListener}.
 533      * If the {@code Action} is already a registered
 534      * {@code ActionListener}
 535      * for the {@code ActionEvent} source, it is not re-registered.
 536      * <p>
 537      * Setting the {@code Action} results in immediately changing
 538      * all the properties described in <a href="Action.html#buttonActions">
 539      * Swing Components Supporting {@code Action}</a>.
 540      * Subsequently, the textfield's properties are automatically updated
 541      * as the {@code Action}'s properties change.
 542      * <p>
 543      * This method uses three other methods to set
 544      * and help track the {@code Action}'s property values.
 545      * It uses the {@code configurePropertiesFromAction} method
 546      * to immediately change the textfield's properties.
 547      * To track changes in the {@code Action}'s property values,
 548      * this method registers the {@code PropertyChangeListener}
 549      * returned by {@code createActionPropertyChangeListener}. The
 550      * default {@code PropertyChangeListener} invokes the
 551      * {@code actionPropertyChanged} method when a property in the
 552      * {@code Action} changes.
 553      *
 554      * @param a the {@code Action} for the {@code JTextField},
 555      *          or {@code null}
 556      * @since 1.3
 557      * @see Action
 558      * @see #getAction
 559      * @see #configurePropertiesFromAction
 560      * @see #createActionPropertyChangeListener
 561      * @see #actionPropertyChanged
 562      * @beaninfo
 563      *        bound: true
 564      *    attribute: visualUpdate true
 565      *  description: the Action instance connected with this ActionEvent source
 566      */
 567     public void setAction(Action a) {
 568         Action oldValue = getAction();
 569         if (action==null || !action.equals(a)) {
 570             action = a;
 571             if (oldValue!=null) {
 572                 removeActionListener(oldValue);
 573                 oldValue.removePropertyChangeListener(actionPropertyChangeListener);
 574                 actionPropertyChangeListener = null;
 575             }


 582                 // Reverse linkage:
 583                 actionPropertyChangeListener = createActionPropertyChangeListener(action);
 584                 action.addPropertyChangeListener(actionPropertyChangeListener);
 585             }
 586             firePropertyChange("action", oldValue, action);
 587         }
 588     }
 589 
 590     private boolean isListener(Class<?> c, ActionListener a) {
 591         boolean isListener = false;
 592         Object[] listeners = listenerList.getListenerList();
 593         for (int i = listeners.length-2; i>=0; i-=2) {
 594             if (listeners[i]==c && listeners[i+1]==a) {
 595                     isListener=true;
 596             }
 597         }
 598         return isListener;
 599     }
 600 
 601     /**
 602      * Returns the currently set {@code Action} for this
 603      * {@code ActionEvent} source, or {@code null}
 604      * if no {@code Action} is set.
 605      *
 606      * @return the {@code Action} for this {@code ActionEvent} source,
 607      *          or {@code null}
 608      * @since 1.3
 609      * @see Action
 610      * @see #setAction
 611      */
 612     public Action getAction() {
 613         return action;
 614     }
 615 
 616     /**
 617      * Sets the properties on this textfield to match those in the specified
 618      * {@code Action}.  Refer to <a href="Action.html#buttonActions">
 619      * Swing Components Supporting {@code Action}</a> for more
 620      * details as to which properties this sets.
 621      *
 622      * @param a the {@code Action} from which to get the properties,
 623      *          or {@code null}
 624      * @since 1.3
 625      * @see Action
 626      * @see #setAction
 627      */
 628     protected void configurePropertiesFromAction(Action a) {
 629         AbstractAction.setEnabledFromAction(this, a);
 630         AbstractAction.setToolTipTextFromAction(this, a);
 631         setActionCommandFromAction(a);
 632     }
 633 
 634     /**
 635      * Updates the textfield's state in response to property changes in
 636      * associated action. This method is invoked from the
 637      * {@code PropertyChangeListener} returned from
 638      * {@code createActionPropertyChangeListener}. Subclasses do not normally
 639      * need to invoke this. Subclasses that support additional {@code Action}
 640      * properties should override this and
 641      * {@code configurePropertiesFromAction}.
 642      * <p>
 643      * Refer to the table at <a href="Action.html#buttonActions">
 644      * Swing Components Supporting {@code Action}</a> for a list of
 645      * the properties this method sets.
 646      *
 647      * @param action the {@code Action} associated with this textfield
 648      * @param propertyName the name of the property that changed
 649      * @since 1.6
 650      * @see Action
 651      * @see #configurePropertiesFromAction
 652      */
 653     protected void actionPropertyChanged(Action action, String propertyName) {
 654         if (propertyName == Action.ACTION_COMMAND_KEY) {
 655             setActionCommandFromAction(action);
 656         } else if (propertyName == "enabled") {
 657             AbstractAction.setEnabledFromAction(this, action);
 658         } else if (propertyName == Action.SHORT_DESCRIPTION) {
 659             AbstractAction.setToolTipTextFromAction(this, action);
 660         }
 661     }
 662 
 663     private void setActionCommandFromAction(Action action) {
 664         setActionCommand((action == null) ? null :
 665                          (String)action.getValue(Action.ACTION_COMMAND_KEY));
 666     }
 667 
 668     /**
 669      * Creates and returns a {@code PropertyChangeListener} that is
 670      * responsible for listening for changes from the specified
 671      * {@code Action} and updating the appropriate properties.
 672      * <p>
 673      * <b>Warning:</b> If you subclass this do not create an anonymous
 674      * inner class.  If you do the lifetime of the textfield will be tied to
 675      * that of the {@code Action}.
 676      *
 677      * @param a the textfield's action
 678      * @return a {@code PropertyChangeListener} that is responsible for
 679      *         listening for changes from the specified {@code Action} and
 680      *         updating the appropriate properties
 681      * @since 1.3
 682      * @see Action
 683      * @see #setAction
 684      */
 685     protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
 686         return new TextFieldActionPropertyChangeListener(this, a);
 687     }
 688 
 689     private static class TextFieldActionPropertyChangeListener extends
 690                          ActionPropertyChangeListener<JTextField> {
 691         TextFieldActionPropertyChangeListener(JTextField tf, Action a) {
 692             super(tf, a);
 693         }
 694 
 695         protected void actionPropertyChanged(JTextField textField,


 701                 textField.actionPropertyChanged(action, e.getPropertyName());
 702             }
 703         }
 704     }
 705 
 706     /**
 707      * Fetches the command list for the editor.  This is
 708      * the list of commands supported by the plugged-in UI
 709      * augmented by the collection of commands that the
 710      * editor itself supports.  These are useful for binding
 711      * to events, such as in a keymap.
 712      *
 713      * @return the command list
 714      */
 715     public Action[] getActions() {
 716         return TextAction.augmentList(super.getActions(), defaultActions);
 717     }
 718 
 719     /**
 720      * Processes action events occurring on this textfield by
 721      * dispatching them to any registered {@code ActionListener} objects.
 722      * This is normally called by the controller registered with
 723      * textfield.
 724      */
 725     public void postActionEvent() {
 726         fireActionPerformed();
 727     }
 728 
 729     // --- Scrolling support -----------------------------------
 730 
 731     /**
 732      * Gets the visibility of the text field.  This can
 733      * be adjusted to change the location of the visible
 734      * area if the size of the field is greater than
 735      * the area that was allocated to the field.
 736      *
 737      * <p>
 738      * The fields look-and-feel implementation manages
 739      * the values of the minimum, maximum, and extent
 740      * properties on the {@code BoundedRangeModel}.
 741      *
 742      * @return the visibility
 743      * @see BoundedRangeModel
 744      */
 745     public BoundedRangeModel getHorizontalVisibility() {
 746         return visibility;
 747     }
 748 
 749     /**
 750      * Gets the scroll offset, in pixels.
 751      *
 752      * @return the offset &gt;= 0
 753      */
 754     public int getScrollOffset() {
 755         return visibility.getValue();
 756     }
 757 
 758     /**
 759      * Sets the scroll offset, in pixels.
 760      *


 767     /**
 768      * Scrolls the field left or right.
 769      *
 770      * @param r the region to scroll
 771      */
 772     public void scrollRectToVisible(Rectangle r) {
 773         // convert to coordinate system of the bounded range
 774         Insets i = getInsets();
 775         int x0 = r.x + visibility.getValue() - i.left;
 776         int x1 = x0 + r.width;
 777         if (x0 < visibility.getValue()) {
 778             // Scroll to the left
 779             visibility.setValue(x0);
 780         } else if(x1 > visibility.getValue() + visibility.getExtent()) {
 781             // Scroll to the right
 782             visibility.setValue(x1 - visibility.getExtent());
 783         }
 784     }
 785 
 786     /**
 787      * Returns true if the receiver has an {@code ActionListener}
 788      * installed.
 789      */
 790     boolean hasActionListener() {
 791         // Guaranteed to return a non-null array
 792         Object[] listeners = listenerList.getListenerList();
 793         // Process the listeners last to first, notifying
 794         // those that are interested in this event
 795         for (int i = listeners.length-2; i>=0; i-=2) {
 796             if (listeners[i]==ActionListener.class) {
 797                 return true;
 798             }
 799         }
 800         return false;
 801     }
 802 
 803     // --- variables -------------------------------------------
 804 
 805     /**
 806      * Name of the action to send notification that the
 807      * contents of the field have been accepted.  Typically


 844 
 845         public boolean isEnabled() {
 846             JTextComponent target = getFocusedComponent();
 847             if (target instanceof JTextField) {
 848                 return ((JTextField)target).hasActionListener();
 849             }
 850             return false;
 851         }
 852     }
 853 
 854     class ScrollRepainter implements ChangeListener, Serializable {
 855 
 856         public void stateChanged(ChangeEvent e) {
 857             repaint();
 858         }
 859 
 860     }
 861 
 862 
 863     /**
 864      * See {@code readObject} and {@code writeObject} in
 865      * {@code JComponent} for more
 866      * information about serialization in Swing.
 867      */
 868     private void writeObject(ObjectOutputStream s) throws IOException {
 869         s.defaultWriteObject();
 870         if (getUIClassID().equals(uiClassID)) {
 871             byte count = JComponent.getWriteObjCounter(this);
 872             JComponent.setWriteObjCounter(this, --count);
 873             if (count == 0 && ui != null) {
 874                 ui.installUI(this);
 875             }
 876         }
 877     }
 878 
 879 
 880     /**
 881      * Returns a string representation of this {@code JTextField}.
 882      * This method is intended to be used only for debugging purposes,
 883      * and the content and format of the returned string may vary between
 884      * implementations. The returned string may be empty but may not
 885      * be {@code null}.
 886      *
 887      * @return  a string representation of this {@code JTextField}
 888      */
 889     protected String paramString() {
 890         String horizontalAlignmentString;
 891         if (horizontalAlignment == LEFT) {
 892             horizontalAlignmentString = "LEFT";
 893         } else if (horizontalAlignment == CENTER) {
 894             horizontalAlignmentString = "CENTER";
 895         } else if (horizontalAlignment == RIGHT) {
 896             horizontalAlignmentString = "RIGHT";
 897         } else if (horizontalAlignment == LEADING) {
 898             horizontalAlignmentString = "LEADING";
 899         } else if (horizontalAlignment == TRAILING) {
 900             horizontalAlignmentString = "TRAILING";
 901         } else horizontalAlignmentString = "";
 902         String commandString = (command != null ?
 903                                 command : "");
 904 
 905         return super.paramString() +
 906         ",columns=" + columns +
 907         ",columnWidth=" + columnWidth +
 908         ",command=" + commandString +
 909         ",horizontalAlignment=" + horizontalAlignmentString;
 910     }
 911 
 912 
 913 /////////////////
 914 // Accessibility support
 915 ////////////////
 916 
 917 
 918     /**
 919      * Gets the {@code AccessibleContext} associated with this
 920      * {@code JTextField}. For {@code JTextFields},
 921      * the {@code AccessibleContext} takes the form of an
 922      * {@code AccessibleJTextField}.
 923      * A new {@code AccessibleJTextField} instance is created
 924      * if necessary.
 925      *
 926      * @return an {@code AccessibleJTextField} that serves as the
 927      *         {@code AccessibleContext} of this {@code JTextField}
 928      */
 929     public AccessibleContext getAccessibleContext() {
 930         if (accessibleContext == null) {
 931             accessibleContext = new AccessibleJTextField();
 932         }
 933         return accessibleContext;
 934     }
 935 
 936     /**
 937      * This class implements accessibility support for the
 938      * {@code JTextField} class.  It provides an implementation of the
 939      * Java Accessibility API appropriate to text field user-interface
 940      * elements.
 941      * <p>
 942      * <strong>Warning:</strong>
 943      * Serialized objects of this class will not be compatible with
 944      * future Swing releases. The current serialization support is
 945      * appropriate for short term storage or RMI between applications running
 946      * the same version of Swing.  As of 1.4, support for long term storage
 947      * of all JavaBeans&trade;
 948      * has been added to the {@code java.beans} package.
 949      * Please see {@link java.beans.XMLEncoder}.
 950      */
 951     @SuppressWarnings("serial") // Same-version serialization only
 952     protected class AccessibleJTextField extends AccessibleJTextComponent {
 953 
 954         /**
 955          * Gets the state set of this object.
 956          *
 957          * @return an instance of AccessibleStateSet describing the states
 958          * of the object
 959          * @see AccessibleState
 960          */
 961         public AccessibleStateSet getAccessibleStateSet() {
 962             AccessibleStateSet states = super.getAccessibleStateSet();
 963             states.add(AccessibleState.SINGLE_LINE);
 964             return states;
 965         }
 966     }
 967 }
< prev index next >