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