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 }
|