1. /*
  2. * @(#)TextField.java 1.80 04/05/18
  3. *
  4. * Copyright 2004 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.80, 05/18/04
  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. @Deprecated
  229. public synchronized void setEchoCharacter(char c) {
  230. if (echoChar != c) {
  231. echoChar = c;
  232. TextFieldPeer peer = (TextFieldPeer)this.peer;
  233. if (peer != null) {
  234. peer.setEchoCharacter(c);
  235. }
  236. }
  237. }
  238. /**
  239. * Sets the text that is presented by this
  240. * text component to be the specified text.
  241. * @param t the new text.
  242. * @see java.awt.TextComponent#getText
  243. */
  244. public void setText(String t) {
  245. super.setText(t);
  246. // This could change the preferred size of the Component.
  247. if (valid) {
  248. invalidate();
  249. }
  250. }
  251. /**
  252. * Indicates whether or not this text field has a
  253. * character set for echoing.
  254. * <p>
  255. * An echo character is useful for text fields where
  256. * user input should not be echoed to the screen, as in
  257. * the case of a text field for entering a password.
  258. * @return <code>true</code> if this text field has
  259. * a character set for echoing;
  260. * <code>false</code> otherwise.
  261. * @see java.awt.TextField#setEchoChar
  262. * @see java.awt.TextField#getEchoChar
  263. */
  264. public boolean echoCharIsSet() {
  265. return echoChar != 0;
  266. }
  267. /**
  268. * Gets the number of columns in this text field. A column is an
  269. * approximate average character width that is platform-dependent.
  270. * @return the number of columns.
  271. * @see java.awt.TextField#setColumns
  272. * @since JDK1.1
  273. */
  274. public int getColumns() {
  275. return columns;
  276. }
  277. /**
  278. * Sets the number of columns in this text field. A column is an
  279. * approximate average character width that is platform-dependent.
  280. * @param columns the number of columns.
  281. * @see java.awt.TextField#getColumns
  282. * @exception IllegalArgumentException if the value
  283. * supplied for <code>columns</code>
  284. * is less than <code>0</code>.
  285. * @since JDK1.1
  286. */
  287. public synchronized void setColumns(int columns) {
  288. int oldVal = this.columns;
  289. if (columns < 0) {
  290. throw new IllegalArgumentException("columns less than zero.");
  291. }
  292. if (columns != oldVal) {
  293. this.columns = columns;
  294. invalidate();
  295. }
  296. }
  297. /**
  298. * Gets the preferred size of this text field
  299. * with the specified number of columns.
  300. * @param columns the number of columns
  301. * in this text field.
  302. * @return the preferred dimensions for
  303. * displaying this text field.
  304. * @since JDK1.1
  305. */
  306. public Dimension getPreferredSize(int columns) {
  307. return preferredSize(columns);
  308. }
  309. /**
  310. * @deprecated As of JDK version 1.1,
  311. * replaced by <code>getPreferredSize(int)</code>.
  312. */
  313. @Deprecated
  314. public Dimension preferredSize(int columns) {
  315. synchronized (getTreeLock()) {
  316. TextFieldPeer peer = (TextFieldPeer)this.peer;
  317. return (peer != null) ?
  318. peer.preferredSize(columns) :
  319. super.preferredSize();
  320. }
  321. }
  322. /**
  323. * Gets the preferred size of this text field.
  324. * @return the preferred dimensions for
  325. * displaying this text field.
  326. * @since JDK1.1
  327. */
  328. public Dimension getPreferredSize() {
  329. return preferredSize();
  330. }
  331. /**
  332. * @deprecated As of JDK version 1.1,
  333. * replaced by <code>getPreferredSize()</code>.
  334. */
  335. @Deprecated
  336. public Dimension preferredSize() {
  337. synchronized (getTreeLock()) {
  338. return (columns > 0) ?
  339. preferredSize(columns) :
  340. super.preferredSize();
  341. }
  342. }
  343. /**
  344. * Gets the minumum dimensions for a text field with
  345. * the specified number of columns.
  346. * @param columns the number of columns in
  347. * this text field.
  348. * @since JDK1.1
  349. */
  350. public Dimension getMinimumSize(int columns) {
  351. return minimumSize(columns);
  352. }
  353. /**
  354. * @deprecated As of JDK version 1.1,
  355. * replaced by <code>getMinimumSize(int)</code>.
  356. */
  357. @Deprecated
  358. public Dimension minimumSize(int columns) {
  359. synchronized (getTreeLock()) {
  360. TextFieldPeer peer = (TextFieldPeer)this.peer;
  361. return (peer != null) ?
  362. peer.minimumSize(columns) :
  363. super.minimumSize();
  364. }
  365. }
  366. /**
  367. * Gets the minumum dimensions for this text field.
  368. * @return the minimum dimensions for
  369. * displaying this text field.
  370. * @since JDK1.1
  371. */
  372. public Dimension getMinimumSize() {
  373. return minimumSize();
  374. }
  375. /**
  376. * @deprecated As of JDK version 1.1,
  377. * replaced by <code>getMinimumSize()</code>.
  378. */
  379. @Deprecated
  380. public Dimension minimumSize() {
  381. synchronized (getTreeLock()) {
  382. return (columns > 0) ?
  383. minimumSize(columns) :
  384. super.minimumSize();
  385. }
  386. }
  387. /**
  388. * Adds the specified action listener to receive
  389. * action events from this text field.
  390. * If l is null, no exception is thrown and no action is performed.
  391. *
  392. * @param l the action listener.
  393. * @see #removeActionListener
  394. * @see #getActionListeners
  395. * @see java.awt.event.ActionListener
  396. * @since JDK1.1
  397. */
  398. public synchronized void addActionListener(ActionListener l) {
  399. if (l == null) {
  400. return;
  401. }
  402. actionListener = AWTEventMulticaster.add(actionListener, l);
  403. newEventsOnly = true;
  404. }
  405. /**
  406. * Removes the specified action listener so that it no longer
  407. * receives action events from this text field.
  408. * If l is null, no exception is thrown and no action is performed.
  409. *
  410. * @param l the action listener.
  411. * @see #addActionListener
  412. * @see #getActionListeners
  413. * @see java.awt.event.ActionListener
  414. * @since JDK1.1
  415. */
  416. public synchronized void removeActionListener(ActionListener l) {
  417. if (l == null) {
  418. return;
  419. }
  420. actionListener = AWTEventMulticaster.remove(actionListener, l);
  421. }
  422. /**
  423. * Returns an array of all the action listeners
  424. * registered on this textfield.
  425. *
  426. * @return all of this textfield's <code>ActionListener</code>s
  427. * or an empty array if no action
  428. * listeners are currently registered
  429. *
  430. * @see #addActionListener
  431. * @see #removeActionListener
  432. * @see java.awt.event#ActionListener
  433. * @since 1.4
  434. */
  435. public synchronized ActionListener[] getActionListeners() {
  436. return (ActionListener[])(getListeners(ActionListener.class));
  437. }
  438. /**
  439. * Returns an array of all the objects currently registered
  440. * as <code><em>Foo</em>Listener</code>s
  441. * upon this <code>TextField</code>.
  442. * <code><em>Foo</em>Listener</code>s are registered using the
  443. * <code>add<em>Foo</em>Listener</code> method.
  444. *
  445. * <p>
  446. * You can specify the <code>listenerType</code> argument
  447. * with a class literal, such as
  448. * <code><em>Foo</em>Listener.class</code>.
  449. * For example, you can query a
  450. * <code>TextField</code> <code>t</code>
  451. * for its action listeners with the following code:
  452. *
  453. * <pre>ActionListener[] als = (ActionListener[])(t.getListeners(ActionListener.class));</pre>
  454. *
  455. * If no such listeners exist, this method returns an empty array.
  456. *
  457. * @param listenerType the type of listeners requested; this parameter
  458. * should specify an interface that descends from
  459. * <code>java.util.EventListener</code>
  460. * @return an array of all objects registered as
  461. * <code><em>Foo</em>Listener</code>s on this textfield,
  462. * or an empty array if no such
  463. * listeners have been added
  464. * @exception ClassCastException if <code>listenerType</code>
  465. * doesn't specify a class or interface that implements
  466. * <code>java.util.EventListener</code>
  467. *
  468. * @see #getActionListeners
  469. * @since 1.3
  470. */
  471. public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
  472. EventListener l = null;
  473. if (listenerType == ActionListener.class) {
  474. l = actionListener;
  475. } else {
  476. return super.getListeners(listenerType);
  477. }
  478. return AWTEventMulticaster.getListeners(l, listenerType);
  479. }
  480. // REMIND: remove when filtering is done at lower level
  481. boolean eventEnabled(AWTEvent e) {
  482. if (e.id == ActionEvent.ACTION_PERFORMED) {
  483. if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||
  484. actionListener != null) {
  485. return true;
  486. }
  487. return false;
  488. }
  489. return super.eventEnabled(e);
  490. }
  491. /**
  492. * Processes events on this text field. If the event
  493. * is an instance of <code>ActionEvent</code>,
  494. * it invokes the <code>processActionEvent</code>
  495. * method. Otherwise, it invokes <code>processEvent</code>
  496. * on the superclass.
  497. * <p>Note that if the event parameter is <code>null</code>
  498. * the behavior is unspecified and may result in an
  499. * exception.
  500. *
  501. * @param e the event
  502. * @see java.awt.event.ActionEvent
  503. * @see java.awt.TextField#processActionEvent
  504. * @since JDK1.1
  505. */
  506. protected void processEvent(AWTEvent e) {
  507. if (e instanceof ActionEvent) {
  508. processActionEvent((ActionEvent)e);
  509. return;
  510. }
  511. super.processEvent(e);
  512. }
  513. /**
  514. * Processes action events occurring on this text field by
  515. * dispatching them to any registered
  516. * <code>ActionListener</code> objects.
  517. * <p>
  518. * This method is not called unless action events are
  519. * enabled for this component. Action events are enabled
  520. * when one of the following occurs:
  521. * <p><ul>
  522. * <li>An <code>ActionListener</code> object is registered
  523. * via <code>addActionListener</code>.
  524. * <li>Action events are enabled via <code>enableEvents</code>.
  525. * </ul>
  526. * <p>Note that if the event parameter is <code>null</code>
  527. * the behavior is unspecified and may result in an
  528. * exception.
  529. *
  530. * @param e the action event
  531. * @see java.awt.event.ActionListener
  532. * @see java.awt.TextField#addActionListener
  533. * @see java.awt.Component#enableEvents
  534. * @since JDK1.1
  535. */
  536. protected void processActionEvent(ActionEvent e) {
  537. ActionListener listener = actionListener;
  538. if (listener != null) {
  539. listener.actionPerformed(e);
  540. }
  541. }
  542. /**
  543. * Returns a string representing the state of this <code>TextField</code>.
  544. * This method is intended to be used only for debugging purposes, and the
  545. * content and format of the returned string may vary between
  546. * implementations. The returned string may be empty but may not be
  547. * <code>null</code>.
  548. *
  549. * @return the parameter string of this text field
  550. */
  551. protected String paramString() {
  552. String str = super.paramString();
  553. if (echoChar != 0) {
  554. str += ",echo=" + echoChar;
  555. }
  556. return str;
  557. }
  558. /*
  559. * Serialization support.
  560. */
  561. /**
  562. * The textField Serialized Data Version.
  563. *
  564. * @serial
  565. */
  566. private int textFieldSerializedDataVersion = 1;
  567. /**
  568. * Writes default serializable fields to stream. Writes
  569. * a list of serializable ActionListener(s) as optional data.
  570. * The non-serializable ActionListener(s) are detected and
  571. * no attempt is made to serialize them.
  572. *
  573. * @serialData Null terminated sequence of zero or more pairs.
  574. * A pair consists of a String and Object.
  575. * The String indicates the type of object and
  576. * is one of the following :
  577. * ActionListenerK indicating and ActionListener object.
  578. *
  579. * @see AWTEventMulticaster#save(ObjectOutputStream, String, EventListener)
  580. * @see java.awt.Component#actionListenerK
  581. */
  582. private void writeObject(ObjectOutputStream s)
  583. throws IOException
  584. {
  585. s.defaultWriteObject();
  586. AWTEventMulticaster.save(s, actionListenerK, actionListener);
  587. s.writeObject(null);
  588. }
  589. /**
  590. * Read the ObjectInputStream and if it isn't null,
  591. * add a listener to receive action events fired by the
  592. * TextField. Unrecognized keys or values will be
  593. * ignored.
  594. *
  595. * @exception HeadlessException if
  596. * <code>GraphicsEnvironment.isHeadless()</code> returns
  597. * <code>true</code>
  598. * @see #removeActionListener(ActionListener)
  599. * @see #addActionListener(ActionListener)
  600. * @see java.awt.GraphicsEnvironment#isHeadless
  601. */
  602. private void readObject(ObjectInputStream s)
  603. throws ClassNotFoundException, IOException, HeadlessException
  604. {
  605. // HeadlessException will be thrown by TextComponent's readObject
  606. s.defaultReadObject();
  607. // Make sure the state we just read in for columns has legal values
  608. if (columns < 0) {
  609. columns = 0;
  610. }
  611. // Read in listeners, if any
  612. Object keyOrNull;
  613. while(null != (keyOrNull = s.readObject())) {
  614. String key = ((String)keyOrNull).intern();
  615. if (actionListenerK == key) {
  616. addActionListener((ActionListener)(s.readObject()));
  617. } else {
  618. // skip value for unrecognized key
  619. s.readObject();
  620. }
  621. }
  622. }
  623. /////////////////
  624. // Accessibility support
  625. ////////////////
  626. /**
  627. * Gets the AccessibleContext associated with this TextField.
  628. * For text fields, the AccessibleContext takes the form of an
  629. * AccessibleAWTTextField.
  630. * A new AccessibleAWTTextField instance is created if necessary.
  631. *
  632. * @return an AccessibleAWTTextField that serves as the
  633. * AccessibleContext of this TextField
  634. */
  635. public AccessibleContext getAccessibleContext() {
  636. if (accessibleContext == null) {
  637. accessibleContext = new AccessibleAWTTextField();
  638. }
  639. return accessibleContext;
  640. }
  641. /**
  642. * This class implements accessibility support for the
  643. * <code>TextField</code> class. It provides an implementation of the
  644. * Java Accessibility API appropriate to text field user-interface elements.
  645. */
  646. protected class AccessibleAWTTextField extends AccessibleAWTTextComponent
  647. {
  648. /*
  649. * JDK 1.3 serialVersionUID
  650. */
  651. private static final long serialVersionUID = 6219164359235943158L;
  652. /**
  653. * Gets the state set of this object.
  654. *
  655. * @return an instance of AccessibleStateSet describing the states
  656. * of the object
  657. * @see AccessibleState
  658. */
  659. public AccessibleStateSet getAccessibleStateSet() {
  660. AccessibleStateSet states = super.getAccessibleStateSet();
  661. states.add(AccessibleState.SINGLE_LINE);
  662. return states;
  663. }
  664. }
  665. }