/* JTextComponent.java --
   Copyright (C) 2002, 2004, 2005  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 javax.swing.text;

import gnu.java.lang.CPStringBuilder;

import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.InputMethodListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.text.BreakIterator;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleEditableText;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import javax.accessibility.AccessibleText;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.InputMapUIResource;
import javax.swing.plaf.TextUI;

public abstract class JTextComponent extends JComponent
  implements Scrollable, Accessible
{
  /**
   * AccessibleJTextComponent implements accessibility hooks for
   * JTextComponent.  It allows an accessibility driver to read and
   * manipulate the text component's contents as well as update UI
   * elements such as the caret.
   */
  public class AccessibleJTextComponent extends AccessibleJComponent implements
      AccessibleText, CaretListener, DocumentListener, AccessibleAction,
      AccessibleEditableText
  {
    private static final long serialVersionUID = 7664188944091413696L;

    /**
     * The caret's offset.
     */
    private int caretDot;

    /**
     * Construct an AccessibleJTextComponent.
     */
    public AccessibleJTextComponent()
    {
      super();
      JTextComponent.this.addCaretListener(this);
      caretDot = getCaretPosition();
    }

    /**
     * Retrieve the current caret position.  The index of the first
     * caret position is 0.
     *
     * @return caret position
     */
    public int getCaretPosition()
    {
      return JTextComponent.this.getCaretPosition();
    }

    /**
     * Retrieve the current text selection.  If no text is selected
     * this method returns null.
     *
     * @return the currently selected text or null
     */
    public String getSelectedText()
    {
      return JTextComponent.this.getSelectedText();
    }

    /**
     * Retrieve the index of the first character in the current text
     * selection.  If there is no text in the text component, this
     * method returns 0.  If there is text in the text component, but
     * there is no selection, this method returns the current caret
     * position.
     *
     * @return the index of the first character in the selection, the
     * current caret position or 0
     */
    public int getSelectionStart()
    {
      if (getSelectedText() == null
          || (JTextComponent.this.getText().equals("")))
        return 0;
      return JTextComponent.this.getSelectionStart();
    }

    /**
     * Retrieve the index of the last character in the current text
     * selection.  If there is no text in the text component, this
     * method returns 0.  If there is text in the text component, but
     * there is no selection, this method returns the current caret
     * position.
     *
     * @return the index of the last character in the selection, the
     * current caret position or 0
     */
    public int getSelectionEnd()
    {
      return JTextComponent.this.getSelectionEnd();
    }

    /**
     * Handle a change in the caret position and fire any applicable
     * property change events.
     *
     * @param e - the caret update event
     */
    public void caretUpdate(CaretEvent e)
    {
      int dot = e.getDot();
      int mark = e.getMark();
      if (caretDot != dot)
        {
          firePropertyChange(ACCESSIBLE_CARET_PROPERTY, new Integer(caretDot),
                             new Integer(dot));
          caretDot = dot;
        }
      if (mark != dot)
        {
          firePropertyChange(ACCESSIBLE_SELECTION_PROPERTY, null,
                             getSelectedText());
        }
    }

    /**
     * Retreive the accessible state set of this component.
     *
     * @return the accessible state set of this component
     */
    public AccessibleStateSet getAccessibleStateSet()
    {
      AccessibleStateSet state = super.getAccessibleStateSet();
      if (isEditable())
        state.add(AccessibleState.EDITABLE);
      return state;
    }

    /**
     * Retrieve the accessible role of this component.
     *
     * @return the accessible role of this component
     *
     * @see AccessibleRole
     */
    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.TEXT;
    }

    /**
     * Retrieve an AccessibleEditableText object that controls this
     * text component.
     *
     * @return this
     */
    public AccessibleEditableText getAccessibleEditableText()
    {
      return this;
    }

    /**
     * Retrieve an AccessibleText object that controls this text
     * component.
     *
     * @return this
     *
     * @see AccessibleText
     */
    public AccessibleText getAccessibleText()
    {
      return this;
    }

    /**
     * Handle a text insertion event and fire an
     * AccessibleContext.ACCESSIBLE_TEXT_PROPERTY property change
     * event.
     *
     * @param e - the insertion event
     */
    public void insertUpdate(DocumentEvent e)
    {
      firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null,
                         new Integer(e.getOffset()));
    }

    /**
     * Handle a text removal event and fire an
     * AccessibleContext.ACCESSIBLE_TEXT_PROPERTY property change
     * event.
     *
     * @param e - the removal event
     */
    public void removeUpdate(DocumentEvent e)
    {
      firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null,
                         new Integer(e.getOffset()));
    }

    /**
     * Handle a text change event and fire an
     * AccessibleContext.ACCESSIBLE_TEXT_PROPERTY property change
     * event.
     *
     * @param e - text change event
     */
    public void changedUpdate(DocumentEvent e)
    {
      firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null,
                         new Integer(e.getOffset()));
    }

    /**
     * Get the index of the character at the given point, in component
     * pixel co-ordinates.  If the point argument is invalid this
     * method returns -1.
     *
     * @param p - a point in component pixel co-ordinates
     *
     * @return a character index, or -1
     */
    public int getIndexAtPoint(Point p)
    {
      return viewToModel(p);
    }

    /**
     * Calculate the bounding box of the character at the given index.
     * The returned x and y co-ordinates are relative to this text
     * component's top-left corner.  If the index is invalid this
     * method returns null.
     *
     * @param index - the character index
     *
     * @return a character's bounding box, or null
     */
    public Rectangle getCharacterBounds(int index)
    {
      // This is basically the same as BasicTextUI.modelToView().

      Rectangle bounds = null;
      if (index >= 0 && index < doc.getLength() - 1)
        {
          if (doc instanceof AbstractDocument)
            ((AbstractDocument) doc).readLock();
          try
            {
              TextUI ui = getUI();
              if (ui != null)
                {
                  // Get editor rectangle.
                  Rectangle rect = new Rectangle();
                  Insets insets = getInsets();
                  rect.x = insets.left;
                  rect.y = insets.top;
                  rect.width = getWidth() - insets.left - insets.right;
                  rect.height = getHeight() - insets.top - insets.bottom;
                  View rootView = ui.getRootView(JTextComponent.this);
                  if (rootView != null)
                    {
                      rootView.setSize(rect.width, rect.height);
                      Shape s = rootView.modelToView(index,
                                                     Position.Bias.Forward,
                                                     index + 1,
                                                     Position.Bias.Backward,
                                                     rect);
                      if (s != null)
                        bounds = s.getBounds();
                    }
                }
            }
          catch (BadLocationException ex)
            {
              // Ignore (return null).
            }
          finally
            {
              if (doc instanceof AbstractDocument)
                ((AbstractDocument) doc).readUnlock();
            }
        }
      return bounds;
    }

    /**
     * Return the length of the text in this text component.
     *
     * @return a character length
     */
    public int getCharCount()
    {
      return JTextComponent.this.getText().length();
    }

   /**
    * Gets the character attributes of the character at index. If
    * the index is out of bounds, null is returned.
    *
    * @param index - index of the character
    *
    * @return the character's attributes
    */
    public AttributeSet getCharacterAttribute(int index)
    {
      AttributeSet atts;
      if (doc instanceof AbstractDocument)
        ((AbstractDocument) doc).readLock();
      try
        {
          Element el = doc.getDefaultRootElement();
          while (! el.isLeaf())
            {
              int i = el.getElementIndex(index);
              el = el.getElement(i);
            }
          atts = el.getAttributes();
        }
      finally
        {
          if (doc instanceof AbstractDocument)
            ((AbstractDocument) doc).readUnlock();
        }
      return atts;
    }

    /**
     * Gets the text located at index. null is returned if the index
     * or part is invalid.
     *
     * @param part - {@link #CHARACTER}, {@link #WORD}, or {@link #SENTENCE}
     * @param index - index of the part
     *
     * @return the part of text at that index, or null
     */
    public String getAtIndex(int part, int index)
    {
      return getAtIndexImpl(part, index, 0);
    }

    /**
     * Gets the text located after index. null is returned if the index
     * or part is invalid.
     *
     * @param part - {@link #CHARACTER}, {@link #WORD}, or {@link #SENTENCE}
     * @param index - index after the part
     *
     * @return the part of text after that index, or null
     */
    public String getAfterIndex(int part, int index)
    {
      return getAtIndexImpl(part, index, 1);
    }

    /**
     * Gets the text located before index. null is returned if the index
     * or part is invalid.
     *
     * @param part - {@link #CHARACTER}, {@link #WORD}, or {@link #SENTENCE}
     * @param index - index before the part
     *
     * @return the part of text before that index, or null
     */
    public String getBeforeIndex(int part, int index)
    {
      return getAtIndexImpl(part, index, -1);
    }

    /**
     * Implements getAtIndex(), getBeforeIndex() and getAfterIndex().
     *
     * @param part the part to return, either CHARACTER, WORD or SENTENCE
     * @param index the index
     * @param dir the direction, -1 for backwards, 0 for here, +1 for forwards
     *
     * @return the resulting string
     */
    private String getAtIndexImpl(int part, int index, int dir)
    {
      String ret = null;
      if (doc instanceof AbstractDocument)
        ((AbstractDocument) doc).readLock();
      try
        {
          BreakIterator iter = null;
          switch (part)
          {
            case CHARACTER:
              iter = BreakIterator.getCharacterInstance(getLocale());
              break;
            case WORD:
              iter = BreakIterator.getWordInstance(getLocale());
              break;
            case SENTENCE:
              iter = BreakIterator.getSentenceInstance(getLocale());
              break;
            default:
              break;
          }
          String text = doc.getText(0, doc.getLength() - 1);
          iter.setText(text);
          int start = index;
          int end = index;
          switch (dir)
          {
          case 0:
            if (iter.isBoundary(index))
              {
                start = index;
                end = iter.following(index);
              }
            else
              {
                start = iter.preceding(index);
                end = iter.next();
              }
            break;
          case 1:
            start = iter.following(index);
            end = iter.next();
            break;
          case -1:
            end = iter.preceding(index);
            start = iter.previous();
            break;
          default:
            assert false;
          }
          ret = text.substring(start, end);
        }
      catch (BadLocationException ex)
        {
          // Ignore (return null).
        }
      finally
        {
          if (doc instanceof AbstractDocument)
            ((AbstractDocument) doc).readUnlock();
        }
      return ret;
    }

    /**
     * Returns the number of actions for this object. The zero-th
     * object represents the default action.
     *
     * @return the number of actions (0-based).
     */
    public int getAccessibleActionCount()
    {
      return getActions().length;
    }

    /**
     * Returns the description of the i-th action. Null is returned if
     * i is out of bounds.
     *
     * @param i - the action to get the description for
     *
     * @return description of the i-th action
     */
    public String getAccessibleActionDescription(int i)
    {
      String desc = null;
      Action[] actions = getActions();
      if (i >= 0 && i < actions.length)
        desc = (String) actions[i].getValue(Action.NAME);
      return desc;
    }

    /**
     * Performs the i-th action. Nothing happens if i is
     * out of bounds.
     *
     * @param i - the action to perform
     *
     * @return true if the action was performed successfully
     */
    public boolean doAccessibleAction(int i)
    {
      boolean ret = false;
      Action[] actions = getActions();
      if (i >= 0 && i < actions.length)
        {
          ActionEvent ev = new ActionEvent(JTextComponent.this,
                                           ActionEvent.ACTION_PERFORMED, null);
          actions[i].actionPerformed(ev);
          ret = true;
        }
      return ret;
    }

    /**
     * Sets the text contents.
     *
     * @param s - the new text contents.
     */
    public void setTextContents(String s)
    {
      setText(s);
    }

    /**
     * Inserts the text at the given index.
     *
     * @param index - the index to insert the new text at.
     * @param s - the new text
     */
    public void insertTextAtIndex(int index, String s)
    {
      try
        {
          doc.insertString(index, s, null);
        }
      catch (BadLocationException ex)
        {
          // What should we do with this?
          ex.printStackTrace();
        }
    }

    /**
     * Gets the text between two indexes.
     *
     * @param start - the starting index (inclusive)
     * @param end - the ending index (exclusive)
     */
    public String getTextRange(int start, int end)
    {
      try
      {
        return JTextComponent.this.getText(start, end - start);
      }
      catch (BadLocationException ble)
      {
        return "";
      }
    }

    /**
     * Deletes the text between two indexes.
     *
     * @param start - the starting index (inclusive)
     * @param end - the ending index (exclusive)
     */
    public void delete(int start, int end)
    {
      replaceText(start, end, "");
    }

    /**
     * Cuts the text between two indexes. The text is put
     * into the system clipboard.
     *
     * @param start - the starting index (inclusive)
     * @param end - the ending index (exclusive)
     */
    public void cut(int start, int end)
    {
      JTextComponent.this.select(start, end);
      JTextComponent.this.cut();
    }

    /**
     * Pastes the text from the system clipboard to the given index.
     *
     * @param start - the starting index
     */
    public void paste(int start)
    {
      JTextComponent.this.setCaretPosition(start);
      JTextComponent.this.paste();
    }

    /**
     * Replaces the text between two indexes with the given text.
     *
     *
     * @param start - the starting index (inclusive)
     * @param end - the ending index (exclusive)
     * @param s - the text to paste
     */
    public void replaceText(int start, int end, String s)
    {
      JTextComponent.this.select(start, end);
      JTextComponent.this.replaceSelection(s);
    }

    /**
     * Selects the text between two indexes.
     *
     * @param start - the starting index (inclusive)
     * @param end - the ending index (exclusive)
     */
    public void selectText(int start, int end)
    {
      JTextComponent.this.select(start, end);
    }

    /**
     * Sets the attributes of all the text between two indexes.
     *
     * @param start - the starting index (inclusive)
     * @param end - the ending index (exclusive)
     * @param s - the new attribute set for the text in the range
     */
    public void setAttributes(int start, int end, AttributeSet s)
    {
      if (doc instanceof StyledDocument)
        {
          StyledDocument sdoc = (StyledDocument) doc;
          sdoc.setCharacterAttributes(start, end - start, s, true);
        }
    }
  }

  public static class KeyBinding
  {
    public KeyStroke key;
    public String actionName;

    /**
     * Creates a new <code>KeyBinding</code> instance.
     *
     * @param key a <code>KeyStroke</code> value
     * @param actionName a <code>String</code> value
     */
    public KeyBinding(KeyStroke key, String actionName)
    {
      this.key = key;
      this.actionName = actionName;
    }
  }

  /**
   * According to <a
   * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">this
   * report</a>, a pair of private classes wraps a {@link
   * javax.swing.text.Keymap} in the new {@link InputMap} / {@link
   * ActionMap} interfaces, such that old Keymap-using code can make use of
   * the new framework.
   *
   * <p>A little bit of experimentation with these classes reveals the following
   * structure:
   *
   * <ul>
   *
   * <li>KeymapWrapper extends {@link InputMap} and holds a reference to
   * the underlying {@link Keymap}.</li>
   *
   * <li>KeymapWrapper maps {@link KeyStroke} objects to {@link Action}
   * objects, by delegation to the underlying {@link Keymap}.</li>
   *
   * <li>KeymapActionMap extends {@link ActionMap} also holds a reference to
   * the underlying {@link Keymap} but only appears to use it for listing
   * its keys. </li>
   *
   * <li>KeymapActionMap maps all {@link Action} objects to
   * <em>themselves</em>, whether they exist in the underlying {@link
   * Keymap} or not, and passes other objects to the parent {@link
   * ActionMap} for resolving.
   *
   * </ul>
   */

  private class KeymapWrapper extends InputMap
  {
    Keymap map;

    public KeymapWrapper(Keymap k)
    {
      map = k;
    }

    public int size()
    {
      return map.getBoundKeyStrokes().length + super.size();
    }

    public Object get(KeyStroke ks)
    {
      Action mapped = null;
      Keymap m = map;
      while(mapped == null && m != null)
        {
          mapped = m.getAction(ks);
          if (mapped == null && ks.getKeyEventType() == KeyEvent.KEY_TYPED)
            mapped = m.getDefaultAction();
          if (mapped == null)
            m = m.getResolveParent();
        }

      if (mapped == null)
        return super.get(ks);
      else
        return mapped;
    }

    public KeyStroke[] keys()
    {
      KeyStroke[] superKeys = super.keys();
      KeyStroke[] mapKeys = map.getBoundKeyStrokes();
      KeyStroke[] bothKeys = new KeyStroke[superKeys.length + mapKeys.length];
      for (int i = 0; i < superKeys.length; ++i)
        bothKeys[i] = superKeys[i];
      for (int i = 0; i < mapKeys.length; ++i)
        bothKeys[i + superKeys.length] = mapKeys[i];
      return bothKeys;
    }

    public KeyStroke[] allKeys()
    {
      KeyStroke[] superKeys = super.allKeys();
      KeyStroke[] mapKeys = map.getBoundKeyStrokes();
      int skl = 0;
      int mkl = 0;
      if (superKeys != null)
        skl = superKeys.length;
      if (mapKeys != null)
        mkl = mapKeys.length;
      KeyStroke[] bothKeys = new KeyStroke[skl + mkl];
      for (int i = 0; i < skl; ++i)
        bothKeys[i] = superKeys[i];
      for (int i = 0; i < mkl; ++i)
        bothKeys[i + skl] = mapKeys[i];
      return bothKeys;
    }
  }

  private class KeymapActionMap extends ActionMap
  {
    Keymap map;

    public KeymapActionMap(Keymap k)
    {
      map = k;
    }

    public Action get(Object cmd)
    {
      if (cmd instanceof Action)
        return (Action) cmd;
      else
        return super.get(cmd);
    }

    public int size()
    {
      return map.getBoundKeyStrokes().length + super.size();
    }

    public Object[] keys()
    {
      Object[] superKeys = super.keys();
      Object[] mapKeys = map.getBoundKeyStrokes();
      Object[] bothKeys = new Object[superKeys.length + mapKeys.length];
      for (int i = 0; i < superKeys.length; ++i)
        bothKeys[i] = superKeys[i];
      for (int i = 0; i < mapKeys.length; ++i)
        bothKeys[i + superKeys.length] = mapKeys[i];
      return bothKeys;
    }

    public Object[] allKeys()
    {
      Object[] superKeys = super.allKeys();
      Object[] mapKeys = map.getBoundKeyStrokes();
      Object[] bothKeys = new Object[superKeys.length + mapKeys.length];
      for (int i = 0; i < superKeys.length; ++i)
        bothKeys[i] = superKeys[i];
      for (int i = 0; i < mapKeys.length; ++i)
        bothKeys[i + superKeys.length] = mapKeys[i];
      return bothKeys;
    }

  }

  static class DefaultKeymap implements Keymap
  {
    String name;
    Keymap parent;
    Hashtable map;
    Action defaultAction;

    public DefaultKeymap(String name)
    {
      this.name = name;
      this.map = new Hashtable();
    }

    public void addActionForKeyStroke(KeyStroke key, Action a)
    {
      map.put(key, a);
    }

    /**
     * Looks up a KeyStroke either in the current map or the parent Keymap;
     * does <em>not</em> return the default action if lookup fails.
     *
     * @param key The KeyStroke to look up an Action for.
     *
     * @return The mapping for <code>key</code>, or <code>null</code>
     * if no mapping exists in this Keymap or any of its parents.
     */
    public Action getAction(KeyStroke key)
    {
      if (map.containsKey(key))
        return (Action) map.get(key);
      else if (parent != null)
        return parent.getAction(key);
      else
        return null;
    }

    public Action[] getBoundActions()
    {
      Action [] ret = new Action[map.size()];
      Enumeration e = map.elements();
      int i = 0;
      while (e.hasMoreElements())
        {
          ret[i++] = (Action) e.nextElement();
        }
      return ret;
    }

    public KeyStroke[] getBoundKeyStrokes()
    {
      KeyStroke [] ret = new KeyStroke[map.size()];
      Enumeration e = map.keys();
      int i = 0;
      while (e.hasMoreElements())
        {
          ret[i++] = (KeyStroke) e.nextElement();
        }
      return ret;
    }

    public Action getDefaultAction()
    {
      return defaultAction;
    }

    public KeyStroke[] getKeyStrokesForAction(Action a)
    {
      int i = 0;
      Enumeration e = map.keys();
      while (e.hasMoreElements())
        {
          if (map.get(e.nextElement()).equals(a))
            ++i;
        }
      KeyStroke [] ret = new KeyStroke[i];
      i = 0;
      e = map.keys();
      while (e.hasMoreElements())
        {
          KeyStroke k = (KeyStroke) e.nextElement();
          if (map.get(k).equals(a))
            ret[i++] = k;
        }
      return ret;
    }

    public String getName()
    {
      return name;
    }

    public Keymap getResolveParent()
    {
      return parent;
    }

    public boolean isLocallyDefined(KeyStroke key)
    {
      return map.containsKey(key);
    }

    public void removeBindings()
    {
      map.clear();
    }

    public void removeKeyStrokeBinding(KeyStroke key)
    {
      map.remove(key);
    }

    public void setDefaultAction(Action a)
    {
      defaultAction = a;
    }

    public void setResolveParent(Keymap p)
    {
      parent = p;
    }
  }

  class DefaultTransferHandler extends TransferHandler
  {
    public boolean canImport(JComponent component, DataFlavor[] flavors)
    {
      JTextComponent textComponent = (JTextComponent) component;

      if (! (textComponent.isEnabled()
             && textComponent.isEditable()
             && flavors != null))
        return false;

      for (int i = 0; i < flavors.length; ++i)
        if (flavors[i].equals(DataFlavor.stringFlavor))
           return true;

      return false;
    }

    public void exportToClipboard(JComponent component, Clipboard clipboard,
                                  int action)
    {
      JTextComponent textComponent = (JTextComponent) component;
      int start = textComponent.getSelectionStart();
      int end = textComponent.getSelectionEnd();

      if (start == end)
        return;

      try
        {
          // Copy text to clipboard.
          String data = textComponent.getDocument().getText(start, end);
          StringSelection selection = new StringSelection(data);
          clipboard.setContents(selection, null);

          // Delete selected text on cut action.
          if (action == MOVE)
            doc.remove(start, end - start);
        }
      catch (BadLocationException e)
        {
          // Ignore this and do nothing.
        }
    }

    public int getSourceActions()
    {
      return NONE;
    }

    public boolean importData(JComponent component, Transferable transferable)
    {
      DataFlavor flavor = null;
      DataFlavor[] flavors = transferable.getTransferDataFlavors();

      if (flavors == null)
        return false;

      for (int i = 0; i < flavors.length; ++i)
        if (flavors[i].equals(DataFlavor.stringFlavor))
          flavor = flavors[i];

      if (flavor == null)
        return false;

      try
        {
          JTextComponent textComponent = (JTextComponent) component;
          String data = (String) transferable.getTransferData(flavor);
          textComponent.replaceSelection(data);
          return true;
        }
      catch (IOException e)
        {
          // Ignored.
        }
      catch (UnsupportedFlavorException e)
        {
          // Ignored.
        }

      return false;
    }
  }

  private static final long serialVersionUID = -8796518220218978795L;

  public static final String DEFAULT_KEYMAP = "default";
  public static final String FOCUS_ACCELERATOR_KEY = "focusAcceleratorKey";

  private static DefaultTransferHandler defaultTransferHandler;
  private static Hashtable keymaps = new Hashtable();
  private Keymap keymap;
  private char focusAccelerator = '\0';
  private NavigationFilter navigationFilter;

  /**
   * Get a Keymap from the global keymap table, by name.
   *
   * @param n The name of the Keymap to look up
   *
   * @return A Keymap associated with the provided name, or
   * <code>null</code> if no such Keymap exists
   *
   * @see #addKeymap
   * @see #removeKeymap
   * @see #keymaps
   */
  public static Keymap getKeymap(String n)
  {
    return (Keymap) keymaps.get(n);
  }

  /**
   * Remove a Keymap from the global Keymap table, by name.
   *
   * @param n The name of the Keymap to remove
   *
   * @return The keymap removed from the global table
   *
   * @see #addKeymap
   * @see #getKeymap()
   * @see #keymaps
   */
  public static Keymap removeKeymap(String n)
  {
    Keymap km = (Keymap) keymaps.get(n);
    keymaps.remove(n);
    return km;
  }

  /**
   * Create a new Keymap with a specific name and parent, and add the new
   * Keymap to the global keymap table. The name may be <code>null</code>,
   * in which case the new Keymap will <em>not</em> be added to the global
   * Keymap table. The parent may also be <code>null</code>, which is
   * harmless.
   *
   * @param n The name of the new Keymap, or <code>null</code>
   * @param parent The parent of the new Keymap, or <code>null</code>
   *
   * @return The newly created Keymap
   *
   * @see #removeKeymap
   * @see #getKeymap()
   * @see #keymaps
   */
  public static Keymap addKeymap(String n, Keymap parent)
  {
    Keymap k = new DefaultKeymap(n);
    k.setResolveParent(parent);
    if (n != null)
      keymaps.put(n, k);
    return k;
  }

  /**
   * Get the current Keymap of this component.
   *
   * @return The component's current Keymap
   *
   * @see #setKeymap
   * @see #keymap
   */
  public Keymap getKeymap()
  {
    return keymap;
  }

  /**
   * Set the current Keymap of this component, installing appropriate
   * {@link KeymapWrapper} and {@link KeymapActionMap} objects in the
   * {@link InputMap} and {@link ActionMap} parent chains, respectively,
   * and fire a property change event with name <code>"keymap"</code>.
   *
   * @see #getKeymap()
   * @see #keymap
   */
  public void setKeymap(Keymap k)
  {

    // phase 1: replace the KeymapWrapper entry in the InputMap chain.
    // the goal here is to always maintain the following ordering:
    //
    //   [InputMap]? -> [KeymapWrapper]? -> [InputMapUIResource]*
    //
    // that is to say, component-specific InputMaps need to remain children
    // of Keymaps, and Keymaps need to remain children of UI-installed
    // InputMaps (and the order of each group needs to be preserved, of
    // course).

    KeymapWrapper kw = (k == null ? null : new KeymapWrapper(k));
    InputMap childInputMap = getInputMap(JComponent.WHEN_FOCUSED);
    if (childInputMap == null)
      setInputMap(JComponent.WHEN_FOCUSED, kw);
    else
      {
        while (childInputMap.getParent() != null
               && !(childInputMap.getParent() instanceof KeymapWrapper)
               && !(childInputMap.getParent() instanceof InputMapUIResource))
          childInputMap = childInputMap.getParent();

        // option 1: there is nobody to replace at the end of the chain
        if (childInputMap.getParent() == null)
          childInputMap.setParent(kw);

        // option 2: there is already a KeymapWrapper in the chain which
        // needs replacing (possibly with its own parents, possibly without)
        else if (childInputMap.getParent() instanceof KeymapWrapper)
          {
            if (kw == null)
              childInputMap.setParent(childInputMap.getParent().getParent());
            else
              {
                kw.setParent(childInputMap.getParent().getParent());
                childInputMap.setParent(kw);
              }
          }

        // option 3: there is an InputMapUIResource in the chain, which marks
        // the place where we need to stop and insert ourselves
        else if (childInputMap.getParent() instanceof InputMapUIResource)
          {
            if (kw != null)
              {
                kw.setParent(childInputMap.getParent());
                childInputMap.setParent(kw);
              }
          }
      }

    // phase 2: replace the KeymapActionMap entry in the ActionMap chain

    KeymapActionMap kam = (k == null ? null : new KeymapActionMap(k));
    ActionMap childActionMap = getActionMap();
    if (childActionMap == null)
      setActionMap(kam);
    else
      {
        while (childActionMap.getParent() != null
               && !(childActionMap.getParent() instanceof KeymapActionMap)
               && !(childActionMap.getParent() instanceof ActionMapUIResource))
          childActionMap = childActionMap.getParent();

        // option 1: there is nobody to replace at the end of the chain
        if (childActionMap.getParent() == null)
          childActionMap.setParent(kam);

        // option 2: there is already a KeymapActionMap in the chain which
        // needs replacing (possibly with its own parents, possibly without)
        else if (childActionMap.getParent() instanceof KeymapActionMap)
          {
            if (kam == null)
              childActionMap.setParent(childActionMap.getParent().getParent());
            else
              {
                kam.setParent(childActionMap.getParent().getParent());
                childActionMap.setParent(kam);
              }
          }

        // option 3: there is an ActionMapUIResource in the chain, which marks
        // the place where we need to stop and insert ourselves
        else if (childActionMap.getParent() instanceof ActionMapUIResource)
          {
            if (kam != null)
              {
                kam.setParent(childActionMap.getParent());
                childActionMap.setParent(kam);
              }
          }
      }

    // phase 3: update the explicit keymap field

    Keymap old = keymap;
    keymap = k;
    firePropertyChange("keymap", old, k);
  }

  /**
   * Resolves a set of bindings against a set of actions and inserts the
   * results into a {@link Keymap}. Specifically, for each provided binding
   * <code>b</code>, if there exists a provided action <code>a</code> such
   * that <code>a.getValue(Action.NAME) == b.ActionName</code> then an
   * entry is added to the Keymap mapping <code>b</code> to
   * <code>a</code>.
   *
   * @param map The Keymap to add new mappings to
   * @param bindings The set of bindings to add to the Keymap
   * @param actions The set of actions to resolve binding names against
   *
   * @see Action#NAME
   * @see Action#getValue
   * @see KeyBinding#actionName
   */
  public static void loadKeymap(Keymap map,
                                JTextComponent.KeyBinding[] bindings,
                                Action[] actions)
  {
    Hashtable acts = new Hashtable(actions.length);
    for (int i = 0; i < actions.length; ++i)
      acts.put(actions[i].getValue(Action.NAME), actions[i]);
      for (int i = 0; i < bindings.length; ++i)
      if (acts.containsKey(bindings[i].actionName))
        map.addActionForKeyStroke(bindings[i].key, (Action) acts.get(bindings[i].actionName));
  }

  /**
   * Returns the set of available Actions this component's associated
   * editor can run.  Equivalent to calling
   * <code>getUI().getEditorKit().getActions()</code>. This set of Actions
   * is a reasonable value to provide as a parameter to {@link
   * #loadKeymap}, when resolving a set of {@link KeyBinding} objects
   * against this component.
   *
   * @return The set of available Actions on this component's {@link EditorKit}
   *
   * @see TextUI#getEditorKit
   * @see EditorKit#getActions()
   */
  public Action[] getActions()
  {
    return getUI().getEditorKit(this).getActions();
  }

  // These are package-private to avoid an accessor method.
  Document doc;
  Caret caret;
  boolean editable;

  private Highlighter highlighter;
  private Color caretColor;
  private Color disabledTextColor;
  private Color selectedTextColor;
  private Color selectionColor;
  private Insets margin;
  private boolean dragEnabled;

  /**
   * Creates a new <code>JTextComponent</code> instance.
   */
  public JTextComponent()
  {
    Keymap defkeymap = getKeymap(DEFAULT_KEYMAP);
    if (defkeymap == null)
      {
        defkeymap = addKeymap(DEFAULT_KEYMAP, null);
        defkeymap.setDefaultAction(new DefaultEditorKit.DefaultKeyTypedAction());
      }

    setFocusable(true);
    setEditable(true);
    enableEvents(AWTEvent.KEY_EVENT_MASK);
    setOpaque(true);
    updateUI();
  }

  public void setDocument(Document newDoc)
  {
    Document oldDoc = doc;
    try
      {
        if (oldDoc instanceof AbstractDocument)
          ((AbstractDocument) oldDoc).readLock();

        doc = newDoc;
        firePropertyChange("document", oldDoc, newDoc);
      }
    finally
      {
        if (oldDoc instanceof AbstractDocument)
          ((AbstractDocument) oldDoc).readUnlock();
      }
    revalidate();
    repaint();
  }

  public Document getDocument()
  {
    return doc;
  }

  /**
   * Get the <code>AccessibleContext</code> of this object.
   *
   * @return an <code>AccessibleContext</code> object
   */
  public AccessibleContext getAccessibleContext()
  {
    return new AccessibleJTextComponent();
  }

  public void setMargin(Insets m)
  {
    margin = m;
  }

  public Insets getMargin()
  {
    return margin;
  }

  public void setText(String text)
  {
    try
      {
        if (doc instanceof AbstractDocument)
          ((AbstractDocument) doc).replace(0, doc.getLength(), text, null);
        else
          {
            doc.remove(0, doc.getLength());
            doc.insertString(0, text, null);
          }
      }
    catch (BadLocationException e)
      {
        // This can never happen.
        throw (InternalError) new InternalError().initCause(e);
      }
  }

  /**
   * Retrieves the current text in this text document.
   *
   * @return the text
   *
   * @exception NullPointerException if the underlaying document is null
   */
  public String getText()
  {
    if (doc == null)
      return null;

    try
      {
        return doc.getText(0, doc.getLength());
      }
    catch (BadLocationException e)
      {
        // This should never happen.
        return "";
      }
  }

  /**
   * Retrieves a part of the current text in this document.
   *
   * @param offset the postion of the first character
   * @param length the length of the text to retrieve
   *
   * @return the text
   *
   * @exception BadLocationException if arguments do not hold pre-conditions
   */
  public String getText(int offset, int length)
    throws BadLocationException
  {
    return getDocument().getText(offset, length);
  }

  /**
   * Retrieves the currently selected text in this text document.
   *
   * @return the selected text
   *
   * @exception NullPointerException if the underlaying document is null
   */
  public String getSelectedText()
  {
    int start = getSelectionStart();
    int offset = getSelectionEnd() - start;

    if (offset <= 0)
      return null;

    try
      {
        return doc.getText(start, offset);
      }
    catch (BadLocationException e)
      {
        // This should never happen.
        return null;
      }
  }

  /**
   * Returns a string that specifies the name of the Look and Feel class
   * that renders this component.
   *
   * @return the string "TextComponentUI"
   */
  public String getUIClassID()
  {
    return "TextComponentUI";
  }

  /**
   * Returns a string representation of this JTextComponent.
   */
  protected String paramString()
  {
    // TODO: Do something useful here.
    return super.paramString();
  }

  /**
   * This method returns the label's UI delegate.
   *
   * @return The label's UI delegate.
   */
  public TextUI getUI()
  {
    return (TextUI) ui;
  }

  /**
   * This method sets the label's UI delegate.
   *
   * @param newUI The label's UI delegate.
   */
  public void setUI(TextUI newUI)
  {
    super.setUI(newUI);
  }

  /**
   * This method resets the label's UI delegate to the default UI for the
   * current look and feel.
   */
  public void updateUI()
  {
    setUI((TextUI) UIManager.getUI(this));
  }

  public Dimension getPreferredScrollableViewportSize()
  {
    return getPreferredSize();
  }

  public int getScrollableUnitIncrement(Rectangle visible, int orientation,
                                        int direction)
  {
    // We return 1/10 of the visible area as documented in Sun's API docs.
    if (orientation == SwingConstants.HORIZONTAL)
      return visible.width / 10;
    else if (orientation == SwingConstants.VERTICAL)
      return visible.height / 10;
    else
      throw new IllegalArgumentException("orientation must be either "
                                      + "javax.swing.SwingConstants.VERTICAL "
                                      + "or "
                                      + "javax.swing.SwingConstants.HORIZONTAL"
                                         );
  }

  public int getScrollableBlockIncrement(Rectangle visible, int orientation,
                                         int direction)
  {
    // We return the whole visible area as documented in Sun's API docs.
    if (orientation == SwingConstants.HORIZONTAL)
      return visible.width;
    else if (orientation == SwingConstants.VERTICAL)
      return visible.height;
    else
      throw new IllegalArgumentException("orientation must be either "
                                      + "javax.swing.SwingConstants.VERTICAL "
                                      + "or "
                                      + "javax.swing.SwingConstants.HORIZONTAL"
                                         );
  }

  /**
   * Checks whether this text component it editable.
   *
   * @return true if editable, false otherwise
   */
  public boolean isEditable()
  {
    return editable;
  }

  /**
   * Enables/disabled this text component's editability.
   *
   * @param newValue true to make it editable, false otherwise.
   */
  public void setEditable(boolean newValue)
  {
    if (editable == newValue)
      return;

    boolean oldValue = editable;
    editable = newValue;
    firePropertyChange("editable", oldValue, newValue);
  }

  /**
   * The <code>Caret</code> object used in this text component.
   *
   * @return the caret object
   */
  public Caret getCaret()
  {
    return caret;
  }

  /**
   * Sets a new <code>Caret</code> for this text component.
   *
   * @param newCaret the new <code>Caret</code> to set
   */
  public void setCaret(Caret newCaret)
  {
    if (caret != null)
      caret.deinstall(this);

    Caret oldCaret = caret;
    caret = newCaret;

    if (caret != null)
      caret.install(this);

    firePropertyChange("caret", oldCaret, newCaret);
  }

  public Color getCaretColor()
  {
    return caretColor;
  }

  public void setCaretColor(Color newColor)
  {
    Color oldCaretColor = caretColor;
    caretColor = newColor;
    firePropertyChange("caretColor", oldCaretColor, newColor);
  }

  public Color getDisabledTextColor()
  {
    return disabledTextColor;
  }

  public void setDisabledTextColor(Color newColor)
  {
    Color oldColor = disabledTextColor;
    disabledTextColor = newColor;
    firePropertyChange("disabledTextColor", oldColor, newColor);
  }

  public Color getSelectedTextColor()
  {
    return selectedTextColor;
  }

  public void setSelectedTextColor(Color newColor)
  {
    Color oldColor = selectedTextColor;
    selectedTextColor = newColor;
    firePropertyChange("selectedTextColor", oldColor, newColor);
  }

  public Color getSelectionColor()
  {
    return selectionColor;
  }

  public void setSelectionColor(Color newColor)
  {
    Color oldColor = selectionColor;
    selectionColor = newColor;
    firePropertyChange("selectionColor", oldColor, newColor);
  }

  /**
   * Retrisves the current caret position.
   *
   * @return the current position
   */
  public int getCaretPosition()
  {
    return caret.getDot();
  }

  /**
   * Sets the caret to a new position.
   *
   * @param position the new position
   */
  public void setCaretPosition(int position)
  {
    if (doc == null)
      return;

    if (position < 0 || position > doc.getLength())
      throw new IllegalArgumentException();

    caret.setDot(position);
  }

  /**
   * Moves the caret to a given position. This selects the text between
   * the old and the new position of the caret.
   */
  public void moveCaretPosition(int position)
  {
    if (doc == null)
      return;

    if (position < 0 || position > doc.getLength())
      throw new IllegalArgumentException();

    caret.moveDot(position);
  }

  public Highlighter getHighlighter()
  {
    return highlighter;
  }

  public void setHighlighter(Highlighter newHighlighter)
  {
    if (highlighter != null)
      highlighter.deinstall(this);

    Highlighter oldHighlighter = highlighter;
    highlighter = newHighlighter;

    if (highlighter != null)
      highlighter.install(this);

    firePropertyChange("highlighter", oldHighlighter, newHighlighter);
  }

  /**
   * Returns the start postion of the currently selected text.
   *
   * @return the start postion
   */
  public int getSelectionStart()
  {
    return Math.min(caret.getDot(), caret.getMark());
  }

  /**
   * Selects the text from the given postion to the selection end position.
   *
   * @param start the start positon of the selected text.
   */
  public void setSelectionStart(int start)
  {
    select(start, getSelectionEnd());
  }

  /**
   * Returns the end postion of the currently selected text.
   *
   * @return the end postion
   */
  public int getSelectionEnd()
  {
    return Math.max(caret.getDot(), caret.getMark());
  }

  /**
   * Selects the text from the selection start postion to the given position.
   *
   * @param end the end positon of the selected text.
   */
  public void setSelectionEnd(int end)
  {
    select(getSelectionStart(), end);
  }

  /**
   * Selects a part of the content of the text component.
   *
   * @param start the start position of the selected text
   * @param end the end position of the selected text
   */
  public void select(int start, int end)
  {
    int length = doc.getLength();

    start = Math.max(start, 0);
    start = Math.min(start, length);

    end = Math.max(end, start);
    end = Math.min(end, length);

    setCaretPosition(start);
    moveCaretPosition(end);
  }

  /**
   * Selects the whole content of the text component.
   */
  public void selectAll()
  {
    select(0, doc.getLength());
  }

  public synchronized void replaceSelection(String content)
  {
    int dot = caret.getDot();
    int mark = caret.getMark();

    // If content is empty delete selection.
    if (content == null)
      {
        caret.setDot(dot);
        return;
      }

    try
      {
        int start = getSelectionStart();
        int end = getSelectionEnd();

        // Remove selected text.
        if (dot != mark)
          doc.remove(start, end - start);

        // Insert new text.
        doc.insertString(start, content, null);

        // Set dot to new position,
        dot = start + content.length();
        setCaretPosition(dot);

        // and update it's magic position.
        caret.setMagicCaretPosition(modelToView(dot).getLocation());
      }
    catch (BadLocationException e)
      {
        // This should never happen.
      }
  }

  public boolean getScrollableTracksViewportHeight()
  {
    if (getParent() instanceof JViewport)
      return getParent().getHeight() > getPreferredSize().height;

    return false;
  }

  public boolean getScrollableTracksViewportWidth()
  {
    boolean res = false;
    Container c = getParent();
    if (c instanceof JViewport)
      res = ((JViewport) c).getExtentSize().width > getPreferredSize().width;

    return res;
  }

  /**
   * Adds a <code>CaretListener</code> object to this text component.
   *
   * @param listener the listener to add
   */
  public void addCaretListener(CaretListener listener)
  {
    listenerList.add(CaretListener.class, listener);
  }

  /**
   * Removed a <code>CaretListener</code> object from this text component.
   *
   * @param listener the listener to remove
   */
  public void removeCaretListener(CaretListener listener)
  {
    listenerList.remove(CaretListener.class, listener);
  }

  /**
   * Returns all added <code>CaretListener</code> objects.
   *
   * @return an array of listeners
   */
  public CaretListener[] getCaretListeners()
  {
    return (CaretListener[]) getListeners(CaretListener.class);
  }

  /**
   * Notifies all registered <code>CaretListener</code> objects that the caret
   * was updated.
   *
   * @param event the event to send
   */
  protected void fireCaretUpdate(CaretEvent event)
  {
    CaretListener[] listeners = getCaretListeners();

    for (int index = 0; index < listeners.length; ++index)
      listeners[index].caretUpdate(event);
  }

  /**
   * Adds an <code>InputListener</code> object to this text component.
   *
   * @param listener the listener to add
   */
  public void addInputMethodListener(InputMethodListener listener)
  {
    listenerList.add(InputMethodListener.class, listener);
  }

  /**
   * Removes an <code>InputListener</code> object from this text component.
   *
   * @param listener the listener to remove
   */
  public void removeInputMethodListener(InputMethodListener listener)
  {
    listenerList.remove(InputMethodListener.class, listener);
  }

  /**
   * Returns all added <code>InputMethodListener</code> objects.
   *
   * @return an array of listeners
   */
  public InputMethodListener[] getInputMethodListeners()
  {
    return (InputMethodListener[]) getListeners(InputMethodListener.class);
  }

  public Rectangle modelToView(int position) throws BadLocationException
  {
    return getUI().modelToView(this, position);
  }

  public boolean getDragEnabled()
  {
    return dragEnabled;
  }

  public void setDragEnabled(boolean enabled)
  {
    dragEnabled = enabled;
  }

  public int viewToModel(Point pt)
  {
    return getUI().viewToModel(this, pt);
  }

  public void copy()
  {
    if (isEnabled())
    doTransferAction("copy", TransferHandler.getCopyAction());
  }

  public void cut()
  {
    if (editable && isEnabled())
      doTransferAction("cut", TransferHandler.getCutAction());
  }

  public void paste()
  {
    if (editable && isEnabled())
      doTransferAction("paste", TransferHandler.getPasteAction());
  }

  private void doTransferAction(String name, Action action)
  {
    // Install default TransferHandler if none set.
    if (getTransferHandler() == null)
      {
        if (defaultTransferHandler == null)
          defaultTransferHandler = new DefaultTransferHandler();

        setTransferHandler(defaultTransferHandler);
      }

    // Perform action.
    ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
                                        action.getValue(Action.NAME).toString());
    action.actionPerformed(event);
  }

  public void setFocusAccelerator(char newKey)
  {
    if (focusAccelerator == newKey)
      return;

    char oldKey = focusAccelerator;
    focusAccelerator = newKey;
    firePropertyChange(FOCUS_ACCELERATOR_KEY, oldKey, newKey);
  }

  public char getFocusAccelerator()
  {
    return focusAccelerator;
  }

  /**
   * @since 1.4
   */
  public NavigationFilter getNavigationFilter()
  {
    return navigationFilter;
  }

  /**
   * @since 1.4
   */
  public void setNavigationFilter(NavigationFilter filter)
  {
    navigationFilter = filter;
  }

  /**
   * Read and set the content this component. If not overridden, the
   * method reads the component content as a plain text.
   *
   * The second parameter of this method describes the input stream. It can
   * be String, URL, File and so on. If not null, this object is added to
   * the properties of the associated document under the key
   * {@link Document#StreamDescriptionProperty}.
   *
   * @param input an input stream to read from.
   * @param streamDescription an object, describing the stream.
   *
   * @throws IOException if the reader throws it.
   *
   * @see #getDocument()
   * @see Document#getProperty(Object)
   */
  public void read(Reader input, Object streamDescription)
            throws IOException
  {
    if (streamDescription != null)
      {
        Document d = getDocument();
        if (d != null)
          d.putProperty(Document.StreamDescriptionProperty, streamDescription);
      }

    CPStringBuilder b = new CPStringBuilder();
    int c;

    // Read till -1 (EOF).
    while ((c = input.read()) >= 0)
      b.append((char) c);

    setText(b.toString());
  }

  /**
   * Write the content of this component to the given stream. If not
   * overridden, the method writes the component content as a plain text.
   *
   * @param output the writer to write into.
   *
   * @throws IOException if the writer throws it.
   */
  public void write(Writer output)
             throws IOException
  {
    output.write(getText());
  }

  /**
   * Returns the tooltip text for this text component for the given mouse
   * event. This forwards the call to
   * {@link TextUI#getToolTipText(JTextComponent, Point)}.
   *
   * @param ev the mouse event
   *
   * @return the tooltip text for this text component for the given mouse
   *         event
   */
  public String getToolTipText(MouseEvent ev)
  {
    return getUI().getToolTipText(this, ev.getPoint());
  }
}
