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