blob: 8f53daf2aca917c52853dcbe7cb3aa4271178563 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package javax.swing;
26
27import java.awt.*;
28import java.awt.event.*;
29import javax.swing.text.*;
30import javax.swing.plaf.*;
31import javax.accessibility.*;
32
33import java.util.Collections;
34import java.util.Set;
35import java.util.StringTokenizer;
36
37import java.io.ObjectOutputStream;
38import java.io.ObjectInputStream;
39import 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://java.sun.com/docs/books/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 */
127public 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, new Integer(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 * <p>
448 * This method is thread safe, although most Swing methods
449 * are not. Please see
450 * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How
451 * to Use Threads</A> for more information.
452 *
453 * @param str the text to insert
454 * @param pos the position at which to insert >= 0
455 * @exception IllegalArgumentException if pos is an
456 * invalid position in the model
457 * @see TextComponent#setText
458 * @see #replaceRange
459 */
460 public void insert(String str, int pos) {
461 Document doc = getDocument();
462 if (doc != null) {
463 try {
464 doc.insertString(pos, str, null);
465 } catch (BadLocationException e) {
466 throw new IllegalArgumentException(e.getMessage());
467 }
468 }
469 }
470
471 /**
472 * Appends the given text to the end of the document. Does nothing if
473 * the model is null or the string is null or empty.
474 * <p>
475 * This method is thread safe, although most Swing methods
476 * are not. Please see
477 * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How
478 * to Use Threads</A> for more information.
479 *
480 * @param str the text to insert
481 * @see #insert
482 */
483 public void append(String str) {
484 Document doc = getDocument();
485 if (doc != null) {
486 try {
487 doc.insertString(doc.getLength(), str, null);
488 } catch (BadLocationException e) {
489 }
490 }
491 }
492
493 /**
494 * Replaces text from the indicated start to end position with the
495 * new text specified. Does nothing if the model is null. Simply
496 * does a delete if the new string is null or empty.
497 * <p>
498 * This method is thread safe, although most Swing methods
499 * are not. Please see
500 * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How
501 * to Use Threads</A> for more information.
502 *
503 * @param str the text to use as the replacement
504 * @param start the start position >= 0
505 * @param end the end position >= start
506 * @exception IllegalArgumentException if part of the range is an
507 * invalid position in the model
508 * @see #insert
509 * @see #replaceRange
510 */
511 public void replaceRange(String str, int start, int end) {
512 if (end < start) {
513 throw new IllegalArgumentException("end before start");
514 }
515 Document doc = getDocument();
516 if (doc != null) {
517 try {
518 if (doc instanceof AbstractDocument) {
519 ((AbstractDocument)doc).replace(start, end - start, str,
520 null);
521 }
522 else {
523 doc.remove(start, end - start);
524 doc.insertString(start, str, null);
525 }
526 } catch (BadLocationException e) {
527 throw new IllegalArgumentException(e.getMessage());
528 }
529 }
530 }
531
532 /**
533 * Returns the number of rows in the TextArea.
534 *
535 * @return the number of rows >= 0
536 */
537 public int getRows() {
538 return rows;
539 }
540
541 /**
542 * Sets the number of rows for this TextArea. Calls invalidate() after
543 * setting the new value.
544 *
545 * @param rows the number of rows >= 0
546 * @exception IllegalArgumentException if rows is less than 0
547 * @see #getRows
548 * @beaninfo
549 * description: the number of rows preferred for display
550 */
551 public void setRows(int rows) {
552 int oldVal = this.rows;
553 if (rows < 0) {
554 throw new IllegalArgumentException("rows less than zero.");
555 }
556 if (rows != oldVal) {
557 this.rows = rows;
558 invalidate();
559 }
560 }
561
562 /**
563 * Defines the meaning of the height of a row. This defaults to
564 * the height of the font.
565 *
566 * @return the height >= 1
567 */
568 protected int getRowHeight() {
569 if (rowHeight == 0) {
570 FontMetrics metrics = getFontMetrics(getFont());
571 rowHeight = metrics.getHeight();
572 }
573 return rowHeight;
574 }
575
576 /**
577 * Returns the number of columns in the TextArea.
578 *
579 * @return number of columns >= 0
580 */
581 public int getColumns() {
582 return columns;
583 }
584
585 /**
586 * Sets the number of columns for this TextArea. Does an invalidate()
587 * after setting the new value.
588 *
589 * @param columns the number of columns >= 0
590 * @exception IllegalArgumentException if columns is less than 0
591 * @see #getColumns
592 * @beaninfo
593 * description: the number of columns preferred for display
594 */
595 public void setColumns(int columns) {
596 int oldVal = this.columns;
597 if (columns < 0) {
598 throw new IllegalArgumentException("columns less than zero.");
599 }
600 if (columns != oldVal) {
601 this.columns = columns;
602 invalidate();
603 }
604 }
605
606 /**
607 * Gets column width.
608 * The meaning of what a column is can be considered a fairly weak
609 * notion for some fonts. This method is used to define the width
610 * of a column. By default this is defined to be the width of the
611 * character <em>m</em> for the font used. This method can be
612 * redefined to be some alternative amount.
613 *
614 * @return the column width >= 1
615 */
616 protected int getColumnWidth() {
617 if (columnWidth == 0) {
618 FontMetrics metrics = getFontMetrics(getFont());
619 columnWidth = metrics.charWidth('m');
620 }
621 return columnWidth;
622 }
623
624 // --- Component methods -----------------------------------------
625
626 /**
627 * Returns the preferred size of the TextArea. This is the
628 * maximum of the size needed to display the text and the
629 * size requested for the viewport.
630 *
631 * @return the size
632 */
633 public Dimension getPreferredSize() {
634 Dimension d = super.getPreferredSize();
635 d = (d == null) ? new Dimension(400,400) : d;
636 Insets insets = getInsets();
637
638 if (columns != 0) {
639 d.width = Math.max(d.width, columns * getColumnWidth() +
640 insets.left + insets.right);
641 }
642 if (rows != 0) {
643 d.height = Math.max(d.height, rows * getRowHeight() +
644 insets.top + insets.bottom);
645 }
646 return d;
647 }
648
649 /**
650 * Sets the current font. This removes cached row height and column
651 * width so the new font will be reflected, and calls revalidate().
652 *
653 * @param f the font to use as the current font
654 */
655 public void setFont(Font f) {
656 super.setFont(f);
657 rowHeight = 0;
658 columnWidth = 0;
659 }
660
661
662 /**
663 * Returns a string representation of this JTextArea. This method
664 * is intended to be used only for debugging purposes, and the
665 * content and format of the returned string may vary between
666 * implementations. The returned string may be empty but may not
667 * be <code>null</code>.
668 *
669 * @return a string representation of this JTextArea.
670 */
671 protected String paramString() {
672 String wrapString = (wrap ?
673 "true" : "false");
674 String wordString = (word ?
675 "true" : "false");
676
677 return super.paramString() +
678 ",colums=" + columns +
679 ",columWidth=" + columnWidth +
680 ",rows=" + rows +
681 ",rowHeight=" + rowHeight +
682 ",word=" + wordString +
683 ",wrap=" + wrapString;
684 }
685
686 // --- Scrollable methods ----------------------------------------
687
688 /**
689 * Returns true if a viewport should always force the width of this
690 * Scrollable to match the width of the viewport. This is implemented
691 * to return true if the line wrapping policy is true, and false
692 * if lines are not being wrapped.
693 *
694 * @return true if a viewport should force the Scrollables width
695 * to match its own.
696 */
697 public boolean getScrollableTracksViewportWidth() {
698 return (wrap) ? true : super.getScrollableTracksViewportWidth();
699 }
700
701 /**
702 * Returns the preferred size of the viewport if this component
703 * is embedded in a JScrollPane. This uses the desired column
704 * and row settings if they have been set, otherwise the superclass
705 * behavior is used.
706 *
707 * @return The preferredSize of a JViewport whose view is this Scrollable.
708 * @see JViewport#getPreferredSize
709 */
710 public Dimension getPreferredScrollableViewportSize() {
711 Dimension size = super.getPreferredScrollableViewportSize();
712 size = (size == null) ? new Dimension(400,400) : size;
713 Insets insets = getInsets();
714
715 size.width = (columns == 0) ? size.width :
716 columns * getColumnWidth() + insets.left + insets.right;
717 size.height = (rows == 0) ? size.height :
718 rows * getRowHeight() + insets.top + insets.bottom;
719 return size;
720 }
721
722 /**
723 * Components that display logical rows or columns should compute
724 * the scroll increment that will completely expose one new row
725 * or column, depending on the value of orientation. This is implemented
726 * to use the values returned by the <code>getRowHeight</code> and
727 * <code>getColumnWidth</code> methods.
728 * <p>
729 * Scrolling containers, like JScrollPane, will use this method
730 * each time the user requests a unit scroll.
731 *
732 * @param visibleRect the view area visible within the viewport
733 * @param orientation Either SwingConstants.VERTICAL or
734 * SwingConstants.HORIZONTAL.
735 * @param direction Less than zero to scroll up/left,
736 * greater than zero for down/right.
737 * @return The "unit" increment for scrolling in the specified direction
738 * @exception IllegalArgumentException for an invalid orientation
739 * @see JScrollBar#setUnitIncrement
740 * @see #getRowHeight
741 * @see #getColumnWidth
742 */
743 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
744 switch (orientation) {
745 case SwingConstants.VERTICAL:
746 return getRowHeight();
747 case SwingConstants.HORIZONTAL:
748 return getColumnWidth();
749 default:
750 throw new IllegalArgumentException("Invalid orientation: " + orientation);
751 }
752 }
753
754 /**
755 * See readObject() and writeObject() in JComponent for more
756 * information about serialization in Swing.
757 */
758 private void writeObject(ObjectOutputStream s) throws IOException {
759 s.defaultWriteObject();
760 if (getUIClassID().equals(uiClassID)) {
761 byte count = JComponent.getWriteObjCounter(this);
762 JComponent.setWriteObjCounter(this, --count);
763 if (count == 0 && ui != null) {
764 ui.installUI(this);
765 }
766 }
767 }
768
769/////////////////
770// Accessibility support
771////////////////
772
773
774 /**
775 * Gets the AccessibleContext associated with this JTextArea.
776 * For JTextAreas, the AccessibleContext takes the form of an
777 * AccessibleJTextArea.
778 * A new AccessibleJTextArea instance is created if necessary.
779 *
780 * @return an AccessibleJTextArea that serves as the
781 * AccessibleContext of this JTextArea
782 */
783 public AccessibleContext getAccessibleContext() {
784 if (accessibleContext == null) {
785 accessibleContext = new AccessibleJTextArea();
786 }
787 return accessibleContext;
788 }
789
790 /**
791 * This class implements accessibility support for the
792 * <code>JTextArea</code> class. It provides an implementation of the
793 * Java Accessibility API appropriate to text area user-interface
794 * elements.
795 * <p>
796 * <strong>Warning:</strong>
797 * Serialized objects of this class will not be compatible with
798 * future Swing releases. The current serialization support is
799 * appropriate for short term storage or RMI between applications running
800 * the same version of Swing. As of 1.4, support for long term storage
801 * of all JavaBeans<sup><font size="-2">TM</font></sup>
802 * has been added to the <code>java.beans</code> package.
803 * Please see {@link java.beans.XMLEncoder}.
804 */
805 protected class AccessibleJTextArea extends AccessibleJTextComponent {
806
807 /**
808 * Gets the state set of this object.
809 *
810 * @return an instance of AccessibleStateSet describing the states
811 * of the object
812 * @see AccessibleStateSet
813 */
814 public AccessibleStateSet getAccessibleStateSet() {
815 AccessibleStateSet states = super.getAccessibleStateSet();
816 states.add(AccessibleState.MULTI_LINE);
817 return states;
818 }
819 }
820
821 // --- variables -------------------------------------------------
822
823 private int rows;
824 private int columns;
825 private int columnWidth;
826 private int rowHeight;
827 private boolean wrap;
828 private boolean word;
829
830}