/* JComponent.java -- Every component in swing inherits from this class.
   Copyright (C) 2002, 2004, 2005, 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 javax.swing;

import gnu.java.lang.CPStringBuilder;

import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FocusTraversalPolicy;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.peer.LightweightPeer;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Set;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleExtendedComponent;
import javax.accessibility.AccessibleKeyBinding;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.EventListenerList;
import javax.swing.plaf.ComponentUI;

/**
 * The base class of all Swing components.
 * It contains generic methods to manage events, properties and sizes. Actual
 * drawing of the component is channeled to a look-and-feel class that is
 * implemented elsewhere.
 *
 * @author Ronald Veldema (rveldema&064;cs.vu.nl)
 * @author Graydon Hoare (graydon&064;redhat.com)
 */
public abstract class JComponent extends Container implements Serializable
{
  private static final long serialVersionUID = -7908749299918704233L;

  /** 
   * The accessible context of this <code>JComponent</code>.
   */
  protected AccessibleContext accessibleContext;

  /**
   * Basic accessibility support for <code>JComponent</code> derived
   * widgets.
   */
  public abstract class AccessibleJComponent 
    extends AccessibleAWTContainer
    implements AccessibleExtendedComponent
  {
    /**
     * Receives notification if the focus on the JComponent changes and
     * fires appropriate PropertyChangeEvents to listeners registered with
     * the AccessibleJComponent.
     */
    protected class AccessibleFocusHandler 
      implements FocusListener
    {
      /**
       * Creates a new AccessibleFocusHandler.
       */
      protected AccessibleFocusHandler()
      {
        // Nothing to do here.
      }

      /**
       * Receives notification when the JComponent gained focus and fires
       * a PropertyChangeEvent to listeners registered on the
       * AccessibleJComponent with a property name of
       * {@link AccessibleContext#ACCESSIBLE_STATE_PROPERTY} and a new value
       * of {@link AccessibleState#FOCUSED}.
       */
      public void focusGained(FocusEvent event)
      {
        AccessibleJComponent.this.firePropertyChange
          (AccessibleContext.ACCESSIBLE_STATE_PROPERTY, null,
           AccessibleState.FOCUSED);
      }

      /**
       * Receives notification when the JComponent lost focus and fires
       * a PropertyChangeEvent to listeners registered on the
       * AccessibleJComponent with a property name of
       * {@link AccessibleContext#ACCESSIBLE_STATE_PROPERTY} and an old value
       * of {@link AccessibleState#FOCUSED}.
       */
      public void focusLost(FocusEvent valevent)
      {
        AccessibleJComponent.this.firePropertyChange
          (AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
           AccessibleState.FOCUSED, null);
      }
    }

    /**
     * Receives notification if there are child components are added or removed
     * from the JComponent and fires appropriate PropertyChangeEvents to
     * interested listeners on the AccessibleJComponent.
     */
    protected class AccessibleContainerHandler 
      implements ContainerListener
    {
      /**
       * Creates a new AccessibleContainerHandler.
       */
      protected AccessibleContainerHandler()
      {
        // Nothing to do here.
      }

      /**
       * Receives notification when a child component is added to the
       * JComponent and fires a PropertyChangeEvent on listeners registered
       * with the AccessibleJComponent with a property name of
       * {@link AccessibleContext#ACCESSIBLE_CHILD_PROPERTY}.
       *
       * @param event the container event
       */
      public void componentAdded(ContainerEvent event)
      {
        Component c = event.getChild();
        if (c != null && c instanceof Accessible)
          {
            AccessibleContext childCtx = c.getAccessibleContext();
            AccessibleJComponent.this.firePropertyChange
              (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, null, childCtx);
          }
      }

      /**
       * Receives notification when a child component is removed from the
       * JComponent and fires a PropertyChangeEvent on listeners registered
       * with the AccessibleJComponent with a property name of
       * {@link AccessibleContext#ACCESSIBLE_CHILD_PROPERTY}.
       *
       * @param event the container event
       */
      public void componentRemoved(ContainerEvent event)
      {
        Component c = event.getChild();
        if (c != null && c instanceof Accessible)
          {
            AccessibleContext childCtx = c.getAccessibleContext();
            AccessibleJComponent.this.firePropertyChange
              (AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, childCtx, null);
          }
      }
    }

    private static final long serialVersionUID = -7047089700479897799L;

    /**
     * Receives notification when a child component is added to the
     * JComponent and fires a PropertyChangeEvent on listeners registered
     * with the AccessibleJComponent.
     *
     * @specnote AccessibleAWTContainer has a protected field with the same
     *           name. Looks like a bug or nasty misdesign to me.
     */
    protected ContainerListener accessibleContainerHandler;

    /**
     * Receives notification if the focus on the JComponent changes and
     * fires appropriate PropertyChangeEvents to listeners registered with
     * the AccessibleJComponent.
     *
     * @specnote AccessibleAWTComponent has a protected field
     *           accessibleAWTFocusHandler. Looks like a bug or nasty misdesign
     *           to me.
     */
    protected FocusListener accessibleFocusHandler;

    /**
     * Creates a new AccessibleJComponent.
     */
    protected AccessibleJComponent()
    {
      // Nothing to do here.
    }

    /**
     * Adds a property change listener to the list of registered listeners.
     *
     * This sets up the {@link #accessibleContainerHandler} and
     * {@link #accessibleFocusHandler} fields and calls
     * <code>super.addPropertyChangeListener(listener)</code>.
     *
     * @param listener the listener to add
     */
    public void addPropertyChangeListener(PropertyChangeListener listener)
    {
      // Tests seem to indicate that this method also sets up the other two
      // handlers.
      if (accessibleContainerHandler == null)
        {
          accessibleContainerHandler = new AccessibleContainerHandler();
          addContainerListener(accessibleContainerHandler);
        }
      if (accessibleFocusHandler == null)
        {
          accessibleFocusHandler = new AccessibleFocusHandler();
          addFocusListener(accessibleFocusHandler);
        }
      super.addPropertyChangeListener(listener);
    }

    /**
     * Removes a property change listener from the list of registered listeners.
     *
     * This uninstalls the {@link #accessibleContainerHandler} and
     * {@link #accessibleFocusHandler} fields and calls
     * <code>super.removePropertyChangeListener(listener)</code>.
     *
     * @param listener the listener to remove
     */
    public void removePropertyChangeListener(PropertyChangeListener listener)
    {
      // Tests seem to indicate that this method also resets the other two
      // handlers.
      if (accessibleContainerHandler != null)
        {
          removeContainerListener(accessibleContainerHandler);
          accessibleContainerHandler = null;
        }
      if (accessibleFocusHandler != null)
        {
          removeFocusListener(accessibleFocusHandler);
          accessibleFocusHandler = null;
        }
      super.removePropertyChangeListener(listener);
    }

    /**
     * Returns the number of accessible children of this object.
     *
     * @return  the number of accessible children of this object
     */
    public int getAccessibleChildrenCount()
    {
      // TODO: The functionality should be performed in the superclass.
      // Find out why this is overridden. However, it is very well possible
      // that this is left over from times when there was no such superclass
      // method.
      return super.getAccessibleChildrenCount();
    }

    /**
     * Returns the accessible child component at index <code>i</code>.
     *
     * @param i the index of the accessible child to return
     *
     * @return the accessible child component at index <code>i</code>
     */
    public Accessible getAccessibleChild(int i)
    {
      // TODO: The functionality should be performed in the superclass.
      // Find out why this is overridden. However, it is very well possible
      // that this is left over from times when there was no such superclass
      // method.
      return super.getAccessibleChild(i);
    }

    /**
     * Returns the accessible state set of this component.
     *
     * @return the accessible state set of this component
     */
    public AccessibleStateSet getAccessibleStateSet()
    {
      // Note: While the java.awt.Component has an 'opaque' property, it
      // seems that it is not added to the accessible state set there, even
      // if this property is true. However, it is handled for JComponent, so
      // we add it here.
      AccessibleStateSet state = super.getAccessibleStateSet();
      if (isOpaque())
        state.add(AccessibleState.OPAQUE);
      return state;
    }

    /**
     * Returns the localized name for this object. Generally this should
     * almost never return {@link Component#getName()} since that is not
     * a localized name. If the object is some kind of text component (like
     * a menu item), then the value of the object may be returned. Also, if
     * the object has a tooltip, the value of the tooltip may also be
     * appropriate.
     *
     * @return the localized name for this object or <code>null</code> if this
     *         object has no name
     */
    public String getAccessibleName()
    {
      String name = super.getAccessibleName();

      // There are two fallbacks provided by the JComponent in the case the
      // superclass returns null:
      // - If the component is inside a titled border, then it inherits the
      //   name from the border title.
      // - If the component is not inside a titled border but has a label
      //   (via JLabel.setLabelFor()), then it gets the name from the label's
      //   accessible context.

      if (name == null)
        {
          name = getTitledBorderText();
        }

      if (name == null)
        {
          Object l = getClientProperty(JLabel.LABEL_PROPERTY);
          if (l instanceof Accessible)
            {
              AccessibleContext labelCtx =
                ((Accessible) l).getAccessibleContext();
              name = labelCtx.getAccessibleName();
            }
        }

      return name;
    }

    /**
     * Returns the localized description of this object.
     *
     * @return the localized description of this object or <code>null</code>
     *         if this object has no description
     */
    public String getAccessibleDescription()
    {
      // There are two fallbacks provided by the JComponent in the case the
      // superclass returns null:
      // - If the component has a tooltip, then inherit the description from
      //   the tooltip.
      // - If the component is not inside a titled border but has a label
      //   (via JLabel.setLabelFor()), then it gets the name from the label's
      //   accessible context.
      String descr = super.getAccessibleDescription();

      if (descr == null)
        {
          descr = getToolTipText();
        }

      if (descr == null)
        {
          Object l = getClientProperty(JLabel.LABEL_PROPERTY);
          if (l instanceof Accessible)
            {
              AccessibleContext labelCtx =
                ((Accessible) l).getAccessibleContext();
              descr = labelCtx.getAccessibleName();
            }
        }

      return descr;
    }

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

    /**
     * Recursivly searches a border hierarchy (starting at <code>border) for
     * a titled border and returns the title if one is found, <code>null</code>
     * otherwise.
     *
     * @param border the border to start search from
     *
     * @return the border title of a possibly found titled border
     */
    protected String getBorderTitle(Border border)
    {
      String title = null;
      if (border instanceof CompoundBorder)
        {
          CompoundBorder compound = (CompoundBorder) border;
          Border inner = compound.getInsideBorder();
          title = getBorderTitle(inner);
          if (title == null)
            {
              Border outer = compound.getOutsideBorder();
              title = getBorderTitle(outer);
            }
        }
      else if (border instanceof TitledBorder)
        {
          TitledBorder titled = (TitledBorder) border;
          title = titled.getTitle(); 
        }
      return title;
    }

    /**
     * Returns the tooltip text for this accessible component.
     *
     * @return the tooltip text for this accessible component
     */
    public String getToolTipText()
    {
      return JComponent.this.getToolTipText();
    }

    /**
     * Returns the title of the border of this accessible component if
     * this component has a titled border, otherwise returns <code>null</code>.
     *
     * @return the title of the border of this accessible component if
     *         this component has a titled border, otherwise returns
     *         <code>null</code>
     */
    public String getTitledBorderText()
    {
      return getBorderTitle(getBorder()); 
    }

    /**
     * Returns the keybindings associated with this accessible component or
     * <code>null</code> if the component does not support key bindings.
     *
     * @return the keybindings associated with this accessible component
     */
    public AccessibleKeyBinding getAccessibleKeyBinding()
    {
      // The reference implementation seems to always return null here,
      // independent of the key bindings of the JComponent. So do we.
      return null;
    }
  }

  /**
   * A value between 0.0 and 1.0 indicating the preferred horizontal
   * alignment of the component, relative to its siblings. The values
   * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
   * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
   * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
   * managers use this property.
   *
   * @see #getAlignmentX
   * @see #setAlignmentX
   * @see javax.swing.OverlayLayout
   * @see javax.swing.BoxLayout
   */
  float alignmentX = -1.0F;

  /**
   * A value between 0.0 and 1.0 indicating the preferred vertical
   * alignment of the component, relative to its siblings. The values
   * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
   * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
   * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
   * managers use this property.
   *
   * @see #getAlignmentY
   * @see #setAlignmentY
   * @see javax.swing.OverlayLayout
   * @see javax.swing.BoxLayout
   */
  float alignmentY = -1.0F;

  /** 
   * The border painted around this component.
   * 
   * @see #paintBorder
   */
  Border border;

  /**
   * The popup menu for the component.
   * 
   * @see #getComponentPopupMenu()
   * @see #setComponentPopupMenu(JPopupMenu)
   */
  JPopupMenu componentPopupMenu;
   
  /**
   * A flag that controls whether the {@link #getComponentPopupMenu()} method
   * looks to the component's parent when the <code>componentPopupMenu</code>
   * field is <code>null</code>.
   */
  boolean inheritsPopupMenu;
  
  /** 
   * <p>Whether to double buffer this component when painting. This flag
   * should generally be <code>true</code>, to ensure good painting
   * performance.</p>
   *
   * <p>All children of a double buffered component are painted into the
   * double buffer automatically, so only the top widget in a window needs
   * to be double buffered.</p>
   *
   * @see #setDoubleBuffered
   * @see #isDoubleBuffered
   * @see #paint
   */
  boolean doubleBuffered = true;

  /**
   * A set of flags indicating which debugging graphics facilities should
   * be enabled on this component. The values should be a combination of
   * {@link DebugGraphics#NONE_OPTION}, {@link DebugGraphics#LOG_OPTION},
   * {@link DebugGraphics#FLASH_OPTION}, or {@link
   * DebugGraphics#BUFFERED_OPTION}.
   *
   * @see #setDebugGraphicsOptions
   * @see #getDebugGraphicsOptions
   * @see DebugGraphics
   * @see #getComponentGraphics
   */
  int debugGraphicsOptions;

  /** 
   * <p>This property controls two independent behaviors simultaneously.</p>
   *
   * <p>First, it controls whether to fill the background of this widget
   * when painting its body. This affects calls to {@link
   * JComponent#paintComponent}, which in turn calls {@link
   * ComponentUI#update} on the component's {@link #ui} property. If the
   * component is opaque during this call, the background will be filled
   * before calling {@link ComponentUI#paint}. This happens merely as a
   * convenience; you may fill the component's background yourself too,
   * but there is no need to do so if you will be filling with the same
   * color.</p>
   *
   * <p>Second, it the opaque property informs swing's repaint system
   * whether it will be necessary to paint the components "underneath" this
   * component, in Z-order. If the component is opaque, it is considered to
   * completely occlude components "underneath" it, so they will not be
   * repainted along with the opaque component.</p>
   *
   * <p>The default value for this property is <code>false</code>, but most
   * components will want to set it to <code>true</code> when installing UI
   * defaults in {@link ComponentUI#installUI}.</p>
   *
   * @see #setOpaque
   * @see #isOpaque
   * @see #paintComponent
   */
  boolean opaque = false;

  /** 
   * The user interface delegate for this component. Event delivery and
   * repainting of the component are usually delegated to this object. 
   *
   * @see #setUI
   * @see #getUIClassID
   * @see #updateUI
   */
  protected ComponentUI ui;

  /**
   * A hint to the focus system that this component should or should not
   * get focus. If this is <code>false</code>, swing will not try to
   * request focus on this component; if <code>true</code>, swing might
   * try to request focus, but the request might fail. Thus it is only 
   * a hint guiding swing's behavior.
   *
   * @see #requestFocus()
   * @see #isRequestFocusEnabled
   * @see #setRequestFocusEnabled
   */
  boolean requestFocusEnabled;

  /**
   * Flag indicating behavior of this component when the mouse is dragged
   * outside the component and the mouse <em>stops moving</em>. If
   * <code>true</code>, synthetic mouse events will be delivered on regular
   * timed intervals, continuing off in the direction the mouse exited the
   * component, until the mouse is released or re-enters the component.
   *
   * @see #setAutoscrolls
   * @see #getAutoscrolls
   */
  boolean autoscrolls = false;

  /**
   * Indicates whether the current paint call is already double buffered or
   * not. 
   */
  static boolean paintingDoubleBuffered = false;

  /**
   * Indicates whether we are calling paintDoubleBuffered() from
   * paintImmadiately (RepaintManager) or from paint() (AWT refresh).
   */
  static boolean isRepainting = false;

  /**
   * Listeners for events other than {@link PropertyChangeEvent} are
   * handled by this listener list. PropertyChangeEvents are handled in
   * {@link #changeSupport}.
   */
  protected EventListenerList listenerList = new EventListenerList();

  /**
   * Handles VetoableChangeEvents.
   */
  private VetoableChangeSupport vetoableChangeSupport;

  /** 
   * Storage for "client properties", which are key/value pairs associated
   * with this component by a "client", such as a user application or a
   * layout manager. This is lazily constructed when the component gets its
   * first client property.
   */
  private Hashtable clientProperties;
  
  private InputMap inputMap_whenFocused;
  private InputMap inputMap_whenAncestorOfFocused;
  private ComponentInputMap inputMap_whenInFocusedWindow;
  private ActionMap actionMap;
  /** @since 1.3 */
  private boolean verifyInputWhenFocusTarget = true;
  private InputVerifier inputVerifier;

  private TransferHandler transferHandler;

  /**
   * Indicates if this component is currently painting a tile or not.
   */
  private boolean paintingTile;

  /**
   * A temporary buffer used for fast dragging of components.
   */
  private Image dragBuffer;

  /**
   * Indicates if the dragBuffer is already initialized.
   */
  private boolean dragBufferInitialized;

  /**
   * A cached Rectangle object to be reused. Be careful when you use that,
   * so that it doesn't get modified in another context within the same
   * method call chain.
   */
  private static transient Rectangle rectCache;

  /**
   * The default locale of the component.
   * 
   * @see #getDefaultLocale
   * @see #setDefaultLocale
   */
  private static Locale defaultLocale;
  
  public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";

  /**
   * Constant used to indicate that no condition has been assigned to a
   * particular action.
   *
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
   */
  public static final int UNDEFINED_CONDITION = -1;

  /**
   * Constant used to indicate that an action should be performed only when 
   * the component has focus.
   *
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
   */
  public static final int WHEN_FOCUSED = 0;

  /**
   * Constant used to indicate that an action should be performed only when 
   * the component is an ancestor of the component which has focus.
   *
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
   */
  public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;

  /**
   * Constant used to indicate that an action should be performed only when 
   * the component is in the window which has focus.
   *
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
   */
  public static final int WHEN_IN_FOCUSED_WINDOW = 2;


  /**
   * Used to optimize painting. This is set in paintImmediately2() to specify
   * the exact component path to be painted by paintChildren.
   */
  Component paintChild;

  /**
   * Indicates if the opaque property has been set by a client program or by
   * the UI.
   *
   * @see #setUIProperty(String, Object)
   * @see LookAndFeel#installProperty(JComponent, String, Object)
   */
  private boolean clientOpaqueSet = false;

  /**
   * Indicates if the autoscrolls property has been set by a client program or
   * by the UI.
   *
   * @see #setUIProperty(String, Object)
   * @see LookAndFeel#installProperty(JComponent, String, Object)
   */
  private boolean clientAutoscrollsSet = false;

  /**
   * Creates a new <code>JComponent</code> instance.
   */
  public JComponent()
  {
    super();
    setDropTarget(new DropTarget());
    setLocale(getDefaultLocale());
    debugGraphicsOptions = DebugGraphics.NONE_OPTION;
    setRequestFocusEnabled(true);
  }

  /**
   * Helper to lazily construct and return the client properties table.
   * 
   * @return The current client properties table
   *
   * @see #clientProperties
   * @see #getClientProperty
   * @see #putClientProperty
   */
  private Hashtable getClientProperties()
  {
    if (clientProperties == null)
      clientProperties = new Hashtable();
    return clientProperties;
  }

  /**
   * Get a client property associated with this component and a particular
   * key.
   *
   * @param key The key with which to look up the client property
   *
   * @return A client property associated with this object and key
   *
   * @see #clientProperties
   * @see #getClientProperties
   * @see #putClientProperty
   */
  public final Object getClientProperty(Object key)
  {
    return getClientProperties().get(key);
  }

  /**
   * Add a client property <code>value</code> to this component, associated
   * with <code>key</code>. If there is an existing client property
   * associated with <code>key</code>, it will be replaced.  A
   * {@link PropertyChangeEvent} is sent to registered listeners (with the
   * name of the property being <code>key.toString()</code>).
   *
   * @param key The key of the client property association to add
   * @param value The value of the client property association to add
   *
   * @see #clientProperties
   * @see #getClientProperties
   * @see #getClientProperty
   */
  public final void putClientProperty(Object key, Object value)
  {
    Hashtable t = getClientProperties();
    Object old = t.get(key);
    if (value != null)
      t.put(key, value);
    else
      t.remove(key);

    // When both old and new value are null, no event is fired. This is
    // different from what firePropertyChange() normally does, so we add this
    // check here.
    if (old != null || value != null)
      firePropertyChange(key.toString(), old, value);
  }

  /**
   * Unregister an <code>AncestorListener</code>.
   *
   * @param listener The listener to unregister
   * 
   * @see #addAncestorListener
   */
  public void removeAncestorListener(AncestorListener listener)
  {
    listenerList.remove(AncestorListener.class, listener);
  }

  /**
   * Unregister a <code>VetoableChangeChangeListener</code>.
   *
   * @param listener The listener to unregister
   *
   * @see #addVetoableChangeListener
   */
  public void removeVetoableChangeListener(VetoableChangeListener listener)
  {
    if (vetoableChangeSupport != null)
      vetoableChangeSupport.removeVetoableChangeListener(listener);
  }

  /**
   * Register an <code>AncestorListener</code>.
   *
   * @param listener The listener to register
   *
   * @see #removeVetoableChangeListener
   */
  public void addAncestorListener(AncestorListener listener)
  {
    listenerList.add(AncestorListener.class, listener);
  }

  /**
   * Register a <code>VetoableChangeListener</code>.
   *
   * @param listener The listener to register
   *
   * @see #removeVetoableChangeListener
   * @see #listenerList
   */
  public void addVetoableChangeListener(VetoableChangeListener listener)
  {
    // Lazily instantiate this, it's rarely needed.
    if (vetoableChangeSupport == null)
      vetoableChangeSupport = new VetoableChangeSupport(this);
    vetoableChangeSupport.addVetoableChangeListener(listener);
  }

  /**
   * Returns all registered {@link EventListener}s of the given 
   * <code>listenerType</code>.
   *
   * @param listenerType the class of listeners to filter (<code>null</code> 
   *                     not permitted).
   *                     
   * @return An array of registered listeners.
   * 
   * @throws ClassCastException if <code>listenerType</code> does not implement
   *                            the {@link EventListener} interface.
   * @throws NullPointerException if <code>listenerType</code> is 
   *                              <code>null</code>.
   *                            
   * @see #getAncestorListeners()
   * @see #listenerList
   * 
   * @since 1.3
   */
  public <T extends EventListener> T[] getListeners(Class<T> listenerType)
  {
    if (listenerType == PropertyChangeListener.class)
      return (T[]) getPropertyChangeListeners();
    else if (listenerType == VetoableChangeListener.class)
      return (T[]) getVetoableChangeListeners();
    else
      return listenerList.getListeners(listenerType);
  }

  /**
   * Return all registered <code>AncestorListener</code> objects.
   *
   * @return The set of <code>AncestorListener</code> objects in {@link
   * #listenerList}
   */
  public AncestorListener[] getAncestorListeners()
  {
    return (AncestorListener[]) getListeners(AncestorListener.class);
  }

  /**
   * Return all registered <code>VetoableChangeListener</code> objects.
   *
   * @return An array of the <code>VetoableChangeListener</code> objects 
   *     registered with this component (possibly empty but never 
   *     <code>null</code>).
   * 
   * @since 1.4
   */
  public VetoableChangeListener[] getVetoableChangeListeners()
  {    
    return vetoableChangeSupport == null ? new VetoableChangeListener[0]
        : vetoableChangeSupport.getVetoableChangeListeners();
  }

  /**
   * Call {@link VetoableChangeListener#vetoableChange} on all listeners
   * registered to listen to a given property. Any method which changes
   * the specified property of this component should call this method.
   *
   * @param propertyName The property which changed
   * @param oldValue The old value of the property
   * @param newValue The new value of the property
   *
   * @throws PropertyVetoException if the change was vetoed by a listener
   *
   * @see #addVetoableChangeListener
   * @see #removeVetoableChangeListener
   */
  protected void fireVetoableChange(String propertyName, Object oldValue,
                                    Object newValue)
    throws PropertyVetoException
  {
    if (vetoableChangeSupport != null)
      vetoableChangeSupport.fireVetoableChange(propertyName, oldValue, newValue);
  }


  /**
   * Fires a property change for a primitive integer property.
   *
   * @param property the name of the property
   * @param oldValue the old value of the property
   * @param newValue the new value of the property
   *
   * @specnote This method is implemented in
   *           {@link Component#firePropertyChange(String, int, int)}. It is
   *           only here because it is specified to be public, whereas the
   *           Component method is protected.
   */
  public void firePropertyChange(String property, int oldValue, int newValue)
  {
    super.firePropertyChange(property, oldValue, newValue);
  }
  
  /**
   * Fires a property change for a primitive boolean property.
   *
   * @param property the name of the property
   * @param oldValue the old value of the property
   * @param newValue the new value of the property
   *
   * @specnote This method is implemented in
   *           {@link Component#firePropertyChange(String, boolean, boolean)}.
   *           It is only here because it is specified to be public, whereas
   *           the Component method is protected.
   */
  public void firePropertyChange(String property, boolean oldValue,
                                 boolean newValue)
  {
    super.firePropertyChange(property, oldValue, newValue);
  }

  /**
   * Get the value of the accessibleContext property for this component.
   *
   * @return the current value of the property
   */
  public AccessibleContext getAccessibleContext()
  {
    return null;
  }

  /**
   * Get the value of the {@link #alignmentX} property.
   *
   * @return The current value of the property.
   *
   * @see #setAlignmentX
   * @see #alignmentY
   */
  public float getAlignmentX()
  {
    float ret = alignmentX;
    if (alignmentX < 0)
      // alignment has not been set explicitly.
      ret = super.getAlignmentX();

    return ret;
  }

  /**
   * Get the value of the {@link #alignmentY} property.
   *
   * @return The current value of the property.
   *
   * @see #setAlignmentY
   * @see #alignmentX
   */
  public float getAlignmentY()
  {
    float ret = alignmentY;
    if (alignmentY < 0)
      // alignment has not been set explicitly.
      ret = super.getAlignmentY();

    return ret;
  }

  /**
   * Get the current value of the {@link #autoscrolls} property.
   *
   * @return The current value of the property
   */
  public boolean getAutoscrolls()
  {
    return autoscrolls;
  }

  /**
   * Set the value of the {@link #border} property.
   *   
   * @param newBorder The new value of the property
   *
   * @see #getBorder
   */
  public void setBorder(Border newBorder)
  {
    Border oldBorder = getBorder();
    if (oldBorder == newBorder)
      return;

    border = newBorder;
    firePropertyChange("border", oldBorder, newBorder);
    repaint();
  }

  /**
   * Get the value of the {@link #border} property.
   *
   * @return The property's current value
   *
   * @see #setBorder
   */
  public Border getBorder()
  {
    return border;
  }

  /**
   * Get the component's current bounding box. If a rectangle is provided,
   * use this as the return value (adjusting its fields in place);
   * otherwise (of <code>null</code> is provided) return a new {@link
   * Rectangle}.
   *
   * @param rv Optional return value to use
   *
   * @return A rectangle bounding the component
   */
  public Rectangle getBounds(Rectangle rv)
  {
    if (rv == null)
      return new Rectangle(getX(), getY(), getWidth(), getHeight());
    else
      {
        rv.setBounds(getX(), getY(), getWidth(), getHeight());
        return rv;
      }
  }

  /**
   * Prepares a graphics context for painting this object. If {@link
   * #debugGraphicsOptions} is not equal to {@link
   * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object
   * wrapping the parameter. Otherwise configure the parameter with this
   * component's foreground color and font.
   *
   * @param g The graphics context to wrap or configure
   *
   * @return A graphics context to paint this object with
   *
   * @see #debugGraphicsOptions
   * @see #paint
   */
  protected Graphics getComponentGraphics(Graphics g)
  {
    Graphics g2 = g;
    int options = getDebugGraphicsOptions();
    if (options != DebugGraphics.NONE_OPTION)
      {
        if (!(g2 instanceof DebugGraphics))
          g2 = new DebugGraphics(g);
        DebugGraphics dg = (DebugGraphics) g2;
        dg.setDebugOptions(dg.getDebugOptions() | options);
      }
    g2.setFont(this.getFont());
    g2.setColor(this.getForeground());
    return g2;
  }

  /**
   * Get the value of the {@link #debugGraphicsOptions} property.
   *
   * @return The current value of the property.
   *
   * @see #setDebugGraphicsOptions
   * @see #debugGraphicsOptions
   */
  public int getDebugGraphicsOptions()
  {
    String option = System.getProperty("gnu.javax.swing.DebugGraphics");
    int options = debugGraphicsOptions;
    if (option != null && option.length() != 0)
      {
        if (options < 0)
          options = 0;

        if (option.equals("LOG"))
          options |= DebugGraphics.LOG_OPTION;
        else if (option.equals("FLASH"))
          options |= DebugGraphics.FLASH_OPTION;
      }
    return options;
  }

  /**
   * Get the component's insets, which are calculated from
   * the {@link #border} property. If the border is <code>null</code>,
   * calls {@link Container#getInsets}.
   *
   * @return The component's current insets
   */
  public Insets getInsets()
  {
    if (border == null)
      return super.getInsets();
    return getBorder().getBorderInsets(this);
  }

  /**
   * Get the component's insets, which are calculated from the {@link
   * #border} property. If the border is <code>null</code>, calls {@link
   * Container#getInsets}. The passed-in {@link Insets} value will be
   * used as the return value, if possible.
   *
   * @param insets Return value object to reuse, if possible
   *
   * @return The component's current insets
   */
  public Insets getInsets(Insets insets)
  {
    Insets t = getInsets();

    if (insets == null)
      return t;

    insets.left = t.left;
    insets.right = t.right;
    insets.top = t.top;
    insets.bottom = t.bottom;
    return insets;
  }

  /**
   * Get the component's location. The passed-in {@link Point} value
   * will be used as the return value, if possible.
   *
   * @param rv Return value object to reuse, if possible
   *
   * @return The component's current location
   */
  public Point getLocation(Point rv)
  {
    if (rv == null)
      return new Point(getX(), getY());

    rv.setLocation(getX(), getY());
    return rv;
  }

  /**
   * Get the component's maximum size. If the <code>maximumSize</code> property
   * has been explicitly set, it is returned. If the <code>maximumSize</code>
   * property has not been set but the {@link #ui} property has been, the
   * result of {@link ComponentUI#getMaximumSize} is returned. If neither
   * property has been set, the result of {@link Container#getMaximumSize}
   * is returned.
   *
   * @return the maximum size of the component
   *
   * @see Component#setMaximumSize
   * @see Component#getMaximumSize()
   * @see Component#isMaximumSizeSet()
   * @see ComponentUI#getMaximumSize(JComponent)
   */
  public Dimension getMaximumSize()
  {
    Dimension size = null; 
    if (isMaximumSizeSet())
      size = super.getMaximumSize();
    else
      {
        if (ui != null)
          size = ui.getMaximumSize(this);
        if (size == null)
          size = super.getMaximumSize();
      }
    return size;
  }

  /**
   * Get the component's minimum size. If the <code>minimumSize</code> property
   * has been explicitly set, it is returned. If the <code>minimumSize</code>
   * property has not been set but the {@link #ui} property has been, the
   * result of {@link ComponentUI#getMinimumSize} is returned. If neither
   * property has been set, the result of {@link Container#getMinimumSize}
   * is returned.
   *
   * @return The minimum size of the component
   *
   * @see Component#setMinimumSize
   * @see Component#getMinimumSize()
   * @see Component#isMinimumSizeSet()
   * @see ComponentUI#getMinimumSize(JComponent)
   */
  public Dimension getMinimumSize()
  {
    Dimension size = null; 
    if (isMinimumSizeSet())
      size = super.getMinimumSize();
    else
      {
        if (ui != null)
          size = ui.getMinimumSize(this);
        if (size == null)
          size = super.getMinimumSize();
      }
    return size;
  }

  /**
   * Get the component's preferred size. If the <code>preferredSize</code>
   * property has been explicitly set, it is returned. If the
   * <code>preferredSize</code> property has not been set but the {@link #ui}
   * property has been, the result of {@link ComponentUI#getPreferredSize} is
   * returned. If neither property has been set, the result of {@link
   * Container#getPreferredSize} is returned.
   *
   * @return The preferred size of the component
   *
   * @see Component#setPreferredSize
   * @see Component#getPreferredSize()
   * @see Component#isPreferredSizeSet()
   * @see ComponentUI#getPreferredSize(JComponent)
   */
  public Dimension getPreferredSize()
  {
    Dimension size = null; 
    if (isPreferredSizeSet())
      size = super.getPreferredSize();
    else
      {
        if (ui != null)
          size = ui.getPreferredSize(this);
        if (size == null)
          size = super.getPreferredSize();
      }
    return size;
  }

  /**
   * Return the value of the <code>nextFocusableComponent</code> property.
   *
   * @return The current value of the property, or <code>null</code>
   * if none has been set.
   * 
   * @deprecated See {@link java.awt.FocusTraversalPolicy}
   */
  public Component getNextFocusableComponent()
  {
    Container focusRoot = this;
    if (! this.isFocusCycleRoot())
      focusRoot = getFocusCycleRootAncestor();

    FocusTraversalPolicy policy  = focusRoot.getFocusTraversalPolicy();
    return policy.getComponentAfter(focusRoot, this);
  }

  /**
   * Return the set of {@link KeyStroke} objects which are registered
   * to initiate actions on this component.
   *
   * @return An array of the registered keystrokes (possibly empty but never
   *     <code>null</code>).
   */
  public KeyStroke[] getRegisteredKeyStrokes()
  {
    KeyStroke[] ks0;
    KeyStroke[] ks1;
    KeyStroke[] ks2;
    if (inputMap_whenFocused != null)
      ks0 = inputMap_whenFocused.keys();
    else 
      ks0 = new KeyStroke[0];
    if (inputMap_whenAncestorOfFocused != null)
      ks1 = inputMap_whenAncestorOfFocused.keys();
    else 
      ks1 = new KeyStroke[0];
    if (inputMap_whenInFocusedWindow != null)
      ks2 = inputMap_whenInFocusedWindow.keys();
    else
      ks2 = new KeyStroke[0];
    int count = ks0.length + ks1.length + ks2.length;
    KeyStroke[] result = new KeyStroke[count];
    System.arraycopy(ks0, 0, result, 0, ks0.length);
    System.arraycopy(ks1, 0, result, ks0.length, ks1.length);
    System.arraycopy(ks2, 0, result, ks0.length + ks1.length, ks2.length);
    return result;
  }

  /**
   * Returns the first ancestor of this component which is a {@link JRootPane}.
   * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>.
   *
   * @return An ancestral JRootPane, or <code>null</code> if none exists.
   */
  public JRootPane getRootPane()
  {
    JRootPane p = SwingUtilities.getRootPane(this);
    return p;
  }

  /**
   * Get the component's size. The passed-in {@link Dimension} value
   * will be used as the return value, if possible.
   *
   * @param rv Return value object to reuse, if possible
   *
   * @return The component's current size
   */
  public Dimension getSize(Dimension rv)
  {
    if (rv == null)
      return new Dimension(getWidth(), getHeight());
    else
      {
        rv.setSize(getWidth(), getHeight());
        return rv;
      }
  }

  /**
   * Return the <code>toolTip</code> property of this component, creating it and
   * setting it if it is currently <code>null</code>. This method can be
   * overridden in subclasses which wish to control the exact form of
   * tooltip created.
   *
   * @return The current toolTip
   */
  public JToolTip createToolTip()
  {
    JToolTip toolTip = new JToolTip();
    toolTip.setComponent(this);
    return toolTip;
  }

  /**
   * Return the location at which the <code>toolTipText</code> property should
   * be displayed, when triggered by a particular mouse event. 
   *
   * @param event The event the tooltip is being presented in response to
   *
   * @return The point at which to display a tooltip, or <code>null</code>
   *     if swing is to choose a default location.
   */
  public Point getToolTipLocation(MouseEvent event)
  {
    return null;
  }

  /**
   * Set the tooltip text for this component. If a non-<code>null</code>
   * value is set, this component is registered in the
   * <code>ToolTipManager</code> in order to turn on tooltips for this
   * component. If a <code>null</code> value is set, tooltips are turne off
   * for this component.
   *
   * @param text the tooltip text for this component
   *
   * @see #getToolTipText()
   * @see #getToolTipText(MouseEvent)
   */
  public void setToolTipText(String text)
  {
    String old = getToolTipText();
    putClientProperty(TOOL_TIP_TEXT_KEY, text);
    ToolTipManager ttm = ToolTipManager.sharedInstance();
    if (text == null)
      ttm.unregisterComponent(this);
    else if (old == null)
      ttm.registerComponent(this);
  }

  /**
   * Returns the current tooltip text for this component, or <code>null</code>
   * if none has been set.
   *
   * @return the current tooltip text for this component, or <code>null</code>
   *         if none has been set
   *
   * @see #setToolTipText
   * @see #getToolTipText(MouseEvent)
   */
  public String getToolTipText()
  {
    return (String) getClientProperty(TOOL_TIP_TEXT_KEY);
  }

  /**
   * Returns the tooltip text for this component for a particular mouse
   * event. This can be used to support context sensitive tooltips that can
   * change with the mouse location. By default this returns the static
   * tooltip text returned by {@link #getToolTipText()}.
   *
   * @param event the mouse event which triggered the tooltip
   *
   * @return the tooltip text for this component for a particular mouse
   *         event
   *
   * @see #setToolTipText
   * @see #getToolTipText()
   */
  public String getToolTipText(MouseEvent event)
  {
    return getToolTipText();
  }
  
  /**
   * Returns the flag that controls whether or not the component inherits its
   * parent's popup menu when no popup menu is specified for this component.
   * 
   * @return A boolean.
   * 
   * @since 1.5
   * 
   * @see #setInheritsPopupMenu(boolean)
   */
  public boolean getInheritsPopupMenu()
  {
    return inheritsPopupMenu; 
  }
  
  /**
   * Sets the flag that controls whether or not the component inherits its
   * parent's popup menu when no popup menu is specified for this component.
   * This is a bound property with the property name 'inheritsPopupMenu'.
   * 
   * @param inherit  the new flag value.
   * 
   * @since 1.5
   * 
   * @see #getInheritsPopupMenu()
   */
  public void setInheritsPopupMenu(boolean inherit)
  {
    if (inheritsPopupMenu != inherit)
      {
        inheritsPopupMenu = inherit;
        this.firePropertyChange("inheritsPopupMenu", ! inherit, inherit);
      }
  }
  
  /**
   * Returns the popup menu for this component.  If the popup menu is 
   * <code>null</code> AND the {@link #getInheritsPopupMenu()} method returns
   * <code>true</code>, this method will return the parent's popup menu (if it
   * has one).
   * 
   * @return The popup menu (possibly <code>null</code>.
   * 
   * @since 1.5
   * 
   * @see #setComponentPopupMenu(JPopupMenu)
   * @see #getInheritsPopupMenu()
   */
  public JPopupMenu getComponentPopupMenu()
  {
    if (componentPopupMenu == null && getInheritsPopupMenu())
      {
        Container parent = getParent(); 
        if (parent instanceof JComponent)
          return ((JComponent) parent).getComponentPopupMenu();
        else
          return null;
      }
    else
      return componentPopupMenu;
  }

  /**
   * Sets the popup menu for this component (this is a bound property with 
   * the property name 'componentPopupMenu').
   * 
   * @param popup  the popup menu (<code>null</code> permitted).
   *
   * @since 1.5
   * 
   * @see #getComponentPopupMenu()
   */
  public void setComponentPopupMenu(JPopupMenu popup)
  {
    if (componentPopupMenu != popup)
      {
        JPopupMenu old = componentPopupMenu;
        componentPopupMenu = popup;
        firePropertyChange("componentPopupMenu", old, popup);
      }
  }
  
  /**
   * Return the top level ancestral container (usually a {@link
   * java.awt.Window} or {@link java.applet.Applet}) which this component is
   * contained within, or <code>null</code> if no ancestors exist.
   *
   * @return The top level container, if it exists
   */
  public Container getTopLevelAncestor()
  {
    Container c = getParent();
    for (Container peek = c; peek != null; peek = peek.getParent())
      c = peek;
    return c;
  }

  /**
   * Compute the component's visible rectangle, which is defined
   * recursively as either the component's bounds, if it has no parent, or
   * the intersection of the component's bounds with the visible rectangle
   * of its parent.
   *
   * @param rect The return value slot to place the visible rectangle in
   */
  public void computeVisibleRect(Rectangle rect)
  {
    Component c = getParent();
    if (c != null && c instanceof JComponent)
      {
        ((JComponent) c).computeVisibleRect(rect);
        rect.translate(-getX(), -getY());
        rect = SwingUtilities.computeIntersection(0, 0, getWidth(),
                                                  getHeight(), rect);
      }
    else
      rect.setRect(0, 0, getWidth(), getHeight());
  }

  /**
   * Return the component's visible rectangle in a new {@link Rectangle},
   * rather than via a return slot.
   *
   * @return the component's visible rectangle
   *
   * @see #computeVisibleRect(Rectangle)
   */
  public Rectangle getVisibleRect()
  {
    Rectangle r = new Rectangle();
    computeVisibleRect(r);
    return r;
  }

  /**
   * <p>Requests that this component receive input focus, giving window
   * focus to the top level ancestor of this component. Only works on
   * displayable, focusable, visible components.</p>
   *
   * <p>This method should not be called by clients; it is intended for
   * focus implementations. Use {@link Component#requestFocus()} instead.</p>
   *
   * @see Component#requestFocus()
   */
  public void grabFocus()
  {
    requestFocus();
  }

  /**
   * Get the value of the {@link #doubleBuffered} property.
   *
   * @return The property's current value
   */
  public boolean isDoubleBuffered()
  {
    return doubleBuffered;
  }

  /**
   * Return <code>true</code> if the provided component has no native peer;
   * in other words, if it is a "lightweight component".
   *
   * @param c The component to test for lightweight-ness
   *
   * @return Whether or not the component is lightweight
   */
  public static boolean isLightweightComponent(Component c)
  {
    return c.getPeer() instanceof LightweightPeer;
  }

  /**
   * Return <code>true</code> if you wish this component to manage its own
   * focus. In particular: if you want this component to be sent
   * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not
   * have its children considered as focus transfer targets. If
   * <code>true</code>, focus traversal around this component changes to
   * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>.
   *
   * @return <code>true</code> if you want this component to manage its own
   *     focus, otherwise (by default) <code>false</code>
   *
   * @deprecated 1.4 Use {@link Component#setFocusTraversalKeys(int, Set)} and
   *     {@link Container#setFocusCycleRoot(boolean)} instead
   */
  public boolean isManagingFocus()
  {
    return false;
  }

  /**
   * Return the current value of the {@link #opaque} property. 
   *
   * @return The current property value
   */
  public boolean isOpaque()
  {
    return opaque;
  }

  /**
   * Return <code>true</code> if the component can guarantee that none of its
   * children will overlap in Z-order. This is a hint to the painting system.
   * The default is to return <code>true</code>, but some components such as
   * {@link JLayeredPane} should override this to return <code>false</code>.
   *
   * @return Whether the component tiles its children
   */
  public boolean isOptimizedDrawingEnabled()
  {
    return true;
  }

  /**
   * Return <code>true</code> if this component is currently painting a tile,
   * this means that paint() is called again on another child component. This
   * method returns <code>false</code> if this component does not paint a tile
   * or if the last tile is currently painted.
   *
   * @return whether the component is painting a tile
   */
  public boolean isPaintingTile()
  {
    return paintingTile;
  }

  /**
   * Get the value of the {@link #requestFocusEnabled} property.
   *
   * @return The current value of the property
   */
  public boolean isRequestFocusEnabled()
  {
    return requestFocusEnabled;
  }

  /**
   * Return <code>true</code> if this component is a validation root; this
   * will cause calls to {@link #invalidate()} in this component's children
   * to be "captured" at this component, and not propagate to its parents.
   * For most components this should return <code>false</code>, but some
   * components such as {@link JViewport} will want to return
   * <code>true</code>.
   *
   * @return Whether this component is a validation root
   */
  public boolean isValidateRoot()
  {
    return false;
  }

  /**
   * <p>Paint the component. This is a delicate process, and should only be
   * called from the repaint thread, under control of the {@link
   * RepaintManager}. Client code should usually call {@link #repaint()} to
   * trigger painting.</p>
   *
   * <p>The body of the <code>paint</code> call involves calling {@link
   * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in
   * order. If you want to customize painting behavior, you should override
   * one of these methods rather than <code>paint</code>.</p>
   *
   * <p>For more details on the painting sequence, see <a
   * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">
   * this article</a>.</p>
   *
   * @param g The graphics context to paint with
   *
   * @see #paintImmediately(Rectangle)
   */
  public void paint(Graphics g)
  {
    RepaintManager rm = RepaintManager.currentManager(this);
    // We do a little stunt act here to switch on double buffering if it's
    // not already on. If we are not already doublebuffered, then we jump
    // into the method paintDoubleBuffered, which turns on the double buffer
    // and then calls paint(g) again. In the second call we go into the else
    // branch of this if statement and actually paint things to the double
    // buffer. When this method completes, the call stack unwinds back to
    // paintDoubleBuffered, where the buffer contents is finally drawn to the
    // screen.
    if (!paintingDoubleBuffered && isDoubleBuffered()
        && rm.isDoubleBufferingEnabled())
      {
        Rectangle clip = g.getClipBounds();
        paintDoubleBuffered(clip.x, clip.y, clip.width, clip.height);
      }
    else
      {
        if (getClientProperty("bufferedDragging") != null
            && dragBuffer == null)
          {
            initializeDragBuffer();
          }
        else if (getClientProperty("bufferedDragging") == null
            && dragBuffer != null)
          {
            dragBuffer = null;
          }

        Rectangle clip = g.getClipBounds();
        int clipX, clipY, clipW, clipH;
        if (clip == null)
          {
            clipX = 0;
            clipY = 0;
            clipW = getWidth();
            clipH = getHeight();
          }
        else
          {
            clipX = clip.x;
            clipY = clip.y;
            clipW = clip.width;
            clipH = clip.height;
          }
        if (dragBuffer != null && dragBufferInitialized)
          {
            g.drawImage(dragBuffer, 0, 0, this);
          }
        else
          {
            Graphics g2 = getComponentGraphics(g);
            if (! isOccupiedByChild(clipX, clipY, clipW, clipH))
              {
                paintComponent(g2);
                paintBorder(g2);
              }
            paintChildren(g2);
          }
      }
  }

  /**
   * Determines if a region of this component is completely occupied by
   * an opaque child component, in which case we don't need to bother
   * painting this component at all.
   *
   * @param x the area, x coordinate
   * @param y the area, y coordinate
   * @param w the area, width
   * @param h the area, height
   *
   * @return <code>true</code> if the specified area is completely covered
   *         by a child component, <code>false</code> otherwise
   */
  private boolean isOccupiedByChild(int x, int y, int w, int h)
  {
    boolean occupied = false;
    int count = getComponentCount();
    for (int i = 0; i < count; i++)
      {
        Component child = getComponent(i);
        int cx = child.getX();
        int cy = child.getY();
        int cw = child.getWidth();
        int ch = child.getHeight();
        if (child.isVisible() && x >= cx && x + w <= cx + cw && y >= cy
            && y + h <= cy + ch)
          {
            occupied = child.isOpaque();
            break;
          }
      }
    return occupied;
  }

  /**
   * Initializes the drag buffer by creating a new image and painting this
   * component into it.
   */
  private void initializeDragBuffer()
  {
    dragBufferInitialized = false;
    // Allocate new dragBuffer if the current one is too small.
    if (dragBuffer == null || dragBuffer.getWidth(this) < getWidth()
        || dragBuffer.getHeight(this) < getHeight())
      {
        dragBuffer = createImage(getWidth(), getHeight());
      }
    Graphics g = dragBuffer.getGraphics();
    paint(g);
    g.dispose();
    dragBufferInitialized = true;
  }

  /**
   * Paint the component's border. This usually means calling {@link
   * Border#paintBorder} on the {@link #border} property, if it is
   * non-<code>null</code>. You may override this if you wish to customize
   * border painting behavior. The border is painted after the component's
   * body, but before the component's children.
   *
   * @param g The graphics context with which to paint the border
   *
   * @see #paint
   * @see #paintChildren
   * @see #paintComponent
   */
  protected void paintBorder(Graphics g)
  {
    if (getBorder() != null)
      getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight());
  }

  /**
   * Paint the component's children. This usually means calling {@link
   * Container#paint}, which recursively calls {@link #paint} on any of the
   * component's children, with appropriate changes to coordinate space and
   * clipping region. You may override this if you wish to customize
   * children painting behavior. The children are painted after the
   * component's body and border.
   *
   * @param g The graphics context with which to paint the children
   *
   * @see #paint
   * @see #paintBorder
   * @see #paintComponent
   */
  protected void paintChildren(Graphics g)
  {
    if (getComponentCount() > 0)
      {
        // Need to lock the tree to avoid problems with AWT and concurrency.
        synchronized (getTreeLock())
          {
            // Fast forward to the child to paint, if set by
            // paintImmediately2()
            int i = getComponentCount() - 1;
            if (paintChild != null && paintChild.isOpaque())
              {
                for (; i >= 0 && getComponent(i) != paintChild; i--)
                  ;
              }
            for (; i >= 0; i--)
              {
                Component child = getComponent(i);
                if (child != null && child.isLightweight()
                    && child.isVisible())
                  {
                    int cx = child.getX();
                    int cy = child.getY();
                    int cw = child.getWidth();
                    int ch = child.getHeight();
                    if (g.hitClip(cx, cy, cw, ch))
                      {
                        if ((! isOptimizedDrawingEnabled()) && i > 0)
                          {
                            // Check if the child is completely obscured.
                            Rectangle clip = g.getClipBounds(); // A copy.
                            SwingUtilities.computeIntersection(cx, cy, cw, ch,
                                                               clip);
                            if (isCompletelyObscured(i, clip.x, clip.y,
                                                     clip.width, clip.height))
                              continue; // Continues the for-loop.
                          }
                        Graphics cg = g.create(cx, cy, cw, ch);
                        cg.setColor(child.getForeground());
                        cg.setFont(child.getFont());
                        try
                          {
                            child.paint(cg);
                          }
                        finally
                          {
                            cg.dispose();
                          }
                      }
                  }
              }
          }
      }
  }

  /**
   * Determines if a region of a child component is completely obscured by one
   * of its siblings.
   *
   * @param index the index of the child component
   * @param x the region to check, x coordinate
   * @param y the region to check, y coordinate
   * @param w the region to check, width
   * @param h the region to check, height
   *
   * @return <code>true</code> if the region is completely obscured by a
   *         sibling, <code>false</code> otherwise
   */
  private boolean isCompletelyObscured(int index, int x, int y, int w, int h)
  {
    boolean obscured = false;
    for (int i = index - 1; i >= 0 && obscured == false; i--)
      {
        Component sib = getComponent(i);
        if (sib.isVisible())
          {
            Rectangle sibRect = sib.getBounds(rectCache);
            if (sib.isOpaque() && x >= sibRect.x
                && (x + w) <= (sibRect.x + sibRect.width)
                && y >= sibRect.y
                && (y + h) <= (sibRect.y + sibRect.height))
              {
                obscured = true;
              }
          }
      }
    return obscured;
  }

  /**
   * Checks if a component/rectangle is partially obscured by one of its
   * siblings.
   * Note that this doesn't check for completely obscured, this is
   * done by isCompletelyObscured() and should probably also be checked.
   *
   * @param i the component index from which to start searching
   * @param x the x coordinate of the rectangle to check
   * @param y the y coordinate of the rectangle to check
   * @param w the width of the rectangle to check
   * @param h the height of the rectangle to check
   *
   * @return <code>true</code> if the rectangle is partially obscured
   */
  private boolean isPartiallyObscured(int i, int x, int y, int w, int h)
  {
    boolean obscured = false;
    for (int j = i - 1; j >= 0 && ! obscured; j--)
      {
        Component sibl = getComponent(j);
        if (sibl.isVisible())
          {
            Rectangle rect = sibl.getBounds(rectCache);
            if (!(x + w <= rect.x)
                  || (y + h <= rect.y)
                  || (x >= rect.x + rect.width)
                  || (y >= rect.y + rect.height))
              obscured = true;
          }
      }
    return obscured;
  }

  /**
   * Paint the component's body. This usually means calling {@link
   * ComponentUI#update} on the {@link #ui} property of the component, if
   * it is non-<code>null</code>. You may override this if you wish to
   * customize the component's body-painting behavior. The component's body
   * is painted first, before the border and children.
   *
   * @param g The graphics context with which to paint the body
   *
   * @see #paint
   * @see #paintBorder
   * @see #paintChildren
   */
  protected void paintComponent(Graphics g)
  {
    if (ui != null)
      {
        Graphics g2 = g.create();
        try
          {
            ui.update(g2, this);
          }
        finally
          {
            g2.dispose();
          }
      }
  }

  /**
   * A variant of {@link #paintImmediately(Rectangle)} which takes
   * integer parameters.
   *
   * @param x The left x coordinate of the dirty region
   * @param y The top y coordinate of the dirty region
   * @param w The width of the dirty region
   * @param h The height of the dirty region
   */
  public void paintImmediately(int x, int y, int w, int h)
  {
    // Find opaque parent and call paintImmediately2() on it.
    if (isShowing())
      {
        Component c = this;
        Component p;
        while (c != null && ! c.isOpaque())
          {
            p = c.getParent();
            if (p != null)
              {
                x += c.getX();
                y += c.getY();
                c = p;
              }
          }
        if (c instanceof JComponent)
          ((JComponent) c).paintImmediately2(x, y, w, h);
        else
          c.repaint(x, y, w, h);
      }
  }

  /**
   * Transform the provided dirty rectangle for this component into the
   * appropriate ancestral {@link JRootPane} and call {@link #paint} on
   * that root pane. This method is called from the {@link RepaintManager}
   * and should always be called within the painting thread.
   *
   * <p>This method will acquire a double buffer from the {@link
   * RepaintManager} if the component's {@link #doubleBuffered} property is
   * <code>true</code> and the <code>paint</code> call is the
   * <em>first</em> recursive <code>paint</code> call inside swing.</p>
   *
   * <p>The method will also modify the provided {@link Graphics} context
   * via the {@link #getComponentGraphics} method. If you want to customize
   * the graphics object used for painting, you should override that method
   * rather than <code>paint</code>.</p>
   *
   * @param r The dirty rectangle to paint
   */
  public void paintImmediately(Rectangle r)
  {
    paintImmediately(r.x, r.y, r.width, r.height);
  }

  /**
   * Performs the actual work of paintImmediatly on the repaint root.
   *
   * @param x the area to be repainted, X coordinate
   * @param y the area to be repainted, Y coordinate
   */
  void paintImmediately2(int x, int y, int w, int h)
  {
    // Optimization for components that are always painted on top.
    boolean onTop = onTop() && isOpaque();

    // Fetch the RepaintManager.
    RepaintManager rm = RepaintManager.currentManager(this);

    // The painting clip;
    int paintX = x;
    int paintY = y;
    int paintW = w;
    int paintH = h;

    // If we should paint buffered or not.
    boolean haveBuffer = false;

    // The component that is finally triggered for painting.
    JComponent paintRoot = this;
    
    // Stores the component and all its parents. This will be used to limit
    // the actually painted components in paintChildren by setting
    // the field paintChild.
    int pIndex = -1;
    int pCount = 0;
    ArrayList components = new ArrayList();

    // Offset to subtract from the paintRoot rectangle when painting.
    int offsX = 0;
    int offsY = 0;

    // The current component and its child.
    Component child;
    Container c;

    // Find appropriate paint root.
    for (c = this, child = null;
         c != null && ! (c instanceof Window) && ! (c instanceof Applet);
         child = c, c = c.getParent())
      {
        JComponent jc = c instanceof JComponent ? (JComponent) c : null;
        components.add(c);
        if (! onTop && jc != null  && ! jc.isOptimizedDrawingEnabled())
          {
            // Indicates whether we reset the paint root to be the current
            // component.
            boolean updatePaintRoot = false;

            // Check obscured state of the child.
            // Generally, we have 3 cases here:
            // 1. Not obscured. No need to paint from the parent.
            // 2. Partially obscured. Paint from the parent.
            // 3. Completely obscured. No need to paint anything.
            if (c != this)
              {
                if (jc.isPaintRoot())
                  updatePaintRoot = true;
                else
                  {
                    int count = c.getComponentCount();
                    int i = 0;
                    for (; i < count && c.getComponent(i) != child; i++)
                      ;

                    if (jc.isCompletelyObscured(i, paintX, paintY, paintW,
                                                paintH))
                      return; // No need to paint anything.
                    else if (jc.isPartiallyObscured(i, paintX, paintY, paintW,
                                                    paintH))
                      updatePaintRoot = true;
                      
                  }
              }
            if (updatePaintRoot)
              {
                // Paint from parent.
                paintRoot = jc;
                pIndex = pCount;
                offsX = 0;
                offsY = 0;
                haveBuffer = false;
              }
          }
        pCount++;
        // Check if component is double buffered.
        if (rm.isDoubleBufferingEnabled() && jc != null
            && jc.isDoubleBuffered())
          {
            haveBuffer = true;
          }

        // Clip the paint region with the parent.
        if (! onTop)
          {
            paintX = Math.max(0, paintX);
            paintY = Math.max(0, paintY);
            paintW = Math.min(c.getWidth(), paintW + paintX) - paintX;
            paintH = Math.min(c.getHeight(), paintH + paintY) - paintY;
            int dx = c.getX();
            int dy = c.getY();
            paintX += dx;
            paintY += dy;
            offsX += dx;
            offsY += dy;
          }
      }
    if (c != null && c.getPeer() != null && paintW > 0 && paintH > 0)
      {
        isRepainting = true;
        paintX -= offsX;
        paintY -= offsY;

        // Set the painting path so that paintChildren paints only what we
        // want.
        if (paintRoot != this)
          {
            for (int i = pIndex; i > 0; i--)
              {
                Component paintParent = (Component) components.get(i);
                if (paintParent instanceof JComponent)
                  ((JComponent) paintParent).paintChild =
                    (Component) components.get(i - 1);
              }
          }

        // Actually trigger painting.
        if (haveBuffer)
          paintRoot.paintDoubleBuffered(paintX, paintY, paintW, paintH);
        else
          {
            Graphics g = paintRoot.getGraphics();
            try
              {
                g.setClip(paintX, paintY, paintW, paintH);
                paintRoot.paint(g);
              }
            finally
              {
                g.dispose();
              }
          }

        // Reset the painting path.
        if (paintRoot != this)
          {
            for (int i = pIndex; i > 0; i--)
              {
                Component paintParent = (Component) components.get(i);
                if (paintParent instanceof JComponent)
                  ((JComponent) paintParent).paintChild = null;
              }
          }

        isRepainting = false;
      }
  }

  /**
   * Returns <code>true</code> if the component is guaranteed to be painted
   * on top of others. This returns false by default and is overridden by
   * components like JMenuItem, JPopupMenu and JToolTip to return true for
   * added efficiency.
   *
   * @return <code>true</code> if the component is guaranteed to be painted
   *         on top of others
   */
  boolean onTop()
  {
    return false;
  }

  /**
   * This returns true when a component needs to force itself as a paint
   * origin. This is used for example in JViewport to make sure that it
   * gets to update its backbuffer.
   *
   * @return true when a component needs to force itself as a paint
   *         origin
   */
  boolean isPaintRoot()
  {
    return false;
  }

  /**
   * Performs double buffered repainting.
   */
  private void paintDoubleBuffered(int x, int y, int w, int h)
  {
    RepaintManager rm = RepaintManager.currentManager(this);

    // Paint on the offscreen buffer.
    Component root = SwingUtilities.getRoot(this);
    Image buffer = rm.getVolatileOffscreenBuffer(this, root.getWidth(),
                                                 root.getHeight());

    // The volatile offscreen buffer may be null when that's not supported
    // by the AWT backend. Fall back to normal backbuffer in this case.
    if (buffer == null)
      buffer = rm.getOffscreenBuffer(this, root.getWidth(), root.getHeight());

    //Rectangle targetClip = SwingUtilities.convertRectangle(this, r, root);
    Graphics g2 = buffer.getGraphics();
    clipAndTranslateGraphics(root, this, g2);
    g2.clipRect(x, y, w, h);
    g2 = getComponentGraphics(g2);
    paintingDoubleBuffered = true;
    try
      {
        if (isRepainting) // Called from paintImmediately, go through paint().
          paint(g2);
        else // Called from paint() (AWT refresh), don't call it again.
          {
            paintComponent(g2);
            paintBorder(g2);
            paintChildren(g2);
          }
      }
    finally
      {
        paintingDoubleBuffered = false;
        g2.dispose();
      }

    // Paint the buffer contents on screen.
    rm.commitBuffer(this, x, y, w, h);
  }

  /**
   * Clips and translates the Graphics instance for painting on the double
   * buffer. This has to be done, so that it reflects the component clip of the
   * target component.
   *
   * @param root the root component (top-level container usually)
   * @param target the component to be painted
   * @param g the Graphics instance
   */
  private void clipAndTranslateGraphics(Component root, Component target,
                                        Graphics g)
  {
    Component parent = target;
    int deltaX = 0;
    int deltaY = 0;
    while (parent != root)
      {
        deltaX += parent.getX();
        deltaY += parent.getY();
        parent = parent.getParent();
      }
    g.translate(deltaX, deltaY);
    g.clipRect(0, 0, target.getWidth(), target.getHeight());
  }

  /**
   * Performs normal painting without double buffering.
   *
   * @param r the area that should be repainted
   */
  void paintSimple(Rectangle r)
  {
    Graphics g = getGraphics();
    Graphics g2 = getComponentGraphics(g);
    g2.setClip(r);
    paint(g2);
    g2.dispose();
    if (g != g2)
      g.dispose();
  }

  /**
   * Return a string representation for this component, for use in
   * debugging.
   *
   * @return A string describing this component.
   */
  protected String paramString()
  {
    CPStringBuilder sb = new CPStringBuilder();
    sb.append(super.paramString());
    sb.append(",alignmentX=").append(getAlignmentX());
    sb.append(",alignmentY=").append(getAlignmentY());
    sb.append(",border=");
    if (getBorder() != null)
      sb.append(getBorder());
    sb.append(",maximumSize=");
    if (getMaximumSize() != null)
      sb.append(getMaximumSize());
    sb.append(",minimumSize=");
    if (getMinimumSize() != null)
      sb.append(getMinimumSize());
    sb.append(",preferredSize=");
    if (getPreferredSize() != null)
      sb.append(getPreferredSize());
    return sb.toString();
  }

  /**
   * A variant of {@link
   * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which
   * provides <code>null</code> for the command name.
   * 
   * @param act  the action listener to notify when the keystroke occurs.
   * @param stroke  the key stroke.
   * @param cond  the condition (one of {@link #WHEN_FOCUSED}, 
   *     {@link #WHEN_IN_FOCUSED_WINDOW} and 
   *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}).
   */
  public void registerKeyboardAction(ActionListener act,
                                     KeyStroke stroke, 
                                     int cond)
  {
    registerKeyboardAction(act, null, stroke, cond);
  }

  /* 
   * There is some charmingly undocumented behavior sun seems to be using
   * to simulate the old register/unregister keyboard binding API. It's not
   * clear to me why this matters, but we shall endeavour to follow suit.
   *
   * Two main thing seem to be happening when you do registerKeyboardAction():
   * 
   *  - no actionMap() entry gets created, just an entry in inputMap()
   *
   *  - the inputMap() entry is a proxy class which invokes the the
   *  binding's actionListener as a target, and which clobbers the command
   *  name sent in the ActionEvent, providing the binding command name
   *  instead.
   *
   * This much you can work out just by asking the input and action maps
   * what they contain after making bindings, and watching the event which
   * gets delivered to the recipient. Beyond that, it seems to be a
   * sun-private solution so I will only immitate it as much as it matters
   * to external observers.
   */
  private static class ActionListenerProxy
    extends AbstractAction
  {
    ActionListener target;
    String bindingCommandName;

    public ActionListenerProxy(ActionListener li, 
                               String cmd)
    {
      target = li;
      bindingCommandName = cmd;
    }

    public void actionPerformed(ActionEvent e)
    {
      ActionEvent derivedEvent = new ActionEvent(e.getSource(),
                                                 e.getID(),
                                                 bindingCommandName,
                                                 e.getModifiers());
      target.actionPerformed(derivedEvent);
    }
  }

  
  /**
   * An obsolete method to register a keyboard action on this component.
   * You should use <code>getInputMap</code> and <code>getActionMap</code>
   * to fetch mapping tables from keystrokes to commands, and commands to
   * actions, respectively, and modify those mappings directly.
   *
   * @param act The action to be registered
   * @param cmd The command to deliver in the delivered {@link
   *     java.awt.event.ActionEvent}
   * @param stroke The keystroke to register on
   * @param cond One of the values {@link #UNDEFINED_CONDITION},
   *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or
   *     {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must
   *     be met for the action to be fired
   *
   * @see #unregisterKeyboardAction
   * @see #getConditionForKeyStroke
   * @see #resetKeyboardActions
   */
  public void registerKeyboardAction(ActionListener act, 
                                     String cmd,
                                     KeyStroke stroke, 
                                     int cond)
  {
    ActionListenerProxy proxy = new ActionListenerProxy(act, cmd);
    getInputMap(cond).put(stroke, proxy);
    getActionMap().put(proxy, proxy);
  }

  /**
   * Sets the input map for the given condition.
   * 
   * @param condition  the condition (one of {@link #WHEN_FOCUSED}, 
   *     {@link #WHEN_IN_FOCUSED_WINDOW} and 
   *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}).
   * @param map  the map.
   * 
   * @throws IllegalArgumentException if <code>condition</code> is not one of
   *     the specified values.
   */
  public final void setInputMap(int condition, InputMap map)
  {
    enableEvents(AWTEvent.KEY_EVENT_MASK);
    switch (condition)
      {
      case WHEN_FOCUSED:
        inputMap_whenFocused = map;
        break;

      case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
        inputMap_whenAncestorOfFocused = map;
        break;

      case WHEN_IN_FOCUSED_WINDOW:
        if (map != null && !(map instanceof ComponentInputMap))
            throw new 
              IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW " + 
                                       "InputMap must be a ComponentInputMap");
        inputMap_whenInFocusedWindow = (ComponentInputMap)map;
        break;
        
      case UNDEFINED_CONDITION:
      default:
        throw new IllegalArgumentException();
      }
  }

  /**
   * Returns the input map associated with this component for the given
   * state/condition.
   * 
   * @param condition  the state (one of {@link #WHEN_FOCUSED}, 
   *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT} and 
   *     {@link #WHEN_IN_FOCUSED_WINDOW}).
   * 
   * @return The input map.
   * @throws IllegalArgumentException if <code>condition</code> is not one of 
   *             the specified values.
   * @since 1.3
   */
  public final InputMap getInputMap(int condition)
  {
    enableEvents(AWTEvent.KEY_EVENT_MASK);
    switch (condition)
      {
      case WHEN_FOCUSED:
        if (inputMap_whenFocused == null)
          inputMap_whenFocused = new InputMap();
        return inputMap_whenFocused;

      case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
        if (inputMap_whenAncestorOfFocused == null)
          inputMap_whenAncestorOfFocused = new InputMap();
        return inputMap_whenAncestorOfFocused;

      case WHEN_IN_FOCUSED_WINDOW:
        if (inputMap_whenInFocusedWindow == null)
          inputMap_whenInFocusedWindow = new ComponentInputMap(this);
        return inputMap_whenInFocusedWindow;

      case UNDEFINED_CONDITION:
      default:
        throw new IllegalArgumentException("Invalid 'condition' argument: " 
                                           + condition);
      }
  }

  /**
   * Returns the input map associated with this component for the 
   * {@link #WHEN_FOCUSED} state.
   * 
   * @return The input map.
   * 
   * @since 1.3
   * @see #getInputMap(int)
   */
  public final InputMap getInputMap()
  {
    return getInputMap(WHEN_FOCUSED);
  }

  public final ActionMap getActionMap()
  {
    if (actionMap == null)
      actionMap = new ActionMap();
    return actionMap;
  }

  public final void setActionMap(ActionMap map)
  {
    actionMap = map;
  }

  /**
   * Return the condition that determines whether a registered action
   * occurs in response to the specified keystroke.
   *
   * As of 1.3 KeyStrokes can be registered with multiple simultaneous
   * conditions.
   *
   * @param ks The keystroke to return the condition of
   *
   * @return One of the values {@link #UNDEFINED_CONDITION}, {@link
   *     #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link
   *     #WHEN_IN_FOCUSED_WINDOW}
   *
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)   
   * @see #unregisterKeyboardAction   
   * @see #resetKeyboardActions
   */
  public int getConditionForKeyStroke(KeyStroke ks)
  {
    if (inputMap_whenFocused != null 
        && inputMap_whenFocused.get(ks) != null)
      return WHEN_FOCUSED;
    else if (inputMap_whenAncestorOfFocused != null 
             && inputMap_whenAncestorOfFocused.get(ks) != null)
      return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
    else if (inputMap_whenInFocusedWindow != null 
             && inputMap_whenInFocusedWindow.get(ks) != null)
      return WHEN_IN_FOCUSED_WINDOW;
    else
      return UNDEFINED_CONDITION;
  }

  /**
   * Get the ActionListener (typically an {@link Action} object) which is
   * associated with a particular keystroke. 
   *
   * @param ks The keystroke to retrieve the action of
   *
   * @return The action associated with the specified keystroke
   */
  public ActionListener getActionForKeyStroke(KeyStroke ks)
  {
    Object key = getInputMap(JComponent.WHEN_FOCUSED).get(ks);
    if (key == null)
      key = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).get(ks);
    if (key == null)
      key = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).get(ks);
    if (key != null)
      {
        if (key instanceof ActionListenerProxy)
          return ((ActionListenerProxy) key).target;
        else
          return getActionMap().get(key);
      }
    return null;
  }

  /**
   * A hook for subclasses which want to customize event processing.
   */
  protected void processComponentKeyEvent(KeyEvent e)
  {
    // This method does nothing, it is meant to be overridden by subclasses.
  }

  /**
   * Override the default key dispatch system from Component to hook into
   * the swing {@link InputMap} / {@link ActionMap} system.
   *
   * See <a
   * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">
   * this report</a> for more details, it's somewhat complex.
   */
  protected void processKeyEvent(KeyEvent e)
  {
    // let the AWT event processing send KeyEvents to registered listeners
    super.processKeyEvent(e);
    processComponentKeyEvent(e);

    if (e.isConsumed())
      return;

    // Input maps are checked in this order:
    // 1. The focused component's WHEN_FOCUSED map is checked.
    // 2. The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT map.
    // 3. The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps of the focused
    //    component's parent, then its parent's parent, and so on.
    //    Note: Input maps for disabled components are skipped.
    // 4. The WHEN_IN_FOCUSED_WINDOW maps of all the enabled components in
    //    the focused window are searched.
    
    KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
    boolean pressed = e.getID() == KeyEvent.KEY_PRESSED;
    
    if (processKeyBinding(keyStroke, e, WHEN_FOCUSED, pressed))
      {
        // This is step 1 from above comment.
        e.consume();
        return;
      }
    else if (processKeyBinding
             (keyStroke, e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
      {
        // This is step 2 from above comment.
        e.consume();
        return;
      }
    
    // This is step 3 from above comment.
    Container current = getParent();    
    while (current != null)
      { 
        // If current is a JComponent, see if it handles the event in its
        // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps.
        if ((current instanceof JComponent) && 
            ((JComponent)current).processKeyBinding 
            (keyStroke, e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
          {
            e.consume();
            return;
          }     
        
        // Stop when we've tried a top-level container and it didn't handle it
        if (current instanceof Window || current instanceof Applet)
          break;        
        
        // Move up the hierarchy
        current = current.getParent();
      }
    
    // Current being null means the JComponent does not currently have a
    // top-level ancestor, in which case we don't need to check 
    // WHEN_IN_FOCUSED_WINDOW bindings.
    if (current == null || e.isConsumed())
      return;
    
    // This is step 4 from above comment.  KeyboardManager maintains mappings
    // related to WHEN_IN_FOCUSED_WINDOW bindings so that we don't have to 
    // traverse the containment hierarchy each time.
    if (KeyboardManager.getManager().processKeyStroke(current, keyStroke, e))
      e.consume();
  }

  protected boolean processKeyBinding(KeyStroke ks,
                                      KeyEvent e,
                                      int condition,
                                      boolean pressed)
  {
    if (isEnabled())
      {
        Action act = null;
        Object cmd = null;
        InputMap map = getInputMap(condition);
        if (map != null)
          {
            cmd = map.get(ks);
            if (cmd != null)
              {
                if (cmd instanceof ActionListenerProxy)
                  act = (Action) cmd;
                else 
                  act = getActionMap().get(cmd);
              }
          }
        if (act != null && act.isEnabled())
          {
            // Need to synchronize here so we don't get in trouble with
            // our __command__ hack.
            synchronized (act)
              {
                // We add the command as value to the action, so that
                // the action can later determine the command with which it
                // was called. This is undocumented, but shouldn't affect
                // compatibility. It allows us to use only one Action instance
                // to do the work for all components of one type, instead of
                // having loads of small Actions. This effectivly saves startup
                // time of Swing.
                act.putValue("__command__", cmd);
                return SwingUtilities.notifyAction(act, ks, e, this,
                                                   e.getModifiers());
              }
          }
      }
    return false;
  }
  
  /**
   * Remove a keyboard action registry.
   *
   * @param aKeyStroke The keystroke to unregister
   *
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
   * @see #getConditionForKeyStroke
   * @see #resetKeyboardActions
   */
  public void unregisterKeyboardAction(KeyStroke aKeyStroke)
  {
    ActionMap am = getActionMap();
    // This loops through the conditions WHEN_FOCUSED,
    // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT and WHEN_IN_FOCUSED_WINDOW.
    for (int cond = 0; cond < 3; cond++)
      {
        InputMap im = getInputMap(cond);
        if (im != null)
          {
            Object action = im.get(aKeyStroke);
            if (action != null && am != null)
              am.remove(action);
            im.remove(aKeyStroke);
          }
      }
  }


  /**
   * Reset all keyboard action registries.
   *
   * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
   * @see #unregisterKeyboardAction
   * @see #getConditionForKeyStroke
   */
  public void resetKeyboardActions()
  {
    if (inputMap_whenFocused != null)
      inputMap_whenFocused.clear();
    if (inputMap_whenAncestorOfFocused != null)
      inputMap_whenAncestorOfFocused.clear();
    if (inputMap_whenInFocusedWindow != null)
      inputMap_whenInFocusedWindow.clear();
    if (actionMap != null)
      actionMap.clear();
  }

  /**
   * Mark the described region of this component as dirty in the current
   * {@link RepaintManager}. This will queue an asynchronous repaint using
   * the system painting thread in the near future.
   *
   * @param tm ignored
   * @param x coordinate of the region to mark as dirty
   * @param y coordinate of the region to mark as dirty
   * @param width dimension of the region to mark as dirty
   * @param height dimension of the region to mark as dirty
   */
  public void repaint(long tm, int x, int y, int width, int height)
  {
     RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width,
                                                        height);
  }

  /**
   * Mark the described region of this component as dirty in the current
   * {@link RepaintManager}. This will queue an asynchronous repaint using
   * the system painting thread in the near future.
   *
   * @param r The rectangle to mark as dirty
   */
  public void repaint(Rectangle r)
  {
    RepaintManager.currentManager(this).addDirtyRegion(this, r.x, r.y, r.width,
                                                       r.height);
  }

  /**
   * Request focus on the default component of this component's {@link
   * FocusTraversalPolicy}.
   *
   * @return The result of {@link #requestFocus()}
   *
   * @deprecated Use {@link #requestFocus()} on the default component provided
   *     from the {@link FocusTraversalPolicy} instead.
   */
  public boolean requestDefaultFocus()
  {
    return false;
  }

  /**
   * Queue a an invalidation and revalidation of this component, using 
   * {@link RepaintManager#addInvalidComponent}.
   */
  public void revalidate()
  {
    // As long as we don't have a parent we don't need to do any layout, since
    // this is done anyway as soon as we get connected to a parent.
    if (getParent() == null)
      return;

    if (! EventQueue.isDispatchThread())
      SwingUtilities.invokeLater(new Runnable()
        {
          public void run()
          {
            revalidate();
          }
        });
    else
      {
        invalidate();
        RepaintManager.currentManager(this).addInvalidComponent(this);
      }
  }

  /**
   * Calls <code>scrollRectToVisible</code> on the component's parent. 
   * Components which can service this call should override.
   *
   * @param r The rectangle to make visible
   */
  public void scrollRectToVisible(Rectangle r)
  {
    // Search nearest JComponent.
    int xOffs = getX();
    int yOffs = getY();
    Component p;
    for (p = getParent(); p != null && ! (p instanceof JComponent);
         p = p.getParent())
      {
        xOffs += p.getX();
        yOffs += p.getY();
      }
    if (p != null)
      {
        r.x += xOffs;
        r.y += yOffs;
        JComponent jParent = (JComponent) p;
        jParent.scrollRectToVisible(r);
        r.x -= xOffs;
        r.y -= yOffs;
      }
  }

  /**
   * Set the value of the {@link #alignmentX} property.
   *
   * @param a The new value of the property
   */
  public void setAlignmentX(float a)
  {
    if (a < 0.0F)
      alignmentX = 0.0F;
    else if (a > 1.0)
      alignmentX = 1.0F;
    else
      alignmentX = a;
  }

  /**
   * Set the value of the {@link #alignmentY} property.
   *
   * @param a The new value of the property
   */
  public void setAlignmentY(float a)
  {
    if (a < 0.0F)
      alignmentY = 0.0F;
    else if (a > 1.0)
      alignmentY = 1.0F;
    else
      alignmentY = a;
  }

  /**
   * Set the value of the {@link #autoscrolls} property.
   *
   * @param a The new value of the property
   */
  public void setAutoscrolls(boolean a)
  {
    autoscrolls = a;
    clientAutoscrollsSet = true;
  }

  /**
   * Set the value of the {@link #debugGraphicsOptions} property.
   *
   * @param debugOptions The new value of the property
   */
  public void setDebugGraphicsOptions(int debugOptions)
  {
    debugGraphicsOptions = debugOptions;
  }

  /**
   * Set the value of the {@link #doubleBuffered} property.
   *
   * @param db The new value of the property
   */
  public void setDoubleBuffered(boolean db)
  {
    doubleBuffered = db;
  }

  /**
   * Set the value of the <code>enabled</code> property.
   *
   * @param enable The new value of the property
   */
  public void setEnabled(boolean enable)
  {
    if (enable == isEnabled())
      return;
    super.setEnabled(enable);
    firePropertyChange("enabled", !enable, enable);
    repaint();
  }

  /**
   * Set the value of the <code>font</code> property.
   *
   * @param f The new value of the property
   */
  public void setFont(Font f)
  {
    if (f == getFont())
      return;
    super.setFont(f);
    revalidate();
    repaint();
  }

  /**
   * Set the value of the <code>background</code> property.
   *
   * @param bg The new value of the property
   */
  public void setBackground(Color bg)
  {
    if (bg == getBackground())
      return;
    super.setBackground(bg);
    repaint();
  }

  /**
   * Set the value of the <code>foreground</code> property.
   *
   * @param fg The new value of the property
   */
  public void setForeground(Color fg)
  {
    if (fg == getForeground())
      return;
    super.setForeground(fg);
    repaint();
  }

  /**
   * Set the specified component to be the next component in the 
   * focus cycle, overriding the {@link FocusTraversalPolicy} for
   * this component.
   *
   * @param aComponent The component to set as the next focusable
   *
   * @deprecated Use FocusTraversalPolicy instead
   */
  public void setNextFocusableComponent(Component aComponent)
  {
    Container focusRoot = this;
    if (! this.isFocusCycleRoot())
      focusRoot = getFocusCycleRootAncestor();

    FocusTraversalPolicy policy  = focusRoot.getFocusTraversalPolicy();
    if (policy instanceof CompatibilityFocusTraversalPolicy)
      {
        policy = new CompatibilityFocusTraversalPolicy(policy);
        focusRoot.setFocusTraversalPolicy(policy);
      }
    CompatibilityFocusTraversalPolicy p =
      (CompatibilityFocusTraversalPolicy) policy;

    Component old = getNextFocusableComponent();
    if (old != null)
      {
        p.removeNextFocusableComponent(this, old);
      }

    if (aComponent != null)
      {
        p.addNextFocusableComponent(this, aComponent);
      }
  }

  /**
   * Set the value of the {@link #requestFocusEnabled} property.
   *
   * @param e The new value of the property
   */
  public void setRequestFocusEnabled(boolean e)
  {
    requestFocusEnabled = e;
  }

  /**
   * Get the value of the {@link #transferHandler} property.
   *
   * @return The current value of the property
   *
   * @see #setTransferHandler
   */

  public TransferHandler getTransferHandler()
  {
    return transferHandler;
  }

  /**
   * Set the value of the {@link #transferHandler} property.
   *
   * @param newHandler The new value of the property
   *
   * @see #getTransferHandler
   */

  public void setTransferHandler(TransferHandler newHandler)
  {
    if (transferHandler == newHandler)
      return;

    TransferHandler oldHandler = transferHandler;
    transferHandler = newHandler;
    firePropertyChange("transferHandler", oldHandler, newHandler);
  }

  /**
   * Set if the component should paint all pixels withing its bounds.
   * If this property is set to false, the component expects the cleared
   * background.
   *
   * @param isOpaque if true, paint all pixels. If false, expect the clean
   * background. 
   *
   * @see ComponentUI#update
   */
  public void setOpaque(boolean isOpaque)
  {
    boolean oldOpaque = opaque;
    opaque = isOpaque;
    clientOpaqueSet = true;
    firePropertyChange("opaque", oldOpaque, opaque);
  }

  /**
   * Set the value of the visible property.
   *
   * If the value is changed, then the AncestorListeners of this component
   * and all its children (recursivly) are notified.
   *
   * @param v The new value of the property
   */
  public void setVisible(boolean v)
  {
    // No need to do anything if the actual value doesn't change.
    if (isVisible() == v)
      return;

    super.setVisible(v);

    // Notify AncestorListeners.
    if (v == true)
      fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
    else
      fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);

    Container parent = getParent();
    if (parent != null)
      parent.repaint(getX(), getY(), getWidth(), getHeight());
    revalidate();
  }

  /**
   * Call {@link #paint}. 
   * 
   * @param g The graphics context to paint into
   */
  public void update(Graphics g)
  {
    paint(g);
  }

  /**
   * Get the value of the UIClassID property. This property should be a key
   * in the {@link UIDefaults} table managed by {@link UIManager}, the
   * value of which is the name of a class to load for the component's
   * {@link #ui} property.
   *
   * @return A "symbolic" name which will map to a class to use for the
   * component's UI, such as <code>"ComponentUI"</code>
   *
   * @see #setUI
   * @see #updateUI
   */
  public String getUIClassID()
  {
    return "ComponentUI";
  }

  /**
   * Install a new UI delegate as the component's {@link #ui} property. In
   * the process, this will call {@link ComponentUI#uninstallUI} on any
   * existing value for the {@link #ui} property, and {@link
   * ComponentUI#installUI} on the new UI delegate.
   *
   * @param newUI The new UI delegate to install
   *
   * @see #updateUI
   * @see #getUIClassID
   */
  protected void setUI(ComponentUI newUI)
  {
    if (ui != null)
      ui.uninstallUI(this);

    ComponentUI oldUI = ui;
    ui = newUI;

    if (ui != null)
      ui.installUI(this);

    firePropertyChange("UI", oldUI, newUI);
    revalidate();
    repaint();
  }

  /**
   * This method should be overridden in subclasses. In JComponent, the
   * method does nothing. In subclasses, it should a UI delegate
   * (corresponding to the symbolic name returned from {@link
   * #getUIClassID}) from the {@link UIManager}, and calls {@link #setUI}
   * with the new delegate.
   */
  public void updateUI()
  {
    // Nothing to do here.
  }

  /**
   * Returns the locale used as the default for all new components.  The 
   * default value is {@link Locale#getDefault()} (that is, the platform
   * default locale).
   * 
   * @return The locale (never <code>null</code>).
   * 
   * @see #setDefaultLocale(Locale)
   */
  public static Locale getDefaultLocale()
  {
    if (defaultLocale == null)
      defaultLocale = Locale.getDefault();
    return defaultLocale;
  }
  
  /**
   * Sets the locale to be used as the default for all new components.  If this
   * is set to <code>null</code>, the {@link #getDefaultLocale()} method will
   * return the platform default locale.
   * 
   * @param l  the locale (<code>null</code> permitted).
   */
  public static void setDefaultLocale(Locale l)
  {
    defaultLocale = l;
  }
  
  /**
   * Returns the currently set input verifier for this component.
   *
   * @return the input verifier, or <code>null</code> if none
   */
  public InputVerifier getInputVerifier()
  {
    return inputVerifier;
  }

  /**
   * Sets the input verifier to use by this component.
   *
   * @param verifier the input verifier, or <code>null</code>
   */
  public void setInputVerifier(InputVerifier verifier)
  {
    InputVerifier oldVerifier = inputVerifier;
    inputVerifier = verifier;
    firePropertyChange("inputVerifier", oldVerifier, verifier);
  }

  /**
   * @since 1.3
   */
  public boolean getVerifyInputWhenFocusTarget()
  {
    return verifyInputWhenFocusTarget;
  }

  /**
   * @since 1.3
   */
  public void setVerifyInputWhenFocusTarget(boolean verifyInputWhenFocusTarget)
  {
    if (this.verifyInputWhenFocusTarget == verifyInputWhenFocusTarget)
      return;

    this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
    firePropertyChange("verifyInputWhenFocusTarget",
                       ! verifyInputWhenFocusTarget,
                       verifyInputWhenFocusTarget);
  }

  /**
   * Requests that this component gets the input focus if the
   * requestFocusEnabled property is set to <code>true</code>.
   * This also means that this component's top-level window becomes
   * the focused window, if that is not already the case.
   *
   * The preconditions that have to be met to become a focus owner is that
   * the component must be displayable, visible and focusable.
   *
   * Note that this signals only a request for becoming focused. There are
   * situations in which it is not possible to get the focus. So developers
   * should not assume that the component has the focus until it receives
   * a {@link java.awt.event.FocusEvent} with a value of
   * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
   *
   * @see Component#requestFocus()
   */
  public void requestFocus()
  {
    if (isRequestFocusEnabled())
      super.requestFocus();
  }

  /**
   * This method is overridden to make it public so that it can be used
   * by look and feel implementations.
   *
   * You should not use this method directly. Instead you are strongly
   * encouraged to call {@link #requestFocus()} or 
   * {@link #requestFocusInWindow()} instead.
   *
   * @param temporary if the focus change is temporary
   *
   * @return <code>false</code> if the focus change request will definitly
   *     fail, <code>true</code> if it will likely succeed
   *
   * @see Component#requestFocus(boolean)
   *
   * @since 1.4
   */
  public boolean requestFocus(boolean temporary)
  {
    return super.requestFocus(temporary);
  }

  /**
   * Requests that this component gets the input focus if the top level
   * window that contains this component has the focus and the
   * requestFocusEnabled property is set to <code>true</code>.
   *
   * The preconditions that have to be met to become a focus owner is that
   * the component must be displayable, visible and focusable.
   *
   * Note that this signals only a request for becoming focused. There are
   * situations in which it is not possible to get the focus. So developers
   * should not assume that the component has the focus until it receives
   * a {@link java.awt.event.FocusEvent} with a value of
   * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
   *
   * @return <code>false</code> if the focus change request will definitly
   *     fail, <code>true</code> if it will likely succeed
   *
   * @see Component#requestFocusInWindow()
   */
  public boolean requestFocusInWindow()
  {
    if (isRequestFocusEnabled())
      return super.requestFocusInWindow();
    else
      return false;
  }

  /**
   * This method is overridden to make it public so that it can be used
   * by look and feel implementations.
   *
   * You should not use this method directly. Instead you are strongly
   * encouraged to call {@link #requestFocus()} or 
   * {@link #requestFocusInWindow()} instead.
   *
   * @param temporary if the focus change is temporary
   *
   * @return <code>false</code> if the focus change request will definitly
   *     fail, <code>true</code> if it will likely succeed
   *
   * @see Component#requestFocus(boolean)
   *
   * @since 1.4
   */
  protected boolean requestFocusInWindow(boolean temporary)
  {
    return super.requestFocusInWindow(temporary);
  }

  /**
   * Receives notification if this component is added to a parent component.
   *
   * Notification is sent to all registered AncestorListeners about the
   * new parent.
   *
   * This method sets up ActionListeners for all registered KeyStrokes of
   * this component in the chain of parent components.
   *
   * A PropertyChange event is fired to indicate that the ancestor property
   * has changed.
   *
   * This method is used internally and should not be used in applications.
   */
  public void addNotify()
  {
    // Register the WHEN_IN_FOCUSED_WINDOW keyboard bindings
    // Note that here we unregister all bindings associated with
    // this component and then re-register them.  This may be more than
    // necessary if the top-level ancestor hasn't changed.  Should
    // maybe improve this.
    KeyboardManager km = KeyboardManager.getManager();
    km.clearBindingsForComp(this);
    km.registerEntireMap((ComponentInputMap)
                         this.getInputMap(WHEN_IN_FOCUSED_WINDOW));
    super.addNotify();

    // Notify AncestorListeners.
    fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);

    // fire property change event for 'ancestor'
    firePropertyChange("ancestor", null, getParent());
  }

  /**
   * Receives notification that this component no longer has a parent.
   *
   * This method sends an AncestorEvent to all registered AncestorListeners,
   * notifying them that the parent is gone.
   *
   * The keybord actions of this component are removed from the parent and
   * its ancestors.
   *
   * A PropertyChangeEvent is fired to indicate that the 'ancestor' property
   * has changed.
   *
   * This method is called before the component is actually removed from
   * its parent, so the parent is still visible through 
   * {@link Component#getParent}.
   */
  public void removeNotify()
  {
    super.removeNotify();

    KeyboardManager.getManager().clearBindingsForComp(this);
    
    // Notify ancestor listeners.
    fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);

    // fire property change event for 'ancestor'
    firePropertyChange("ancestor", getParent(), null);
  }

  /**
   * Returns <code>true</code> if the coordinates (x, y) lie within
   * the bounds of this component and <code>false</code> otherwise.
   * x and y are relative to the coordinate space of the component.
   *
   * @param x the X coordinate of the point to check
   * @param y the Y coordinate of the point to check
   *
   * @return <code>true</code> if the specified point lies within the bounds
   *     of this component, <code>false</code> otherwise
   */
  public boolean contains(int x, int y)
  {
    if (ui == null)
      return super.contains(x, y);
    else
      return ui.contains(this, x, y);
  }

  /**
   * Disables this component.
   *
   * @deprecated replaced by {@link #setEnabled(boolean)}
   */
  public void disable()
  {
    super.disable();
  }

  /**
   * Enables this component.
   *
   * @deprecated replaced by {@link #setEnabled(boolean)}
   */
  public void enable()
  {
    super.enable();
  }

  /**
   * Returns the Graphics context for this component. This can be used
   * to draw on a component.
   *
   * @return the Graphics context for this component
   */
  public Graphics getGraphics()
  {
    return super.getGraphics();
  }

  /**
   * Returns the X coordinate of the upper left corner of this component.
   * Prefer this method over {@link #getBounds} or {@link #getLocation}
   * because it does not cause any heap allocation.
   *
   * @return the X coordinate of the upper left corner of the component
   */
  public int getX()
  {
    return super.getX();
  }

  /**
   * Returns the Y coordinate of the upper left corner of this component.
   * Prefer this method over {@link #getBounds} or {@link #getLocation}
   * because it does not cause any heap allocation.
   *
   * @return the Y coordinate of the upper left corner of the component
   */
  public int getY()
  {
    return super.getY();
  }

  /**
   * Returns the height of this component. Prefer this method over
   * {@link #getBounds} or {@link #getSize} because it does not cause
   * any heap allocation.
   *
   * @return the height of the component
   */
  public int getHeight()
  {
    return super.getHeight();
  }

  /**
   * Returns the width of this component. Prefer this method over
   * {@link #getBounds} or {@link #getSize} because it does not cause
   * any heap allocation.
   *
   * @return the width of the component
   */
  public int getWidth()
  {
    return super.getWidth();
  }

  /**
   * Prints this component to the given Graphics context. A call to this
   * method results in calls to the methods {@link #printComponent},
   * {@link #printBorder} and {@link #printChildren} in this order.
   *
   * Double buffering is temporarily turned off so the painting goes directly
   * to the supplied Graphics context.
   *
   * @param g the Graphics context to print onto
   */
  public void print(Graphics g)
  {
    boolean doubleBufferState = isDoubleBuffered();
    setDoubleBuffered(false);
    printComponent(g);
    printBorder(g);
    printChildren(g);
    setDoubleBuffered(doubleBufferState);
  }

  /**
   * Prints this component to the given Graphics context. This invokes
   * {@link #print}.
   *
   * @param g the Graphics context to print onto
   */
  public void printAll(Graphics g)
  {
    print(g);
  }

  /**
   * Prints this component to the specified Graphics context. The default
   * behaviour is to invoke {@link #paintComponent}. Override this
   * if you want special behaviour for printing.
   *
   * @param g the Graphics context to print onto
   *
   * @since 1.3
   */
  protected void printComponent(Graphics g)
  {
    paintComponent(g);
  }

  /**
   * Print this component's children to the specified Graphics context.
   * The default behaviour is to invoke {@link #paintChildren}. Override this
   * if you want special behaviour for printing.
   *
   * @param g the Graphics context to print onto
   *
   * @since 1.3
   */
  protected void printChildren(Graphics g)
  {
    paintChildren(g);
  }

  /**
   * Print this component's border to the specified Graphics context.
   * The default behaviour is to invoke {@link #paintBorder}. Override this
   * if you want special behaviour for printing.
   *
   * @param g the Graphics context to print onto
   *
   * @since 1.3
   */
  protected void printBorder(Graphics g)
  {
    paintBorder(g);
  }

  /**
   * Processes mouse motion event, like dragging and moving.
   *
   * @param ev the MouseEvent describing the mouse motion
   */
  protected void processMouseMotionEvent(MouseEvent ev)
  {
    super.processMouseMotionEvent(ev);
  }

  /**
   * Moves and resizes the component.
   *
   * @param x the new horizontal location
   * @param y the new vertial location
   * @param w the new width
   * @param h the new height
   */
  public void reshape(int x, int y, int w, int h)
  {
    int oldX = getX();
    int oldY = getY();
    super.reshape(x, y, w, h);
    // Notify AncestorListeners.
    if (oldX != getX() || oldY != getY())
      fireAncestorEvent(this, AncestorEvent.ANCESTOR_MOVED);
  }

  /**
   * Fires an AncestorEvent to this component's and all of its child
   * component's AncestorListeners.
   *
   * @param ancestor the component that triggered the event
   * @param id the kind of ancestor event that should be fired
   */
  void fireAncestorEvent(JComponent ancestor, int id)
  {
    // Fire event for registered ancestor listeners of this component.
    AncestorListener[] listeners = getAncestorListeners();
    if (listeners.length > 0)
      {
        AncestorEvent ev = new AncestorEvent(this, id,
                                             ancestor, ancestor.getParent());
        for (int i = 0; i < listeners.length; i++)
          {
            switch (id)
              {
              case AncestorEvent.ANCESTOR_MOVED:
                listeners[i].ancestorMoved(ev);
                break;
              case AncestorEvent.ANCESTOR_ADDED:
                listeners[i].ancestorAdded(ev);
                break;
              case AncestorEvent.ANCESTOR_REMOVED:
                listeners[i].ancestorRemoved(ev);
                break;
              }
          }
      }
    // Dispatch event to all children.
    int numChildren = getComponentCount();
    for (int i = 0; i < numChildren; i++)
      {
        Component child = getComponent(i);
        if (! (child instanceof JComponent))
          continue;
        JComponent jc = (JComponent) child;
        jc.fireAncestorEvent(ancestor, id);
      }
  }
  
  /**
   * This is the method that gets called when the WHEN_IN_FOCUSED_WINDOW map
   * is changed.
   *
   * @param changed the JComponent associated with the WHEN_IN_FOCUSED_WINDOW
   *        map
   */
  void updateComponentInputMap(ComponentInputMap changed)
  {
    // Since you can change a component's input map via
    // setInputMap, we have to check if <code>changed</code>
    // is still in our WHEN_IN_FOCUSED_WINDOW map hierarchy
    InputMap curr = getInputMap(WHEN_IN_FOCUSED_WINDOW);
    while (curr != null && curr != changed)
      curr = curr.getParent();
    
    // If curr is null then changed is not in the hierarchy
    if (curr == null)
      return;
    
    // Now we have to update the keyboard manager's hashtable
    KeyboardManager km = KeyboardManager.getManager();
    
    // This is a poor strategy, should be improved.  We currently 
    // delete all the old bindings for the component and then register
    // the current bindings.
    km.clearBindingsForComp(changed.getComponent());
    km.registerEntireMap((ComponentInputMap) 
                         getInputMap(WHEN_IN_FOCUSED_WINDOW));
  }

  /**
   * Helper method for
   * {@link LookAndFeel#installProperty(JComponent, String, Object)}.
   * 
   * @param propertyName the name of the property
   * @param value the value of the property
   *
   * @throws IllegalArgumentException if the specified property cannot be set
   *         by this method
   * @throws ClassCastException if the property value does not match the
   *         property type
   * @throws NullPointerException if <code>c</code> or
   *         <code>propertyValue</code> is <code>null</code>
   */
  void setUIProperty(String propertyName, Object value)
  {
    if (propertyName.equals("opaque"))
      {
        if (! clientOpaqueSet)
          {
            setOpaque(((Boolean) value).booleanValue());
            clientOpaqueSet = false;
          }
      }
    else if (propertyName.equals("autoscrolls"))
      {
        if (! clientAutoscrollsSet)
          {
            setAutoscrolls(((Boolean) value).booleanValue());
            clientAutoscrollsSet = false;
          }
      }
    else
      {
        throw new IllegalArgumentException
            ("Unsupported property for LookAndFeel.installProperty(): "
             + propertyName);
      }
  }
}
