001 /*
002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025 package javax.swing;
026
027 import java.awt.*;
028 import java.awt.event.*;
029 import javax.swing.text.*;
030 import javax.swing.plaf.*;
031 import javax.accessibility.*;
032
033 import java.util.Collections;
034 import java.util.Set;
035 import java.util.StringTokenizer;
036
037 import java.io.ObjectOutputStream;
038 import java.io.ObjectInputStream;
039 import java.io.IOException;
040
041 /**
042 * A <code>JTextArea</code> is a multi-line area that displays plain text.
043 * It is intended to be a lightweight component that provides source
044 * compatibility with the <code>java.awt.TextArea</code> class where it can
045 * reasonably do so.
046 * You can find information and examples of using all the text components in
047 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/text.html">Using Text Components</a>,
048 * a section in <em>The Java Tutorial.</em>
049 *
050 * <p>
051 * This component has capabilities not found in the
052 * <code>java.awt.TextArea</code> class. The superclass should be
053 * consulted for additional capabilities.
054 * Alternative multi-line text classes with
055 * more capabilities are <code>JTextPane</code> and <code>JEditorPane</code>.
056 * <p>
057 * The <code>java.awt.TextArea</code> internally handles scrolling.
058 * <code>JTextArea</code> is different in that it doesn't manage scrolling,
059 * but implements the swing <code>Scrollable</code> interface. This allows it
060 * to be placed inside a <code>JScrollPane</code> if scrolling
061 * behavior is desired, and used directly if scrolling is not desired.
062 * <p>
063 * The <code>java.awt.TextArea</code> has the ability to do line wrapping.
064 * This was controlled by the horizontal scrolling policy. Since
065 * scrolling is not done by <code>JTextArea</code> directly, backward
066 * compatibility must be provided another way. <code>JTextArea</code> has
067 * a bound property for line wrapping that controls whether or
068 * not it will wrap lines. By default, the line wrapping property
069 * is set to false (not wrapped).
070 * <p>
071 * <code>java.awt.TextArea</code> has two properties <code>rows</code>
072 * and <code>columns</code> that are used to determine the preferred size.
073 * <code>JTextArea</code> uses these properties to indicate the
074 * preferred size of the viewport when placed inside a <code>JScrollPane</code>
075 * to match the functionality provided by <code>java.awt.TextArea</code>.
076 * <code>JTextArea</code> has a preferred size of what is needed to
077 * display all of the text, so that it functions properly inside of
078 * a <code>JScrollPane</code>. If the value for <code>rows</code>
079 * or <code>columns</code> is equal to zero,
080 * the preferred size along that axis is used for
081 * the viewport preferred size along the same axis.
082 * <p>
083 * The <code>java.awt.TextArea</code> could be monitored for changes by adding
084 * a <code>TextListener</code> for <code>TextEvent</code>s.
085 * In the <code>JTextComponent</code> based
086 * components, changes are broadcasted from the model via a
087 * <code>DocumentEvent</code> to <code>DocumentListeners</code>.
088 * The <code>DocumentEvent</code> gives
089 * the location of the change and the kind of change if desired.
090 * The code fragment might look something like:
091 * <pre>
092 * DocumentListener myListener = ??;
093 * JTextArea myArea = ??;
094 * myArea.getDocument().addDocumentListener(myListener);
095 * </pre>
096 * <p>
097 * <dl>
098 * <dt><b><font size=+1>Newlines</font></b>
099 * <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 * @version 1.104 05/05/07
125 * @see JTextPane
126 * @see JEditorPane
127 */
128 public class JTextArea extends JTextComponent {
129
130 /**
131 * @see #getUIClassID
132 * @see #readObject
133 */
134 private static final String uiClassID = "TextAreaUI";
135
136 /**
137 * Constructs a new TextArea. A default model is set, the initial string
138 * is null, and rows/columns are set to 0.
139 */
140 public JTextArea() {
141 this (null, null, 0, 0);
142 }
143
144 /**
145 * Constructs a new TextArea with the specified text displayed.
146 * A default model is created and rows/columns are set to 0.
147 *
148 * @param text the text to be displayed, or null
149 */
150 public JTextArea(String text) {
151 this (null, text, 0, 0);
152 }
153
154 /**
155 * Constructs a new empty TextArea with the specified number of
156 * rows and columns. A default model is created, and the initial
157 * string is null.
158 *
159 * @param rows the number of rows >= 0
160 * @param columns the number of columns >= 0
161 * @exception IllegalArgumentException if the rows or columns
162 * arguments are negative.
163 */
164 public JTextArea(int rows, int columns) {
165 this (null, null, rows, columns);
166 }
167
168 /**
169 * Constructs a new TextArea with the specified text and number
170 * of rows and columns. A default model is created.
171 *
172 * @param text the text to be displayed, or null
173 * @param rows the number of rows >= 0
174 * @param columns the number of columns >= 0
175 * @exception IllegalArgumentException if the rows or columns
176 * arguments are negative.
177 */
178 public JTextArea(String text, int rows, int columns) {
179 this (null, text, rows, columns);
180 }
181
182 /**
183 * Constructs a new JTextArea with the given document model, and defaults
184 * for all of the other arguments (null, 0, 0).
185 *
186 * @param doc the model to use
187 */
188 public JTextArea(Document doc) {
189 this (doc, null, 0, 0);
190 }
191
192 /**
193 * Constructs a new JTextArea with the specified number of rows
194 * and columns, and the given model. All of the constructors
195 * feed through this constructor.
196 *
197 * @param doc the model to use, or create a default one if null
198 * @param text the text to be displayed, null if none
199 * @param rows the number of rows >= 0
200 * @param columns the number of columns >= 0
201 * @exception IllegalArgumentException if the rows or columns
202 * arguments are negative.
203 */
204 public JTextArea(Document doc, String text, int rows, int columns) {
205 super ();
206 this .rows = rows;
207 this .columns = columns;
208 if (doc == null) {
209 doc = createDefaultModel();
210 }
211 setDocument(doc);
212 if (text != null) {
213 setText(text);
214 select(0, 0);
215 }
216 if (rows < 0) {
217 throw new IllegalArgumentException("rows: " + rows);
218 }
219 if (columns < 0) {
220 throw new IllegalArgumentException("columns: " + columns);
221 }
222 LookAndFeel.installProperty(this , "focusTraversalKeysForward",
223 JComponent.getManagingFocusForwardTraversalKeys());
224 LookAndFeel.installProperty(this , "focusTraversalKeysBackward",
225 JComponent.getManagingFocusBackwardTraversalKeys());
226 }
227
228 /**
229 * Returns the class ID for the UI.
230 *
231 * @return the ID ("TextAreaUI")
232 * @see JComponent#getUIClassID
233 * @see UIDefaults#getUI
234 */
235 public String getUIClassID() {
236 return uiClassID;
237 }
238
239 /**
240 * Creates the default implementation of the model
241 * to be used at construction if one isn't explicitly
242 * given. A new instance of PlainDocument is returned.
243 *
244 * @return the default document model
245 */
246 protected Document createDefaultModel() {
247 return new PlainDocument();
248 }
249
250 /**
251 * Sets the number of characters to expand tabs to.
252 * This will be multiplied by the maximum advance for
253 * variable width fonts. A PropertyChange event ("tabSize") is fired
254 * when the tab size changes.
255 *
256 * @param size number of characters to expand to
257 * @see #getTabSize
258 * @beaninfo
259 * preferred: true
260 * bound: true
261 * description: the number of characters to expand tabs to
262 */
263 public void setTabSize(int size) {
264 Document doc = getDocument();
265 if (doc != null) {
266 int old = getTabSize();
267 doc.putProperty(PlainDocument.tabSizeAttribute,
268 new Integer(size));
269 firePropertyChange("tabSize", old, size);
270 }
271 }
272
273 /**
274 * Gets the number of characters used to expand tabs. If the document is
275 * null or doesn't have a tab setting, return a default of 8.
276 *
277 * @return the number of characters
278 */
279 public int getTabSize() {
280 int size = 8;
281 Document doc = getDocument();
282 if (doc != null) {
283 Integer i = (Integer) doc
284 .getProperty(PlainDocument.tabSizeAttribute);
285 if (i != null) {
286 size = i.intValue();
287 }
288 }
289 return size;
290 }
291
292 /**
293 * Sets the line-wrapping policy of the text area. If set
294 * to true the lines will be wrapped if they are too long
295 * to fit within the allocated width. If set to false,
296 * the lines will always be unwrapped. A <code>PropertyChange</code>
297 * event ("lineWrap") is fired when the policy is changed.
298 * By default this property is false.
299 *
300 * @param wrap indicates if lines should be wrapped
301 * @see #getLineWrap
302 * @beaninfo
303 * preferred: true
304 * bound: true
305 * description: should lines be wrapped
306 */
307 public void setLineWrap(boolean wrap) {
308 boolean old = this .wrap;
309 this .wrap = wrap;
310 firePropertyChange("lineWrap", old, wrap);
311 }
312
313 /**
314 * Gets the line-wrapping policy of the text area. If set
315 * to true the lines will be wrapped if they are too long
316 * to fit within the allocated width. If set to false,
317 * the lines will always be unwrapped.
318 *
319 * @return if lines will be wrapped
320 */
321 public boolean getLineWrap() {
322 return wrap;
323 }
324
325 /**
326 * Sets the style of wrapping used if the text area is wrapping
327 * lines. If set to true the lines will be wrapped at word
328 * boundaries (whitespace) if they are too long
329 * to fit within the allocated width. If set to false,
330 * the lines will be wrapped at character boundaries.
331 * By default this property is false.
332 *
333 * @param word indicates if word boundaries should be used
334 * for line wrapping
335 * @see #getWrapStyleWord
336 * @beaninfo
337 * preferred: false
338 * bound: true
339 * description: should wrapping occur at word boundaries
340 */
341 public void setWrapStyleWord(boolean word) {
342 boolean old = this .word;
343 this .word = word;
344 firePropertyChange("wrapStyleWord", old, word);
345 }
346
347 /**
348 * Gets the style of wrapping used if the text area is wrapping
349 * lines. If set to true the lines will be wrapped at word
350 * boundaries (ie whitespace) if they are too long
351 * to fit within the allocated width. If set to false,
352 * the lines will be wrapped at character boundaries.
353 *
354 * @return if the wrap style should be word boundaries
355 * instead of character boundaries
356 * @see #setWrapStyleWord
357 */
358 public boolean getWrapStyleWord() {
359 return word;
360 }
361
362 /**
363 * Translates an offset into the components text to a
364 * line number.
365 *
366 * @param offset the offset >= 0
367 * @return the line number >= 0
368 * @exception BadLocationException thrown if the offset is
369 * less than zero or greater than the document length.
370 */
371 public int getLineOfOffset(int offset) throws BadLocationException {
372 Document doc = getDocument();
373 if (offset < 0) {
374 throw new BadLocationException(
375 "Can't translate offset to line", -1);
376 } else if (offset > doc.getLength()) {
377 throw new BadLocationException(
378 "Can't translate offset to line",
379 doc.getLength() + 1);
380 } else {
381 Element map = getDocument().getDefaultRootElement();
382 return map.getElementIndex(offset);
383 }
384 }
385
386 /**
387 * Determines the number of lines contained in the area.
388 *
389 * @return the number of lines > 0
390 */
391 public int getLineCount() {
392 Element map = getDocument().getDefaultRootElement();
393 return map.getElementCount();
394 }
395
396 /**
397 * Determines the offset of the start of the given line.
398 *
399 * @param line the line number to translate >= 0
400 * @return the offset >= 0
401 * @exception BadLocationException thrown if the line is
402 * less than zero or greater or equal to the number of
403 * lines contained in the document (as reported by
404 * getLineCount).
405 */
406 public int getLineStartOffset(int line) throws BadLocationException {
407 int lineCount = getLineCount();
408 if (line < 0) {
409 throw new BadLocationException("Negative line", -1);
410 } else if (line >= lineCount) {
411 throw new BadLocationException("No such line",
412 getDocument().getLength() + 1);
413 } else {
414 Element map = getDocument().getDefaultRootElement();
415 Element lineElem = map.getElement(line);
416 return lineElem.getStartOffset();
417 }
418 }
419
420 /**
421 * Determines the offset of the end of the given line.
422 *
423 * @param line the line >= 0
424 * @return the offset >= 0
425 * @exception BadLocationException Thrown if the line is
426 * less than zero or greater or equal to the number of
427 * lines contained in the document (as reported by
428 * getLineCount).
429 */
430 public int getLineEndOffset(int line) throws BadLocationException {
431 int lineCount = getLineCount();
432 if (line < 0) {
433 throw new BadLocationException("Negative line", -1);
434 } else if (line >= lineCount) {
435 throw new BadLocationException("No such line",
436 getDocument().getLength() + 1);
437 } else {
438 Element map = getDocument().getDefaultRootElement();
439 Element lineElem = map.getElement(line);
440 int endOffset = lineElem.getEndOffset();
441 // hide the implicit break at the end of the document
442 return ((line == lineCount - 1) ? (endOffset - 1)
443 : endOffset);
444 }
445 }
446
447 // --- java.awt.TextArea methods ---------------------------------
448
449 /**
450 * Inserts the specified text at the specified position. Does nothing
451 * if the model is null or if the text is null or empty.
452 * <p>
453 * This method is thread safe, although most Swing methods
454 * are not. Please see
455 * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How
456 * to Use Threads</A> for more information.
457 *
458 * @param str the text to insert
459 * @param pos the position at which to insert >= 0
460 * @exception IllegalArgumentException if pos is an
461 * invalid position in the model
462 * @see TextComponent#setText
463 * @see #replaceRange
464 */
465 public void insert(String str, int pos) {
466 Document doc = getDocument();
467 if (doc != null) {
468 try {
469 doc.insertString(pos, str, null);
470 } catch (BadLocationException e) {
471 throw new IllegalArgumentException(e.getMessage());
472 }
473 }
474 }
475
476 /**
477 * Appends the given text to the end of the document. Does nothing if
478 * the model is null or the string is null or empty.
479 * <p>
480 * This method is thread safe, although most Swing methods
481 * are not. Please see
482 * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How
483 * to Use Threads</A> for more information.
484 *
485 * @param str the text to insert
486 * @see #insert
487 */
488 public void append(String str) {
489 Document doc = getDocument();
490 if (doc != null) {
491 try {
492 doc.insertString(doc.getLength(), str, null);
493 } catch (BadLocationException e) {
494 }
495 }
496 }
497
498 /**
499 * Replaces text from the indicated start to end position with the
500 * new text specified. Does nothing if the model is null. Simply
501 * does a delete if the new string is null or empty.
502 * <p>
503 * This method is thread safe, although most Swing methods
504 * are not. Please see
505 * <A HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How
506 * to Use Threads</A> for more information.
507 *
508 * @param str the text to use as the replacement
509 * @param start the start position >= 0
510 * @param end the end position >= start
511 * @exception IllegalArgumentException if part of the range is an
512 * invalid position in the model
513 * @see #insert
514 * @see #replaceRange
515 */
516 public void replaceRange(String str, int start, int end) {
517 if (end < start) {
518 throw new IllegalArgumentException("end before start");
519 }
520 Document doc = getDocument();
521 if (doc != null) {
522 try {
523 if (doc instanceof AbstractDocument) {
524 ((AbstractDocument) doc).replace(start,
525 end - start, str, null);
526 } else {
527 doc.remove(start, end - start);
528 doc.insertString(start, str, null);
529 }
530 } catch (BadLocationException e) {
531 throw new IllegalArgumentException(e.getMessage());
532 }
533 }
534 }
535
536 /**
537 * Returns the number of rows in the TextArea.
538 *
539 * @return the number of rows >= 0
540 */
541 public int getRows() {
542 return rows;
543 }
544
545 /**
546 * Sets the number of rows for this TextArea. Calls invalidate() after
547 * setting the new value.
548 *
549 * @param rows the number of rows >= 0
550 * @exception IllegalArgumentException if rows is less than 0
551 * @see #getRows
552 * @beaninfo
553 * description: the number of rows preferred for display
554 */
555 public void setRows(int rows) {
556 int oldVal = this .rows;
557 if (rows < 0) {
558 throw new IllegalArgumentException("rows less than zero.");
559 }
560 if (rows != oldVal) {
561 this .rows = rows;
562 invalidate();
563 }
564 }
565
566 /**
567 * Defines the meaning of the height of a row. This defaults to
568 * the height of the font.
569 *
570 * @return the height >= 1
571 */
572 protected int getRowHeight() {
573 if (rowHeight == 0) {
574 FontMetrics metrics = getFontMetrics(getFont());
575 rowHeight = metrics.getHeight();
576 }
577 return rowHeight;
578 }
579
580 /**
581 * Returns the number of columns in the TextArea.
582 *
583 * @return number of columns >= 0
584 */
585 public int getColumns() {
586 return columns;
587 }
588
589 /**
590 * Sets the number of columns for this TextArea. Does an invalidate()
591 * after setting the new value.
592 *
593 * @param columns the number of columns >= 0
594 * @exception IllegalArgumentException if columns is less than 0
595 * @see #getColumns
596 * @beaninfo
597 * description: the number of columns preferred for display
598 */
599 public void setColumns(int columns) {
600 int oldVal = this .columns;
601 if (columns < 0) {
602 throw new IllegalArgumentException(
603 "columns less than zero.");
604 }
605 if (columns != oldVal) {
606 this .columns = columns;
607 invalidate();
608 }
609 }
610
611 /**
612 * Gets column width.
613 * The meaning of what a column is can be considered a fairly weak
614 * notion for some fonts. This method is used to define the width
615 * of a column. By default this is defined to be the width of the
616 * character <em>m</em> for the font used. This method can be
617 * redefined to be some alternative amount.
618 *
619 * @return the column width >= 1
620 */
621 protected int getColumnWidth() {
622 if (columnWidth == 0) {
623 FontMetrics metrics = getFontMetrics(getFont());
624 columnWidth = metrics.charWidth('m');
625 }
626 return columnWidth;
627 }
628
629 // --- Component methods -----------------------------------------
630
631 /**
632 * Returns the preferred size of the TextArea. This is the
633 * maximum of the size needed to display the text and the
634 * size requested for the viewport.
635 *
636 * @return the size
637 */
638 public Dimension getPreferredSize() {
639 Dimension d = super .getPreferredSize();
640 d = (d == null) ? new Dimension(400, 400) : d;
641 Insets insets = getInsets();
642
643 if (columns != 0) {
644 d.width = Math.max(d.width, columns * getColumnWidth()
645 + insets.left + insets.right);
646 }
647 if (rows != 0) {
648 d.height = Math.max(d.height, rows * getRowHeight()
649 + insets.top + insets.bottom);
650 }
651 return d;
652 }
653
654 /**
655 * Sets the current font. This removes cached row height and column
656 * width so the new font will be reflected, and calls revalidate().
657 *
658 * @param f the font to use as the current font
659 */
660 public void setFont(Font f) {
661 super .setFont(f);
662 rowHeight = 0;
663 columnWidth = 0;
664 }
665
666 /**
667 * Returns a string representation of this JTextArea. This method
668 * is intended to be used only for debugging purposes, and the
669 * content and format of the returned string may vary between
670 * implementations. The returned string may be empty but may not
671 * be <code>null</code>.
672 *
673 * @return a string representation of this JTextArea.
674 */
675 protected String paramString() {
676 String wrapString = (wrap ? "true" : "false");
677 String wordString = (word ? "true" : "false");
678
679 return super .paramString() + ",colums=" + columns
680 + ",columWidth=" + columnWidth + ",rows=" + rows
681 + ",rowHeight=" + rowHeight + ",word=" + wordString
682 + ",wrap=" + wrapString;
683 }
684
685 // --- Scrollable methods ----------------------------------------
686
687 /**
688 * Returns true if a viewport should always force the width of this
689 * Scrollable to match the width of the viewport. This is implemented
690 * to return true if the line wrapping policy is true, and false
691 * if lines are not being wrapped.
692 *
693 * @return true if a viewport should force the Scrollables width
694 * to match its own.
695 */
696 public boolean getScrollableTracksViewportWidth() {
697 return (wrap) ? true : super .getScrollableTracksViewportWidth();
698 }
699
700 /**
701 * Returns the preferred size of the viewport if this component
702 * is embedded in a JScrollPane. This uses the desired column
703 * and row settings if they have been set, otherwise the superclass
704 * behavior is used.
705 *
706 * @return The preferredSize of a JViewport whose view is this Scrollable.
707 * @see JViewport#getPreferredSize
708 */
709 public Dimension getPreferredScrollableViewportSize() {
710 Dimension size = super .getPreferredScrollableViewportSize();
711 size = (size == null) ? new Dimension(400, 400) : size;
712 Insets insets = getInsets();
713
714 size.width = (columns == 0) ? size.width : columns
715 * getColumnWidth() + insets.left + insets.right;
716 size.height = (rows == 0) ? size.height : rows * getRowHeight()
717 + insets.top + insets.bottom;
718 return size;
719 }
720
721 /**
722 * Components that display logical rows or columns should compute
723 * the scroll increment that will completely expose one new row
724 * or column, depending on the value of orientation. This is implemented
725 * to use the values returned by the <code>getRowHeight</code> and
726 * <code>getColumnWidth</code> methods.
727 * <p>
728 * Scrolling containers, like JScrollPane, will use this method
729 * each time the user requests a unit scroll.
730 *
731 * @param visibleRect the view area visible within the viewport
732 * @param orientation Either SwingConstants.VERTICAL or
733 * SwingConstants.HORIZONTAL.
734 * @param direction Less than zero to scroll up/left,
735 * greater than zero for down/right.
736 * @return The "unit" increment for scrolling in the specified direction
737 * @exception IllegalArgumentException for an invalid orientation
738 * @see JScrollBar#setUnitIncrement
739 * @see #getRowHeight
740 * @see #getColumnWidth
741 */
742 public int getScrollableUnitIncrement(Rectangle visibleRect,
743 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: "
751 + orientation);
752 }
753 }
754
755 /**
756 * See readObject() and writeObject() in JComponent for more
757 * information about serialization in Swing.
758 */
759 private void writeObject(ObjectOutputStream s) throws IOException {
760 s.defaultWriteObject();
761 if (getUIClassID().equals(uiClassID)) {
762 byte count = JComponent.getWriteObjCounter(this );
763 JComponent.setWriteObjCounter(this , --count);
764 if (count == 0 && ui != null) {
765 ui.installUI(this );
766 }
767 }
768 }
769
770 /////////////////
771 // Accessibility support
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
806 AccessibleJTextComponent {
807
808 /**
809 * Gets the state set of this object.
810 *
811 * @return an instance of AccessibleStateSet describing the states
812 * of the object
813 * @see AccessibleStateSet
814 */
815 public AccessibleStateSet getAccessibleStateSet() {
816 AccessibleStateSet states = super .getAccessibleStateSet();
817 states.add(AccessibleState.MULTI_LINE);
818 return states;
819 }
820 }
821
822 // --- variables -------------------------------------------------
823
824 private int rows;
825 private int columns;
826 private int columnWidth;
827 private int rowHeight;
828 private boolean wrap;
829 private boolean word;
830
831 }
|