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 */ 127 @SuppressWarnings("serial") // Same-version serialization only 128 public class JTextArea extends JTextComponent { 129 130 /** 131 * @see #getUIClassID 132 * @see #readObject 133 */ 134 private static final String uiClassID = "TextAreaUI"; 135 136 /** 137 * Constructs a new TextArea. A default model is set, the initial string 138 * is null, and rows/columns are set to 0. 139 */ 140 public JTextArea() { 141 this(null, null, 0, 0); 142 } 143 144 /** 145 * Constructs a new TextArea with the specified text displayed. 146 * A default model is created and rows/columns are set to 0. 147 * 148 * @param text the text to be displayed, or null 149 */ 150 public JTextArea(String text) { 151 this(null, text, 0, 0); 152 } 153 154 /** 155 * Constructs a new empty TextArea with the specified number of 156 * rows and columns. A default model is created, and the initial 157 * string is null. 158 * 159 * @param rows the number of rows >= 0 160 * @param columns the number of columns >= 0 161 * @exception IllegalArgumentException if the rows or columns 162 * arguments are negative. 163 */ 164 public JTextArea(int rows, int columns) { 165 this(null, null, rows, columns); 166 } 167 168 /** 169 * Constructs a new TextArea with the specified text and number 170 * of rows and columns. A default model is created. 171 * 172 * @param text the text to be displayed, or null 173 * @param rows the number of rows >= 0 174 * @param columns the number of columns >= 0 175 * @exception IllegalArgumentException if the rows or columns 176 * arguments are negative. 177 */ 178 public JTextArea(String text, int rows, int columns) { 179 this(null, text, rows, columns); 180 } 181 182 /** 183 * Constructs a new JTextArea with the given document model, and defaults 184 * for all of the other arguments (null, 0, 0). 185 * 186 * @param doc the model to use 187 */ 188 public JTextArea(Document doc) { 189 this(doc, null, 0, 0); 190 } 191 192 /** 193 * Constructs a new JTextArea with the specified number of rows 194 * and columns, and the given model. All of the constructors 195 * feed through this constructor. 196 * 197 * @param doc the model to use, or create a default one if null 198 * @param text the text to be displayed, null if none 199 * @param rows the number of rows >= 0 200 * @param columns the number of columns >= 0 201 * @exception IllegalArgumentException if the rows or columns 202 * arguments are negative. 203 */ 204 public JTextArea(Document doc, String text, int rows, int columns) { 205 super(); 206 this.rows = rows; 207 this.columns = columns; 208 if (doc == null) { 209 doc = createDefaultModel(); 210 } 211 setDocument(doc); 212 if (text != null) { 213 setText(text); 214 select(0, 0); 215 } 216 if (rows < 0) { 217 throw new IllegalArgumentException("rows: " + rows); 218 } 219 if (columns < 0) { 220 throw new IllegalArgumentException("columns: " + columns); 221 } 222 LookAndFeel.installProperty(this, 223 "focusTraversalKeysForward", 224 JComponent. 225 getManagingFocusForwardTraversalKeys()); 226 LookAndFeel.installProperty(this, 227 "focusTraversalKeysBackward", 228 JComponent. 229 getManagingFocusBackwardTraversalKeys()); 230 } 231 232 /** 233 * Returns the class ID for the UI. 234 * 235 * @return the ID ("TextAreaUI") 236 * @see JComponent#getUIClassID 237 * @see UIDefaults#getUI 238 */ 239 public String getUIClassID() { 240 return uiClassID; 241 } 242 243 /** 244 * Creates the default implementation of the model 245 * to be used at construction if one isn't explicitly 246 * given. A new instance of PlainDocument is returned. 247 * 248 * @return the default document model 249 */ 250 protected Document createDefaultModel() { 251 return new PlainDocument(); 252 } 253 254 /** 255 * Sets the number of characters to expand tabs to. 256 * This will be multiplied by the maximum advance for 257 * variable width fonts. A PropertyChange event ("tabSize") is fired 258 * when the tab size changes. 259 * 260 * @param size number of characters to expand to 261 * @see #getTabSize 262 * @beaninfo 263 * preferred: true 264 * bound: true 265 * description: the number of characters to expand tabs to 266 */ 267 public void setTabSize(int size) { 268 Document doc = getDocument(); 269 if (doc != null) { 270 int old = getTabSize(); 271 doc.putProperty(PlainDocument.tabSizeAttribute, Integer.valueOf(size)); 272 firePropertyChange("tabSize", old, size); 273 } 274 } 275 276 /** 277 * Gets the number of characters used to expand tabs. If the document is 278 * null or doesn't have a tab setting, return a default of 8. 279 * 280 * @return the number of characters 281 */ 282 public int getTabSize() { 283 int size = 8; 284 Document doc = getDocument(); 285 if (doc != null) { 286 Integer i = (Integer) doc.getProperty(PlainDocument.tabSizeAttribute); 287 if (i != null) { 288 size = i.intValue(); 289 } 290 } 291 return size; 292 } 293 294 /** 295 * Sets the line-wrapping policy of the text area. If set 296 * to true the lines will be wrapped if they are too long 297 * to fit within the allocated width. If set to false, 298 * the lines will always be unwrapped. A <code>PropertyChange</code> 299 * event ("lineWrap") is fired when the policy is changed. 300 * By default this property is false. 301 * 302 * @param wrap indicates if lines should be wrapped 303 * @see #getLineWrap 304 * @beaninfo 305 * preferred: true 306 * bound: true 307 * description: should lines be wrapped 308 */ 309 public void setLineWrap(boolean wrap) { 310 boolean old = this.wrap; 311 this.wrap = wrap; 312 firePropertyChange("lineWrap", old, wrap); 313 } 314 315 /** 316 * Gets the line-wrapping policy of the text area. If set 317 * to true the lines will be wrapped if they are too long 318 * to fit within the allocated width. If set to false, 319 * the lines will always be unwrapped. 320 * 321 * @return if lines will be wrapped 322 */ 323 public boolean getLineWrap() { 324 return wrap; 325 } 326 327 /** 328 * Sets the style of wrapping used if the text area is wrapping 329 * lines. If set to true the lines will be wrapped at word 330 * boundaries (whitespace) if they are too long 331 * to fit within the allocated width. If set to false, 332 * the lines will be wrapped at character boundaries. 333 * By default this property is false. 334 * 335 * @param word indicates if word boundaries should be used 336 * for line wrapping 337 * @see #getWrapStyleWord 338 * @beaninfo 339 * preferred: false 340 * bound: true 341 * description: should wrapping occur at word boundaries 342 */ 343 public void setWrapStyleWord(boolean word) { 344 boolean old = this.word; 345 this.word = word; 346 firePropertyChange("wrapStyleWord", old, word); 347 } 348 349 /** 350 * Gets the style of wrapping used if the text area is wrapping 351 * lines. If set to true the lines will be wrapped at word 352 * boundaries (ie whitespace) if they are too long 353 * to fit within the allocated width. If set to false, 354 * the lines will be wrapped at character boundaries. 355 * 356 * @return if the wrap style should be word boundaries 357 * instead of character boundaries 358 * @see #setWrapStyleWord 359 */ 360 public boolean getWrapStyleWord() { 361 return word; 362 } 363 364 /** 365 * Translates an offset into the components text to a 366 * line number. 367 * 368 * @param offset the offset >= 0 369 * @return the line number >= 0 370 * @exception BadLocationException thrown if the offset is 371 * less than zero or greater than the document length. 372 */ 373 public int getLineOfOffset(int offset) throws BadLocationException { 374 Document doc = getDocument(); 375 if (offset < 0) { 376 throw new BadLocationException("Can't translate offset to line", -1); 377 } else if (offset > doc.getLength()) { 378 throw new BadLocationException("Can't translate offset to line", doc.getLength()+1); 379 } else { 380 Element map = getDocument().getDefaultRootElement(); 381 return map.getElementIndex(offset); 382 } 383 } 384 385 /** 386 * Determines the number of lines contained in the area. 387 * 388 * @return the number of lines > 0 389 */ 390 public int getLineCount() { 391 Element map = getDocument().getDefaultRootElement(); 392 return map.getElementCount(); 393 } 394 395 /** 396 * Determines the offset of the start of the given line. 397 * 398 * @param line the line number to translate >= 0 399 * @return the offset >= 0 400 * @exception BadLocationException thrown if the line is 401 * less than zero or greater or equal to the number of 402 * lines contained in the document (as reported by 403 * getLineCount). 404 */ 405 public int getLineStartOffset(int line) throws BadLocationException { 406 int lineCount = getLineCount(); 407 if (line < 0) { 408 throw new BadLocationException("Negative line", -1); 409 } else if (line >= lineCount) { 410 throw new BadLocationException("No such line", getDocument().getLength()+1); 411 } else { 412 Element map = getDocument().getDefaultRootElement(); 413 Element lineElem = map.getElement(line); 414 return lineElem.getStartOffset(); 415 } 416 } 417 418 /** 419 * Determines the offset of the end of the given line. 420 * 421 * @param line the line >= 0 422 * @return the offset >= 0 423 * @exception BadLocationException Thrown if the line is 424 * less than zero or greater or equal to the number of 425 * lines contained in the document (as reported by 426 * getLineCount). 427 */ 428 public int getLineEndOffset(int line) throws BadLocationException { 429 int lineCount = getLineCount(); 430 if (line < 0) { 431 throw new BadLocationException("Negative line", -1); 432 } else if (line >= lineCount) { 433 throw new BadLocationException("No such line", getDocument().getLength()+1); 434 } else { 435 Element map = getDocument().getDefaultRootElement(); 436 Element lineElem = map.getElement(line); 437 int endOffset = lineElem.getEndOffset(); 438 // hide the implicit break at the end of the document 439 return ((line == lineCount - 1) ? (endOffset - 1) : endOffset); 440 } 441 } 442 443 // --- java.awt.TextArea methods --------------------------------- 444 445 /** 446 * Inserts the specified text at the specified position. Does nothing 447 * if the model is null or if the text is null or empty. 448 * 449 * @param str the text to insert 450 * @param pos the position at which to insert >= 0 451 * @exception IllegalArgumentException if pos is an 452 * invalid position in the model 453 * @see TextComponent#setText 454 * @see #replaceRange 455 */ 456 public void insert(String str, int pos) { 457 Document doc = getDocument(); 458 if (doc != null) { 459 try { 460 doc.insertString(pos, str, null); 461 } catch (BadLocationException e) { 462 throw new IllegalArgumentException(e.getMessage()); 463 } 464 } 465 } 466 467 /** 468 * Appends the given text to the end of the document. Does nothing if 469 * the model is null or the string is null or empty. 470 * 471 * @param str the text to insert 472 * @see #insert 473 */ 474 public void append(String str) { 475 Document doc = getDocument(); 476 if (doc != null) { 477 try { 478 doc.insertString(doc.getLength(), str, null); 479 } catch (BadLocationException e) { 480 } 481 } 482 } 483 484 /** 485 * Replaces text from the indicated start to end position with the 486 * new text specified. Does nothing if the model is null. Simply 487 * does a delete if the new string is null or empty. 488 * 489 * @param str the text to use as the replacement 490 * @param start the start position >= 0 491 * @param end the end position >= start 492 * @exception IllegalArgumentException if part of the range is an 493 * invalid position in the model 494 * @see #insert 495 * @see #replaceRange 496 */ 497 public void replaceRange(String str, int start, int end) { 498 if (end < start) { 499 throw new IllegalArgumentException("end before start"); 500 } 501 Document doc = getDocument(); 502 if (doc != null) { 503 try { 504 if (doc instanceof AbstractDocument) { 505 ((AbstractDocument)doc).replace(start, end - start, str, 506 null); 507 } 508 else { 509 doc.remove(start, end - start); 510 doc.insertString(start, str, null); 511 } 512 } catch (BadLocationException e) { 513 throw new IllegalArgumentException(e.getMessage()); 514 } 515 } 516 } 517 518 /** 519 * Returns the number of rows in the TextArea. 520 * 521 * @return the number of rows >= 0 522 */ 523 public int getRows() { 524 return rows; 525 } 526 527 /** 528 * Sets the number of rows for this TextArea. Calls invalidate() after 529 * setting the new value. 530 * 531 * @param rows the number of rows >= 0 532 * @exception IllegalArgumentException if rows is less than 0 533 * @see #getRows 534 * @beaninfo 535 * description: the number of rows preferred for display 536 */ 537 public void setRows(int rows) { 538 int oldVal = this.rows; 539 if (rows < 0) { 540 throw new IllegalArgumentException("rows less than zero."); 541 } 542 if (rows != oldVal) { 543 this.rows = rows; 544 invalidate(); 545 } 546 } 547 548 /** 549 * Defines the meaning of the height of a row. This defaults to 550 * the height of the font. 551 * 552 * @return the height >= 1 553 */ 554 protected int getRowHeight() { 555 if (rowHeight == 0) { 556 FontMetrics metrics = getFontMetrics(getFont()); 557 rowHeight = metrics.getHeight(); 558 } 559 return rowHeight; 560 } 561 562 /** 563 * Returns the number of columns in the TextArea. 564 * 565 * @return number of columns >= 0 566 */ 567 public int getColumns() { 568 return columns; 569 } 570 571 /** 572 * Sets the number of columns for this TextArea. Does an invalidate() 573 * after setting the new value. 574 * 575 * @param columns the number of columns >= 0 576 * @exception IllegalArgumentException if columns is less than 0 577 * @see #getColumns 578 * @beaninfo 579 * description: the number of columns preferred for display 580 */ 581 public void setColumns(int columns) { 582 int oldVal = this.columns; 583 if (columns < 0) { 584 throw new IllegalArgumentException("columns less than zero."); 585 } 586 if (columns != oldVal) { 587 this.columns = columns; 588 invalidate(); 589 } 590 } 591 592 /** 593 * Gets column width. 594 * The meaning of what a column is can be considered a fairly weak 595 * notion for some fonts. This method is used to define the width 596 * of a column. By default this is defined to be the width of the 597 * character <em>m</em> for the font used. This method can be 598 * redefined to be some alternative amount. 599 * 600 * @return the column width >= 1 601 */ 602 protected int getColumnWidth() { 603 if (columnWidth == 0) { 604 FontMetrics metrics = getFontMetrics(getFont()); 605 columnWidth = metrics.charWidth('m'); 606 } 607 return columnWidth; 608 } 609 610 // --- Component methods ----------------------------------------- 611 612 /** 613 * Returns the preferred size of the TextArea. This is the 614 * maximum of the size needed to display the text and the 615 * size requested for the viewport. 616 * 617 * @return the size 618 */ 619 public Dimension getPreferredSize() { 620 Dimension d = super.getPreferredSize(); 621 d = (d == null) ? new Dimension(400,400) : d; 622 Insets insets = getInsets(); 623 624 if (columns != 0) { 625 d.width = Math.max(d.width, columns * getColumnWidth() + 626 insets.left + insets.right); 627 } 628 if (rows != 0) { 629 d.height = Math.max(d.height, rows * getRowHeight() + 630 insets.top + insets.bottom); 631 } 632 return d; 633 } 634 635 /** 636 * Sets the current font. This removes cached row height and column 637 * width so the new font will be reflected, and calls revalidate(). 638 * 639 * @param f the font to use as the current font 640 */ 641 public void setFont(Font f) { 642 super.setFont(f); 643 rowHeight = 0; 644 columnWidth = 0; 645 } 646 647 648 /** 649 * Returns a string representation of this JTextArea. This method 650 * is intended to be used only for debugging purposes, and the 651 * content and format of the returned string may vary between 652 * implementations. The returned string may be empty but may not 653 * be <code>null</code>. 654 * 655 * @return a string representation of this JTextArea. 656 */ 657 protected String paramString() { 658 String wrapString = (wrap ? 659 "true" : "false"); 660 String wordString = (word ? 661 "true" : "false"); 662 663 return super.paramString() + 664 ",colums=" + columns + 665 ",columWidth=" + columnWidth + 666 ",rows=" + rows + 667 ",rowHeight=" + rowHeight + 668 ",word=" + wordString + 669 ",wrap=" + wrapString; 670 } 671 672 // --- Scrollable methods ---------------------------------------- 673 674 /** 675 * Returns true if a viewport should always force the width of this 676 * Scrollable to match the width of the viewport. This is implemented 677 * to return true if the line wrapping policy is true, and false 678 * if lines are not being wrapped. 679 * 680 * @return true if a viewport should force the Scrollables width 681 * to match its own. 682 */ 683 public boolean getScrollableTracksViewportWidth() { 684 return (wrap) ? true : super.getScrollableTracksViewportWidth(); 685 } 686 687 /** 688 * Returns the preferred size of the viewport if this component 689 * is embedded in a JScrollPane. This uses the desired column 690 * and row settings if they have been set, otherwise the superclass 691 * behavior is used. 692 * 693 * @return The preferredSize of a JViewport whose view is this Scrollable. 694 * @see JViewport#getPreferredSize 695 */ 696 public Dimension getPreferredScrollableViewportSize() { 697 Dimension size = super.getPreferredScrollableViewportSize(); 698 size = (size == null) ? new Dimension(400,400) : size; 699 Insets insets = getInsets(); 700 701 size.width = (columns == 0) ? size.width : 702 columns * getColumnWidth() + insets.left + insets.right; 703 size.height = (rows == 0) ? size.height : 704 rows * getRowHeight() + insets.top + insets.bottom; 705 return size; 706 } 707 708 /** 709 * Components that display logical rows or columns should compute 710 * the scroll increment that will completely expose one new row 711 * or column, depending on the value of orientation. This is implemented 712 * to use the values returned by the <code>getRowHeight</code> and 713 * <code>getColumnWidth</code> methods. 714 * <p> 715 * Scrolling containers, like JScrollPane, will use this method 716 * each time the user requests a unit scroll. 717 * 718 * @param visibleRect the view area visible within the viewport 719 * @param orientation Either SwingConstants.VERTICAL or 720 * SwingConstants.HORIZONTAL. 721 * @param direction Less than zero to scroll up/left, 722 * greater than zero for down/right. 723 * @return The "unit" increment for scrolling in the specified direction 724 * @exception IllegalArgumentException for an invalid orientation 725 * @see JScrollBar#setUnitIncrement 726 * @see #getRowHeight 727 * @see #getColumnWidth 728 */ 729 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { 730 switch (orientation) { 731 case SwingConstants.VERTICAL: 732 return getRowHeight(); 733 case SwingConstants.HORIZONTAL: 734 return getColumnWidth(); 735 default: 736 throw new IllegalArgumentException("Invalid orientation: " + orientation); 737 } 738 } 739 740 /** 741 * See readObject() and writeObject() in JComponent for more 742 * information about serialization in Swing. 743 */ 744 private void writeObject(ObjectOutputStream s) throws IOException { 745 s.defaultWriteObject(); 746 if (getUIClassID().equals(uiClassID)) { 747 byte count = JComponent.getWriteObjCounter(this); 748 JComponent.setWriteObjCounter(this, --count); 749 if (count == 0 && ui != null) { 750 ui.installUI(this); 751 } 752 } 753 } 754 755 ///////////////// 756 // Accessibility support 757 //////////////// 758 759 760 /** 761 * Gets the AccessibleContext associated with this JTextArea. 762 * For JTextAreas, the AccessibleContext takes the form of an 763 * AccessibleJTextArea. 764 * A new AccessibleJTextArea instance is created if necessary. 765 * 766 * @return an AccessibleJTextArea that serves as the 767 * AccessibleContext of this JTextArea 768 */ 769 public AccessibleContext getAccessibleContext() { 770 if (accessibleContext == null) { 771 accessibleContext = new AccessibleJTextArea(); 772 } 773 return accessibleContext; 774 } 775 776 /** 777 * This class implements accessibility support for the 778 * <code>JTextArea</code> class. It provides an implementation of the 779 * Java Accessibility API appropriate to text area user-interface 780 * elements. 781 * <p> 782 * <strong>Warning:</strong> 783 * Serialized objects of this class will not be compatible with 784 * future Swing releases. The current serialization support is 785 * appropriate for short term storage or RMI between applications running 786 * the same version of Swing. As of 1.4, support for long term storage 787 * of all JavaBeans™ 788 * has been added to the <code>java.beans</code> package. 789 * Please see {@link java.beans.XMLEncoder}. 790 */ 791 @SuppressWarnings("serial") // Same-version serialization only 792 protected class AccessibleJTextArea extends AccessibleJTextComponent { 793 794 /** 795 * Gets the state set of this object. 796 * 797 * @return an instance of AccessibleStateSet describing the states 798 * of the object 799 * @see AccessibleStateSet 800 */ 801 public AccessibleStateSet getAccessibleStateSet() { 802 AccessibleStateSet states = super.getAccessibleStateSet(); 803 states.add(AccessibleState.MULTI_LINE); 804 return states; 805 } 806 } 807 808 // --- variables ------------------------------------------------- 809 810 private int rows; 811 private int columns; 812 private int columnWidth; 813 private int rowHeight; 814 private boolean wrap; 815 private boolean word; 816 817 }