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