001/* TextField.java -- A one line text entry field
002   Copyright (C) 1999, 2002, 2004, 2006,  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.awt;
040
041import java.awt.event.ActionEvent;
042import java.awt.event.ActionListener;
043import java.awt.peer.ComponentPeer;
044import java.awt.peer.TextFieldPeer;
045import java.util.EventListener;
046
047import javax.accessibility.AccessibleContext;
048import javax.accessibility.AccessibleStateSet;
049
050/**
051 * This class implements a single line text entry field widget
052 *
053 * @author Aaron M. Renn (arenn@urbanophile.com)
054 */
055public class TextField extends TextComponent
056{
057
058  /**
059   * The number used to generate the name returned by getName.
060   */
061  private static transient long next_textfield_number;
062
063
064  private static final long serialVersionUID = -2966288784432217853L;
065
066
067  /**
068   * @serial The number of columns in the text entry field.
069   */
070  private int columns;
071
072  /**
073   * @serial The character that is echoed when doing protected input
074   */
075  private char echoChar;
076
077  // List of registered ActionListener's for this object.
078  private ActionListener action_listeners;
079
080  /**
081   * Initializes a new instance of <code>TextField</code> that is empty
082   * and has one column.
083   *
084   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
085   */
086  public TextField()
087  {
088    this("", 0);
089  }
090
091  /**
092   * Initializes a new instance of <code>TextField</code> containing
093   * the specified text.  The number of columns will be equal to the
094   * length of the text string.
095   *
096   * @param text The text to display in the field.
097   *
098   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
099   */
100  public TextField(String text)
101  {
102    this(text, (text == null) ? 0 : text.length());
103  }
104
105  /**
106   * Initializes a new instance of <code>TextField</code> that is empty
107   * and has the specified number of columns.
108   *
109   * @param columns The number of columns in the text field.
110   *
111   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
112   */
113  public TextField(int columns)
114  {
115    this("", columns);
116  }
117
118  /**
119   * Initializes a new instance of <code>TextField</code> with the
120   * specified text and number of columns.
121   *
122   * @param text The text to display in the field.
123   * @param columns The number of columns in the field.
124   *
125   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
126   */
127  public TextField(String text, int columns)
128  {
129    super(text);
130
131    if (columns < 0)
132      this.columns = 0;
133    else
134      this.columns = columns;
135
136    if (GraphicsEnvironment.isHeadless())
137      throw new HeadlessException ();
138  }
139
140  /**
141   * Returns the number of columns in the field.
142   *
143   * @return The number of columns in the field.
144   */
145  public int getColumns()
146  {
147    return(columns);
148  }
149
150  /**
151   * Sets the number of columns in this field to the specified value.
152   *
153   * @param columns The new number of columns in the field.
154   *
155   * @exception IllegalArgumentException If columns is less than zero.
156   */
157  public synchronized void setColumns(int columns)
158  {
159    if (columns < 0)
160      throw new IllegalArgumentException("Value is less than zero: " +
161                                         columns);
162
163    this.columns = columns;
164    // FIXME: How to we communicate this to our peer?
165  }
166
167  /**
168   * Returns the character that is echoed to the screen when a text
169   * field is protected (such as when a password is being entered).
170   *
171   * @return The echo character for this text field.
172   */
173  public char getEchoChar()
174  {
175    return(echoChar);
176  }
177
178  /**
179   * Sets the character that is echoed when protected input such as
180   * a password is displayed.
181   *
182   * @param echoChar The new echo character.
183   */
184  public void setEchoChar(char echoChar)
185  {
186    setEchoCharacter(echoChar);
187  }
188
189  /**
190   * Sets the character that is echoed when protected input such as
191   * a password is displayed.
192   *
193   * @param echoChar The new echo character.
194   *
195   * @deprecated This method is deprecated in favor of
196   * <code>setEchoChar()</code>
197   */
198  public void setEchoCharacter(char echoChar)
199  {
200    this.echoChar = echoChar;
201
202    TextFieldPeer peer = (TextFieldPeer) getPeer ();
203    if (peer != null)
204      peer.setEchoChar (echoChar);
205  }
206
207  /**
208   * Tests whether or not this text field has an echo character set
209   * so that characters the user type are not echoed to the screen.
210   *
211   * @return <code>true</code> if an echo character is set,
212   * <code>false</code> otherwise.
213   */
214  public boolean echoCharIsSet()
215  {
216    if (echoChar == '\u0000')
217      return(false);
218    else
219      return(true);
220  }
221
222  /**
223   * Returns the minimum size for this text field.
224   *
225   * @return The minimum size for this text field.
226   */
227  public Dimension getMinimumSize()
228  {
229    return getMinimumSize (getColumns ());
230  }
231
232  /**
233   * Returns the minimum size of a text field with the specified number
234   * of columns.
235   *
236   * @param columns The number of columns to get the minimum size for.
237   */
238  public Dimension getMinimumSize(int columns)
239  {
240    return minimumSize(columns);
241  }
242
243  /**
244   * Returns the minimum size for this text field.
245   *
246   * @return The minimum size for this text field.
247   *
248   * @deprecated This method is deprecated in favor of
249   * <code>getMinimumSize()</code>.
250   */
251  public Dimension minimumSize()
252  {
253    return minimumSize(getColumns ());
254  }
255
256  /**
257   * Returns the minimum size of a text field with the specified number
258   * of columns.
259   *
260   * @param columns The number of columns to get the minimum size for.
261   *
262   * @deprecated This method is deprecated in favor of
263   * <code>getMinimumSize(int)</code>.
264   */
265  public Dimension minimumSize(int columns)
266  {
267    if (isMinimumSizeSet())
268      return new Dimension(minSize);
269
270    TextFieldPeer peer = (TextFieldPeer) getPeer ();
271    if (peer == null)
272      return new Dimension(getWidth(), getHeight());
273
274    return peer.getMinimumSize (columns);
275  }
276
277  /**
278   * Returns the preferred size for this text field.
279   *
280   * @return The preferred size for this text field.
281   */
282  public Dimension getPreferredSize()
283  {
284    return getPreferredSize(getColumns ());
285  }
286
287  /**
288   * Returns the preferred size of a text field with the specified number
289   * of columns.
290   *
291   * @param columns The number of columns to get the preferred size for.
292   */
293  public Dimension getPreferredSize(int columns)
294  {
295    return preferredSize(columns);
296  }
297
298  /**
299   * Returns the preferred size for this text field.
300   *
301   * @return The preferred size for this text field.
302   *
303   * @deprecated This method is deprecated in favor of
304   * <code>getPreferredSize()</code>.
305   */
306  public Dimension preferredSize()
307  {
308    return preferredSize(getColumns ());
309  }
310
311  /**
312   * Returns the preferred size of a text field with the specified number
313   * of columns.
314   *
315   * @param columns The number of columns to get the preferred size for.
316   *
317   * @deprecated This method is deprecated in favor of
318   * <code>getPreferredSize(int)</code>.
319   */
320  public Dimension preferredSize(int columns)
321  {
322    if (isPreferredSizeSet())
323      return new Dimension(prefSize);
324
325    TextFieldPeer peer = (TextFieldPeer) getPeer ();
326    if (peer == null)
327      return new Dimension (getWidth(), getHeight());
328
329    return peer.getPreferredSize (columns);
330  }
331
332  /**
333   * Notifies this object that it should create its native peer.
334   */
335  public void addNotify()
336  {
337    if (getPeer() != null)
338      return;
339
340    setPeer((ComponentPeer)getToolkit().createTextField(this));
341    super.addNotify();
342  }
343
344  /**
345   * Addes a new listener to the list of action listeners for this
346   * object.
347   *
348   * @param listener The listener to add to the list.
349   */
350  public synchronized void addActionListener(ActionListener listener)
351  {
352    action_listeners = AWTEventMulticaster.add(action_listeners, listener);
353
354    enableEvents(AWTEvent.ACTION_EVENT_MASK);
355  }
356
357  /**
358   * Removes the specified listener from the list of action listeners
359   * for this object.
360   *
361   * @param listener The listener to remove from the list.
362   */
363  public synchronized void removeActionListener(ActionListener listener)
364  {
365    action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
366  }
367
368  /**
369   * Processes the specified event.  If the event is an instance of
370   * <code>ActionEvent</code> then <code>processActionEvent()</code> is
371   * called to process it, otherwise the event is sent to the
372   * superclass.
373   *
374   * @param event The event to process.
375   */
376  protected void processEvent(AWTEvent event)
377  {
378    if (event instanceof ActionEvent)
379      processActionEvent((ActionEvent)event);
380    else
381      super.processEvent(event);
382  }
383
384  /**
385   * Processes an action event by calling any registered listeners.
386   * Note to subclasses: This method is not called unless action events
387   * are enabled on this object.  This will be true if any listeners
388   * are registered, or if action events were specifically enabled
389   * using <code>enableEvents()</code>.
390   *
391   * @param event The event to process.
392   */
393  protected void processActionEvent(ActionEvent event)
394  {
395    if (action_listeners != null)
396      action_listeners.actionPerformed(event);
397  }
398
399  void dispatchEventImpl(AWTEvent e)
400  {
401    if (e.id <= ActionEvent.ACTION_LAST
402        && e.id >= ActionEvent.ACTION_FIRST
403        && (action_listeners != null
404            || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
405      processEvent(e);
406    else
407      super.dispatchEventImpl(e);
408  }
409
410 /**
411  * Returns a debug string for this object.
412  *
413  * @return A debug string for this object.
414  */
415  protected String paramString()
416  {
417    return(getClass().getName() + "(columns=" + getColumns() + ",echoChar=" +
418           getEchoChar());
419  }
420
421  /**
422   * Returns an array of all the objects currently registered as FooListeners
423   * upon this <code>TextField</code>. FooListeners are registered using the
424   * addFooListener method.
425   *
426   * @exception ClassCastException If listenerType doesn't specify a class or
427   * interface that implements java.util.EventListener.
428   *
429   * @since 1.3
430   */
431  public <T extends EventListener> T[] getListeners (Class<T> listenerType)
432  {
433    if (listenerType == ActionListener.class)
434      return AWTEventMulticaster.getListeners (action_listeners, listenerType);
435
436    return super.getListeners (listenerType);
437  }
438
439  /**
440   * Return all ActionListeners register to this <code>TextField</code> object
441   * as an array.
442   *
443   * @since 1.4
444   */
445  public ActionListener[] getActionListeners ()
446  {
447    return (ActionListener[]) getListeners (ActionListener.class);
448  }
449
450  /**
451   * Generate a unique name for this <code>TextField</code>.
452   *
453   * @return A unique name for this <code>TextField</code>.
454   */
455  String generateName()
456  {
457    return "textfield" + getUniqueLong();
458  }
459
460  private static synchronized long getUniqueLong()
461  {
462    return next_textfield_number++;
463  }
464
465  protected class AccessibleAWTTextField extends AccessibleAWTTextComponent
466  {
467    private static final long serialVersionUID = 6219164359235943158L;
468
469    protected AccessibleAWTTextField()
470    {
471    }
472
473    public AccessibleStateSet getAccessibleStateSet()
474    {
475      return super.getAccessibleStateSet();
476    }
477  }
478
479  public AccessibleContext getAccessibleContext()
480  {
481    return new AccessibleAWTTextField();
482  }
483
484}