1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing; 26 27 import java.awt.*; 28 import java.awt.event.*; 29 import javax.swing.text.*; 30 import javax.swing.plaf.*; 31 import javax.accessibility.*; 32 33 import java.util.Collections; 34 import java.util.Set; 35 import java.util.StringTokenizer; 36 37 import java.io.ObjectOutputStream; 38 import java.io.ObjectInputStream; 39 import java.io.IOException; 40 41 /** 42 * A <code>JTextArea</code> is a multi-line area that displays plain text. 43 * It is intended to be a lightweight component that provides source 44 * compatibility with the <code>java.awt.TextArea</code> class where it can 45 * reasonably do so. 46 * You can find information and examples of using all the text components in 47 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/text.html">Using Text Components</a>, 48 * a section in <em>The Java Tutorial.</em> 49 * 50 * <p> 51 * This component has capabilities not found in the 52 * <code>java.awt.TextArea</code> class. The superclass should be 53 * consulted for additional capabilities. 54 * Alternative multi-line text classes with 55 * more capabilities are <code>JTextPane</code> and <code>JEditorPane</code>. 56 * <p> 57 * The <code>java.awt.TextArea</code> internally handles scrolling. 58 * <code>JTextArea</code> is different in that it doesn't manage scrolling, 59 * but implements the swing <code>Scrollable</code> interface. This allows it 60 * to be placed inside a <code>JScrollPane</code> if scrolling 61 * behavior is desired, and used directly if scrolling is not desired. 62 * <p> 63 * The <code>java.awt.TextArea</code> has the ability to do line wrapping. 64 * This was controlled by the horizontal scrolling policy. Since 65 * scrolling is not done by <code>JTextArea</code> directly, backward 66 * compatibility must be provided another way. <code>JTextArea</code> has 67 * a bound property for line wrapping that controls whether or 68 * not it will wrap lines. By default, the line wrapping property 69 * is set to false (not wrapped). 70 * <p> 71 * <code>java.awt.TextArea</code> has two properties <code>rows</code> 72 * and <code>columns</code> that are used to determine the preferred size. 73 * <code>JTextArea</code> uses these properties to indicate the 74 * preferred size of the viewport when placed inside a <code>JScrollPane</code> 75 * to match the functionality provided by <code>java.awt.TextArea</code>. 76 * <code>JTextArea</code> has a preferred size of what is needed to 77 * display all of the text, so that it functions properly inside of 78 * a <code>JScrollPane</code>. If the value for <code>rows</code> 79 * or <code>columns</code> is equal to zero, 80 * the preferred size along that axis is used for 81 * the viewport preferred size along the same axis. 82 * <p> 83 * The <code>java.awt.TextArea</code> could be monitored for changes by adding 84 * a <code>TextListener</code> for <code>TextEvent</code>s. 85 * In the <code>JTextComponent</code> based 86 * components, changes are broadcasted from the model via a 87 * <code>DocumentEvent</code> to <code>DocumentListeners</code>. 88 * The <code>DocumentEvent</code> gives 89 * the location of the change and the kind of change if desired. 90 * The code fragment might look something like: 91 * <pre> 92 * DocumentListener myListener = ??; 93 * JTextArea myArea = ??; 94 * myArea.getDocument().addDocumentListener(myListener); 95 * </pre> 96 * 97 * <dl> 98 * <dt><b>Newlines</b> 99 * <dd> 100 * For a discussion on how newlines are handled, see 101 * <a href="text/DefaultEditorKit.html">DefaultEditorKit</a>. 102 * </dl> 103 * 104 * <p> 105 * <strong>Warning:</strong> Swing is not thread safe. For more 106 * information see <a 107 * href="package-summary.html#threading">Swing's Threading 108 * Policy</a>. 109 * <p> 110 * <strong>Warning:</strong> 111 * Serialized objects of this class will not be compatible with 112 * future Swing releases. The current serialization support is 113 * appropriate for short term storage or RMI between applications running 114 * the same version of Swing. As of 1.4, support for long term storage 115 * of all JavaBeans™ 116 * has been added to the <code>java.beans</code> package. 117 * Please see {@link java.beans.XMLEncoder}. 118 * 119 * @beaninfo 120 * attribute: isContainer false 121 * description: A multi-line area that displays plain text. 122 * 123 * @author Timothy Prinzing 124 * @see JTextPane 125 * @see JEditorPane 126 * @since 1.2 127 */ 128 @SuppressWarnings("serial") // Same-version serialization only 129 public class JTextArea extends JTextComponent { 130 131 /** 132 * @see #getUIClassID 133 * @see #readObject 134 */ 135 private static final String uiClassID = "TextAreaUI"; 136 137 /** 138 * Constructs a new TextArea. A default model is set, the initial string 139 * is null, and rows/columns are set to 0. 140 */ 141 public JTextArea() { 142 this(null, null, 0, 0); 143 } 144 145 /** 146 * Constructs a new TextArea with the specified text displayed. 147 * A default model is created and rows/columns are set to 0. 148 * 149 * @param text the text to be displayed, or null 150 */ 151 public JTextArea(String text) { 152 this(null, text, 0, 0); 153 } 154 155 /** 156 * Constructs a new empty TextArea with the specified number of 157 * rows and columns. A default model is created, and the initial 158 * string is null. 159 * 160 * @param rows the number of rows >= 0 161 * @param columns the number of columns >= 0 162 * @exception IllegalArgumentException if the rows or columns 163 * arguments are negative. 164 */ 165 public JTextArea(int rows, int columns) { 166 this(null, null, rows, columns); 167 } 168 169 /** 170 * Constructs a new TextArea with the specified text and number 171 * of rows and columns. A default model is created. 172 * 173 * @param text the text to be displayed, or null 174 * @param rows the number of rows >= 0 175 * @param columns the number of columns >= 0 176 * @exception IllegalArgumentException if the rows or columns 177 * arguments are negative. 178 */ 179 public JTextArea(String text, int rows, int columns) { 180 this(null, text, rows, columns); 181 } 182 183 /** 184 * Constructs a new JTextArea with the given document model, and defaults 185 * for all of the other arguments (null, 0, 0). 186 * 187 * @param doc the model to use 188 */ 189 public JTextArea(Document doc) { 190 this(doc, null, 0, 0); 191 } 192 193 /** 194 * Constructs a new JTextArea with the specified number of rows 195 * and columns, and the given model. All of the constructors 196 * feed through this constructor. 197 * 198 * @param doc the model to use, or create a default one if null 199 * @param text the text to be displayed, null if none 200 * @param rows the number of rows >= 0 201 * @param columns the number of columns >= 0 202 * @exception IllegalArgumentException if the rows or columns 203 * arguments are negative. 204 */ 205 public JTextArea(Document doc, String text, int rows, int columns) { 206 super(); 207 this.rows = rows; 208 this.columns = columns; 209 if (doc == null) { 210 doc = createDefaultModel(); 211 } 212 setDocument(doc); 213 if (text != null) { 214 setText(text); 215 select(0, 0); 216 } 217 if (rows < 0) { 218 throw new IllegalArgumentException("rows: " + rows); 219 } 220 if (columns < 0) { 221 throw new IllegalArgumentException("columns: " + columns); 222 } 223 LookAndFeel.installProperty(this, 224 "focusTraversalKeysForward", 225 JComponent. 226 getManagingFocusForwardTraversalKeys()); 227 LookAndFeel.installProperty(this, 228 "focusTraversalKeysBackward", 229 JComponent. 230 getManagingFocusBackwardTraversalKeys()); 231 } 232 233 /** 234 * Returns the class ID for the UI. 235 * 236 * @return the ID ("TextAreaUI") 237 * @see JComponent#getUIClassID 238 * @see UIDefaults#getUI 239 */ 240 public String getUIClassID() { 241 return uiClassID; 242 } 243 244 /** 245 * Creates the default implementation of the model 246 * to be used at construction if one isn't explicitly 247 * given. A new instance of PlainDocument is returned. 248 * 249 * @return the default document model 250 */ 251 protected Document createDefaultModel() { 252 return new PlainDocument(); 253 } 254 255 /** 256 * Sets the number of characters to expand tabs to. 257 * This will be multiplied by the maximum advance for 258 * variable width fonts. A PropertyChange event ("tabSize") is fired 259 * when the tab size changes. 260 * 261 * @param size number of characters to expand to 262 * @see #getTabSize 263 * @beaninfo 264 * preferred: true 265 * bound: true 266 * description: the number of characters to expand tabs to 267 */ 268 public void setTabSize(int size) { 269 Document doc = getDocument(); 270 if (doc != null) { 271 int old = getTabSize(); 272 doc.putProperty(PlainDocument.tabSizeAttribute, Integer.valueOf(size)); 273 firePropertyChange("tabSize", old, size); 274 } 275 } 276 277 /** 278 * Gets the number of characters used to expand tabs. If the document is 279 * null or doesn't have a tab setting, return a default of 8. 280 * 281 * @return the number of characters 282 */ 283 public int getTabSize() { 284 int size = 8; 285 Document doc = getDocument(); 286 if (doc != null) { 287 Integer i = (Integer) doc.getProperty(PlainDocument.tabSizeAttribute); 288 if (i != null) { 289 size = i.intValue(); 290 } 291 } 292 return size; 293 } 294 295 /** 296 * Sets the line-wrapping policy of the text area. If set 297 * to true the lines will be wrapped if they are too long 298 * to fit within the allocated width. If set to false, 299 * the lines will always be unwrapped. A <code>PropertyChange</code> 300 * event ("lineWrap") is fired when the policy is changed. 301 * By default this property is false. 302 * 303 * @param wrap indicates if lines should be wrapped 304 * @see #getLineWrap 305 * @beaninfo 306 * preferred: true 307 * bound: true 308 * description: should lines be wrapped 309 */ 310 public void setLineWrap(boolean wrap) { 311 boolean old = this.wrap; 312 this.wrap = wrap; 313 firePropertyChange("lineWrap", old, wrap); 314 } 315 316 /** 317 * Gets the line-wrapping policy of the text area. If set 318 * to true the lines will be wrapped if they are too long 319 * to fit within the allocated width. If set to false, 320 * the lines will always be unwrapped. 321 * 322 * @return if lines will be wrapped 323 */ 324 public boolean getLineWrap() { 325 return wrap; 326 } 327 328 /** 329 * Sets the style of wrapping used if the text area is wrapping 330 * lines. If set to true the lines will be wrapped at word 331 * boundaries (whitespace) if they are too long 332 * to fit within the allocated width. If set to false, 333 * the lines will be wrapped at character boundaries. 334 * By default this property is false. 335 * 336 * @param word indicates if word boundaries should be used 337 * for line wrapping 338 * @see #getWrapStyleWord 339 * @beaninfo 340 * preferred: false 341 * bound: true 342 * description: should wrapping occur at word boundaries 343 */ 344 public void setWrapStyleWord(boolean word) { 345 boolean old = this.word; 346 this.word = word; 347 firePropertyChange("wrapStyleWord", old, word); 348 } 349 350 /** 351 * Gets the style of wrapping used if the text area is wrapping 352 * lines. If set to true the lines will be wrapped at word 353 * boundaries (ie whitespace) if they are too long 354 * to fit within the allocated width. If set to false, 355 * the lines will be wrapped at character boundaries. 356 * 357 * @return if the wrap style should be word boundaries 358 * instead of character boundaries 359 * @see #setWrapStyleWord 360 */ 361 public boolean getWrapStyleWord() { 362 return word; 363 } 364 365 /** 366 * Translates an offset into the components text to a 367 * line number. 368 * 369 * @param offset the offset >= 0 370 * @return the line number >= 0 371 * @exception BadLocationException thrown if the offset is 372 * less than zero or greater than the document length. 373 */ 374 public int getLineOfOffset(int offset) throws BadLocationException { 375 Document doc = getDocument(); 376 if (offset < 0) { 377 throw new BadLocationException("Can't translate offset to line", -1); 378 } else if (offset > doc.getLength()) { 379 throw new BadLocationException("Can't translate offset to line", doc.getLength()+1); 380 } else { 381 Element map = getDocument().getDefaultRootElement(); 382 return map.getElementIndex(offset); 383 } 384 } 385 386 /** 387 * Determines the number of lines contained in the area. 388 * 389 * @return the number of lines > 0 390 */ 391 public int getLineCount() { 392 Element map = getDocument().getDefaultRootElement(); 393 return map.getElementCount(); 394 } 395 396 /** 397 * Determines the offset of the start of the given line. 398 * 399 * @param line the line number to translate >= 0 400 * @return the offset >= 0 401 * @exception BadLocationException thrown if the line is 402 * less than zero or greater or equal to the number of 403 * lines contained in the document (as reported by 404 * getLineCount). 405 */ 406 public int getLineStartOffset(int line) throws BadLocationException { 407 int lineCount = getLineCount(); 408 if (line < 0) { 409 throw new BadLocationException("Negative line", -1); 410 } else if (line >= lineCount) { 411 throw new BadLocationException("No such line", getDocument().getLength()+1); 412 } else { 413 Element map = getDocument().getDefaultRootElement(); 414 Element lineElem = map.getElement(line); 415 return lineElem.getStartOffset(); 416 } 417 } 418 419 /** 420 * Determines the offset of the end of the given line. 421 * 422 * @param line the line >= 0 423 * @return the offset >= 0 424 * @exception BadLocationException Thrown if the line is 425 * less than zero or greater or equal to the number of 426 * lines contained in the document (as reported by 427 * getLineCount). 428 */ 429 public int getLineEndOffset(int line) throws BadLocationException { 430 int lineCount = getLineCount(); 431 if (line < 0) { 432 throw new BadLocationException("Negative line", -1); 433 } else if (line >= lineCount) { 434 throw new BadLocationException("No such line", getDocument().getLength()+1); 435 } else { 436 Element map = getDocument().getDefaultRootElement(); 437 Element lineElem = map.getElement(line); 438 int endOffset = lineElem.getEndOffset(); 439 // hide the implicit break at the end of the document 440 return ((line == lineCount - 1) ? (endOffset - 1) : endOffset); 441 } 442 } 443 444 // --- java.awt.TextArea methods --------------------------------- 445 446 /** 447 * Inserts the specified text at the specified position. Does nothing 448 * if the model is null or if the text is null or empty. 449 * 450 * @param str the text to insert 451 * @param pos the position at which to insert >= 0 452 * @exception IllegalArgumentException if pos is an 453 * invalid position in the model 454 * @see TextComponent#setText 455 * @see #replaceRange 456 */ 457 public void insert(String str, int pos) { 458 Document doc = getDocument(); 459 if (doc != null) { 460 try { 461 doc.insertString(pos, str, null); 462 } catch (BadLocationException e) { 463 throw new IllegalArgumentException(e.getMessage()); 464 } 465 } 466 } 467 468 /** 469 * Appends the given text to the end of the document. Does nothing if 470 * the model is null or the string is null or empty. 471 * 472 * @param str the text to insert 473 * @see #insert 474 */ 475 public void append(String str) { 476 Document doc = getDocument(); 477 if (doc != null) { 478 try { 479 doc.insertString(doc.getLength(), str, null); 480 } catch (BadLocationException e) { 481 } 482 } 483 } 484 485 /** 486 * Replaces text from the indicated start to end position with the 487 * new text specified. Does nothing if the model is null. Simply 488 * does a delete if the new string is null or empty. 489 * 490 * @param str the text to use as the replacement 491 * @param start the start position >= 0 492 * @param end the end position >= start 493 * @exception IllegalArgumentException if part of the range is an 494 * invalid position in the model 495 * @see #insert 496 * @see #replaceRange 497 */ 498 public void replaceRange(String str, int start, int end) { 499 if (end < start) { 500 throw new IllegalArgumentException("end before start"); 501 } 502 Document doc = getDocument(); 503 if (doc != null) { 504 try { 505 if (doc instanceof AbstractDocument) { 506 ((AbstractDocument)doc).replace(start, end - start, str, 507 null); 508 } 509 else { 510 doc.remove(start, end - start); 511 doc.insertString(start, str, null); 512 } 513 } catch (BadLocationException e) { 514 throw new IllegalArgumentException(e.getMessage()); 515 } 516 } 517 } 518 519 /** 520 * Returns the number of rows in the TextArea. 521 * 522 * @return the number of rows >= 0 523 */ 524 public int getRows() { 525 return rows; 526 } 527 528 /** 529 * Sets the number of rows for this TextArea. Calls invalidate() after 530 * setting the new value. 531 * 532 * @param rows the number of rows >= 0 533 * @exception IllegalArgumentException if rows is less than 0 534 * @see #getRows 535 * @beaninfo 536 * description: the number of rows preferred for display 537 */ 538 public void setRows(int rows) { 539 int oldVal = this.rows; 540 if (rows < 0) { 541 throw new IllegalArgumentException("rows less than zero."); 542 } 543 if (rows != oldVal) { 544 this.rows = rows; 545 invalidate(); 546 } 547 } 548 549 /** 550 * Defines the meaning of the height of a row. This defaults to 551 * the height of the font. 552 * 553 * @return the height >= 1 554 */ 555 protected int getRowHeight() { 556 if (rowHeight == 0) { 557 FontMetrics metrics = getFontMetrics(getFont()); 558 rowHeight = metrics.getHeight(); 559 } 560 return rowHeight; 561 } 562 563 /** 564 * Returns the number of columns in the TextArea. 565 * 566 * @return number of columns >= 0 567 */ 568 public int getColumns() { 569 return columns; 570 } 571 572 /** 573 * Sets the number of columns for this TextArea. Does an invalidate() 574 * after setting the new value. 575 * 576 * @param columns the number of columns >= 0 577 * @exception IllegalArgumentException if columns is less than 0 578 * @see #getColumns 579 * @beaninfo 580 * description: the number of columns preferred for display 581 */ 582 public void setColumns(int columns) { 583 int oldVal = this.columns; 584 if (columns < 0) { 585 throw new IllegalArgumentException("columns less than zero."); 586 } 587 if (columns != oldVal) { 588 this.columns = columns; 589 invalidate(); 590 } 591 } 592 593 /** 594 * Gets column width. 595 * The meaning of what a column is can be considered a fairly weak 596 * notion for some fonts. This method is used to define the width 597 * of a column. By default this is defined to be the width of the 598 * character <em>m</em> for the font used. This method can be 599 * redefined to be some alternative amount. 600 * 601 * @return the column width >= 1 602 */ 603 protected int getColumnWidth() { 604 if (columnWidth == 0) { 605 FontMetrics metrics = getFontMetrics(getFont()); 606 columnWidth = metrics.charWidth('m'); 607 } 608 return columnWidth; 609 } 610 611 // --- Component methods ----------------------------------------- 612 613 /** 614 * Returns the preferred size of the TextArea. This is the 615 * maximum of the size needed to display the text and the 616 * size requested for the viewport. 617 * 618 * @return the size 619 */ 620 public Dimension getPreferredSize() { 621 Dimension d = super.getPreferredSize(); 622 d = (d == null) ? new Dimension(400,400) : d; 623 Insets insets = getInsets(); 624 625 if (columns != 0) { 626 d.width = Math.max(d.width, columns * getColumnWidth() + 627 insets.left + insets.right); 628 } 629 if (rows != 0) { 630 d.height = Math.max(d.height, rows * getRowHeight() + 631 insets.top + insets.bottom); 632 } 633 return d; 634 } 635 636 /** 637 * Sets the current font. This removes cached row height and column 638 * width so the new font will be reflected, and calls revalidate(). 639 * 640 * @param f the font to use as the current font 641 */ 642 public void setFont(Font f) { 643 super.setFont(f); 644 rowHeight = 0; 645 columnWidth = 0; 646 } 647 648 649 /** 650 * Returns a string representation of this JTextArea. This method 651 * is intended to be used only for debugging purposes, and the 652 * content and format of the returned string may vary between 653 * implementations. The returned string may be empty but may not 654 * be <code>null</code>. 655 * 656 * @return a string representation of this JTextArea. 657 */ 658 protected String paramString() { 659 String wrapString = (wrap ? 660 "true" : "false"); 661 String wordString = (word ? 662 "true" : "false"); 663 664 return super.paramString() + 665 ",colums=" + columns + 666 ",columWidth=" + columnWidth + 667 ",rows=" + rows + 668 ",rowHeight=" + rowHeight + 669 ",word=" + wordString + 670 ",wrap=" + wrapString; 671 } 672 673 // --- Scrollable methods ---------------------------------------- 674 675 /** 676 * Returns true if a viewport should always force the width of this 677 * Scrollable to match the width of the viewport. This is implemented 678 * to return true if the line wrapping policy is true, and false 679 * if lines are not being wrapped. 680 * 681 * @return true if a viewport should force the Scrollables width 682 * to match its own. 683 */ 684 public boolean getScrollableTracksViewportWidth() { 685 return (wrap) ? true : super.getScrollableTracksViewportWidth(); 686 } 687 688 /** 689 * Returns the preferred size of the viewport if this component 690 * is embedded in a JScrollPane. This uses the desired column 691 * and row settings if they have been set, otherwise the superclass 692 * behavior is used. 693 * 694 * @return The preferredSize of a JViewport whose view is this Scrollable. 695 * @see JViewport#getPreferredSize 696 */ 697 public Dimension getPreferredScrollableViewportSize() { 698 Dimension size = super.getPreferredScrollableViewportSize(); 699 size = (size == null) ? new Dimension(400,400) : size; 700 Insets insets = getInsets(); 701 702 size.width = (columns == 0) ? size.width : 703 columns * getColumnWidth() + insets.left + insets.right; 704 size.height = (rows == 0) ? size.height : 705 rows * getRowHeight() + insets.top + insets.bottom; 706 return size; 707 } 708 709 /** 710 * Components that display logical rows or columns should compute 711 * the scroll increment that will completely expose one new row 712 * or column, depending on the value of orientation. This is implemented 713 * to use the values returned by the <code>getRowHeight</code> and 714 * <code>getColumnWidth</code> methods. 715 * <p> 716 * Scrolling containers, like JScrollPane, will use this method 717 * each time the user requests a unit scroll. 718 * 719 * @param visibleRect the view area visible within the viewport 720 * @param orientation Either SwingConstants.VERTICAL or 721 * SwingConstants.HORIZONTAL. 722 * @param direction Less than zero to scroll up/left, 723 * greater than zero for down/right. 724 * @return The "unit" increment for scrolling in the specified direction 725 * @exception IllegalArgumentException for an invalid orientation 726 * @see JScrollBar#setUnitIncrement 727 * @see #getRowHeight 728 * @see #getColumnWidth 729 */ 730 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { 731 switch (orientation) { 732 case SwingConstants.VERTICAL: 733 return getRowHeight(); 734 case SwingConstants.HORIZONTAL: 735 return getColumnWidth(); 736 default: 737 throw new IllegalArgumentException("Invalid orientation: " + orientation); 738 } 739 } 740 741 /** 742 * See readObject() and writeObject() in JComponent for more 743 * information about serialization in Swing. 744 */ 745 private void writeObject(ObjectOutputStream s) throws IOException { 746 s.defaultWriteObject(); 747 if (getUIClassID().equals(uiClassID)) { 748 byte count = JComponent.getWriteObjCounter(this); 749 JComponent.setWriteObjCounter(this, --count); 750 if (count == 0 && ui != null) { 751 ui.installUI(this); 752 } 753 } 754 } 755 756 ///////////////// 757 // Accessibility support 758 //////////////// 759 760 761 /** 762 * Gets the AccessibleContext associated with this JTextArea. 763 * For JTextAreas, the AccessibleContext takes the form of an 764 * AccessibleJTextArea. 765 * A new AccessibleJTextArea instance is created if necessary. 766 * 767 * @return an AccessibleJTextArea that serves as the 768 * AccessibleContext of this JTextArea 769 */ 770 public AccessibleContext getAccessibleContext() { 771 if (accessibleContext == null) { 772 accessibleContext = new AccessibleJTextArea(); 773 } 774 return accessibleContext; 775 } 776 777 /** 778 * This class implements accessibility support for the 779 * <code>JTextArea</code> class. It provides an implementation of the 780 * Java Accessibility API appropriate to text area user-interface 781 * elements. 782 * <p> 783 * <strong>Warning:</strong> 784 * Serialized objects of this class will not be compatible with 785 * future Swing releases. The current serialization support is 786 * appropriate for short term storage or RMI between applications running 787 * the same version of Swing. As of 1.4, support for long term storage 788 * of all JavaBeans™ 789 * has been added to the <code>java.beans</code> package. 790 * Please see {@link java.beans.XMLEncoder}. 791 */ 792 @SuppressWarnings("serial") // Same-version serialization only 793 protected class AccessibleJTextArea extends AccessibleJTextComponent { 794 795 /** 796 * Gets the state set of this object. 797 * 798 * @return an instance of AccessibleStateSet describing the states 799 * of the object 800 * @see AccessibleStateSet 801 */ 802 public AccessibleStateSet getAccessibleStateSet() { 803 AccessibleStateSet states = super.getAccessibleStateSet(); 804 states.add(AccessibleState.MULTI_LINE); 805 return states; 806 } 807 } 808 809 // --- variables ------------------------------------------------- 810 811 private int rows; 812 private int columns; 813 private int columnWidth; 814 private int rowHeight; 815 private boolean wrap; 816 private boolean word; 817 818 }