001: /*
002: * Copyright 1995-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 java.awt;
026:
027: import java.awt.event.InputEvent;
028: import java.awt.event.KeyEvent;
029: import java.awt.peer.TextAreaPeer;
030: import java.io.ObjectOutputStream;
031: import java.io.ObjectInputStream;
032: import java.io.IOException;
033: import java.util.HashSet;
034: import java.util.Set;
035: import javax.accessibility.*;
036:
037: /**
038: * A <code>TextArea</code> object is a multi-line region
039: * that displays text. It can be set to allow editing or
040: * to be read-only.
041: * <p>
042: * The following image shows the appearance of a text area:
043: * <p>
044: * <img src="doc-files/TextArea-1.gif" alt="A TextArea showing the word 'Hello!'"
045: * ALIGN=center HSPACE=10 VSPACE=7>
046: * <p>
047: * This text area could be created by the following line of code:
048: * <p>
049: * <hr><blockquote><pre>
050: * new TextArea("Hello", 5, 40);
051: * </pre></blockquote><hr>
052: * <p>
053: * @version 1.88, 05/05/07
054: * @author Sami Shaio
055: * @since JDK1.0
056: */
057: public class TextArea extends TextComponent {
058:
059: /**
060: * The number of rows in the <code>TextArea</code>.
061: * This parameter will determine the text area's height.
062: * Guaranteed to be non-negative.
063: *
064: * @serial
065: * @see #getRows()
066: * @see #setRows(int)
067: */
068: int rows;
069:
070: /**
071: * The number of columns in the <code>TextArea</code>.
072: * A column is an approximate average character
073: * width that is platform-dependent.
074: * This parameter will determine the text area's width.
075: * Guaranteed to be non-negative.
076: *
077: * @serial
078: * @see #setColumns(int)
079: * @see #getColumns()
080: */
081: int columns;
082:
083: private static final String base = "text";
084: private static int nameCounter = 0;
085:
086: /**
087: * Create and display both vertical and horizontal scrollbars.
088: * @since JDK1.1
089: */
090: public static final int SCROLLBARS_BOTH = 0;
091:
092: /**
093: * Create and display vertical scrollbar only.
094: * @since JDK1.1
095: */
096: public static final int SCROLLBARS_VERTICAL_ONLY = 1;
097:
098: /**
099: * Create and display horizontal scrollbar only.
100: * @since JDK1.1
101: */
102: public static final int SCROLLBARS_HORIZONTAL_ONLY = 2;
103:
104: /**
105: * Do not create or display any scrollbars for the text area.
106: * @since JDK1.1
107: */
108: public static final int SCROLLBARS_NONE = 3;
109:
110: /**
111: * Determines which scrollbars are created for the
112: * text area. It can be one of four values :
113: * <code>SCROLLBARS_BOTH</code> = both scrollbars.<BR>
114: * <code>SCROLLBARS_HORIZONTAL_ONLY</code> = Horizontal bar only.<BR>
115: * <code>SCROLLBARS_VERTICAL_ONLY</code> = Vertical bar only.<BR>
116: * <code>SCROLLBARS_NONE</code> = No scrollbars.<BR>
117: *
118: * @serial
119: * @see #getScrollbarVisibility()
120: */
121: private int scrollbarVisibility;
122:
123: /**
124: * Cache the Sets of forward and backward traversal keys so we need not
125: * look them up each time.
126: */
127: private static Set forwardTraversalKeys, backwardTraversalKeys;
128:
129: /*
130: * JDK 1.1 serialVersionUID
131: */
132: private static final long serialVersionUID = 3692302836626095722L;
133:
134: /**
135: * Initialize JNI field and method ids
136: */
137: private static native void initIDs();
138:
139: static {
140: /* ensure that the necessary native libraries are loaded */
141: Toolkit.loadLibraries();
142: if (!GraphicsEnvironment.isHeadless()) {
143: initIDs();
144: }
145: forwardTraversalKeys = KeyboardFocusManager
146: .initFocusTraversalKeysSet("ctrl TAB", new HashSet());
147: backwardTraversalKeys = KeyboardFocusManager
148: .initFocusTraversalKeysSet("ctrl shift TAB",
149: new HashSet());
150: }
151:
152: /**
153: * Constructs a new text area with the empty string as text.
154: * This text area is created with scrollbar visibility equal to
155: * {@link #SCROLLBARS_BOTH}, so both vertical and horizontal
156: * scrollbars will be visible for this text area.
157: * @exception HeadlessException if
158: * <code>GraphicsEnvironment.isHeadless</code> returns true
159: * @see java.awt.GraphicsEnvironment#isHeadless()
160: */
161: public TextArea() throws HeadlessException {
162: this ("", 0, 0, SCROLLBARS_BOTH);
163: }
164:
165: /**
166: * Constructs a new text area with the specified text.
167: * This text area is created with scrollbar visibility equal to
168: * {@link #SCROLLBARS_BOTH}, so both vertical and horizontal
169: * scrollbars will be visible for this text area.
170: * @param text the text to be displayed; if
171: * <code>text</code> is <code>null</code>, the empty
172: * string <code>""</code> will be displayed
173: * @exception HeadlessException if
174: * <code>GraphicsEnvironment.isHeadless</code> returns true
175: * @see java.awt.GraphicsEnvironment#isHeadless()
176: */
177: public TextArea(String text) throws HeadlessException {
178: this (text, 0, 0, SCROLLBARS_BOTH);
179: }
180:
181: /**
182: * Constructs a new text area with the specified number of
183: * rows and columns and the empty string as text.
184: * A column is an approximate average character
185: * width that is platform-dependent. The text area is created with
186: * scrollbar visibility equal to {@link #SCROLLBARS_BOTH}, so both
187: * vertical and horizontal scrollbars will be visible for this
188: * text area.
189: * @param rows the number of rows
190: * @param columns the number of columns
191: * @exception HeadlessException if
192: * <code>GraphicsEnvironment.isHeadless</code> returns true
193: * @see java.awt.GraphicsEnvironment#isHeadless()
194: */
195: public TextArea(int rows, int columns) throws HeadlessException {
196: this ("", rows, columns, SCROLLBARS_BOTH);
197: }
198:
199: /**
200: * Constructs a new text area with the specified text,
201: * and with the specified number of rows and columns.
202: * A column is an approximate average character
203: * width that is platform-dependent. The text area is created with
204: * scrollbar visibility equal to {@link #SCROLLBARS_BOTH}, so both
205: * vertical and horizontal scrollbars will be visible for this
206: * text area.
207: * @param text the text to be displayed; if
208: * <code>text</code> is <code>null</code>, the empty
209: * string <code>""</code> will be displayed
210: * @param rows the number of rows
211: * @param columns the number of columns
212: * @exception HeadlessException if
213: * <code>GraphicsEnvironment.isHeadless</code> returns true
214: * @see java.awt.GraphicsEnvironment#isHeadless()
215: */
216: public TextArea(String text, int rows, int columns)
217: throws HeadlessException {
218: this (text, rows, columns, SCROLLBARS_BOTH);
219: }
220:
221: /**
222: * Constructs a new text area with the specified text,
223: * and with the rows, columns, and scroll bar visibility
224: * as specified. All <code>TextArea</code> constructors defer to
225: * this one.
226: * <p>
227: * The <code>TextArea</code> class defines several constants
228: * that can be supplied as values for the
229: * <code>scrollbars</code> argument:
230: * <ul>
231: * <li><code>SCROLLBARS_BOTH</code>,
232: * <li><code>SCROLLBARS_VERTICAL_ONLY</code>,
233: * <li><code>SCROLLBARS_HORIZONTAL_ONLY</code>,
234: * <li><code>SCROLLBARS_NONE</code>.
235: * </ul>
236: * Any other value for the
237: * <code>scrollbars</code> argument is invalid and will result in
238: * this text area being created with scrollbar visibility equal to
239: * the default value of {@link #SCROLLBARS_BOTH}.
240: * @param text the text to be displayed; if
241: * <code>text</code> is <code>null</code>, the empty
242: * string <code>""</code> will be displayed
243: * @param rows the number of rows; if
244: * <code>rows</code> is less than <code>0</code>,
245: * <code>rows</code> is set to <code>0</code>
246: * @param columns the number of columns; if
247: * <code>columns</code> is less than <code>0</code>,
248: * <code>columns</code> is set to <code>0</code>
249: * @param scrollbars a constant that determines what
250: * scrollbars are created to view the text area
251: * @since JDK1.1
252: * @exception HeadlessException if
253: * <code>GraphicsEnvironment.isHeadless</code> returns true
254: * @see java.awt.GraphicsEnvironment#isHeadless()
255: */
256: public TextArea(String text, int rows, int columns, int scrollbars)
257: throws HeadlessException {
258: super (text);
259:
260: this .rows = (rows >= 0) ? rows : 0;
261: this .columns = (columns >= 0) ? columns : 0;
262:
263: if (scrollbars >= SCROLLBARS_BOTH
264: && scrollbars <= SCROLLBARS_NONE) {
265: this .scrollbarVisibility = scrollbars;
266: } else {
267: this .scrollbarVisibility = SCROLLBARS_BOTH;
268: }
269:
270: setFocusTraversalKeys(
271: KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
272: forwardTraversalKeys);
273: setFocusTraversalKeys(
274: KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
275: backwardTraversalKeys);
276: }
277:
278: /**
279: * Construct a name for this component. Called by <code>getName</code>
280: * when the name is <code>null</code>.
281: */
282: String constructComponentName() {
283: synchronized (TextArea.class) {
284: return base + nameCounter++;
285: }
286: }
287:
288: /**
289: * Creates the <code>TextArea</code>'s peer. The peer allows us to modify
290: * the appearance of the <code>TextArea</code> without changing any of its
291: * functionality.
292: */
293: public void addNotify() {
294: synchronized (getTreeLock()) {
295: if (peer == null)
296: peer = getToolkit().createTextArea(this );
297: super .addNotify();
298: }
299: }
300:
301: /**
302: * Inserts the specified text at the specified position
303: * in this text area.
304: * <p>Note that passing <code>null</code> or inconsistent
305: * parameters is invalid and will result in unspecified
306: * behavior.
307: *
308: * @param str the non-<code>null</code> text to insert
309: * @param pos the position at which to insert
310: * @see java.awt.TextComponent#setText
311: * @see java.awt.TextArea#replaceRange
312: * @see java.awt.TextArea#append
313: * @since JDK1.1
314: */
315: public void insert(String str, int pos) {
316: insertText(str, pos);
317: }
318:
319: /**
320: * @deprecated As of JDK version 1.1,
321: * replaced by <code>insert(String, int)</code>.
322: */
323: @Deprecated
324: public synchronized void insertText(String str, int pos) {
325: TextAreaPeer peer = (TextAreaPeer) this .peer;
326: if (peer != null) {
327: peer.insertText(str, pos);
328: } else {
329: text = text.substring(0, pos) + str + text.substring(pos);
330: }
331: }
332:
333: /**
334: * Appends the given text to the text area's current text.
335: * <p>Note that passing <code>null</code> or inconsistent
336: * parameters is invalid and will result in unspecified
337: * behavior.
338: *
339: * @param str the non-<code>null</code> text to append
340: * @see java.awt.TextArea#insert
341: * @since JDK1.1
342: */
343: public void append(String str) {
344: appendText(str);
345: }
346:
347: /**
348: * @deprecated As of JDK version 1.1,
349: * replaced by <code>append(String)</code>.
350: */
351: @Deprecated
352: public synchronized void appendText(String str) {
353: if (peer != null) {
354: insertText(str, getText().length());
355: } else {
356: text = text + str;
357: }
358: }
359:
360: /**
361: * Replaces text between the indicated start and end positions
362: * with the specified replacement text. The text at the end
363: * position will not be replaced. The text at the start
364: * position will be replaced (unless the start position is the
365: * same as the end position).
366: * The text position is zero-based. The inserted substring may be
367: * of a different length than the text it replaces.
368: * <p>Note that passing <code>null</code> or inconsistent
369: * parameters is invalid and will result in unspecified
370: * behavior.
371: *
372: * @param str the non-<code>null</code> text to use as
373: * the replacement
374: * @param start the start position
375: * @param end the end position
376: * @see java.awt.TextArea#insert
377: * @since JDK1.1
378: */
379: public void replaceRange(String str, int start, int end) {
380: replaceText(str, start, end);
381: }
382:
383: /**
384: * @deprecated As of JDK version 1.1,
385: * replaced by <code>replaceRange(String, int, int)</code>.
386: */
387: @Deprecated
388: public synchronized void replaceText(String str, int start, int end) {
389: TextAreaPeer peer = (TextAreaPeer) this .peer;
390: if (peer != null) {
391: peer.replaceText(str, start, end);
392: } else {
393: text = text.substring(0, start) + str + text.substring(end);
394: }
395: }
396:
397: /**
398: * Returns the number of rows in the text area.
399: * @return the number of rows in the text area
400: * @see #setRows(int)
401: * @see #getColumns()
402: * @since JDK1
403: */
404: public int getRows() {
405: return rows;
406: }
407:
408: /**
409: * Sets the number of rows for this text area.
410: * @param rows the number of rows
411: * @see #getRows()
412: * @see #setColumns(int)
413: * @exception IllegalArgumentException if the value
414: * supplied for <code>rows</code>
415: * is less than <code>0</code>
416: * @since JDK1.1
417: */
418: public void setRows(int rows) {
419: int oldVal = this .rows;
420: if (rows < 0) {
421: throw new IllegalArgumentException("rows less than zero.");
422: }
423: if (rows != oldVal) {
424: this .rows = rows;
425: invalidate();
426: }
427: }
428:
429: /**
430: * Returns the number of columns in this text area.
431: * @return the number of columns in the text area
432: * @see #setColumns(int)
433: * @see #getRows()
434: */
435: public int getColumns() {
436: return columns;
437: }
438:
439: /**
440: * Sets the number of columns for this text area.
441: * @param columns the number of columns
442: * @see #getColumns()
443: * @see #setRows(int)
444: * @exception IllegalArgumentException if the value
445: * supplied for <code>columns</code>
446: * is less than <code>0</code>
447: * @since JDK1.1
448: */
449: public void setColumns(int columns) {
450: int oldVal = this .columns;
451: if (columns < 0) {
452: throw new IllegalArgumentException(
453: "columns less than zero.");
454: }
455: if (columns != oldVal) {
456: this .columns = columns;
457: invalidate();
458: }
459: }
460:
461: /**
462: * Returns an enumerated value that indicates which scroll bars
463: * the text area uses.
464: * <p>
465: * The <code>TextArea</code> class defines four integer constants
466: * that are used to specify which scroll bars are available.
467: * <code>TextArea</code> has one constructor that gives the
468: * application discretion over scroll bars.
469: *
470: * @return an integer that indicates which scroll bars are used
471: * @see java.awt.TextArea#SCROLLBARS_BOTH
472: * @see java.awt.TextArea#SCROLLBARS_VERTICAL_ONLY
473: * @see java.awt.TextArea#SCROLLBARS_HORIZONTAL_ONLY
474: * @see java.awt.TextArea#SCROLLBARS_NONE
475: * @see java.awt.TextArea#TextArea(java.lang.String, int, int, int)
476: * @since JDK1.1
477: */
478: public int getScrollbarVisibility() {
479: return scrollbarVisibility;
480: }
481:
482: /**
483: * Determines the preferred size of a text area with the specified
484: * number of rows and columns.
485: * @param rows the number of rows
486: * @param columns the number of columns
487: * @return the preferred dimensions required to display
488: * the text area with the specified
489: * number of rows and columns
490: * @see java.awt.Component#getPreferredSize
491: * @since JDK1.1
492: */
493: public Dimension getPreferredSize(int rows, int columns) {
494: return preferredSize(rows, columns);
495: }
496:
497: /**
498: * @deprecated As of JDK version 1.1,
499: * replaced by <code>getPreferredSize(int, int)</code>.
500: */
501: @Deprecated
502: public Dimension preferredSize(int rows, int columns) {
503: synchronized (getTreeLock()) {
504: TextAreaPeer peer = (TextAreaPeer) this .peer;
505: return (peer != null) ? peer.preferredSize(rows, columns)
506: : super .preferredSize();
507: }
508: }
509:
510: /**
511: * Determines the preferred size of this text area.
512: * @return the preferred dimensions needed for this text area
513: * @see java.awt.Component#getPreferredSize
514: * @since JDK1.1
515: */
516: public Dimension getPreferredSize() {
517: return preferredSize();
518: }
519:
520: /**
521: * @deprecated As of JDK version 1.1,
522: * replaced by <code>getPreferredSize()</code>.
523: */
524: @Deprecated
525: public Dimension preferredSize() {
526: synchronized (getTreeLock()) {
527: return ((rows > 0) && (columns > 0)) ? preferredSize(rows,
528: columns) : super .preferredSize();
529: }
530: }
531:
532: /**
533: * Determines the minimum size of a text area with the specified
534: * number of rows and columns.
535: * @param rows the number of rows
536: * @param columns the number of columns
537: * @return the minimum dimensions required to display
538: * the text area with the specified
539: * number of rows and columns
540: * @see java.awt.Component#getMinimumSize
541: * @since JDK1.1
542: */
543: public Dimension getMinimumSize(int rows, int columns) {
544: return minimumSize(rows, columns);
545: }
546:
547: /**
548: * @deprecated As of JDK version 1.1,
549: * replaced by <code>getMinimumSize(int, int)</code>.
550: */
551: @Deprecated
552: public Dimension minimumSize(int rows, int columns) {
553: synchronized (getTreeLock()) {
554: TextAreaPeer peer = (TextAreaPeer) this .peer;
555: return (peer != null) ? peer.minimumSize(rows, columns)
556: : super .minimumSize();
557: }
558: }
559:
560: /**
561: * Determines the minimum size of this text area.
562: * @return the preferred dimensions needed for this text area
563: * @see java.awt.Component#getPreferredSize
564: * @since JDK1.1
565: */
566: public Dimension getMinimumSize() {
567: return minimumSize();
568: }
569:
570: /**
571: * @deprecated As of JDK version 1.1,
572: * replaced by <code>getMinimumSize()</code>.
573: */
574: @Deprecated
575: public Dimension minimumSize() {
576: synchronized (getTreeLock()) {
577: return ((rows > 0) && (columns > 0)) ? minimumSize(rows,
578: columns) : super .minimumSize();
579: }
580: }
581:
582: /**
583: * Returns a string representing the state of this <code>TextArea</code>.
584: * This method is intended to be used only for debugging purposes, and the
585: * content and format of the returned string may vary between
586: * implementations. The returned string may be empty but may not be
587: * <code>null</code>.
588: *
589: * @return the parameter string of this text area
590: */
591: protected String paramString() {
592: String sbVisStr;
593: switch (scrollbarVisibility) {
594: case SCROLLBARS_BOTH:
595: sbVisStr = "both";
596: break;
597: case SCROLLBARS_VERTICAL_ONLY:
598: sbVisStr = "vertical-only";
599: break;
600: case SCROLLBARS_HORIZONTAL_ONLY:
601: sbVisStr = "horizontal-only";
602: break;
603: case SCROLLBARS_NONE:
604: sbVisStr = "none";
605: break;
606: default:
607: sbVisStr = "invalid display policy";
608: }
609:
610: return super .paramString() + ",rows=" + rows + ",columns="
611: + columns + ",scrollbarVisibility=" + sbVisStr;
612: }
613:
614: /*
615: * Serialization support.
616: */
617: /**
618: * The textArea Serialized Data Version.
619: *
620: * @serial
621: */
622: private int textAreaSerializedDataVersion = 2;
623:
624: /**
625: * Read the ObjectInputStream.
626: * @exception HeadlessException if
627: * <code>GraphicsEnvironment.isHeadless()</code> returns
628: * <code>true</code>
629: * @see java.awt.GraphicsEnvironment#isHeadless
630: */
631: private void readObject(ObjectInputStream s)
632: throws ClassNotFoundException, IOException,
633: HeadlessException {
634: // HeadlessException will be thrown by TextComponent's readObject
635: s.defaultReadObject();
636:
637: // Make sure the state we just read in for columns, rows,
638: // and scrollbarVisibility has legal values
639: if (columns < 0) {
640: columns = 0;
641: }
642: if (rows < 0) {
643: rows = 0;
644: }
645:
646: if ((scrollbarVisibility < SCROLLBARS_BOTH)
647: || (scrollbarVisibility > SCROLLBARS_NONE)) {
648: this .scrollbarVisibility = SCROLLBARS_BOTH;
649: }
650:
651: if (textAreaSerializedDataVersion < 2) {
652: setFocusTraversalKeys(
653: KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
654: forwardTraversalKeys);
655: setFocusTraversalKeys(
656: KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
657: backwardTraversalKeys);
658: }
659: }
660:
661: /////////////////
662: // Accessibility support
663: ////////////////
664:
665: /**
666: * Returns the <code>AccessibleContext</code> associated with
667: * this <code>TextArea</code>. For text areas, the
668: * <code>AccessibleContext</code> takes the form of an
669: * <code>AccessibleAWTTextArea</code>.
670: * A new <code>AccessibleAWTTextArea</code> instance is created if necessary.
671: *
672: * @return an <code>AccessibleAWTTextArea</code> that serves as the
673: * <code>AccessibleContext</code> of this <code>TextArea</code>
674: * @since 1.3
675: */
676: public AccessibleContext getAccessibleContext() {
677: if (accessibleContext == null) {
678: accessibleContext = new AccessibleAWTTextArea();
679: }
680: return accessibleContext;
681: }
682:
683: /**
684: * This class implements accessibility support for the
685: * <code>TextArea</code> class. It provides an implementation of the
686: * Java Accessibility API appropriate to text area user-interface elements.
687: * @since 1.3
688: */
689: protected class AccessibleAWTTextArea extends
690: AccessibleAWTTextComponent {
691: /*
692: * JDK 1.3 serialVersionUID
693: */
694: private static final long serialVersionUID = 3472827823632144419L;
695:
696: /**
697: * Gets the state set of this object.
698: *
699: * @return an instance of AccessibleStateSet describing the states
700: * of the object
701: * @see AccessibleStateSet
702: */
703: public AccessibleStateSet getAccessibleStateSet() {
704: AccessibleStateSet states = super.getAccessibleStateSet();
705: states.add(AccessibleState.MULTI_LINE);
706: return states;
707: }
708: }
709:
710: }
|