1 /* 2 * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.peer.TextFieldPeer; 28 import java.awt.event.*; 29 import java.util.EventListener; 30 import java.io.ObjectOutputStream; 31 import java.io.ObjectInputStream; 32 import java.io.IOException; 33 import javax.accessibility.*; 34 35 36 /** 37 * A <code>TextField</code> object is a text component 38 * that allows for the editing of a single line of text. 39 * If the input text contains new line character, 40 * it will be replaced by a space character. 41 * <p> 42 * For example, the following image depicts a frame with four 43 * text fields of varying widths. Two of these text fields 44 * display the predefined text <code>"Hello"</code>. 45 * <p> 46 * <img src="doc-files/TextField-1.gif" alt="The preceding text describes this image." 47 * style="float:center; margin: 7px 10px;"> 48 * <p> 49 * Here is the code that produces these four text fields: 50 * 51 * <hr><blockquote><pre> 52 * TextField tf1, tf2, tf3, tf4; 53 * // a blank text field 54 * tf1 = new TextField(); 55 * // blank field of 20 columns 56 * tf2 = new TextField("", 20); 57 * // predefined text displayed 58 * tf3 = new TextField("Hello!"); 59 * // predefined text in 30 columns 60 * tf4 = new TextField("Hello", 30); 61 * </pre></blockquote><hr> 62 * <p> 63 * Every time the user types a key in the text field, one or 64 * more key events are sent to the text field. A <code>KeyEvent</code> 65 * may be one of three types: keyPressed, keyReleased, or keyTyped. 66 * The properties of a key event indicate which of these types 67 * it is, as well as additional information about the event, 68 * such as what modifiers are applied to the key event and the 69 * time at which the event occurred. 70 * <p> 71 * The key event is passed to every <code>KeyListener</code> 72 * or <code>KeyAdapter</code> object which registered to receive such 73 * events using the component's <code>addKeyListener</code> method. 74 * (<code>KeyAdapter</code> objects implement the 75 * <code>KeyListener</code> interface.) 76 * <p> 77 * It is also possible to fire an <code>ActionEvent</code>. 78 * If action events are enabled for the text field, they may 79 * be fired by pressing the <code>Return</code> key. 80 * <p> 81 * The <code>TextField</code> class's <code>processEvent</code> 82 * method examines the action event and passes it along to 83 * <code>processActionEvent</code>. The latter method redirects the 84 * event to any <code>ActionListener</code> objects that have 85 * registered to receive action events generated by this 86 * text field. 87 * 88 * @author Sami Shaio 89 * @see java.awt.event.KeyEvent 90 * @see java.awt.event.KeyAdapter 91 * @see java.awt.event.KeyListener 92 * @see java.awt.event.ActionEvent 93 * @see java.awt.Component#addKeyListener 94 * @see java.awt.TextField#processEvent 95 * @see java.awt.TextField#processActionEvent 96 * @see java.awt.TextField#addActionListener 97 * @since 1.0 98 */ 99 public class TextField extends TextComponent { 100 101 /** 102 * The number of columns in the text field. 103 * A column is an approximate average character 104 * width that is platform-dependent. 105 * Guaranteed to be non-negative. 106 * 107 * @serial 108 * @see #setColumns(int) 109 * @see #getColumns() 110 */ 111 int columns; 112 113 /** 114 * The echo character, which is used when 115 * the user wishes to disguise the characters 116 * typed into the text field. 117 * The disguises are removed if echoChar = <code>0</code>. 118 * 119 * @serial 120 * @see #getEchoChar() 121 * @see #setEchoChar(char) 122 * @see #echoCharIsSet() 123 */ 124 char echoChar; 125 126 transient ActionListener actionListener; 127 128 private static final String base = "textfield"; 129 private static int nameCounter = 0; 130 131 /* 132 * JDK 1.1 serialVersionUID 133 */ 134 private static final long serialVersionUID = -2966288784432217853L; 135 136 /** 137 * Initialize JNI field and method ids 138 */ 139 private static native void initIDs(); 140 141 static { 142 /* ensure that the necessary native libraries are loaded */ 143 Toolkit.loadLibraries(); 144 if (!GraphicsEnvironment.isHeadless()) { 145 initIDs(); 146 } 147 } 148 149 /** 150 * Constructs a new text field. 151 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 152 * returns true. 153 * @see java.awt.GraphicsEnvironment#isHeadless 154 */ 155 public TextField() throws HeadlessException { 156 this("", 0); 157 } 158 159 /** 160 * Constructs a new text field initialized with the specified text. 161 * @param text the text to be displayed. If 162 * <code>text</code> is <code>null</code>, the empty 163 * string <code>""</code> will be displayed. 164 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 165 * returns true. 166 * @see java.awt.GraphicsEnvironment#isHeadless 167 */ 168 public TextField(String text) throws HeadlessException { 169 this(text, (text != null) ? text.length() : 0); 170 } 171 172 /** 173 * Constructs a new empty text field with the specified number 174 * of columns. A column is an approximate average character 175 * width that is platform-dependent. 176 * @param columns the number of columns. If 177 * <code>columns</code> is less than <code>0</code>, 178 * <code>columns</code> is set to <code>0</code>. 179 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 180 * returns true. 181 * @see java.awt.GraphicsEnvironment#isHeadless 182 */ 183 public TextField(int columns) throws HeadlessException { 184 this("", columns); 185 } 186 187 /** 188 * Constructs a new text field initialized with the specified text 189 * to be displayed, and wide enough to hold the specified 190 * number of columns. A column is an approximate average character 191 * width that is platform-dependent. 192 * @param text the text to be displayed. If 193 * <code>text</code> is <code>null</code>, the empty 194 * string <code>""</code> will be displayed. 195 * @param columns the number of columns. If 196 * <code>columns</code> is less than <code>0</code>, 197 * <code>columns</code> is set to <code>0</code>. 198 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 199 * returns true. 200 * @see java.awt.GraphicsEnvironment#isHeadless 201 */ 202 public TextField(String text, int columns) throws HeadlessException { 203 super(text); 204 this.columns = (columns >= 0) ? columns : 0; 205 } 206 207 /** 208 * Construct a name for this component. Called by getName() when the 209 * name is null. 210 */ 211 String constructComponentName() { 212 synchronized (TextField.class) { 213 return base + nameCounter++; 214 } 215 } 216 217 /** 218 * Creates the TextField's peer. The peer allows us to modify the 219 * appearance of the TextField without changing its functionality. 220 */ 221 public void addNotify() { 222 synchronized (getTreeLock()) { 223 if (peer == null) 224 peer = getComponentFactory().createTextField(this); 225 super.addNotify(); 226 } 227 } 228 229 /** 230 * Gets the character that is to be used for echoing. 231 * <p> 232 * An echo character is useful for text fields where 233 * user input should not be echoed to the screen, as in 234 * the case of a text field for entering a password. 235 * If <code>echoChar</code> = <code>0</code>, user 236 * input is echoed to the screen unchanged. 237 * <p> 238 * A Java platform implementation may support only a limited, 239 * non-empty set of echo characters. This function returns the 240 * echo character originally requested via setEchoChar(). The echo 241 * character actually used by the TextField implementation might be 242 * different. 243 * @return the echo character for this text field. 244 * @see java.awt.TextField#echoCharIsSet 245 * @see java.awt.TextField#setEchoChar 246 */ 247 public char getEchoChar() { 248 return echoChar; 249 } 250 251 /** 252 * Sets the echo character for this text field. 253 * <p> 254 * An echo character is useful for text fields where 255 * user input should not be echoed to the screen, as in 256 * the case of a text field for entering a password. 257 * Setting <code>echoChar</code> = <code>0</code> allows 258 * user input to be echoed to the screen again. 259 * <p> 260 * A Java platform implementation may support only a limited, 261 * non-empty set of echo characters. Attempts to set an 262 * unsupported echo character will cause the default echo 263 * character to be used instead. Subsequent calls to getEchoChar() 264 * will return the echo character originally requested. This might 265 * or might not be identical to the echo character actually 266 * used by the TextField implementation. 267 * @param c the echo character for this text field. 268 * @see java.awt.TextField#echoCharIsSet 269 * @see java.awt.TextField#getEchoChar 270 * @since 1.1 271 */ 272 public void setEchoChar(char c) { 273 setEchoCharacter(c); 274 } 275 276 /** 277 * Sets the character to be echoed when protected input is displayed. 278 * 279 * @param c the echo character for this text field 280 * 281 * @deprecated As of JDK version 1.1, 282 * replaced by <code>setEchoChar(char)</code>. 283 */ 284 @Deprecated 285 public synchronized void setEchoCharacter(char c) { 286 if (echoChar != c) { 287 echoChar = c; 288 TextFieldPeer peer = (TextFieldPeer)this.peer; 289 if (peer != null) { 290 peer.setEchoChar(c); 291 } 292 } 293 } 294 295 /** 296 * Sets the text that is presented by this 297 * text component to be the specified text. 298 * @param t the new text. 299 * @see java.awt.TextComponent#getText 300 */ 301 public void setText(String t) { 302 super.setText(t); 303 304 // This could change the preferred size of the Component. 305 invalidateIfValid(); 306 } 307 308 /** 309 * Indicates whether or not this text field has a 310 * character set for echoing. 311 * <p> 312 * An echo character is useful for text fields where 313 * user input should not be echoed to the screen, as in 314 * the case of a text field for entering a password. 315 * @return <code>true</code> if this text field has 316 * a character set for echoing; 317 * <code>false</code> otherwise. 318 * @see java.awt.TextField#setEchoChar 319 * @see java.awt.TextField#getEchoChar 320 */ 321 public boolean echoCharIsSet() { 322 return echoChar != 0; 323 } 324 325 /** 326 * Gets the number of columns in this text field. A column is an 327 * approximate average character width that is platform-dependent. 328 * @return the number of columns. 329 * @see java.awt.TextField#setColumns 330 * @since 1.1 331 */ 332 public int getColumns() { 333 return columns; 334 } 335 336 /** 337 * Sets the number of columns in this text field. A column is an 338 * approximate average character width that is platform-dependent. 339 * @param columns the number of columns. 340 * @see java.awt.TextField#getColumns 341 * @exception IllegalArgumentException if the value 342 * supplied for <code>columns</code> 343 * is less than <code>0</code>. 344 * @since 1.1 345 */ 346 public void setColumns(int columns) { 347 int oldVal; 348 synchronized (this) { 349 oldVal = this.columns; 350 if (columns < 0) { 351 throw new IllegalArgumentException("columns less than zero."); 352 } 353 if (columns != oldVal) { 354 this.columns = columns; 355 } 356 } 357 358 if (columns != oldVal) { 359 invalidate(); 360 } 361 } 362 363 /** 364 * Gets the preferred size of this text field 365 * with the specified number of columns. 366 * @param columns the number of columns 367 * in this text field. 368 * @return the preferred dimensions for 369 * displaying this text field. 370 * @since 1.1 371 */ 372 public Dimension getPreferredSize(int columns) { 373 return preferredSize(columns); 374 } 375 376 /** 377 * Returns the preferred size for this text field 378 * with the specified number of columns. 379 * 380 * @param columns the number of columns 381 * @return the preferred size for the text field 382 * 383 * @deprecated As of JDK version 1.1, 384 * replaced by <code>getPreferredSize(int)</code>. 385 */ 386 @Deprecated 387 public Dimension preferredSize(int columns) { 388 synchronized (getTreeLock()) { 389 TextFieldPeer peer = (TextFieldPeer)this.peer; 390 return (peer != null) ? 391 peer.getPreferredSize(columns) : 392 super.preferredSize(); 393 } 394 } 395 396 /** 397 * Gets the preferred size of this text field. 398 * @return the preferred dimensions for 399 * displaying this text field. 400 * @since 1.1 401 */ 402 public Dimension getPreferredSize() { 403 return preferredSize(); 404 } 405 406 /** 407 * @deprecated As of JDK version 1.1, 408 * replaced by <code>getPreferredSize()</code>. 409 */ 410 @Deprecated 411 public Dimension preferredSize() { 412 synchronized (getTreeLock()) { 413 return (columns > 0) ? 414 preferredSize(columns) : 415 super.preferredSize(); 416 } 417 } 418 419 /** 420 * Gets the minimum dimensions for a text field with 421 * the specified number of columns. 422 * @param columns the number of columns in 423 * this text field. 424 * @return the minimum size for this text field 425 * @since 1.1 426 */ 427 public Dimension getMinimumSize(int columns) { 428 return minimumSize(columns); 429 } 430 431 /** 432 * Returns the minimum dimensions for a text field with 433 * the specified number of columns. 434 * 435 * @param columns the number of columns 436 * @return the minimum size for this text field 437 * @deprecated As of JDK version 1.1, 438 * replaced by <code>getMinimumSize(int)</code>. 439 */ 440 @Deprecated 441 public Dimension minimumSize(int columns) { 442 synchronized (getTreeLock()) { 443 TextFieldPeer peer = (TextFieldPeer)this.peer; 444 return (peer != null) ? 445 peer.getMinimumSize(columns) : 446 super.minimumSize(); 447 } 448 } 449 450 /** 451 * Gets the minimum dimensions for this text field. 452 * @return the minimum dimensions for 453 * displaying this text field. 454 * @since 1.1 455 */ 456 public Dimension getMinimumSize() { 457 return minimumSize(); 458 } 459 460 /** 461 * @deprecated As of JDK version 1.1, 462 * replaced by <code>getMinimumSize()</code>. 463 */ 464 @Deprecated 465 public Dimension minimumSize() { 466 synchronized (getTreeLock()) { 467 return (columns > 0) ? 468 minimumSize(columns) : 469 super.minimumSize(); 470 } 471 } 472 473 /** 474 * Adds the specified action listener to receive 475 * action events from this text field. 476 * If l is null, no exception is thrown and no action is performed. 477 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 478 * >AWT Threading Issues</a> for details on AWT's threading model. 479 * 480 * @param l the action listener. 481 * @see #removeActionListener 482 * @see #getActionListeners 483 * @see java.awt.event.ActionListener 484 * @since 1.1 485 */ 486 public synchronized void addActionListener(ActionListener l) { 487 if (l == null) { 488 return; 489 } 490 actionListener = AWTEventMulticaster.add(actionListener, l); 491 newEventsOnly = true; 492 } 493 494 /** 495 * Removes the specified action listener so that it no longer 496 * receives action events from this text field. 497 * If l is null, no exception is thrown and no action is performed. 498 * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 499 * >AWT Threading Issues</a> for details on AWT's threading model. 500 * 501 * @param l the action listener. 502 * @see #addActionListener 503 * @see #getActionListeners 504 * @see java.awt.event.ActionListener 505 * @since 1.1 506 */ 507 public synchronized void removeActionListener(ActionListener l) { 508 if (l == null) { 509 return; 510 } 511 actionListener = AWTEventMulticaster.remove(actionListener, l); 512 } 513 514 /** 515 * Returns an array of all the action listeners 516 * registered on this textfield. 517 * 518 * @return all of this textfield's <code>ActionListener</code>s 519 * or an empty array if no action 520 * listeners are currently registered 521 * 522 * @see #addActionListener 523 * @see #removeActionListener 524 * @see java.awt.event.ActionListener 525 * @since 1.4 526 */ 527 public synchronized ActionListener[] getActionListeners() { 528 return getListeners(ActionListener.class); 529 } 530 531 /** 532 * Returns an array of all the objects currently registered 533 * as <code><em>Foo</em>Listener</code>s 534 * upon this <code>TextField</code>. 535 * <code><em>Foo</em>Listener</code>s are registered using the 536 * <code>add<em>Foo</em>Listener</code> method. 537 * 538 * <p> 539 * You can specify the <code>listenerType</code> argument 540 * with a class literal, such as 541 * <code><em>Foo</em>Listener.class</code>. 542 * For example, you can query a 543 * <code>TextField</code> <code>t</code> 544 * for its action listeners with the following code: 545 * 546 * <pre>ActionListener[] als = (ActionListener[])(t.getListeners(ActionListener.class));</pre> 547 * 548 * If no such listeners exist, this method returns an empty array. 549 * 550 * @param listenerType the type of listeners requested; this parameter 551 * should specify an interface that descends from 552 * <code>java.util.EventListener</code> 553 * @return an array of all objects registered as 554 * <code><em>Foo</em>Listener</code>s on this textfield, 555 * or an empty array if no such 556 * listeners have been added 557 * @exception ClassCastException if <code>listenerType</code> 558 * doesn't specify a class or interface that implements 559 * <code>java.util.EventListener</code> 560 * 561 * @see #getActionListeners 562 * @since 1.3 563 */ 564 public <T extends EventListener> T[] getListeners(Class<T> listenerType) { 565 EventListener l = null; 566 if (listenerType == ActionListener.class) { 567 l = actionListener; 568 } else { 569 return super.getListeners(listenerType); 570 } 571 return AWTEventMulticaster.getListeners(l, listenerType); 572 } 573 574 // REMIND: remove when filtering is done at lower level 575 boolean eventEnabled(AWTEvent e) { 576 if (e.id == ActionEvent.ACTION_PERFORMED) { 577 if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 || 578 actionListener != null) { 579 return true; 580 } 581 return false; 582 } 583 return super.eventEnabled(e); 584 } 585 586 /** 587 * Processes events on this text field. If the event 588 * is an instance of <code>ActionEvent</code>, 589 * it invokes the <code>processActionEvent</code> 590 * method. Otherwise, it invokes <code>processEvent</code> 591 * on the superclass. 592 * <p>Note that if the event parameter is <code>null</code> 593 * the behavior is unspecified and may result in an 594 * exception. 595 * 596 * @param e the event 597 * @see java.awt.event.ActionEvent 598 * @see java.awt.TextField#processActionEvent 599 * @since 1.1 600 */ 601 protected void processEvent(AWTEvent e) { 602 if (e instanceof ActionEvent) { 603 processActionEvent((ActionEvent)e); 604 return; 605 } 606 super.processEvent(e); 607 } 608 609 /** 610 * Processes action events occurring on this text field by 611 * dispatching them to any registered 612 * <code>ActionListener</code> objects. 613 * <p> 614 * This method is not called unless action events are 615 * enabled for this component. Action events are enabled 616 * when one of the following occurs: 617 * <ul> 618 * <li>An <code>ActionListener</code> object is registered 619 * via <code>addActionListener</code>. 620 * <li>Action events are enabled via <code>enableEvents</code>. 621 * </ul> 622 * <p>Note that if the event parameter is <code>null</code> 623 * the behavior is unspecified and may result in an 624 * exception. 625 * 626 * @param e the action event 627 * @see java.awt.event.ActionListener 628 * @see java.awt.TextField#addActionListener 629 * @see java.awt.Component#enableEvents 630 * @since 1.1 631 */ 632 protected void processActionEvent(ActionEvent e) { 633 ActionListener listener = actionListener; 634 if (listener != null) { 635 listener.actionPerformed(e); 636 } 637 } 638 639 /** 640 * Returns a string representing the state of this <code>TextField</code>. 641 * This method is intended to be used only for debugging purposes, and the 642 * content and format of the returned string may vary between 643 * implementations. The returned string may be empty but may not be 644 * <code>null</code>. 645 * 646 * @return the parameter string of this text field 647 */ 648 protected String paramString() { 649 String str = super.paramString(); 650 if (echoChar != 0) { 651 str += ",echo=" + echoChar; 652 } 653 return str; 654 } 655 656 657 /* 658 * Serialization support. 659 */ 660 /** 661 * The textField Serialized Data Version. 662 * 663 * @serial 664 */ 665 private int textFieldSerializedDataVersion = 1; 666 667 /** 668 * Writes default serializable fields to stream. Writes 669 * a list of serializable ActionListener(s) as optional data. 670 * The non-serializable ActionListener(s) are detected and 671 * no attempt is made to serialize them. 672 * 673 * @serialData Null terminated sequence of zero or more pairs. 674 * A pair consists of a String and Object. 675 * The String indicates the type of object and 676 * is one of the following : 677 * ActionListenerK indicating and ActionListener object. 678 * 679 * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener) 680 * @see java.awt.Component#actionListenerK 681 */ 682 private void writeObject(ObjectOutputStream s) 683 throws IOException 684 { 685 s.defaultWriteObject(); 686 687 AWTEventMulticaster.save(s, actionListenerK, actionListener); 688 s.writeObject(null); 689 } 690 691 /** 692 * Read the ObjectInputStream and if it isn't null, 693 * add a listener to receive action events fired by the 694 * TextField. Unrecognized keys or values will be 695 * ignored. 696 * 697 * @exception HeadlessException if 698 * <code>GraphicsEnvironment.isHeadless()</code> returns 699 * <code>true</code> 700 * @see #removeActionListener(ActionListener) 701 * @see #addActionListener(ActionListener) 702 * @see java.awt.GraphicsEnvironment#isHeadless 703 */ 704 private void readObject(ObjectInputStream s) 705 throws ClassNotFoundException, IOException, HeadlessException 706 { 707 // HeadlessException will be thrown by TextComponent's readObject 708 s.defaultReadObject(); 709 710 // Make sure the state we just read in for columns has legal values 711 if (columns < 0) { 712 columns = 0; 713 } 714 715 // Read in listeners, if any 716 Object keyOrNull; 717 while(null != (keyOrNull = s.readObject())) { 718 String key = ((String)keyOrNull).intern(); 719 720 if (actionListenerK == key) { 721 addActionListener((ActionListener)(s.readObject())); 722 } else { 723 // skip value for unrecognized key 724 s.readObject(); 725 } 726 } 727 } 728 729 730 ///////////////// 731 // Accessibility support 732 //////////////// 733 734 735 /** 736 * Gets the AccessibleContext associated with this TextField. 737 * For text fields, the AccessibleContext takes the form of an 738 * AccessibleAWTTextField. 739 * A new AccessibleAWTTextField instance is created if necessary. 740 * 741 * @return an AccessibleAWTTextField that serves as the 742 * AccessibleContext of this TextField 743 * @since 1.3 744 */ 745 public AccessibleContext getAccessibleContext() { 746 if (accessibleContext == null) { 747 accessibleContext = new AccessibleAWTTextField(); 748 } 749 return accessibleContext; 750 } 751 752 /** 753 * This class implements accessibility support for the 754 * <code>TextField</code> class. It provides an implementation of the 755 * Java Accessibility API appropriate to text field user-interface elements. 756 * @since 1.3 757 */ 758 protected class AccessibleAWTTextField extends AccessibleAWTTextComponent 759 { 760 /* 761 * JDK 1.3 serialVersionUID 762 */ 763 private static final long serialVersionUID = 6219164359235943158L; 764 765 /** 766 * Gets the state set of this object. 767 * 768 * @return an instance of AccessibleStateSet describing the states 769 * of the object 770 * @see AccessibleState 771 */ 772 public AccessibleStateSet getAccessibleStateSet() { 773 AccessibleStateSet states = super.getAccessibleStateSet(); 774 states.add(AccessibleState.SINGLE_LINE); 775 return states; 776 } 777 } 778 779 }