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