/* TextComponent.java -- Widgets for entering text
   Copyright (C) 1999, 2002, 2003, 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.TextEvent;
import java.awt.event.TextListener;
import java.awt.peer.TextComponentPeer;
import java.io.Serializable;
import java.text.BreakIterator;
import java.util.EventListener;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import javax.accessibility.AccessibleText;
import javax.swing.text.AttributeSet;

/**
 * This class provides common functionality for widgets than 
 * contain text.
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 */
public class TextComponent extends Component
  implements Serializable, Accessible
{

  private static final long serialVersionUID = -2214773872412987419L;

  /**
   * @serial Indicates whether or not this component is editable.
   * This is package-private to avoid an accessor method.
   */
  boolean editable;

  /**
   * @serial The starting position of the selected text region.
   * This is package-private to avoid an accessor method.
   */
  int selectionStart;

  /**
   * @serial The ending position of the selected text region.
   * This is package-private to avoid an accessor method.
   */
  int selectionEnd;

  /**
   * @serial The text in the component
   * This is package-private to avoid an accessor method.
   */
  String text;

  /**
   * A list of listeners that will receive events from this object.
   */
  protected transient TextListener textListener;

  protected class AccessibleAWTTextComponent
    extends AccessibleAWTComponent
    implements AccessibleText, TextListener
  {
    private static final long serialVersionUID = 3631432373506317811L;

    // Constructor
    // Adds a listener for tracking caret changes
    public AccessibleAWTTextComponent()
    {
      TextComponent.this.addTextListener(this);
    }
    
    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.TEXT;
    }
    
    public AccessibleStateSet getAccessibleStateSet()
    {
      // TODO: Docs say PropertyChangeEvent will fire if this state changes.
      // That means that the event has to fire when editable changes.
      AccessibleStateSet ss = super.getAccessibleStateSet();
      if (editable)
        ss.add(AccessibleState.EDITABLE);
      return ss;
    }
    
    public AccessibleText getAccessibleText()
    {
      return this;
    }
    
    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getIndexAtPoint(java.awt.Point)
     */
    public int getIndexAtPoint(Point point)
    {
      return TextComponent.this.getIndexAtPoint(point);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getCharacterBounds(int)
     */
    public Rectangle getCharacterBounds(int index)
    {
      return TextComponent.this.getCharacterBounds(index);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getCharCount()
     */
    public int getCharCount()
    {
      return text.length();
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getCaretPosition()
     */
    public int getCaretPosition()
    {
      return TextComponent.this.getCaretPosition();
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getAtIndex(int, int)
     */
    public String getAtIndex(int part, int index)
    {
      if (index < 0 || index >= text.length())
        return null;
      BreakIterator it = null;
      switch (part)
      {
      	case CHARACTER:
      	  return text.substring(index, index + 1);
      	case WORD:
      	  it = BreakIterator.getWordInstance();
      	  break;
      	case SENTENCE:
      	  it = BreakIterator.getSentenceInstance();
      	  break;
      	default:
      	  return null;
      }
  	  it.setText(text);
  	  int start = index;
  	  if (!it.isBoundary(index))
  	    start = it.preceding(index); 
  	  int end = it.following(index);
  	  if (end == -1)
  	    return text.substring(index);
  	  else
  	    return text.substring(index, end);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getAfterIndex(int, int)
     */
    public String getAfterIndex(int part, int index) {
      if (index < 0 || index >= text.length())
        return null;
      BreakIterator it = null;
      switch (part)
      {
      	case CHARACTER:
      	  return text.substring(index, index + 1);
      	case WORD:
      	  it = BreakIterator.getWordInstance();
      	  break;
      	case SENTENCE:
      	  it = BreakIterator.getSentenceInstance();
      	  break;
      	default:
      	  return null;
      }
  	  it.setText(text);
  	  int start = index;
  	  if (!it.isBoundary(index))
  	    start = it.following(index);
  	  // Make sure there was a complete unit.  I.e. if index is in the middle
  	  // of a word, return null if there is no word after the that one.
  	  if (start == -1)
  	    return null;
  	  int end = it.following(start);
  	  if (end == -1)
  	    return text.substring(index);
  	  else
  	    return text.substring(index, end);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getBeforeIndex(int, int)
     */
    public String getBeforeIndex(int part, int index)
    {
      if (index < 1 || index >= text.length())
        return null;
      BreakIterator it = null;
      switch (part)
      {
      	case CHARACTER:
      	  return text.substring(index - 1, index);
      	case WORD:
      	  it = BreakIterator.getWordInstance();
      	  break;
      	case SENTENCE:
      	  it = BreakIterator.getSentenceInstance();
      	  break;
      	default:
      	  return null;
      }
  	  it.setText(text);
  	  int end = index;
  	  if (!it.isBoundary(index))
  	    end = it.preceding(index); 
  	  // Make sure there was a complete unit.  I.e. if index is in the middle
  	  // of a word, return null if there is no word before that one.
  	  if (end == -1)
  	    return null;
  	  int start = it.preceding(end);
  	  if (start == -1)
  	    return text.substring(0, end);
  	  else
  	    return text.substring(start, end);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getCharacterAttribute(int)
     */
    public AttributeSet getCharacterAttribute(int index)
    {
      // FIXME: I suspect this really gets filled in by subclasses.
      return null;
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getSelectionStart()
     */
    public int getSelectionStart() {
      // TODO Auto-generated method stub
      return selectionStart;
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getSelectionEnd()
     */
    public int getSelectionEnd()
    {
      return selectionEnd;
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleText#getSelectedText()
     */
    public String getSelectedText()
    {
      if (selectionEnd - selectionStart > 0)
        return text.substring(selectionStart, selectionEnd);
      else
        return null;
    }

    /* (non-Javadoc)
     * @see java.awt.event.TextListener#textValueChanged(java.awt.event.TextEvent)
     */
    public void textValueChanged(TextEvent event)
    {
      // TODO Auto-generated method stub
      
    }
    
  }


  TextComponent(String text)
  {
    if (text == null)
      this.text = "";
    else
      this.text = text;
    
    this.editable = true;
  }


  /**
   * Returns the text in this component
   *
   * @return The text in this component.
   */
  public synchronized String getText()
  {
    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      text = tcp.getText();

    return(text);
  }

  /**
   * Sets the text in this component to the specified string.
   *
   * @param text The new text for this component.
   */
  public synchronized void setText(String text)
  {
    if (text == null)
      text = "";

    this.text = text;

    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      tcp.setText(text);
    setCaretPosition(0);
  }

  /**
   * Returns a string that contains the text that is currently selected.
   *
   * @return The currently selected text region.
   */
  public synchronized String getSelectedText()
  {
    String alltext = getText();
    int start = getSelectionStart();
    int end = getSelectionEnd();
  
    return(alltext.substring(start, end));
  }

  /**
   * Returns the starting position of the selected text region.
   * If the text is not selected then caret position is returned. 
   *
   * @return The starting position of the selected text region.
   */
  public synchronized int getSelectionStart()
  {
    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      selectionStart = tcp.getSelectionStart();

    return(selectionStart);
  }

  /**
   * Sets the starting position of the selected region to the
   * specified value.  If the specified value is out of range, then it
   * will be silently changed to the nearest legal value.
   *
   * @param selectionStart The new start position for selected text.
   */
  public synchronized void setSelectionStart(int selectionStart)
  {
    select(selectionStart, getSelectionEnd());
  }

  /**
   * Returns the ending position of the selected text region.
   * If the text is not selected, then caret position is returned 
   *
   * @return The ending position of the selected text region.
   */
  public synchronized int getSelectionEnd()
  {
    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      selectionEnd = tcp.getSelectionEnd();

    return(selectionEnd);
  }

  /**
   * Sets the ending position of the selected region to the
   * specified value.  If the specified value is out of range, then it
   * will be silently changed to the nearest legal value.
   *
   * @param selectionEnd The new start position for selected text.
   */
  public synchronized void setSelectionEnd(int selectionEnd)
  {
    select(getSelectionStart(), selectionEnd);
  }

  /**
   * This method sets the selected text range to the text between the
   * specified start and end positions.  Illegal values for these
   * positions are silently fixed.
   *
   * @param selectionStart The new start position for the selected text.
   * @param selectionEnd The new end position for the selected text.
   */
  public synchronized void select(int selectionStart, int selectionEnd)
  {
    if (selectionStart < 0)
      selectionStart = 0;

    if (selectionStart > getText().length())
      selectionStart = text.length();

    if (selectionEnd > text.length())
      selectionEnd = text.length();

    if (selectionStart > selectionEnd)
      selectionStart = selectionEnd;

    this.selectionStart = selectionStart;
    this.selectionEnd = selectionEnd;
    
    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      tcp.select(selectionStart, selectionEnd);
  }

  /**
   * Selects all of the text in the component.
   */
  public synchronized void selectAll()
  {
    select(0, getText().length());
  }

  /**
   * Returns the current caret position in the text.
   *
   * @return The caret position in the text.
   */
  public synchronized int getCaretPosition()
  {
    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      return(tcp.getCaretPosition());
    else
      return(0);
  }

  /**
   * Sets the caret position to the specified value.
   *
   * @param caretPosition The new caret position.
   *
   * @exception IllegalArgumentException If the value supplied for position
   * is less than zero.
   *
   * @since 1.1
   */
  public synchronized void setCaretPosition(int caretPosition)
  {
    if (caretPosition < 0)
      throw new IllegalArgumentException();
  
    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      tcp.setCaretPosition(caretPosition);
  }

  /**
   * Tests whether or not this component's text can be edited.
   *
   * @return <code>true</code> if the text can be edited, <code>false</code>
   * otherwise.
   */
  public boolean isEditable()
  {
    return(editable);
  }

  /**
   * Sets whether or not this component's text can be edited.
   *
   * @param editable <code>true</code> to enable editing of the text,
   * <code>false</code> to disable it.
   */
  public synchronized void setEditable(boolean editable)
  {
    this.editable = editable;

    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      tcp.setEditable(editable);
  }

  /**
   * Notifies the component that it should destroy its native peer.
   */
  public void removeNotify()
  {
    super.removeNotify();
  }

  /**
   * Adds a new listener to the list of text listeners for this
   * component.
   *
   * @param listener The listener to be added.
   */
  public synchronized void addTextListener(TextListener listener)
  {
    textListener = AWTEventMulticaster.add(textListener, listener);

    enableEvents(AWTEvent.TEXT_EVENT_MASK);  
  }

  /**
   * Removes the specified listener from the list of listeners
   * for this component.
   *
   * @param listener The listener to remove.
   */
  public synchronized void removeTextListener(TextListener listener)
  {
    textListener = AWTEventMulticaster.remove(textListener, listener);
  }

  /**
   * Processes the specified event for this component.  Text events are
   * processed by calling the <code>processTextEvent()</code> method.
   * All other events are passed to the superclass method.
   * 
   * @param event The event to process.
   */
  protected void processEvent(AWTEvent event)
  {
    if (event instanceof TextEvent)
      processTextEvent((TextEvent)event);
    else
      super.processEvent(event);
  }

  /**
   * Processes the specified text event by dispatching it to any listeners
   * that are registered.  Note that this method will only be called
   * if text event's are enabled.  This will be true if there are any
   * registered listeners, or if the event has been specifically
   * enabled using <code>enableEvents()</code>.
   *
   * @param event The text event to process.
   */
  protected void processTextEvent(TextEvent event)
  {
    if (textListener != null)
      textListener.textValueChanged(event);
  }

  void dispatchEventImpl(AWTEvent e)
  {
    if (e.id <= TextEvent.TEXT_LAST 
        && e.id >= TextEvent.TEXT_FIRST
        && (textListener != null 
	    || (eventMask & AWTEvent.TEXT_EVENT_MASK) != 0))
      processEvent(e);
    else
      super.dispatchEventImpl(e); 
  }

  /**
   * Returns a debugging string.
   *
   * @return A debugging string.
   */
  protected String paramString()
  {
    return(getClass().getName() + "(text=" + getText() + ")");
  }

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

    return super.getListeners(listenerType);
  }

  /**
   * Returns all text listeners registered to this object.
   */
  public TextListener[] getTextListeners()
  {
    return (TextListener[]) getListeners(TextListener.class);
  }

  /**
   * Gets the AccessibleContext associated with this <code>TextComponent</code>.
   * The context is created, if necessary.
   *
   * @return the associated context
   */
  public AccessibleContext getAccessibleContext()
  {
    /* Create the context if this is the first request */
    if (accessibleContext == null)
      accessibleContext = new AccessibleAWTTextComponent();
    return accessibleContext;
  }

  
  // Provide AccessibleAWTTextComponent access to several peer functions that
  // aren't publicly exposed.  This is package-private to avoid an accessor
  // method.
  synchronized int getIndexAtPoint(Point p)
  {
    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      return tcp.getIndexAtPoint(p.x, p.y);
    return -1;
  }
  
  synchronized Rectangle getCharacterBounds(int i)
  {
    TextComponentPeer tcp = (TextComponentPeer) getPeer();
    if (tcp != null)
      return tcp.getCharacterBounds(i);
    return null;
  }
  
  /**
   * All old mouse events for this component should
   * be ignored.
   * 
   * @return true to ignore all old mouse events.
   */
  static boolean ignoreOldMouseEvents()
  {
    return true;
  }

} // class TextComponent

