jdk/src/share/classes/javax/swing/JTextArea.java

Print this page




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javax.swing;
  26 
  27 import java.awt.*;
  28 import java.awt.event.*;

  29 import javax.swing.text.*;
  30 import javax.swing.plaf.*;
  31 import javax.accessibility.*;
  32 
  33 import java.util.Collections;
  34 import java.util.Set;
  35 import java.util.StringTokenizer;
  36 
  37 import java.io.ObjectOutputStream;
  38 import java.io.ObjectInputStream;
  39 import java.io.IOException;
  40 
  41 /**
  42  * A <code>JTextArea</code> is a multi-line area that displays plain text.
  43  * It is intended to be a lightweight component that provides source
  44  * compatibility with the <code>java.awt.TextArea</code> class where it can
  45  * reasonably do so.
  46  * You can find information and examples of using all the text components in
  47  * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/text.html">Using Text Components</a>,
  48  * a section in <em>The Java Tutorial.</em>
  49  *
  50  * <p>
  51  * This component has capabilities not found in the
  52  * <code>java.awt.TextArea</code> class.  The superclass should be
  53  * consulted for additional capabilities.
  54  * Alternative multi-line text classes with
  55  * more capabilities are <code>JTextPane</code> and <code>JEditorPane</code>.
  56  * <p>
  57  * The <code>java.awt.TextArea</code> internally handles scrolling.
  58  * <code>JTextArea</code> is different in that it doesn't manage scrolling,


  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&trade;
 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  * @since 1.2
 127  */


 128 @SuppressWarnings("serial") // Same-version serialization only
 129 public class JTextArea extends JTextComponent {
 130 
 131     /**
 132      * @see #getUIClassID
 133      * @see #readObject
 134      */
 135     private static final String uiClassID = "TextAreaUI";
 136 
 137     /**
 138      * Constructs a new TextArea.  A default model is set, the initial string
 139      * is null, and rows/columns are set to 0.
 140      */
 141     public JTextArea() {
 142         this(null, null, 0, 0);
 143     }
 144 
 145     /**
 146      * Constructs a new TextArea with the specified text displayed.
 147      * A default model is created and rows/columns are set to 0.


 220         if (columns < 0) {
 221             throw new IllegalArgumentException("columns: " + columns);
 222         }
 223         LookAndFeel.installProperty(this,
 224                                     "focusTraversalKeysForward",
 225                                     JComponent.
 226                                     getManagingFocusForwardTraversalKeys());
 227         LookAndFeel.installProperty(this,
 228                                     "focusTraversalKeysBackward",
 229                                     JComponent.
 230                                     getManagingFocusBackwardTraversalKeys());
 231     }
 232 
 233     /**
 234      * Returns the class ID for the UI.
 235      *
 236      * @return the ID ("TextAreaUI")
 237      * @see JComponent#getUIClassID
 238      * @see UIDefaults#getUI
 239      */

 240     public String getUIClassID() {
 241         return uiClassID;
 242     }
 243 
 244     /**
 245      * Creates the default implementation of the model
 246      * to be used at construction if one isn't explicitly
 247      * given.  A new instance of PlainDocument is returned.
 248      *
 249      * @return the default document model
 250      */
 251     protected Document createDefaultModel() {
 252         return new PlainDocument();
 253     }
 254 
 255     /**
 256      * Sets the number of characters to expand tabs to.
 257      * This will be multiplied by the maximum advance for
 258      * variable width fonts.  A PropertyChange event ("tabSize") is fired
 259      * when the tab size changes.
 260      *
 261      * @param size number of characters to expand to
 262      * @see #getTabSize
 263      * @beaninfo
 264      *   preferred: true
 265      *       bound: true
 266      * description: the number of characters to expand tabs to
 267      */


 268     public void setTabSize(int size) {
 269         Document doc = getDocument();
 270         if (doc != null) {
 271             int old = getTabSize();
 272             doc.putProperty(PlainDocument.tabSizeAttribute, Integer.valueOf(size));
 273             firePropertyChange("tabSize", old, size);
 274         }
 275     }
 276 
 277     /**
 278      * Gets the number of characters used to expand tabs.  If the document is
 279      * null or doesn't have a tab setting, return a default of 8.
 280      *
 281      * @return the number of characters
 282      */
 283     public int getTabSize() {
 284         int size = 8;
 285         Document doc = getDocument();
 286         if (doc != null) {
 287             Integer i = (Integer) doc.getProperty(PlainDocument.tabSizeAttribute);
 288             if (i != null) {
 289                 size = i.intValue();
 290             }
 291         }
 292         return size;
 293     }
 294 
 295     /**
 296      * Sets the line-wrapping policy of the text area.  If set
 297      * to true the lines will be wrapped if they are too long
 298      * to fit within the allocated width.  If set to false,
 299      * the lines will always be unwrapped.  A <code>PropertyChange</code>
 300      * event ("lineWrap") is fired when the policy is changed.
 301      * By default this property is false.
 302      *
 303      * @param wrap indicates if lines should be wrapped
 304      * @see #getLineWrap
 305      * @beaninfo
 306      *   preferred: true
 307      *       bound: true
 308      * description: should lines be wrapped
 309      */


 310     public void setLineWrap(boolean wrap) {
 311         boolean old = this.wrap;
 312         this.wrap = wrap;
 313         firePropertyChange("lineWrap", old, wrap);
 314     }
 315 
 316     /**
 317      * Gets the line-wrapping policy of the text area.  If set
 318      * to true the lines will be wrapped if they are too long
 319      * to fit within the allocated width.  If set to false,
 320      * the lines will always be unwrapped.
 321      *
 322      * @return if lines will be wrapped
 323      */
 324     public boolean getLineWrap() {
 325         return wrap;
 326     }
 327 
 328     /**
 329      * Sets the style of wrapping used if the text area is wrapping
 330      * lines.  If set to true the lines will be wrapped at word
 331      * boundaries (whitespace) if they are too long
 332      * to fit within the allocated width.  If set to false,
 333      * the lines will be wrapped at character boundaries.
 334      * By default this property is false.
 335      *
 336      * @param word indicates if word boundaries should be used
 337      *   for line wrapping
 338      * @see #getWrapStyleWord
 339      * @beaninfo
 340      *   preferred: false
 341      *       bound: true
 342      * description: should wrapping occur at word boundaries
 343      */


 344     public void setWrapStyleWord(boolean word) {
 345         boolean old = this.word;
 346         this.word = word;
 347         firePropertyChange("wrapStyleWord", old, word);
 348     }
 349 
 350     /**
 351      * Gets the style of wrapping used if the text area is wrapping
 352      * lines.  If set to true the lines will be wrapped at word
 353      * boundaries (ie whitespace) if they are too long
 354      * to fit within the allocated width.  If set to false,
 355      * the lines will be wrapped at character boundaries.
 356      *
 357      * @return if the wrap style should be word boundaries
 358      *  instead of character boundaries
 359      * @see #setWrapStyleWord
 360      */
 361     public boolean getWrapStyleWord() {
 362         return word;
 363     }


 371      * @exception BadLocationException thrown if the offset is
 372      *   less than zero or greater than the document length.
 373      */
 374     public int getLineOfOffset(int offset) throws BadLocationException {
 375         Document doc = getDocument();
 376         if (offset < 0) {
 377             throw new BadLocationException("Can't translate offset to line", -1);
 378         } else if (offset > doc.getLength()) {
 379             throw new BadLocationException("Can't translate offset to line", 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 &gt; 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 &gt;= 0
 400      * @return the offset &gt;= 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) {


 515             }
 516         }
 517     }
 518 
 519     /**
 520      * Returns the number of rows in the TextArea.
 521      *
 522      * @return the number of rows &gt;= 0
 523      */
 524     public int getRows() {
 525         return rows;
 526     }
 527 
 528     /**
 529      * Sets the number of rows for this TextArea.  Calls invalidate() after
 530      * setting the new value.
 531      *
 532      * @param rows the number of rows &gt;= 0
 533      * @exception IllegalArgumentException if rows is less than 0
 534      * @see #getRows
 535      * @beaninfo
 536      * description: the number of rows preferred for display
 537      */


 538     public void setRows(int rows) {
 539         int oldVal = this.rows;
 540         if (rows < 0) {
 541             throw new IllegalArgumentException("rows less than zero.");
 542         }
 543         if (rows != oldVal) {
 544             this.rows = rows;
 545             invalidate();
 546         }
 547     }
 548 
 549     /**
 550      * Defines the meaning of the height of a row.  This defaults to
 551      * the height of the font.
 552      *
 553      * @return the height &gt;= 1
 554      */
 555     protected int getRowHeight() {
 556         if (rowHeight == 0) {
 557             FontMetrics metrics = getFontMetrics(getFont());


 559         }
 560         return rowHeight;
 561     }
 562 
 563     /**
 564      * Returns the number of columns in the TextArea.
 565      *
 566      * @return number of columns &gt;= 0
 567      */
 568     public int getColumns() {
 569         return columns;
 570     }
 571 
 572     /**
 573      * Sets the number of columns for this TextArea.  Does an invalidate()
 574      * after setting the new value.
 575      *
 576      * @param columns the number of columns &gt;= 0
 577      * @exception IllegalArgumentException if columns is less than 0
 578      * @see #getColumns
 579      * @beaninfo
 580      * description: the number of columns preferred for display
 581      */


 582     public void setColumns(int columns) {
 583         int oldVal = this.columns;
 584         if (columns < 0) {
 585             throw new IllegalArgumentException("columns less than zero.");
 586         }
 587         if (columns != oldVal) {
 588             this.columns = columns;
 589             invalidate();
 590         }
 591     }
 592 
 593     /**
 594      * Gets column width.
 595      * The meaning of what a column is can be considered a fairly weak
 596      * notion for some fonts.  This method is used to define the width
 597      * of a column.  By default this is defined to be the width of the
 598      * character <em>m</em> for the font used.  This method can be
 599      * redefined to be some alternative amount.
 600      *
 601      * @return the column width &gt;= 1


 664         return super.paramString() +
 665         ",colums=" + columns +
 666         ",columWidth=" + columnWidth +
 667         ",rows=" + rows +
 668         ",rowHeight=" + rowHeight +
 669         ",word=" + wordString +
 670         ",wrap=" + wrapString;
 671     }
 672 
 673     // --- Scrollable methods ----------------------------------------
 674 
 675     /**
 676      * Returns true if a viewport should always force the width of this
 677      * Scrollable to match the width of the viewport.  This is implemented
 678      * to return true if the line wrapping policy is true, and false
 679      * if lines are not being wrapped.
 680      *
 681      * @return true if a viewport should force the Scrollables width
 682      * to match its own.
 683      */

 684     public boolean getScrollableTracksViewportWidth() {
 685         return (wrap) ? true : super.getScrollableTracksViewportWidth();
 686     }
 687 
 688     /**
 689      * Returns the preferred size of the viewport if this component
 690      * is embedded in a JScrollPane.  This uses the desired column
 691      * and row settings if they have been set, otherwise the superclass
 692      * behavior is used.
 693      *
 694      * @return The preferredSize of a JViewport whose view is this Scrollable.
 695      * @see JViewport#getPreferredSize
 696      */

 697     public Dimension getPreferredScrollableViewportSize() {
 698         Dimension size = super.getPreferredScrollableViewportSize();
 699         size = (size == null) ? new Dimension(400,400) : size;
 700         Insets insets = getInsets();
 701 
 702         size.width = (columns == 0) ? size.width :
 703                 columns * getColumnWidth() + insets.left + insets.right;
 704         size.height = (rows == 0) ? size.height :
 705                 rows * getRowHeight() + insets.top + insets.bottom;
 706         return size;
 707     }
 708 
 709     /**
 710      * Components that display logical rows or columns should compute
 711      * the scroll increment that will completely expose one new row
 712      * or column, depending on the value of orientation.  This is implemented
 713      * to use the values returned by the <code>getRowHeight</code> and
 714      * <code>getColumnWidth</code> methods.
 715      * <p>
 716      * Scrolling containers, like JScrollPane, will use this method


 750             if (count == 0 && ui != null) {
 751                 ui.installUI(this);
 752             }
 753         }
 754     }
 755 
 756 /////////////////
 757 // Accessibility support
 758 ////////////////
 759 
 760 
 761     /**
 762      * Gets the AccessibleContext associated with this JTextArea.
 763      * For JTextAreas, the AccessibleContext takes the form of an
 764      * AccessibleJTextArea.
 765      * A new AccessibleJTextArea instance is created if necessary.
 766      *
 767      * @return an AccessibleJTextArea that serves as the
 768      *         AccessibleContext of this JTextArea
 769      */

 770     public AccessibleContext getAccessibleContext() {
 771         if (accessibleContext == null) {
 772             accessibleContext = new AccessibleJTextArea();
 773         }
 774         return accessibleContext;
 775     }
 776 
 777     /**
 778      * This class implements accessibility support for the
 779      * <code>JTextArea</code> class.  It provides an implementation of the
 780      * Java Accessibility API appropriate to text area user-interface
 781      * elements.
 782      * <p>
 783      * <strong>Warning:</strong>
 784      * Serialized objects of this class will not be compatible with
 785      * future Swing releases. The current serialization support is
 786      * appropriate for short term storage or RMI between applications running
 787      * the same version of Swing.  As of 1.4, support for long term storage
 788      * of all JavaBeans&trade;
 789      * has been added to the <code>java.beans</code> package.




   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,


  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&trade;
 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.


 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     }


 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 &gt; 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 &gt;= 0
 389      * @return the offset &gt;= 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) {


 504             }
 505         }
 506     }
 507 
 508     /**
 509      * Returns the number of rows in the TextArea.
 510      *
 511      * @return the number of rows &gt;= 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 &gt;= 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 &gt;= 1
 543      */
 544     protected int getRowHeight() {
 545         if (rowHeight == 0) {
 546             FontMetrics metrics = getFontMetrics(getFont());


 548         }
 549         return rowHeight;
 550     }
 551 
 552     /**
 553      * Returns the number of columns in the TextArea.
 554      *
 555      * @return number of columns &gt;= 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 &gt;= 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 &gt;= 1


 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


 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&trade;
 781      * has been added to the <code>java.beans</code> package.