home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 20.1 KB | 642 lines |
- /*
- * @(#)JTextArea.java 1.41 98/02/12
- *
- * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the confidential and proprietary information of Sun
- * Microsystems, Inc. ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
- * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
- package java.awt.swing;
-
- import java.awt.*;
- import java.awt.swing.text.*;
- import java.awt.swing.plaf.*;
- import java.awt.accessibility.*;
-
- /**
- * A TextArea is a multi-line area that displays plain text.
- * It is intended to be a lightweight component that provides source
- * compatibility with the java.awt.TextArea class where it can
- * reasonably do so. This component has capabilities not found in
- * the java.awt.TextArea class. The superclass should be consulted for
- * additional capabilities. Alternative multi-line text classes with
- * more capabilitites are JTextPane and JEditorPane.
- * <p>
- * The java.awt.TextArea internally handles scrolling. JTextArea
- * is different in that it doesn't manage scrolling, but implements
- * the swing Scrollable interface. This allows it to be placed
- * inside a JScrollPane if scrolling behavior is desired, and used
- * directly if scrolling is not desired.
- * <p>
- * The java.awt.TextArea has the ability to do line wrapping.
- * This was controlled by the horizontal scrolling policy. Since
- * scrolling is not done by JTextArea directly, backward
- * compatibility must be provided another way. JTextArea has
- * a bound property for line wrapping that controls whether or
- * not it will wrap lines.
- * <p>
- * The java.awt.TextArea could be monitored for changes by adding
- * a TextListener for TextEvent's. In the JTextComponent based
- * components, changes are broadcasted from the model via a
- * DocumentEvent to DocumentListeners. The DocumentEvent gives
- * the location of the change and the kind of change if desired.
- * The code fragment might look something like:
- * <pre><code>
- * DocumentListener myListener = ??;
- * JTextArea myArea = ??;
- * myArea.getDocument().addDocumentListener(myListener);
- * </code></pre>
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- *
- * @beaninfo
- * attribute: isContainer false
- * @author Timothy Prinzing
- * @version 1.41 02/12/98
- * @see JTextPane
- * @see JEditorPane
- */
- public class JTextArea extends JTextComponent {
-
- /**
- * Constructs a new TextArea.
- */
- public JTextArea() {
- this(null, null, 0, 0);
- }
-
- /**
- * Constructs a new TextArea with the specified text displayed.
- *
- * @param text the text to be displayed
- */
- public JTextArea(String text) {
- this(null, text, 0, 0);
- }
-
- /**
- * Constructs a new empty TextArea with the specified number of
- * rows and columns.
- *
- * @param rows the number of rows
- * @param columns the number of columns
- */
- public JTextArea(int rows, int columns) {
- this(null, null, rows, columns);
- }
-
- /**
- * Constructs a new TextArea with the specified text and number
- * of rows and columns.
- *
- * @param text the text to be displayed
- * @param rows the number of rows
- * @param columns the number of columns
- */
- public JTextArea(String text, int rows, int columns) {
- this(null, text, rows, columns);
- }
-
- /**
- * Constructs a new JTextArea with the given document model, and defaults
- * for all of the other arguments.
- *
- * @param doc the model to use
- */
- public JTextArea(Document doc) {
- this(doc, null, 0, 0);
- }
-
- /**
- * Constructs a new JTextArea with the specified number of rows
- * and columns, and the given model. All of the constructors
- * feed through this constructor.
- *
- * @param doc the model to use
- * @param text the text to be displayed
- * @param rows the number of rows
- * @param columns the number of columns
- */
- public JTextArea(Document doc, String text, int rows, int columns) {
- super();
- setName(base + nameCounter++);
- this.rows = rows;
- this.columns = columns;
- if (doc == null) {
- doc = createDefaultModel();
- }
- setDocument(doc);
- if (text != null) {
- setText(text);
- }
- }
-
- /**
- * Returns the class ID for the UI.
- *
- * @return the ID
- * @see JComponent#getUIClassID
- * @see UIDefaults#getUI
- */
- public String getUIClassID() {
- return "TextAreaUI";
- }
-
-
- /**
- * Creates the default implementation of the model
- * to be used at construction if one isn't explicitly
- * given.
- *
- * @return the default document model
- */
- protected Document createDefaultModel() {
- return new PlainDocument();
- }
-
- /**
- * Sets the number of characters to expand tabs to.
- * This will be multiplied by the maximum advance for
- * variable width fonts.
- *
- * @param size number of characters to expand to
- * @see #getTabSize
- * @beaninfo
- * preferred: true
- * bound: true
- * description: the number of characters to expand tabs to
- */
- public void setTabSize(int size) {
- Document doc = getDocument();
- if (doc != null) {
- int old = getTabSize();
- doc.putProperty(PlainDocument.tabSizeAttribute, new Integer(size));
- firePropertyChange("TabSize", old, size);
- }
- }
-
- /**
- * Gets the number of characters used to expand tabs.
- *
- * @return the number of characters
- */
- public int getTabSize() {
- int size = 8;
- Document doc = getDocument();
- if (doc != null) {
- Integer i = (Integer) doc.getProperty(PlainDocument.tabSizeAttribute);
- if (i != null) {
- size = i.intValue();
- }
- }
- return size;
- }
-
- /**
- * Set the line-wrapping policy of the text area. If set
- * to true the lines will be wrapped if they are too long
- * to fit within the allocated width. If set to false,
- * the lines will always be unwrapped.
- *
- * @param wrap indicates if lines should be wrapped.
- * @see #getLineWrap
- * @beaninfo
- * preferred: true
- * bound: true
- * description: should lines be wrapped
- */
- public void setLineWrap(boolean wrap) {
- boolean old = this.wrap;
- this.wrap = wrap;
- firePropertyChange("LineWrap", old, wrap);
- }
-
- /**
- * Get the line-wrapping policy of the text area. If set
- * to true the lines will be wrapped if they are too long
- * to fit within the allocated width. If set to false,
- * the lines will always be unwrapped.
- *
- * @returns if lines will be wrapped.
- */
- public boolean getLineWrap() {
- return wrap;
- }
-
- /**
- * Translate an offset into the components text to a
- * line number.
- * @exception BadLocationException Thrown if the offset is
- * less than zero or greater than the document length.
- */
- public int getLineOfOffset(int offset) throws BadLocationException {
- Document doc = getDocument();
- if (offset < 0) {
- throw new BadLocationException("Can't translate offset to line", -1);
- } else if (offset > doc.getLength()) {
- throw new BadLocationException("Can't translate offset to line", doc.getLength()+1);
- } else {
- Element map = getDocument().getDefaultRootElement();
- return map.getElementIndex(offset);
- }
- }
-
- /**
- * Determine the number of lines contained.
- */
- public int getLineCount() {
- Element map = getDocument().getDefaultRootElement();
- return map.getElementCount();
- }
-
- /**
- * Determine the offset of the start of the given line.
- * @param line The line number to translate. Lines are
- * numbered from 0.
- * @exception BadLocationException Thrown if the line is
- * less than zero or greater or equal to the number of
- * lines contained in the document (as reported by
- * getLineCount).
- */
- public int getLineStartOffset(int line) throws BadLocationException {
- Element map = getDocument().getDefaultRootElement();
- if (line < 0) {
- throw new BadLocationException("Negative line", -1);
- } else if (line >= map.getElementCount()) {
- throw new BadLocationException("No such line", getDocument().getLength()+1);
- } else {
- Element lineElem = map.getElement(line);
- return lineElem.getStartOffset();
- }
- }
-
- /**
- * Determine the offset of the end of the given line.
- * @param line The line number to translate. Lines are
- * numbered from 0.
- * @exception BadLocationException Thrown if the line is
- * less than zero or greater or equal to the number of
- * lines contained in the document (as reported by
- * getLineCount).
- */
- public int getLineEndOffset(int line) throws BadLocationException {
- Element map = getDocument().getDefaultRootElement();
- if (line < 0) {
- throw new BadLocationException("Negative line", -1);
- } else if (line >= map.getElementCount()) {
- throw new BadLocationException("No such line", getDocument().getLength()+1);
- } else {
- Element lineElem = map.getElement(line);
- return lineElem.getEndOffset();
- }
- }
-
- // --- java.awt.TextArea methods ---------------------------------
-
- /**
- * Inserts the specified text at the specified position.
- * <p>
- * This method is thread safe, although most Swing methods
- * are not. Please see
- * <A HREF="http://java.sun.com/products/jfc/swingdoc/threads.html">Threads
- * and Swing</A> for more information.
- *
- * @param str the text to insert
- * @param pos the position at which to insert
- * @exception IllegalArgumentException if pos is an
- * invalid position in the model
- * @see TextComponent#setText
- * @see #replaceRange
- */
- public void insert(String str, int pos) {
- Document doc = getDocument();
- if (doc != null) {
- try {
- doc.insertString(pos, str, null);
- } catch (BadLocationException e) {
- throw new IllegalArgumentException(e.getMessage());
- }
- }
- }
-
- /**
- * Appends the given text to the end of the document.
- * <p>
- * This method is thread safe, although most Swing methods
- * are not. Please see
- * <A HREF="http://java.sun.com/products/jfc/swingdoc/threads.html">Threads
- * and Swing</A> for more information.
- *
- * @param str the text to insert
- * @see #insert
- */
- public void append(String str) {
- Document doc = getDocument();
- if (doc != null) {
- try {
- doc.insertString(doc.getLength(), str, null);
- } catch (BadLocationException e) {
- }
- }
- }
-
- /**
- * Replaces text from the indicated start to end position with the
- * new text specified.
- * <p>
- * This method is thread safe, although most Swing methods
- * are not. Please see
- * <A HREF="http://java.sun.com/products/jfc/swingdoc/threads.html">Threads
- * and Swing</A> for more information.
- *
- * @param str the text to use as the replacement
- * @param start the start position
- * @param end the end position
- * @exception IllegalArgumentException if part of the range is an
- * invalid position in the model
- * @see #insert
- * @see #replaceRange
- */
- public void replaceRange(String str, int start, int end) {
- if (end < start) {
- throw new IllegalArgumentException("end before start");
- }
- Document doc = getDocument();
- if (doc != null) {
- try {
- doc.remove(start, end - start);
- doc.insertString(start, str, null);
- } catch (BadLocationException e) {
- throw new IllegalArgumentException(e.getMessage());
- }
- }
- }
-
- /**
- * Turns off tab traversal once focus gained.
- *
- * @return true, to indicate that the focus is being managed
- */
- public boolean isManagingFocus() {
- return true;
- }
-
- /**
- * Returns the number of rows in the TextArea.
- *
- * @return the number of rows
- */
- public int getRows() {
- return rows;
- }
-
- /**
- * Sets the number of rows for this TextArea.
- *
- * @param rows the number of rows
- * @exception IllegalArgumentException if rows is less than 0
- * @see #getRows
- * @beaninfo
- * description: the number of rows preferred for display
- */
- public void setRows(int rows) {
- int oldVal = this.rows;
- if (rows < 0) {
- throw new IllegalArgumentException("rows less than zero.");
- }
- if (rows != oldVal) {
- this.rows = rows;
- invalidate();
- }
- }
-
- /**
- * Defines the meaning of the height of a row. This defaults to
- * the height of the font.
- *
- * @return the height
- */
- protected int getRowHeight() {
- if (rowHeight == 0) {
- FontMetrics metrics = getFontMetrics(getFont());
- rowHeight = metrics.getHeight();
- }
- return rowHeight;
- }
-
- /**
- * Returns the number of columns in the TextArea.
- *
- * @return number of columns
- */
- public int getColumns() {
- return columns;
- }
-
- /**
- * Sets the number of columns for this TextArea.
- *
- * @param columns the number of columns
- * @exception IllegalArgumentException if columns is less than 0
- * @see #getColumns
- * @beaninfo
- * description: the number of columns preferred for display
- */
- public void setColumns(int columns) {
- int oldVal = this.columns;
- if (columns < 0) {
- throw new IllegalArgumentException("columns less than zero.");
- }
- if (columns != oldVal) {
- this.columns = columns;
- invalidate();
- }
- }
-
- /**
- * Gets column width.
- * The meaning of what a column is can be considered a fairly weak
- * notion for some fonts. This method is used to define the width
- * of a column. By default this is defined to be the width of the
- * character <em>m</em> for the font used. This method can be
- * redefined to be some alternative amount.
- *
- * @return the column width
- */
- protected int getColumnWidth() {
- if (columnWidth == 0) {
- FontMetrics metrics = getFontMetrics(getFont());
- columnWidth = metrics.charWidth('m');
- }
- return columnWidth;
- }
-
-
- /**
- * Returns the minimum size Dimensions of the TextArea.
- * By default this is set to the preferred size.
- *
- * @return the dimensions
- */
- public Dimension getMinimumSize() {
- if ((columns != 0) || (rows != 0)) {
- return getPreferredSize();
- }
- return super.getMinimumSize();
- }
-
- /**
- * Sets the current font. This removes cached row height and column
- * width so the new font will be reflected.
- *
- * @param f the font to use as the current font
- */
- public void setFont(Font f) {
- super.setFont(f);
- rowHeight = 0;
- columnWidth = 0;
- revalidate();
- }
-
- /**
- * Returns the String of parameters for this TextArea.
- *
- * @return the string of parameters
- */
- protected String paramString() {
- return super.paramString() + ",rows=" + rows +
- ",columns=" + columns;
- }
-
- // --- Scrollable methods ----------------------------------------
-
- /**
- * Returns true if a viewport should always force the width of this
- * Scrollable to match the width of the viewport. This is implemented
- * to return true if the line wrapping policy is true, and false
- * if lines are not being wrapped.
- *
- * @return True if a viewport should force the Scrollables width to match its own.
- */
- public boolean getScrollableTracksViewportWidth() {
- return (wrap) ? true : false;
- }
-
- /**
- * Returns the preferred size of the viewport if this component
- * is embedded in a JScrollPane. This uses the desired column
- * and row settings if they have been set, otherwise the superclass
- * behavior is used.
- *
- * @return The preferredSize of a JViewport whose view is this Scrollable.
- * @see JViewport#getPreferredSize
- */
- public Dimension getPreferredScrollableViewportSize() {
- Dimension size = super.getPreferredScrollableViewportSize();
- size = (size == null) ? new Dimension(400,400) : size;
- size.width = (columns == 0) ? size.width : columns * getColumnWidth();
- size.height = (rows == 0) ? size.height : rows * getRowHeight();
- return size;
- }
-
- /**
- * Components that display logical rows or columns should compute
- * the scroll increment that will completely expose one new row
- * or column, depending on the value of orientation. This is implemented
- * to use the vaules returned by the <code>getRowHeight</code> and
- * <code>getColumnWidth</code> methods.
- * <p>
- * Scrolling containers, like JScrollPane, will use this method
- * each time the user requests a unit scroll.
- *
- * @param visibleRect The view area visible within the viewport
- * @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
- * @param direction Less than zero to scroll up/left, greater than zero for down/right.
- * @return The "unit" increment for scrolling in the specified direction
- * @see JScrollBar#setUnitIncrement
- * @see #getRowHeight
- * @see #getColumnWidth
- */
- public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
- switch (orientation) {
- case SwingConstants.VERTICAL:
- return getRowHeight();
- case SwingConstants.HORIZONTAL:
- return getColumnWidth();
- default:
- throw new IllegalArgumentException("Invalid orientation: " + orientation);
- }
- }
-
- /////////////////
- // Accessibility support
- ////////////////
-
-
- /**
- * Get the AccessibleContext associated with this JTextArea
- *
- * @return the AccessibleContext of this JTextArea
- */
- public AccessibleContext getAccessibleContext() {
- if (accessibleContext == null) {
- accessibleContext = new AccessibleJTextArea();
- }
- return accessibleContext;
- }
-
- /**
- * The class used to obtain the accessible role for this object.
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- */
- protected class AccessibleJTextArea extends AccessibleJTextComponent {
-
- /**
- * Gets the state set of this object.
- *
- * @return an instance of AccessibleStateSet describing the states
- * of the object
- * @see AccessibleStateSet
- */
- public AccessibleStateSet getAccessibleStateSet() {
- AccessibleStateSet states = super.getAccessibleStateSet();
- states.add(AccessibleState.MULTI_LINE);
- return states;
- }
- }
-
- // --- variables -------------------------------------------------
-
- private int rows;
- private int columns;
- private int columnWidth;
- private int rowHeight;
- private boolean wrap;
-
- private static final String base = "text";
- private static int nameCounter = 0;
-
- }
-