/* TextField.java -- A one line text entry field
   Copyright (C) 1999, 2002, 2004, 2006,  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.awt;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.peer.ComponentPeer;
import java.awt.peer.TextFieldPeer;
import java.util.EventListener;

import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleStateSet;

/**
 * This class implements a single line text entry field widget
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 */
public class TextField extends TextComponent
{

  /**
   * The number used to generate the name returned by getName.
   */
  private static transient long next_textfield_number;


  private static final long serialVersionUID = -2966288784432217853L;


  /**
   * @serial The number of columns in the text entry field.
   */
  private int columns;

  /**
   * @serial The character that is echoed when doing protected input
   */
  private char echoChar;

  // List of registered ActionListener's for this object.
  private ActionListener action_listeners;

  /**
   * Initializes a new instance of <code>TextField</code> that is empty
   * and has one column.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
   */
  public TextField()
  {
    this("", 0);
  }

  /**
   * Initializes a new instance of <code>TextField</code> containing
   * the specified text.  The number of columns will be equal to the
   * length of the text string.
   *
   * @param text The text to display in the field.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
   */
  public TextField(String text)
  {
    this(text, (text == null) ? 0 : text.length());
  }

  /**
   * Initializes a new instance of <code>TextField</code> that is empty
   * and has the specified number of columns.
   *
   * @param columns The number of columns in the text field.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
   */
  public TextField(int columns)
  {
    this("", columns);
  }

  /**
   * Initializes a new instance of <code>TextField</code> with the
   * specified text and number of columns.
   *
   * @param text The text to display in the field.
   * @param columns The number of columns in the field.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true,
   */
  public TextField(String text, int columns)
  {
    super(text);

    if (columns < 0)
      this.columns = 0;
    else
      this.columns = columns;

    if (GraphicsEnvironment.isHeadless())
      throw new HeadlessException ();
  }

  /**
   * Returns the number of columns in the field.
   *
   * @return The number of columns in the field.
   */
  public int getColumns()
  {
    return(columns);
  }

  /**
   * Sets the number of columns in this field to the specified value.
   *
   * @param columns The new number of columns in the field.
   *
   * @exception IllegalArgumentException If columns is less than zero.
   */
  public synchronized void setColumns(int columns)
  {
    if (columns < 0)
      throw new IllegalArgumentException("Value is less than zero: " +
                                         columns);

    this.columns = columns;
    // FIXME: How to we communicate this to our peer?
  }

  /**
   * Returns the character that is echoed to the screen when a text
   * field is protected (such as when a password is being entered).
   *
   * @return The echo character for this text field.
   */
  public char getEchoChar()
  {
    return(echoChar);
  }

  /**
   * Sets the character that is echoed when protected input such as
   * a password is displayed.
   *
   * @param echoChar The new echo character.
   */
  public void setEchoChar(char echoChar)
  {
    setEchoCharacter(echoChar);
  }

  /**
   * Sets the character that is echoed when protected input such as
   * a password is displayed.
   *
   * @param echoChar The new echo character.
   *
   * @deprecated This method is deprecated in favor of
   * <code>setEchoChar()</code>
   */
  public void setEchoCharacter(char echoChar)
  {
    this.echoChar = echoChar;

    TextFieldPeer peer = (TextFieldPeer) getPeer ();
    if (peer != null)
      peer.setEchoChar (echoChar);
  }

  /**
   * Tests whether or not this text field has an echo character set
   * so that characters the user type are not echoed to the screen.
   *
   * @return <code>true</code> if an echo character is set,
   * <code>false</code> otherwise.
   */
  public boolean echoCharIsSet()
  {
    if (echoChar == '\u0000')
      return(false);
    else
      return(true);
  }

  /**
   * Returns the minimum size for this text field.
   *
   * @return The minimum size for this text field.
   */
  public Dimension getMinimumSize()
  {
    return getMinimumSize (getColumns ());
  }

  /**
   * Returns the minimum size of a text field with the specified number
   * of columns.
   *
   * @param columns The number of columns to get the minimum size for.
   */
  public Dimension getMinimumSize(int columns)
  {
    return minimumSize(columns);
  }

  /**
   * Returns the minimum size for this text field.
   *
   * @return The minimum size for this text field.
   *
   * @deprecated This method is deprecated in favor of
   * <code>getMinimumSize()</code>.
   */
  public Dimension minimumSize()
  {
    return minimumSize(getColumns ());
  }

  /**
   * Returns the minimum size of a text field with the specified number
   * of columns.
   *
   * @param columns The number of columns to get the minimum size for.
   *
   * @deprecated This method is deprecated in favor of
   * <code>getMinimumSize(int)</code>.
   */
  public Dimension minimumSize(int columns)
  {
    if (isMinimumSizeSet())
      return new Dimension(minSize);

    TextFieldPeer peer = (TextFieldPeer) getPeer ();
    if (peer == null)
      return new Dimension(getWidth(), getHeight());

    return peer.getMinimumSize (columns);
  }

  /**
   * Returns the preferred size for this text field.
   *
   * @return The preferred size for this text field.
   */
  public Dimension getPreferredSize()
  {
    return getPreferredSize(getColumns ());
  }

  /**
   * Returns the preferred size of a text field with the specified number
   * of columns.
   *
   * @param columns The number of columns to get the preferred size for.
   */
  public Dimension getPreferredSize(int columns)
  {
    return preferredSize(columns);
  }

  /**
   * Returns the preferred size for this text field.
   *
   * @return The preferred size for this text field.
   *
   * @deprecated This method is deprecated in favor of
   * <code>getPreferredSize()</code>.
   */
  public Dimension preferredSize()
  {
    return preferredSize(getColumns ());
  }

  /**
   * Returns the preferred size of a text field with the specified number
   * of columns.
   *
   * @param columns The number of columns to get the preferred size for.
   *
   * @deprecated This method is deprecated in favor of
   * <code>getPreferredSize(int)</code>.
   */
  public Dimension preferredSize(int columns)
  {
    if (isPreferredSizeSet())
      return new Dimension(prefSize);

    TextFieldPeer peer = (TextFieldPeer) getPeer ();
    if (peer == null)
      return new Dimension (getWidth(), getHeight());

    return peer.getPreferredSize (columns);
  }

  /**
   * Notifies this object that it should create its native peer.
   */
  public void addNotify()
  {
    if (getPeer() != null)
      return;

    setPeer((ComponentPeer)getToolkit().createTextField(this));
    super.addNotify();
  }

  /**
   * Addes a new listener to the list of action listeners for this
   * object.
   *
   * @param listener The listener to add to the list.
   */
  public synchronized void addActionListener(ActionListener listener)
  {
    action_listeners = AWTEventMulticaster.add(action_listeners, listener);

    enableEvents(AWTEvent.ACTION_EVENT_MASK);
  }

  /**
   * Removes the specified listener from the list of action listeners
   * for this object.
   *
   * @param listener The listener to remove from the list.
   */
  public synchronized void removeActionListener(ActionListener listener)
  {
    action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
  }

  /**
   * Processes the specified event.  If the event is an instance of
   * <code>ActionEvent</code> then <code>processActionEvent()</code> is
   * called to process it, otherwise the event is sent to the
   * superclass.
   *
   * @param event The event to process.
   */
  protected void processEvent(AWTEvent event)
  {
    if (event instanceof ActionEvent)
      processActionEvent((ActionEvent)event);
    else
      super.processEvent(event);
  }

  /**
   * Processes an action event by calling any registered listeners.
   * Note to subclasses: This method is not called unless action events
   * are enabled on this object.  This will be true if any listeners
   * are registered, or if action events were specifically enabled
   * using <code>enableEvents()</code>.
   *
   * @param event The event to process.
   */
  protected void processActionEvent(ActionEvent event)
  {
    if (action_listeners != null)
      action_listeners.actionPerformed(event);
  }

  void dispatchEventImpl(AWTEvent e)
  {
    if (e.id <= ActionEvent.ACTION_LAST
        && e.id >= ActionEvent.ACTION_FIRST
        && (action_listeners != null
            || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
      processEvent(e);
    else
      super.dispatchEventImpl(e);
  }

 /**
  * Returns a debug string for this object.
  *
  * @return A debug string for this object.
  */
  protected String paramString()
  {
    return(getClass().getName() + "(columns=" + getColumns() + ",echoChar=" +
           getEchoChar());
  }

  /**
   * Returns an array of all the objects currently registered as FooListeners
   * upon this <code>TextField</code>. FooListeners are registered using the
   * addFooListener method.
   *
   * @exception ClassCastException If listenerType doesn't specify a class or
   * interface that implements java.util.EventListener.
   *
   * @since 1.3
   */
  public <T extends EventListener> T[] getListeners (Class<T> listenerType)
  {
    if (listenerType == ActionListener.class)
      return AWTEventMulticaster.getListeners (action_listeners, listenerType);

    return super.getListeners (listenerType);
  }

  /**
   * Return all ActionListeners register to this <code>TextField</code> object
   * as an array.
   *
   * @since 1.4
   */
  public ActionListener[] getActionListeners ()
  {
    return (ActionListener[]) getListeners (ActionListener.class);
  }

  /**
   * Generate a unique name for this <code>TextField</code>.
   *
   * @return A unique name for this <code>TextField</code>.
   */
  String generateName()
  {
    return "textfield" + getUniqueLong();
  }

  private static synchronized long getUniqueLong()
  {
    return next_textfield_number++;
  }

  protected class AccessibleAWTTextField extends AccessibleAWTTextComponent
  {
    private static final long serialVersionUID = 6219164359235943158L;

    protected AccessibleAWTTextField()
    {
    }

    public AccessibleStateSet getAccessibleStateSet()
    {
      return super.getAccessibleStateSet();
    }
  }

  public AccessibleContext getAccessibleContext()
  {
    return new AccessibleAWTTextField();
  }

}
