1 /*
   2  * Copyright (c) 1995, 2014, 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.event.InputEvent;
  28 import java.awt.event.KeyEvent;
  29 import java.awt.peer.TextAreaPeer;
  30 import java.io.ObjectOutputStream;
  31 import java.io.ObjectInputStream;
  32 import java.io.IOException;
  33 import java.util.HashSet;
  34 import java.util.Set;
  35 import javax.accessibility.*;
  36 
  37 /**
  38  * A <code>TextArea</code> object is a multi-line region
  39  * that displays text. It can be set to allow editing or
  40  * to be read-only.
  41  * <p>
  42  * The following image shows the appearance of a text area:
  43  * <p>
  44  * <img src="doc-files/TextArea-1.gif" alt="A TextArea showing the word 'Hello!'"
  45  * style="float:center; margin: 7px 10px;">
  46  * <p>
  47  * This text area could be created by the following line of code:
  48  *
  49  * <hr><blockquote><pre>
  50  * new TextArea("Hello", 5, 40);
  51  * </pre></blockquote><hr>
  52  *
  53  * @author      Sami Shaio
  54  * @since       JDK1.0
  55  */
  56 public class TextArea extends TextComponent {
  57 
  58     /**
  59      * The number of rows in the <code>TextArea</code>.
  60      * This parameter will determine the text area's height.
  61      * Guaranteed to be non-negative.
  62      *
  63      * @serial
  64      * @see #getRows()
  65      * @see #setRows(int)
  66      */
  67     int rows;
  68 
  69     /**
  70      * The number of columns in the <code>TextArea</code>.
  71      * A column is an approximate average character
  72      * width that is platform-dependent.
  73      * This parameter will determine the text area's width.
  74      * Guaranteed to be non-negative.
  75      *
  76      * @serial
  77      * @see  #setColumns(int)
  78      * @see  #getColumns()
  79      */
  80     int columns;
  81 
  82     private static final String base = "text";
  83     private static int nameCounter = 0;
  84 
  85     /**
  86      * Create and display both vertical and horizontal scrollbars.
  87      * @since JDK1.1
  88      */
  89     public static final int SCROLLBARS_BOTH = 0;
  90 
  91     /**
  92      * Create and display vertical scrollbar only.
  93      * @since JDK1.1
  94      */
  95     public static final int SCROLLBARS_VERTICAL_ONLY = 1;
  96 
  97     /**
  98      * Create and display horizontal scrollbar only.
  99      * @since JDK1.1
 100      */
 101     public static final int SCROLLBARS_HORIZONTAL_ONLY = 2;
 102 
 103     /**
 104      * Do not create or display any scrollbars for the text area.
 105      * @since JDK1.1
 106      */
 107     public static final int SCROLLBARS_NONE = 3;
 108 
 109     /**
 110      * Determines which scrollbars are created for the
 111      * text area. It can be one of four values :
 112      * <code>SCROLLBARS_BOTH</code> = both scrollbars.<BR>
 113      * <code>SCROLLBARS_HORIZONTAL_ONLY</code> = Horizontal bar only.<BR>
 114      * <code>SCROLLBARS_VERTICAL_ONLY</code> = Vertical bar only.<BR>
 115      * <code>SCROLLBARS_NONE</code> = No scrollbars.<BR>
 116      *
 117      * @serial
 118      * @see #getScrollbarVisibility()
 119      */
 120     private int scrollbarVisibility;
 121 
 122     /**
 123      * Cache the Sets of forward and backward traversal keys so we need not
 124      * look them up each time.
 125      */
 126     private static Set<AWTKeyStroke> forwardTraversalKeys, backwardTraversalKeys;
 127 
 128     /*
 129      * JDK 1.1 serialVersionUID
 130      */
 131      private static final long serialVersionUID = 3692302836626095722L;
 132 
 133     /**
 134      * Initialize JNI field and method ids
 135      */
 136     private static native void initIDs();
 137 
 138     static {
 139         /* ensure that the necessary native libraries are loaded */
 140         Toolkit.loadLibraries();
 141         if (!GraphicsEnvironment.isHeadless()) {
 142             initIDs();
 143         }
 144         forwardTraversalKeys = KeyboardFocusManager.initFocusTraversalKeysSet(
 145             "ctrl TAB",
 146             new HashSet<AWTKeyStroke>());
 147         backwardTraversalKeys = KeyboardFocusManager.initFocusTraversalKeysSet(
 148             "ctrl shift TAB",
 149             new HashSet<AWTKeyStroke>());
 150     }
 151 
 152     /**
 153      * Constructs a new text area with the empty string as text.
 154      * This text area is created with scrollbar visibility equal to
 155      * {@link #SCROLLBARS_BOTH}, so both vertical and horizontal
 156      * scrollbars will be visible for this text area.
 157      * @exception HeadlessException if
 158      *    <code>GraphicsEnvironment.isHeadless</code> returns true
 159      * @see java.awt.GraphicsEnvironment#isHeadless()
 160      */
 161     public TextArea() throws HeadlessException {
 162         this("", 0, 0, SCROLLBARS_BOTH);
 163     }
 164 
 165     /**
 166      * Constructs a new text area with the specified text.
 167      * This text area is created with scrollbar visibility equal to
 168      * {@link #SCROLLBARS_BOTH}, so both vertical and horizontal
 169      * scrollbars will be visible for this text area.
 170      * @param      text       the text to be displayed; if
 171      *             <code>text</code> is <code>null</code>, the empty
 172      *             string <code>""</code> will be displayed
 173      * @exception HeadlessException if
 174      *        <code>GraphicsEnvironment.isHeadless</code> returns true
 175      * @see java.awt.GraphicsEnvironment#isHeadless()
 176      */
 177     public TextArea(String text) throws HeadlessException {
 178         this(text, 0, 0, SCROLLBARS_BOTH);
 179     }
 180 
 181     /**
 182      * Constructs a new text area with the specified number of
 183      * rows and columns and the empty string as text.
 184      * A column is an approximate average character
 185      * width that is platform-dependent.  The text area is created with
 186      * scrollbar visibility equal to {@link #SCROLLBARS_BOTH}, so both
 187      * vertical and horizontal scrollbars will be visible for this
 188      * text area.
 189      * @param rows the number of rows
 190      * @param columns the number of columns
 191      * @exception HeadlessException if
 192      *     <code>GraphicsEnvironment.isHeadless</code> returns true
 193      * @see java.awt.GraphicsEnvironment#isHeadless()
 194      */
 195     public TextArea(int rows, int columns) throws HeadlessException {
 196         this("", rows, columns, SCROLLBARS_BOTH);
 197     }
 198 
 199     /**
 200      * Constructs a new text area with the specified text,
 201      * and with the specified number of rows and columns.
 202      * A column is an approximate average character
 203      * width that is platform-dependent.  The text area is created with
 204      * scrollbar visibility equal to {@link #SCROLLBARS_BOTH}, so both
 205      * vertical and horizontal scrollbars will be visible for this
 206      * text area.
 207      * @param      text       the text to be displayed; if
 208      *             <code>text</code> is <code>null</code>, the empty
 209      *             string <code>""</code> will be displayed
 210      * @param     rows      the number of rows
 211      * @param     columns   the number of columns
 212      * @exception HeadlessException if
 213      *   <code>GraphicsEnvironment.isHeadless</code> returns true
 214      * @see java.awt.GraphicsEnvironment#isHeadless()
 215      */
 216     public TextArea(String text, int rows, int columns)
 217         throws HeadlessException {
 218         this(text, rows, columns, SCROLLBARS_BOTH);
 219     }
 220 
 221     /**
 222      * Constructs a new text area with the specified text,
 223      * and with the rows, columns, and scroll bar visibility
 224      * as specified.  All <code>TextArea</code> constructors defer to
 225      * this one.
 226      * <p>
 227      * The <code>TextArea</code> class defines several constants
 228      * that can be supplied as values for the
 229      * <code>scrollbars</code> argument:
 230      * <ul>
 231      * <li><code>SCROLLBARS_BOTH</code>,
 232      * <li><code>SCROLLBARS_VERTICAL_ONLY</code>,
 233      * <li><code>SCROLLBARS_HORIZONTAL_ONLY</code>,
 234      * <li><code>SCROLLBARS_NONE</code>.
 235      * </ul>
 236      * Any other value for the
 237      * <code>scrollbars</code> argument is invalid and will result in
 238      * this text area being created with scrollbar visibility equal to
 239      * the default value of {@link #SCROLLBARS_BOTH}.
 240      * @param      text       the text to be displayed; if
 241      *             <code>text</code> is <code>null</code>, the empty
 242      *             string <code>""</code> will be displayed
 243      * @param      rows       the number of rows; if
 244      *             <code>rows</code> is less than <code>0</code>,
 245      *             <code>rows</code> is set to <code>0</code>
 246      * @param      columns    the number of columns; if
 247      *             <code>columns</code> is less than <code>0</code>,
 248      *             <code>columns</code> is set to <code>0</code>
 249      * @param      scrollbars  a constant that determines what
 250      *             scrollbars are created to view the text area
 251      * @since      JDK1.1
 252      * @exception HeadlessException if
 253      *    <code>GraphicsEnvironment.isHeadless</code> returns true
 254      * @see java.awt.GraphicsEnvironment#isHeadless()
 255      */
 256     public TextArea(String text, int rows, int columns, int scrollbars)
 257         throws HeadlessException {
 258         super(text);
 259 
 260         this.rows = (rows >= 0) ? rows : 0;
 261         this.columns = (columns >= 0) ? columns : 0;
 262 
 263         if (scrollbars >= SCROLLBARS_BOTH && scrollbars <= SCROLLBARS_NONE) {
 264             this.scrollbarVisibility = scrollbars;
 265         } else {
 266             this.scrollbarVisibility = SCROLLBARS_BOTH;
 267         }
 268 
 269         setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 270                               forwardTraversalKeys);
 271         setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 272                               backwardTraversalKeys);
 273     }
 274 
 275     /**
 276      * Construct a name for this component.  Called by <code>getName</code>
 277      * when the name is <code>null</code>.
 278      */
 279     String constructComponentName() {
 280         synchronized (TextArea.class) {
 281             return base + nameCounter++;
 282         }
 283     }
 284 
 285     /**
 286      * Creates the <code>TextArea</code>'s peer.  The peer allows us to modify
 287      * the appearance of the <code>TextArea</code> without changing any of its
 288      * functionality.
 289      */
 290     public void addNotify() {
 291         synchronized (getTreeLock()) {
 292             if (peer == null)
 293                 peer = getToolkit().createTextArea(this);
 294             super.addNotify();
 295         }
 296     }
 297 
 298     /**
 299      * Inserts the specified text at the specified position
 300      * in this text area.
 301      * <p>Note that passing <code>null</code> or inconsistent
 302      * parameters is invalid and will result in unspecified
 303      * behavior.
 304      *
 305      * @param      str the non-<code>null</code> text to insert
 306      * @param      pos the position at which to insert
 307      * @see        java.awt.TextComponent#setText
 308      * @see        java.awt.TextArea#replaceRange
 309      * @see        java.awt.TextArea#append
 310      * @since      JDK1.1
 311      */
 312     public void insert(String str, int pos) {
 313         insertText(str, pos);
 314     }
 315 
 316     /**
 317      * Inserts the specified text at the specified position
 318      * in this text area.
 319      * @param str  the non-{@code null} text to insert
 320      * @param pos  the position at which to insert
 321      * @deprecated As of JDK version 1.1,
 322      * replaced by <code>insert(String, int)</code>.
 323      */
 324     @Deprecated
 325     public synchronized void insertText(String str, int pos) {
 326         TextAreaPeer peer = (TextAreaPeer)this.peer;
 327         if (peer != null) {
 328             peer.insert(str, pos);
 329         } else {
 330             text = text.substring(0, pos) + str + text.substring(pos);
 331         }
 332     }
 333 
 334     /**
 335      * Appends the given text to the text area's current text.
 336      * <p>Note that passing <code>null</code> or inconsistent
 337      * parameters is invalid and will result in unspecified
 338      * behavior.
 339      *
 340      * @param     str the non-<code>null</code> text to append
 341      * @see       java.awt.TextArea#insert
 342      * @since     JDK1.1
 343      */
 344     public void append(String str) {
 345         appendText(str);
 346     }
 347 
 348     /**
 349      * Appends the given text to the text area's current text.
 350      * @param str  the text to append
 351      * @deprecated As of JDK version 1.1,
 352      * replaced by <code>append(String)</code>.
 353      */
 354     @Deprecated
 355     public synchronized void appendText(String str) {
 356         if (peer != null) {
 357             insertText(str, getText().length());
 358         } else {
 359             text = text + str;
 360         }
 361     }
 362 
 363     /**
 364      * Replaces text between the indicated start and end positions
 365      * with the specified replacement text.  The text at the end
 366      * position will not be replaced.  The text at the start
 367      * position will be replaced (unless the start position is the
 368      * same as the end position).
 369      * The text position is zero-based.  The inserted substring may be
 370      * of a different length than the text it replaces.
 371      * <p>Note that passing <code>null</code> or inconsistent
 372      * parameters is invalid and will result in unspecified
 373      * behavior.
 374      *
 375      * @param     str      the non-<code>null</code> text to use as
 376      *                     the replacement
 377      * @param     start    the start position
 378      * @param     end      the end position
 379      * @see       java.awt.TextArea#insert
 380      * @since     JDK1.1
 381      */
 382     public void replaceRange(String str, int start, int end) {
 383         replaceText(str, start, end);
 384     }
 385 
 386     /**
 387      * Replaces a range of characters between
 388      * the indicated start and end positions
 389      * with the specified replacement text (the text at the end
 390      * position will not be replaced).
 391      * @param   str  the non-{@code null} text to use as
 392      *               the replacement
 393      * @param   start  the start position
 394      * @param   end    the end position
 395      * @deprecated As of JDK version 1.1,
 396      * replaced by <code>replaceRange(String, int, int)</code>.
 397      */
 398     @Deprecated
 399     public synchronized void replaceText(String str, int start, int end) {
 400         TextAreaPeer peer = (TextAreaPeer)this.peer;
 401         if (peer != null) {
 402             peer.replaceRange(str, start, end);
 403         } else {
 404             text = text.substring(0, start) + str + text.substring(end);
 405         }
 406     }
 407 
 408     /**
 409      * Returns the number of rows in the text area.
 410      * @return    the number of rows in the text area
 411      * @see       #setRows(int)
 412      * @see       #getColumns()
 413      * @since     JDK1
 414      */
 415     public int getRows() {
 416         return rows;
 417     }
 418 
 419     /**
 420      * Sets the number of rows for this text area.
 421      * @param       rows   the number of rows
 422      * @see         #getRows()
 423      * @see         #setColumns(int)
 424      * @exception   IllegalArgumentException   if the value
 425      *                 supplied for <code>rows</code>
 426      *                 is less than <code>0</code>
 427      * @since       JDK1.1
 428      */
 429     public void setRows(int rows) {
 430         int oldVal = this.rows;
 431         if (rows < 0) {
 432             throw new IllegalArgumentException("rows less than zero.");
 433         }
 434         if (rows != oldVal) {
 435             this.rows = rows;
 436             invalidate();
 437         }
 438     }
 439 
 440     /**
 441      * Returns the number of columns in this text area.
 442      * @return    the number of columns in the text area
 443      * @see       #setColumns(int)
 444      * @see       #getRows()
 445      */
 446     public int getColumns() {
 447         return columns;
 448     }
 449 
 450     /**
 451      * Sets the number of columns for this text area.
 452      * @param       columns   the number of columns
 453      * @see         #getColumns()
 454      * @see         #setRows(int)
 455      * @exception   IllegalArgumentException   if the value
 456      *                 supplied for <code>columns</code>
 457      *                 is less than <code>0</code>
 458      * @since       JDK1.1
 459      */
 460     public void setColumns(int columns) {
 461         int oldVal = this.columns;
 462         if (columns < 0) {
 463             throw new IllegalArgumentException("columns less than zero.");
 464         }
 465         if (columns != oldVal) {
 466             this.columns = columns;
 467             invalidate();
 468         }
 469     }
 470 
 471     /**
 472      * Returns an enumerated value that indicates which scroll bars
 473      * the text area uses.
 474      * <p>
 475      * The <code>TextArea</code> class defines four integer constants
 476      * that are used to specify which scroll bars are available.
 477      * <code>TextArea</code> has one constructor that gives the
 478      * application discretion over scroll bars.
 479      *
 480      * @return     an integer that indicates which scroll bars are used
 481      * @see        java.awt.TextArea#SCROLLBARS_BOTH
 482      * @see        java.awt.TextArea#SCROLLBARS_VERTICAL_ONLY
 483      * @see        java.awt.TextArea#SCROLLBARS_HORIZONTAL_ONLY
 484      * @see        java.awt.TextArea#SCROLLBARS_NONE
 485      * @see        java.awt.TextArea#TextArea(java.lang.String, int, int, int)
 486      * @since      JDK1.1
 487      */
 488     public int getScrollbarVisibility() {
 489         return scrollbarVisibility;
 490     }
 491 
 492 
 493     /**
 494      * Determines the preferred size of a text area with the specified
 495      * number of rows and columns.
 496      * @param     rows   the number of rows
 497      * @param     columns   the number of columns
 498      * @return    the preferred dimensions required to display
 499      *                       the text area with the specified
 500      *                       number of rows and columns
 501      * @see       java.awt.Component#getPreferredSize
 502      * @since     JDK1.1
 503      */
 504     public Dimension getPreferredSize(int rows, int columns) {
 505         return preferredSize(rows, columns);
 506     }
 507 
 508     /**
 509      * Determines the preferred size of the text area with the specified
 510      * number of rows and columns.
 511      * @param   rows     the number of rows
 512      * @param   columns  the number of columns
 513      * @return  the preferred dimensions needed for the text area
 514      * @deprecated As of JDK version 1.1,
 515      * replaced by <code>getPreferredSize(int, int)</code>.
 516      */
 517     @Deprecated
 518     public Dimension preferredSize(int rows, int columns) {
 519         synchronized (getTreeLock()) {
 520             TextAreaPeer peer = (TextAreaPeer)this.peer;
 521             return (peer != null) ?
 522                        peer.getPreferredSize(rows, columns) :
 523                        super.preferredSize();
 524         }
 525     }
 526 
 527     /**
 528      * Determines the preferred size of this text area.
 529      * @return    the preferred dimensions needed for this text area
 530      * @see       java.awt.Component#getPreferredSize
 531      * @since     JDK1.1
 532      */
 533     public Dimension getPreferredSize() {
 534         return preferredSize();
 535     }
 536 
 537     /**
 538      * @deprecated As of JDK version 1.1,
 539      * replaced by <code>getPreferredSize()</code>.
 540      */
 541     @Deprecated
 542     public Dimension preferredSize() {
 543         synchronized (getTreeLock()) {
 544             return ((rows > 0) && (columns > 0)) ?
 545                         preferredSize(rows, columns) :
 546                         super.preferredSize();
 547         }
 548     }
 549 
 550     /**
 551      * Determines the minimum size of a text area with the specified
 552      * number of rows and columns.
 553      * @param     rows   the number of rows
 554      * @param     columns   the number of columns
 555      * @return    the minimum dimensions required to display
 556      *                       the text area with the specified
 557      *                       number of rows and columns
 558      * @see       java.awt.Component#getMinimumSize
 559      * @since     JDK1.1
 560      */
 561     public Dimension getMinimumSize(int rows, int columns) {
 562         return minimumSize(rows, columns);
 563     }
 564 
 565     /**
 566      * Determines the minimum size of the text area with the specified
 567      * number of rows and columns.
 568      * @param rows     the number of rows
 569      * @param columns  the number of columns
 570      * @return  the minimum size for the text area
 571      * @deprecated As of JDK version 1.1,
 572      * replaced by <code>getMinimumSize(int, int)</code>.
 573      */
 574     @Deprecated
 575     public Dimension minimumSize(int rows, int columns) {
 576         synchronized (getTreeLock()) {
 577             TextAreaPeer peer = (TextAreaPeer)this.peer;
 578             return (peer != null) ?
 579                        peer.getMinimumSize(rows, columns) :
 580                        super.minimumSize();
 581         }
 582     }
 583 
 584     /**
 585      * Determines the minimum size of this text area.
 586      * @return    the preferred dimensions needed for this text area
 587      * @see       java.awt.Component#getPreferredSize
 588      * @since     JDK1.1
 589      */
 590     public Dimension getMinimumSize() {
 591         return minimumSize();
 592     }
 593 
 594     /**
 595      * @deprecated As of JDK version 1.1,
 596      * replaced by <code>getMinimumSize()</code>.
 597      */
 598     @Deprecated
 599     public Dimension minimumSize() {
 600         synchronized (getTreeLock()) {
 601             return ((rows > 0) && (columns > 0)) ?
 602                         minimumSize(rows, columns) :
 603                         super.minimumSize();
 604         }
 605     }
 606 
 607     /**
 608      * Returns a string representing the state of this <code>TextArea</code>.
 609      * This method is intended to be used only for debugging purposes, and the
 610      * content and format of the returned string may vary between
 611      * implementations. The returned string may be empty but may not be
 612      * <code>null</code>.
 613      *
 614      * @return      the parameter string of this text area
 615      */
 616     protected String paramString() {
 617         String sbVisStr;
 618         switch (scrollbarVisibility) {
 619             case SCROLLBARS_BOTH:
 620                 sbVisStr = "both";
 621                 break;
 622             case SCROLLBARS_VERTICAL_ONLY:
 623                 sbVisStr = "vertical-only";
 624                 break;
 625             case SCROLLBARS_HORIZONTAL_ONLY:
 626                 sbVisStr = "horizontal-only";
 627                 break;
 628             case SCROLLBARS_NONE:
 629                 sbVisStr = "none";
 630                 break;
 631             default:
 632                 sbVisStr = "invalid display policy";
 633         }
 634 
 635         return super.paramString() + ",rows=" + rows +
 636             ",columns=" + columns +
 637           ",scrollbarVisibility=" + sbVisStr;
 638     }
 639 
 640 
 641     /*
 642      * Serialization support.
 643      */
 644     /**
 645      * The textArea Serialized Data Version.
 646      *
 647      * @serial
 648      */
 649     private int textAreaSerializedDataVersion = 2;
 650 
 651     /**
 652      * Read the ObjectInputStream.
 653      * @exception HeadlessException if
 654      * <code>GraphicsEnvironment.isHeadless()</code> returns
 655      * <code>true</code>
 656      * @see java.awt.GraphicsEnvironment#isHeadless
 657      */
 658     private void readObject(ObjectInputStream s)
 659       throws ClassNotFoundException, IOException, HeadlessException
 660     {
 661         // HeadlessException will be thrown by TextComponent's readObject
 662         s.defaultReadObject();
 663 
 664         // Make sure the state we just read in for columns, rows,
 665         // and scrollbarVisibility has legal values
 666         if (columns < 0) {
 667             columns = 0;
 668         }
 669         if (rows < 0) {
 670             rows = 0;
 671         }
 672 
 673         if ((scrollbarVisibility < SCROLLBARS_BOTH) ||
 674             (scrollbarVisibility > SCROLLBARS_NONE)) {
 675             this.scrollbarVisibility = SCROLLBARS_BOTH;
 676         }
 677 
 678         if (textAreaSerializedDataVersion < 2) {
 679             setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 680                                   forwardTraversalKeys);
 681             setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 682                                   backwardTraversalKeys);
 683         }
 684     }
 685 
 686 
 687 /////////////////
 688 // Accessibility support
 689 ////////////////
 690 
 691 
 692     /**
 693      * Returns the <code>AccessibleContext</code> associated with
 694      * this <code>TextArea</code>. For text areas, the
 695      * <code>AccessibleContext</code> takes the form of an
 696      * <code>AccessibleAWTTextArea</code>.
 697      * A new <code>AccessibleAWTTextArea</code> instance is created if necessary.
 698      *
 699      * @return an <code>AccessibleAWTTextArea</code> that serves as the
 700      *         <code>AccessibleContext</code> of this <code>TextArea</code>
 701      * @since 1.3
 702      */
 703     public AccessibleContext getAccessibleContext() {
 704         if (accessibleContext == null) {
 705             accessibleContext = new AccessibleAWTTextArea();
 706         }
 707         return accessibleContext;
 708     }
 709 
 710     /**
 711      * This class implements accessibility support for the
 712      * <code>TextArea</code> class.  It provides an implementation of the
 713      * Java Accessibility API appropriate to text area user-interface elements.
 714      * @since 1.3
 715      */
 716     protected class AccessibleAWTTextArea extends AccessibleAWTTextComponent
 717     {
 718         /*
 719          * JDK 1.3 serialVersionUID
 720          */
 721         private static final long serialVersionUID = 3472827823632144419L;
 722 
 723         /**
 724          * Gets the state set of this object.
 725          *
 726          * @return an instance of AccessibleStateSet describing the states
 727          * of the object
 728          * @see AccessibleStateSet
 729          */
 730         public AccessibleStateSet getAccessibleStateSet() {
 731             AccessibleStateSet states = super.getAccessibleStateSet();
 732             states.add(AccessibleState.MULTI_LINE);
 733             return states;
 734         }
 735     }
 736 
 737 
 738 }