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 */ TextArea()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 */ TextArea(String text)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 */ TextArea(int rows, int columns)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 */ TextArea(String text, int rows, int columns)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 */ TextArea(String text, int rows, int columns, int scrollbarVisibility)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 */ getColumns()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 */ setColumns(int columns)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 */ getRows()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 */ setRows(int rows)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 */ getMinimumSize()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 */ getMinimumSize(int rows, int columns)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 */ minimumSize()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 */ minimumSize(int rows, int columns)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 */ getPreferredSize()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 */ getPreferredSize(int rows, int columns)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 */ preferredSize()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 */ preferredSize(int rows, int columns)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 */ getScrollbarVisibility()423 public int getScrollbarVisibility () 424 { 425 return scrollbarVisibility; 426 } 427 428 /** 429 * Notify this object that it should create its native peer. 430 */ addNotify()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 */ append(String str)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 */ appendText(String str)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 */ insert(String str, int pos)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 */ insertText(String str, int pos)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 */ replaceRange(String str, int start, int end)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 */ replaceText(String str, int start, int end)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 */ paramString()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 */ generateName()594 String generateName () 595 { 596 return "text" + getUniqueLong (); 597 } 598 getUniqueLong()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 AccessibleAWTTextArea()608 protected AccessibleAWTTextArea() 609 { 610 } 611 getAccessibleStateSet()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 */ getAccessibleContext()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 } 632