Frames | No Frames |
1: /* TextArea.java -- A multi-line text entry component 2: Copyright (C) 1999, 2004 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.awt; 40: 41: import java.awt.event.KeyEvent; 42: import java.awt.peer.ComponentPeer; 43: import java.awt.peer.TextAreaPeer; 44: import java.util.HashSet; 45: import java.util.Set; 46: 47: import javax.accessibility.AccessibleContext; 48: import javax.accessibility.AccessibleStateSet; 49: 50: 51: /** 52: * A TextArea is a text component capable of displaying multiple lines 53: * of user-editable text. A TextArea handles its own scrolling and 54: * can display vertical and horizontal scrollbars as navigation aids. 55: * 56: * @author Aaron M. Renn (arenn@urbanophile.com) 57: */ 58: public class TextArea extends TextComponent implements java.io.Serializable 59: { 60: /** 61: * Display both horiztonal and vertical scroll bars. 62: */ 63: public static final int SCROLLBARS_BOTH = 0; 64: 65: /** 66: * Display vertical scroll bar only. 67: */ 68: public static final int SCROLLBARS_VERTICAL_ONLY = 1; 69: 70: /** 71: * Display horizatonal scroll bar only. 72: */ 73: public static final int SCROLLBARS_HORIZONTAL_ONLY = 2; 74: 75: /** 76: * Do not display scrollbars. 77: */ 78: public static final int SCROLLBARS_NONE = 3; 79: 80: /** 81: * Serialization constant. 82: */ 83: private static final long serialVersionUID = 3692302836626095722L; 84: 85: /** 86: * @serial The number of columns used in this text area's preferred 87: * and minimum size calculations. 88: */ 89: private int columns; 90: 91: /** 92: * @serial The number of rows used in this text area's preferred and 93: * minimum size calculations. 94: */ 95: private int rows; 96: 97: /** 98: * @serial The scrollbar display policy. One of SCROLLBARS_BOTH, 99: * SCROLLBARS_VERTICAL_ONLY, SCROLLBARS_HORIZONTAL_ONLY, 100: * SCROLLBARS_NONE. 101: */ 102: private int scrollbarVisibility; 103: 104: /* 105: * The number used to generate the name returned by getName. 106: */ 107: private static transient long next_text_number; 108: 109: /** 110: * Initialize a new instance of <code>TextArea</code> that is empty. 111: * Conceptually the <code>TextArea</code> has 0 rows and 0 columns 112: * but its initial bounds are defined by its peer or by the 113: * container in which it is packed. Both horizontal and vertical 114: * scrollbars will be displayed. 115: * 116: * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true 117: */ 118: public TextArea () 119: { 120: this ("", 0, 0, SCROLLBARS_BOTH); 121: } 122: 123: /** 124: * Initialize a new instance of <code>TextArea</code> that contains 125: * the specified text. Conceptually the <code>TextArea</code> has 0 126: * rows and 0 columns but its initial bounds are defined by its peer 127: * or by the container in which it is packed. Both horizontal and 128: * veritcal scrollbars will be displayed. The TextArea initially contains 129: * the specified text. If text specified as <code>null<code>, it will 130: * be set to "". 131: * 132: * @param text The text to display in this text area (<code>null</code> permitted). 133: * 134: * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true 135: */ 136: public TextArea (String text) 137: { 138: this (text, 0, 0, SCROLLBARS_BOTH); 139: } 140: 141: /** 142: * Initialize a new instance of <code>TextArea</code> that is empty 143: * and can display the specified number of rows and columns of text, 144: * without the need to scroll. Both horizontal and vertical 145: * scrollbars will be displayed. 146: * 147: * @param rows The number of rows in this text area. 148: * @param columns The number of columns in this text area. 149: * 150: * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true 151: */ 152: public TextArea (int rows, int columns) 153: { 154: this ("", rows, columns, SCROLLBARS_BOTH); 155: } 156: 157: /** 158: * Initialize a new instance of <code>TextArea</code> that can 159: * display the specified number of rows and columns of text, without 160: * the need to scroll. The TextArea initially contains the 161: * specified text. If text specified as <code>null<code>, it will 162: * be set to "". 163: * 164: * @param text The text to display in this text area (<code>null</code> permitted). 165: * @param rows The number of rows in this text area. 166: * @param columns The number of columns in this text area. 167: * 168: * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true 169: */ 170: public TextArea (String text, int rows, int columns) 171: { 172: this (text, rows, columns, SCROLLBARS_BOTH); 173: } 174: 175: /** 176: * Initialize a new instance of <code>TextArea</code> that initially 177: * contains the specified text. The TextArea can display the 178: * specified number of rows and columns of text, without the need to 179: * scroll. This constructor allows specification of the scroll bar 180: * display policy. The TextArea initially contains the specified text. 181: * If text specified as <code>null<code>, it will be set to "". 182: * 183: * @param text The text to display in this text area (<code>null</code> permitted). 184: * @param rows The number of rows in this text area. 185: * @param columns The number of columns in this text area. 186: * @param scrollbarVisibility The scroll bar display policy. One of 187: * SCROLLBARS_BOTH, SCROLLBARS_VERTICAL_ONLY, 188: * SCROLLBARS_HORIZONTAL_ONLY, SCROLLBARS_NONE. 189: * 190: * @exception HeadlessException if GraphicsEnvironment.isHeadless () is true 191: */ 192: public TextArea (String text, int rows, int columns, int scrollbarVisibility) 193: { 194: super (text); 195: 196: if (GraphicsEnvironment.isHeadless ()) 197: throw new HeadlessException (); 198: 199: if (rows < 0) 200: this.rows = 0; 201: else 202: this.rows = rows; 203: 204: if (columns < 0) 205: this.columns = 0; 206: else 207: this.columns = columns; 208: 209: if (scrollbarVisibility < 0 || scrollbarVisibility > 4) 210: this.scrollbarVisibility = SCROLLBARS_BOTH; 211: else 212: this.scrollbarVisibility = scrollbarVisibility; 213: 214: // TextAreas need to receive tab key events so we override the 215: // default forward and backward traversal key sets. 216: Set s = new HashSet (); 217: s.add (AWTKeyStroke.getAWTKeyStroke (KeyEvent.VK_TAB, 218: KeyEvent.CTRL_DOWN_MASK)); 219: setFocusTraversalKeys (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, s); 220: s = new HashSet (); 221: s.add (AWTKeyStroke.getAWTKeyStroke (KeyEvent.VK_TAB, 222: KeyEvent.SHIFT_DOWN_MASK 223: | KeyEvent.CTRL_DOWN_MASK)); 224: setFocusTraversalKeys (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, s); 225: } 226: 227: /** 228: * Retrieve the number of columns that this text area would prefer 229: * to display. This value may or may not correspond to the number 230: * of columns that are actually displayed. 231: * 232: * @return The preferred number of columns. 233: */ 234: public int getColumns () 235: { 236: return columns; 237: } 238: 239: /** 240: * Set the preferred number of columns for this text area. This 241: * method does not cause the number of columns displayed by the text 242: * area to be updated, if the text area is currently visible. 243: * 244: * @param columns The preferred number of columns. 245: * 246: * @exception IllegalArgumentException If columns is less than zero. 247: */ 248: public synchronized void setColumns (int columns) 249: { 250: if (columns < 0) 251: throw new IllegalArgumentException ("Value is less than zero: " 252: + columns); 253: 254: this.columns = columns; 255: } 256: 257: /** 258: * Retrieve the number of rows that this text area would prefer to 259: * display. This value may or may not correspond to the number of 260: * rows that are actually displayed. 261: * 262: * @return The preferred number of rows. 263: */ 264: public int getRows () 265: { 266: return rows; 267: } 268: 269: /** 270: * Set the preferred number of rows for this text area. This method 271: * does not cause the number of columns displayed by the text area 272: * to be updated, if the text area is currently visible. 273: * 274: * @param rows The preferred number of rows. 275: * 276: * @exception IllegalArgumentException If rows is less than zero. 277: */ 278: public synchronized void setRows (int rows) 279: { 280: if (rows < 1) 281: throw new IllegalArgumentException ("Value is less than one: " + rows); 282: 283: this.rows = rows; 284: } 285: 286: /** 287: * Retrieve the minimum size for this text area. 288: * 289: * @return The minimum size for this text field. 290: */ 291: public Dimension getMinimumSize () 292: { 293: return getMinimumSize (getRows (), getColumns ()); 294: } 295: 296: /** 297: * Retrieve the minimum size for this text area. If the minimum 298: * size has been set, then rows and columns are used in the calculation. 299: * 300: * @param rows The number of rows to use in the minimum size 301: * calculation. 302: * @param columns The number of columns to use in the minimum size 303: * calculation. 304: * 305: * @return The minimum size for this text area. 306: */ 307: public Dimension getMinimumSize (int rows, int columns) 308: { 309: return minimumSize (rows, columns); 310: } 311: 312: /** 313: * Retrieve the minimum size for this text area. 314: * 315: * @return The minimum size for this text area. 316: * 317: * @deprecated This method is deprecated in favor of 318: * <code>getMinimumSize ()</code>. 319: */ 320: public Dimension minimumSize () 321: { 322: return minimumSize (getRows (), getColumns ()); 323: } 324: 325: /** 326: * Retrieve the minimum size for this text area. If the minimum 327: * size has been set, then rows and columns are used in the calculation. 328: * 329: * @param rows The number of rows to use in the minimum size 330: * calculation. 331: * @param columns The number of columns to use in the minimum size 332: * calculation. 333: * 334: * @return The minimum size for this text area. 335: * 336: * @deprecated This method is deprecated in favor of 337: * <code>getMinimumSize (int, int)</code>. 338: */ 339: public Dimension minimumSize (int rows, int columns) 340: { 341: if (isMinimumSizeSet()) 342: return new Dimension(minSize); 343: 344: TextAreaPeer peer = (TextAreaPeer) getPeer (); 345: if (peer == null) 346: return new Dimension (getWidth(), getHeight()); 347: 348: return peer.getMinimumSize (rows, columns); 349: } 350: 351: /** 352: * Retrieve the preferred size for this text area. 353: * 354: * @return The preferred size for this text field. 355: */ 356: public Dimension getPreferredSize () 357: { 358: return getPreferredSize (getRows (), getColumns ()); 359: } 360: 361: /** 362: * Retrieve the preferred size for this text area. If the preferred 363: * size has been set, then rows and columns are used in the calculation. 364: * 365: * @param rows The number of rows to use in the preferred size 366: * calculation. 367: * @param columns The number of columns to use in the preferred size 368: * calculation. 369: * 370: * @return The preferred size for this text area. 371: */ 372: public Dimension getPreferredSize (int rows, int columns) 373: { 374: return preferredSize (rows, columns); 375: } 376: 377: /** 378: * Retrieve the preferred size for this text area. 379: * 380: * @return The preferred size for this text field. 381: * 382: * @deprecated This method is deprecated in favor of 383: * <code>getPreferredSize ()</code>. 384: */ 385: public Dimension preferredSize () 386: { 387: return preferredSize (getRows (), getColumns ()); 388: } 389: 390: /** 391: * Retrieve the preferred size for this text area. If the preferred 392: * size has been set, then rows and columns are used in the calculation. 393: * 394: * @param rows The number of rows to use in the preferred size 395: * calculation. 396: * @param columns The number of columns to use in the preferred size 397: * calculation. 398: * 399: * @return The preferred size for this text area. 400: * 401: * @deprecated This method is deprecated in favor of 402: * <code>getPreferredSize (int, int)</code>. 403: */ 404: public Dimension preferredSize (int rows, int columns) 405: { 406: if (isPreferredSizeSet()) 407: return new Dimension(prefSize); 408: 409: TextAreaPeer peer = (TextAreaPeer) getPeer (); 410: if (peer == null) 411: return new Dimension (getWidth(), getHeight()); 412: 413: return peer.getPreferredSize (rows, columns); 414: } 415: 416: /** 417: * Retrieve the scroll bar display policy -- one of SCROLLBARS_BOTH, 418: * SCROLLBARS_VERTICAL_ONLY, SCROLLBARS_HORIZONTAL_ONLY, 419: * SCROLLBARS_NONE. 420: * 421: * @return The current scroll bar display policy. 422: */ 423: public int getScrollbarVisibility () 424: { 425: return scrollbarVisibility; 426: } 427: 428: /** 429: * Notify this object that it should create its native peer. 430: */ 431: public void addNotify () 432: { 433: if (getPeer () == null) 434: setPeer ((ComponentPeer) getToolkit().createTextArea (this)); 435: } 436: 437: /** 438: * Append the specified text to the end of the current text. 439: * 440: * @param str The text to append. 441: */ 442: public void append (String str) 443: { 444: appendText (str); 445: } 446: 447: /** 448: * Append the specified text to the end of the current text. 449: * 450: * @param str The text to append. 451: * 452: * @deprecated This method is deprecated in favor of 453: * <code>append ()</code>. 454: */ 455: public void appendText (String str) 456: { 457: TextAreaPeer peer = (TextAreaPeer) getPeer (); 458: 459: if (peer != null) 460: peer.insert (str, peer.getText().length ()); 461: else 462: setText(getText() + str); 463: } 464: 465: /** 466: * Insert the specified text at the specified position. The first 467: * character in the text area is at position zero. 468: * 469: * @param str The text to insert. 470: * @param pos The position at which to insert text. 471: */ 472: public void insert (String str, int pos) 473: { 474: insertText (str, pos); 475: } 476: 477: /** 478: * Insert the specified text at the specified position. The first 479: * character in the text area is at position zero. 480: * 481: * @param str The text to insert. 482: * @param pos The position at which to insert text. 483: * 484: * @deprecated This method is deprecated in favor of 485: * <code>insert ()</code>. 486: */ 487: public void insertText (String str, int pos) 488: { 489: String tmp1 = null; 490: String tmp2 = null; 491: 492: TextAreaPeer peer = (TextAreaPeer) getPeer (); 493: 494: if (peer != null) 495: peer.insert (str, pos); 496: else 497: { 498: tmp1 = getText().substring(0, pos); 499: tmp2 = getText().substring(pos, getText().length()); 500: setText(tmp1 + str + tmp2); 501: } 502: } 503: 504: /** 505: * Replace a range of characters with the specified text. The 506: * character at the start position will be replaced, unless start == 507: * end. The character at the end posistion will not be replaced. 508: * The first character in the text area is at position zero. The 509: * length of the replacement text may differ from the length of the 510: * text that is replaced. 511: * 512: * @param str The new text for the range. 513: * @param start The start position of the replacement range. 514: * @param end The end position of the replacement range. 515: */ 516: public void replaceRange (String str, int start, int end) 517: { 518: replaceText (str, start, end); 519: } 520: 521: /** 522: * Replace a range of characters with the specified text. The 523: * character at the start position will be replaced, unless start == 524: * end. The character at the end posistion will not be replaced. 525: * The first character in the text area is at position zero. The 526: * length of the replacement text may differ from the length of the 527: * text that is replaced. 528: * 529: * @param str The new text for the range. 530: * @param start The start position of the replacement range. 531: * @param end The end position of the replacement range. 532: * 533: * @deprecated This method is deprecated in favor of 534: * <code>replaceRange ()</code>. 535: */ 536: public void replaceText (String str, int start, int end) 537: { 538: String tmp1 = null; 539: String tmp2 = null; 540: 541: TextAreaPeer peer = (TextAreaPeer) getPeer(); 542: 543: if (peer != null) 544: peer.replaceRange(str, start, end); 545: else 546: { 547: tmp1 = getText().substring(0, start); 548: tmp2 = getText().substring(end, getText().length()); 549: setText(tmp1 + str + tmp2); 550: } 551: } 552: 553: /** 554: * Retrieve a debugging string for this text area. 555: * 556: * @return A debugging string for this text area. 557: */ 558: protected String paramString () 559: { 560: String sbVisibility = ""; 561: 562: switch (scrollbarVisibility) 563: { 564: case SCROLLBARS_BOTH: 565: sbVisibility = "both"; 566: break; 567: case SCROLLBARS_VERTICAL_ONLY: 568: sbVisibility = "vertical-only"; 569: break; 570: case SCROLLBARS_HORIZONTAL_ONLY: 571: sbVisibility = "horizontal-only"; 572: break; 573: case SCROLLBARS_NONE: 574: sbVisibility = "none"; 575: break; 576: } 577: 578: String editable = ""; 579: if (isEditable ()) 580: editable = "editable,"; 581: 582: return getName () + "," + getX () + "," + getY () + "," + getWidth () 583: + "x" + getHeight () + "," + "text=" + getText () + "," + editable 584: + "selection=" + getSelectionStart () + "-" + getSelectionEnd () 585: + ",rows=" + rows + ",columns=" + columns + ",scrollbarVisibility=" 586: + sbVisibility; 587: } 588: 589: /** 590: * Generate a unique name for this text area. 591: * 592: * @return A unique name for this text area. 593: */ 594: String generateName () 595: { 596: return "text" + getUniqueLong (); 597: } 598: 599: private static synchronized long getUniqueLong () 600: { 601: return next_text_number++; 602: } 603: 604: protected class AccessibleAWTTextArea extends AccessibleAWTTextComponent 605: { 606: private static final long serialVersionUID = 3472827823632144419L; 607: 608: protected AccessibleAWTTextArea() 609: { 610: } 611: 612: public AccessibleStateSet getAccessibleStateSet() 613: { 614: return super.getAccessibleStateSet(); 615: } 616: } 617: 618: /** 619: * Gets the AccessibleContext associated with this <code>TextArea</code>. 620: * The context is created, if necessary. 621: * 622: * @return the associated context 623: */ 624: public AccessibleContext getAccessibleContext() 625: { 626: /* Create the context if this is the first request */ 627: if (accessibleContext == null) 628: accessibleContext = new AccessibleAWTTextArea(); 629: return accessibleContext; 630: } 631: }