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