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