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