1 /*
   2  * Copyright (c) 1995, 2015, 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 java.awt;
  26 
  27 import java.awt.peer.TextFieldPeer;
  28 import java.awt.event.*;
  29 import java.util.EventListener;
  30 import java.io.ObjectOutputStream;
  31 import java.io.ObjectInputStream;
  32 import java.io.IOException;
  33 import javax.accessibility.*;
  34 
  35 
  36 /**
  37  * A {@code TextField} object is a text component
  38  * that allows for the editing of a single line of text.
  39  * <p>
  40  * For example, the following image depicts a frame with four
  41  * text fields of varying widths. Two of these text fields
  42  * display the predefined text {@code "Hello"}.
  43  * <p>
  44  * <img src="doc-files/TextField-1.gif" alt="The preceding text describes this image."
  45  * style="float:center; margin: 7px 10px;">
  46  * <p>
  47  * Here is the code that produces these four text fields:
  48  *
  49  * <hr><blockquote><pre>
  50  * TextField tf1, tf2, tf3, tf4;
  51  * // a blank text field
  52  * tf1 = new TextField();
  53  * // blank field of 20 columns
  54  * tf2 = new TextField("", 20);
  55  * // predefined text displayed
  56  * tf3 = new TextField("Hello!");
  57  * // predefined text in 30 columns
  58  * tf4 = new TextField("Hello", 30);
  59  * </pre></blockquote><hr>
  60  * <p>
  61  * Every time the user types a key in the text field, one or
  62  * more key events are sent to the text field.  A {@code KeyEvent}
  63  * may be one of three types: keyPressed, keyReleased, or keyTyped.
  64  * The properties of a key event indicate which of these types
  65  * it is, as well as additional information about the event,
  66  * such as what modifiers are applied to the key event and the
  67  * time at which the event occurred.
  68  * <p>
  69  * The key event is passed to every {@code KeyListener}
  70  * or {@code KeyAdapter} object which registered to receive such
  71  * events using the component's {@code addKeyListener} method.
  72  * ({@code KeyAdapter} objects implement the
  73  * {@code KeyListener} interface.)
  74  * <p>
  75  * It is also possible to fire an {@code ActionEvent}.
  76  * If action events are enabled for the text field, they may
  77  * be fired by pressing the {@code Return} key.
  78  * <p>
  79  * The {@code TextField} class's {@code processEvent}
  80  * method examines the action event and passes it along to
  81  * {@code processActionEvent}. The latter method redirects the
  82  * event to any {@code ActionListener} objects that have
  83  * registered to receive action events generated by this
  84  * text field.
  85  *
  86  * @author      Sami Shaio
  87  * @see         java.awt.event.KeyEvent
  88  * @see         java.awt.event.KeyAdapter
  89  * @see         java.awt.event.KeyListener
  90  * @see         java.awt.event.ActionEvent
  91  * @see         java.awt.Component#addKeyListener
  92  * @see         java.awt.TextField#processEvent
  93  * @see         java.awt.TextField#processActionEvent
  94  * @see         java.awt.TextField#addActionListener
  95  * @since       1.0
  96  */
  97 public class TextField extends TextComponent {
  98 
  99     /**
 100      * The number of columns in the text field.
 101      * A column is an approximate average character
 102      * width that is platform-dependent.
 103      * Guaranteed to be non-negative.
 104      *
 105      * @serial
 106      * @see #setColumns(int)
 107      * @see #getColumns()
 108      */
 109     int columns;
 110 
 111     /**
 112      * The echo character, which is used when
 113      * the user wishes to disguise the characters
 114      * typed into the text field.
 115      * The disguises are removed if echoChar = {@code 0}.
 116      *
 117      * @serial
 118      * @see #getEchoChar()
 119      * @see #setEchoChar(char)
 120      * @see #echoCharIsSet()
 121      */
 122     char echoChar;
 123 
 124     transient ActionListener actionListener;
 125 
 126     private static final String base = "textfield";
 127     private static int nameCounter = 0;
 128 
 129     /*
 130      * JDK 1.1 serialVersionUID
 131      */
 132     private static final long serialVersionUID = -2966288784432217853L;
 133 
 134     /**
 135      * Initialize JNI field and method ids
 136      */
 137     private static native void initIDs();
 138 
 139     static {
 140         /* ensure that the necessary native libraries are loaded */
 141         Toolkit.loadLibraries();
 142         if (!GraphicsEnvironment.isHeadless()) {
 143             initIDs();
 144         }
 145     }
 146 
 147     /**
 148      * Constructs a new text field.
 149      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
 150      * returns true.
 151      * @see java.awt.GraphicsEnvironment#isHeadless
 152      */
 153     public TextField() throws HeadlessException {
 154         this("", 0);
 155     }
 156 
 157     /**
 158      * Constructs a new text field initialized with the specified text.
 159      * @param      text       the text to be displayed. If
 160      *             {@code text} is {@code null}, the empty
 161      *             string {@code ""} will be displayed.
 162      *             If {@code text} contains EOL character, then
 163      *             it will be replaced by space character.
 164      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
 165      * returns true.
 166      * @see java.awt.GraphicsEnvironment#isHeadless
 167      */
 168     public TextField(String text) throws HeadlessException {
 169         this(text, (text != null) ? text.length() : 0);
 170     }
 171 
 172     /**
 173      * Constructs a new empty text field with the specified number
 174      * of columns.  A column is an approximate average character
 175      * width that is platform-dependent.
 176      * @param      columns     the number of columns.  If
 177      *             {@code columns} is less than {@code 0},
 178      *             {@code columns} is set to {@code 0}.
 179      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
 180      * returns true.
 181      * @see java.awt.GraphicsEnvironment#isHeadless
 182      */
 183     public TextField(int columns) throws HeadlessException {
 184         this("", columns);
 185     }
 186 
 187     /**
 188      * Constructs a new text field initialized with the specified text
 189      * to be displayed, and wide enough to hold the specified
 190      * number of columns. A column is an approximate average character
 191      * width that is platform-dependent.
 192      * @param      text       the text to be displayed. If
 193      *             {@code text} is {@code null}, the empty
 194      *             string {@code ""} will be displayed.
 195      *             If {@code text} contains EOL character, then
 196      *             it will be replaced by space character.
 197      * @param      columns     the number of columns.  If
 198      *             {@code columns} is less than {@code 0},
 199      *             {@code columns} is set to {@code 0}.
 200      * @exception HeadlessException if GraphicsEnvironment.isHeadless()
 201      * returns true.
 202      * @see java.awt.GraphicsEnvironment#isHeadless
 203      */
 204     public TextField(String text, int columns) throws HeadlessException {
 205         super(replaceEOL(text));
 206         this.columns = (columns >= 0) ? columns : 0;
 207     }
 208 
 209     /**
 210      * Construct a name for this component.  Called by getName() when the
 211      * name is null.
 212      */
 213     String constructComponentName() {
 214         synchronized (TextField.class) {
 215             return base + nameCounter++;
 216         }
 217     }
 218 
 219     /**
 220      * Creates the TextField's peer.  The peer allows us to modify the
 221      * appearance of the TextField without changing its functionality.
 222      */
 223     public void addNotify() {
 224         synchronized (getTreeLock()) {
 225             if (peer == null)
 226                 peer = getComponentFactory().createTextField(this);
 227             super.addNotify();
 228         }
 229     }
 230 
 231     /**
 232      * Gets the character that is to be used for echoing.
 233      * <p>
 234      * An echo character is useful for text fields where
 235      * user input should not be echoed to the screen, as in
 236      * the case of a text field for entering a password.
 237      * If {@code echoChar} = {@code 0}, user
 238      * input is echoed to the screen unchanged.
 239      * <p>
 240      * A Java platform implementation may support only a limited,
 241      * non-empty set of echo characters. This function returns the
 242      * echo character originally requested via setEchoChar(). The echo
 243      * character actually used by the TextField implementation might be
 244      * different.
 245      * @return      the echo character for this text field.
 246      * @see         java.awt.TextField#echoCharIsSet
 247      * @see         java.awt.TextField#setEchoChar
 248      */
 249     public char getEchoChar() {
 250         return echoChar;
 251     }
 252 
 253     /**
 254      * Sets the echo character for this text field.
 255      * <p>
 256      * An echo character is useful for text fields where
 257      * user input should not be echoed to the screen, as in
 258      * the case of a text field for entering a password.
 259      * Setting {@code echoChar} = {@code 0} allows
 260      * user input to be echoed to the screen again.
 261      * <p>
 262      * A Java platform implementation may support only a limited,
 263      * non-empty set of echo characters. Attempts to set an
 264      * unsupported echo character will cause the default echo
 265      * character to be used instead. Subsequent calls to getEchoChar()
 266      * will return the echo character originally requested. This might
 267      * or might not be identical to the echo character actually
 268      * used by the TextField implementation.
 269      * @param       c   the echo character for this text field.
 270      * @see         java.awt.TextField#echoCharIsSet
 271      * @see         java.awt.TextField#getEchoChar
 272      * @since       1.1
 273      */
 274     public void setEchoChar(char c) {
 275         setEchoCharacter(c);
 276     }
 277 
 278     /**
 279      * Sets the character to be echoed when protected input is displayed.
 280      *
 281      *  @param  c the echo character for this text field
 282      *
 283      * @deprecated As of JDK version 1.1,
 284      * replaced by {@code setEchoChar(char)}.
 285      */
 286     @Deprecated
 287     public synchronized void setEchoCharacter(char c) {
 288         if (echoChar != c) {
 289             echoChar = c;
 290             TextFieldPeer peer = (TextFieldPeer)this.peer;
 291             if (peer != null) {
 292                 peer.setEchoChar(c);
 293             }
 294         }
 295     }
 296 
 297     /**
 298      * Sets the text that is presented by this
 299      * text component to be the specified text.
 300      * @param      t       the new text. If
 301      *             {@code t} is {@code null}, the empty
 302      *             string {@code ""} will be displayed.
 303      *             If {@code t} contains EOL character, then
 304      *             it will be replaced by space character.
 305      * @see         java.awt.TextComponent#getText
 306      */
 307     public void setText(String t) {
 308         super.setText(replaceEOL(t));
 309 
 310         // This could change the preferred size of the Component.
 311         invalidateIfValid();
 312     }
 313 
 314     /**
 315      * Replaces EOL characters from the text variable with a space character.
 316      * @param       text   the new text.
 317      * @return      Returns text after replacing EOL characters.
 318      */
 319     private static String replaceEOL(String text) {
 320         if (text == null) {
 321             return text;
 322         }
 323         String[] strEOLs = {System.lineSeparator(), "\n"};
 324         for (String eol : strEOLs) {
 325             if (text.contains(eol)) {
 326                 text = text.replace(eol, " ");
 327             }
 328         }
 329         return text;
 330     }
 331 
 332 
 333     /**
 334      * Indicates whether or not this text field has a
 335      * character set for echoing.
 336      * <p>
 337      * An echo character is useful for text fields where
 338      * user input should not be echoed to the screen, as in
 339      * the case of a text field for entering a password.
 340      * @return     {@code true} if this text field has
 341      *                 a character set for echoing;
 342      *                 {@code false} otherwise.
 343      * @see        java.awt.TextField#setEchoChar
 344      * @see        java.awt.TextField#getEchoChar
 345      */
 346     public boolean echoCharIsSet() {
 347         return echoChar != 0;
 348     }
 349 
 350     /**
 351      * Gets the number of columns in this text field. A column is an
 352      * approximate average character width that is platform-dependent.
 353      * @return     the number of columns.
 354      * @see        java.awt.TextField#setColumns
 355      * @since      1.1
 356      */
 357     public int getColumns() {
 358         return columns;
 359     }
 360 
 361     /**
 362      * Sets the number of columns in this text field. A column is an
 363      * approximate average character width that is platform-dependent.
 364      * @param      columns   the number of columns.
 365      * @see        java.awt.TextField#getColumns
 366      * @exception  IllegalArgumentException   if the value
 367      *                 supplied for {@code columns}
 368      *                 is less than {@code 0}.
 369      * @since      1.1
 370      */
 371     public void setColumns(int columns) {
 372         int oldVal;
 373         synchronized (this) {
 374             oldVal = this.columns;
 375             if (columns < 0) {
 376                 throw new IllegalArgumentException("columns less than zero.");
 377             }
 378             if (columns != oldVal) {
 379                 this.columns = columns;
 380             }
 381         }
 382 
 383         if (columns != oldVal) {
 384             invalidate();
 385         }
 386     }
 387 
 388     /**
 389      * Gets the preferred size of this text field
 390      * with the specified number of columns.
 391      * @param     columns the number of columns
 392      *                 in this text field.
 393      * @return    the preferred dimensions for
 394      *                 displaying this text field.
 395      * @since     1.1
 396      */
 397     public Dimension getPreferredSize(int columns) {
 398         return preferredSize(columns);
 399     }
 400 
 401     /**
 402      * Returns the preferred size for this text field
 403      * with the specified number of columns.
 404      *
 405      * @param  columns the number of columns
 406      * @return the preferred size for the text field
 407      *
 408      * @deprecated As of JDK version 1.1,
 409      * replaced by {@code getPreferredSize(int)}.
 410      */
 411     @Deprecated
 412     public Dimension preferredSize(int columns) {
 413         synchronized (getTreeLock()) {
 414             TextFieldPeer peer = (TextFieldPeer)this.peer;
 415             return (peer != null) ?
 416                        peer.getPreferredSize(columns) :
 417                        super.preferredSize();
 418         }
 419     }
 420 
 421     /**
 422      * Gets the preferred size of this text field.
 423      * @return     the preferred dimensions for
 424      *                         displaying this text field.
 425      * @since      1.1
 426      */
 427     public Dimension getPreferredSize() {
 428         return preferredSize();
 429     }
 430 
 431     /**
 432      * @deprecated As of JDK version 1.1,
 433      * replaced by {@code getPreferredSize()}.
 434      */
 435     @Deprecated
 436     public Dimension preferredSize() {
 437         synchronized (getTreeLock()) {
 438             return (columns > 0) ?
 439                        preferredSize(columns) :
 440                        super.preferredSize();
 441         }
 442     }
 443 
 444     /**
 445      * Gets the minimum dimensions for a text field with
 446      * the specified number of columns.
 447      * @param  columns the number of columns in
 448      *         this text field.
 449      * @return the minimum size for this text field
 450      * @since    1.1
 451      */
 452     public Dimension getMinimumSize(int columns) {
 453         return minimumSize(columns);
 454     }
 455 
 456     /**
 457      * Returns the minimum dimensions for a text field with
 458      * the specified number of columns.
 459      *
 460      * @param  columns the number of columns
 461      * @return the minimum size for this text field
 462      * @deprecated As of JDK version 1.1,
 463      * replaced by {@code getMinimumSize(int)}.
 464      */
 465     @Deprecated
 466     public Dimension minimumSize(int columns) {
 467         synchronized (getTreeLock()) {
 468             TextFieldPeer peer = (TextFieldPeer)this.peer;
 469             return (peer != null) ?
 470                        peer.getMinimumSize(columns) :
 471                        super.minimumSize();
 472         }
 473     }
 474 
 475     /**
 476      * Gets the minimum dimensions for this text field.
 477      * @return     the minimum dimensions for
 478      *                  displaying this text field.
 479      * @since      1.1
 480      */
 481     public Dimension getMinimumSize() {
 482         return minimumSize();
 483     }
 484 
 485     /**
 486      * @deprecated As of JDK version 1.1,
 487      * replaced by {@code getMinimumSize()}.
 488      */
 489     @Deprecated
 490     public Dimension minimumSize() {
 491         synchronized (getTreeLock()) {
 492             return (columns > 0) ?
 493                        minimumSize(columns) :
 494                        super.minimumSize();
 495         }
 496     }
 497 
 498     /**
 499      * Adds the specified action listener to receive
 500      * action events from this text field.
 501      * If l is null, no exception is thrown and no action is performed.
 502      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 503      * >AWT Threading Issues</a> for details on AWT's threading model.
 504      *
 505      * @param      l the action listener.
 506      * @see        #removeActionListener
 507      * @see        #getActionListeners
 508      * @see        java.awt.event.ActionListener
 509      * @since      1.1
 510      */
 511     public synchronized void addActionListener(ActionListener l) {
 512         if (l == null) {
 513             return;
 514         }
 515         actionListener = AWTEventMulticaster.add(actionListener, l);
 516         newEventsOnly = true;
 517     }
 518 
 519     /**
 520      * Removes the specified action listener so that it no longer
 521      * receives action events from this text field.
 522      * If l is null, no exception is thrown and no action is performed.
 523      * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 524      * >AWT Threading Issues</a> for details on AWT's threading model.
 525      *
 526      * @param           l the action listener.
 527      * @see             #addActionListener
 528      * @see             #getActionListeners
 529      * @see             java.awt.event.ActionListener
 530      * @since           1.1
 531      */
 532     public synchronized void removeActionListener(ActionListener l) {
 533         if (l == null) {
 534             return;
 535         }
 536         actionListener = AWTEventMulticaster.remove(actionListener, l);
 537     }
 538 
 539     /**
 540      * Returns an array of all the action listeners
 541      * registered on this textfield.
 542      *
 543      * @return all of this textfield's {@code ActionListener}s
 544      *         or an empty array if no action
 545      *         listeners are currently registered
 546      *
 547      * @see #addActionListener
 548      * @see #removeActionListener
 549      * @see java.awt.event.ActionListener
 550      * @since 1.4
 551      */
 552     public synchronized ActionListener[] getActionListeners() {
 553         return getListeners(ActionListener.class);
 554     }
 555 
 556     /**
 557      * Returns an array of all the objects currently registered
 558      * as <code><em>Foo</em>Listener</code>s
 559      * upon this {@code TextField}.
 560      * <code><em>Foo</em>Listener</code>s are registered using the
 561      * <code>add<em>Foo</em>Listener</code> method.
 562      *
 563      * <p>
 564      * You can specify the {@code listenerType} argument
 565      * with a class literal, such as
 566      * <code><em>Foo</em>Listener.class</code>.
 567      * For example, you can query a
 568      * {@code TextField t}
 569      * for its action listeners with the following code:
 570      *
 571      * <pre>ActionListener[] als = (ActionListener[])(t.getListeners(ActionListener.class));</pre>
 572      *
 573      * If no such listeners exist, this method returns an empty array.
 574      *
 575      * @param listenerType the type of listeners requested; this parameter
 576      *          should specify an interface that descends from
 577      *          {@code java.util.EventListener}
 578      * @return an array of all objects registered as
 579      *          <code><em>Foo</em>Listener</code>s on this textfield,
 580      *          or an empty array if no such
 581      *          listeners have been added
 582      * @exception ClassCastException if {@code listenerType}
 583      *          doesn't specify a class or interface that implements
 584      *          {@code java.util.EventListener}
 585      *
 586      * @see #getActionListeners
 587      * @since 1.3
 588      */
 589     public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
 590         EventListener l = null;
 591         if  (listenerType == ActionListener.class) {
 592             l = actionListener;
 593         } else {
 594             return super.getListeners(listenerType);
 595         }
 596         return AWTEventMulticaster.getListeners(l, listenerType);
 597     }
 598 
 599     // REMIND: remove when filtering is done at lower level
 600     boolean eventEnabled(AWTEvent e) {
 601         if (e.id == ActionEvent.ACTION_PERFORMED) {
 602             if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||
 603                 actionListener != null) {
 604                 return true;
 605             }
 606             return false;
 607         }
 608         return super.eventEnabled(e);
 609     }
 610 
 611     /**
 612      * Processes events on this text field. If the event
 613      * is an instance of {@code ActionEvent},
 614      * it invokes the {@code processActionEvent}
 615      * method. Otherwise, it invokes {@code processEvent}
 616      * on the superclass.
 617      * <p>Note that if the event parameter is {@code null}
 618      * the behavior is unspecified and may result in an
 619      * exception.
 620      *
 621      * @param      e the event
 622      * @see        java.awt.event.ActionEvent
 623      * @see        java.awt.TextField#processActionEvent
 624      * @since      1.1
 625      */
 626     protected void processEvent(AWTEvent e) {
 627         if (e instanceof ActionEvent) {
 628             processActionEvent((ActionEvent)e);
 629             return;
 630         }
 631         super.processEvent(e);
 632     }
 633 
 634     /**
 635      * Processes action events occurring on this text field by
 636      * dispatching them to any registered
 637      * {@code ActionListener} objects.
 638      * <p>
 639      * This method is not called unless action events are
 640      * enabled for this component. Action events are enabled
 641      * when one of the following occurs:
 642      * <ul>
 643      * <li>An {@code ActionListener} object is registered
 644      * via {@code addActionListener}.
 645      * <li>Action events are enabled via {@code enableEvents}.
 646      * </ul>
 647      * <p>Note that if the event parameter is {@code null}
 648      * the behavior is unspecified and may result in an
 649      * exception.
 650      *
 651      * @param       e the action event
 652      * @see         java.awt.event.ActionListener
 653      * @see         java.awt.TextField#addActionListener
 654      * @see         java.awt.Component#enableEvents
 655      * @since       1.1
 656      */
 657     protected void processActionEvent(ActionEvent e) {
 658         ActionListener listener = actionListener;
 659         if (listener != null) {
 660             listener.actionPerformed(e);
 661         }
 662     }
 663 
 664     /**
 665      * Returns a string representing the state of this {@code TextField}.
 666      * This method is intended to be used only for debugging purposes, and the
 667      * content and format of the returned string may vary between
 668      * implementations. The returned string may be empty but may not be
 669      * {@code null}.
 670      *
 671      * @return      the parameter string of this text field
 672      */
 673     protected String paramString() {
 674         String str = super.paramString();
 675         if (echoChar != 0) {
 676             str += ",echo=" + echoChar;
 677         }
 678         return str;
 679     }
 680 
 681 
 682     /*
 683      * Serialization support.
 684      */
 685     /**
 686      * The textField Serialized Data Version.
 687      *
 688      * @serial
 689      */
 690     private int textFieldSerializedDataVersion = 1;
 691 
 692     /**
 693      * Writes default serializable fields to stream.  Writes
 694      * a list of serializable ActionListener(s) as optional data.
 695      * The non-serializable ActionListener(s) are detected and
 696      * no attempt is made to serialize them.
 697      *
 698      * @serialData Null terminated sequence of zero or more pairs.
 699      *             A pair consists of a String and Object.
 700      *             The String indicates the type of object and
 701      *             is one of the following :
 702      *             ActionListenerK indicating and ActionListener object.
 703      *
 704      * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
 705      * @see java.awt.Component#actionListenerK
 706      */
 707     private void writeObject(ObjectOutputStream s)
 708       throws IOException
 709     {
 710         s.defaultWriteObject();
 711 
 712         AWTEventMulticaster.save(s, actionListenerK, actionListener);
 713         s.writeObject(null);
 714     }
 715 
 716     /**
 717      * Read the ObjectInputStream and if it isn't null,
 718      * add a listener to receive action events fired by the
 719      * TextField.  Unrecognized keys or values will be
 720      * ignored.
 721      *
 722      * @exception HeadlessException if
 723      * {@code GraphicsEnvironment.isHeadless()} returns
 724      * {@code true}
 725      * @see #removeActionListener(ActionListener)
 726      * @see #addActionListener(ActionListener)
 727      * @see java.awt.GraphicsEnvironment#isHeadless
 728      */
 729     private void readObject(ObjectInputStream s)
 730       throws ClassNotFoundException, IOException, HeadlessException
 731     {
 732         // HeadlessException will be thrown by TextComponent's readObject
 733         s.defaultReadObject();
 734         text = replaceEOL(text);
 735 
 736         // Make sure the state we just read in for columns has legal values
 737         if (columns < 0) {
 738             columns = 0;
 739         }
 740 
 741         // Read in listeners, if any
 742         Object keyOrNull;
 743         while(null != (keyOrNull = s.readObject())) {
 744             String key = ((String)keyOrNull).intern();
 745 
 746             if (actionListenerK == key) {
 747                 addActionListener((ActionListener)(s.readObject()));
 748             } else {
 749                 // skip value for unrecognized key
 750                 s.readObject();
 751             }
 752         }
 753     }
 754 
 755 
 756 /////////////////
 757 // Accessibility support
 758 ////////////////
 759 
 760 
 761     /**
 762      * Gets the AccessibleContext associated with this TextField.
 763      * For text fields, the AccessibleContext takes the form of an
 764      * AccessibleAWTTextField.
 765      * A new AccessibleAWTTextField instance is created if necessary.
 766      *
 767      * @return an AccessibleAWTTextField that serves as the
 768      *         AccessibleContext of this TextField
 769      * @since 1.3
 770      */
 771     public AccessibleContext getAccessibleContext() {
 772         if (accessibleContext == null) {
 773             accessibleContext = new AccessibleAWTTextField();
 774         }
 775         return accessibleContext;
 776     }
 777 
 778     /**
 779      * This class implements accessibility support for the
 780      * {@code TextField} class.  It provides an implementation of the
 781      * Java Accessibility API appropriate to text field user-interface elements.
 782      * @since 1.3
 783      */
 784     protected class AccessibleAWTTextField extends AccessibleAWTTextComponent
 785     {
 786         /*
 787          * JDK 1.3 serialVersionUID
 788          */
 789         private static final long serialVersionUID = 6219164359235943158L;
 790 
 791         /**
 792          * Gets the state set of this object.
 793          *
 794          * @return an instance of AccessibleStateSet describing the states
 795          * of the object
 796          * @see AccessibleState
 797          */
 798         public AccessibleStateSet getAccessibleStateSet() {
 799             AccessibleStateSet states = super.getAccessibleStateSet();
 800             states.add(AccessibleState.SINGLE_LINE);
 801             return states;
 802         }
 803     }
 804 
 805 }