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