/* 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 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.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;
    }
  }

  /** 
   * An explicit value for the component's preferred size; if not set by a
   * user, this is calculated on the fly by delegating to the {@link
   * ComponentUI#getPreferredSize} method on the {@link #ui} property. 
   */
  Dimension preferredSize;

  /** 
   * An explicit value for the component's minimum size; if not set by a
   * user, this is calculated on the fly by delegating to the {@link
   * ComponentUI#getMinimumSize} method on the {@link #ui} property. 
   */
  Dimension minimumSize;

  /** 
   * An explicit value for the component's maximum size; if not set by a
   * user, this is calculated on the fly by delegating to the {@link
   * ComponentUI#getMaximumSize} method on the {@link #ui} property.
   */
  Dimension maximumSize;

  /**
   * 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 text to show in the tooltip associated with this component.
   * 
   * @see #setToolTipText
   * @see #getToolTipText()
   */
   String toolTipText;

  /**
   * 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 private 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;

  /**
   * 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);
    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 EventListener[] getListeners(Class listenerType)
  {
    if (listenerType == PropertyChangeListener.class)
      return getPropertyChangeListeners();
    else if (listenerType == VetoableChangeListener.class)
      return 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);
  }

  /**
   * Fires a property change for a primitive character property.
   *
   * @param property the name of the property
   * @param oldValue the old value of the property
   * @param newValue the new value of the property
   */
  public void firePropertyChange(String property, char oldValue,
                                 char newValue)
  {
    //  FIXME - This method is already public in awt Component, but
    //  is included here to work around a compilation bug in gcj 4.1.
    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 {@link #maximumSize} property
   * has been explicitly set, it is returned. If the {@link #maximumSize}
   * 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 #maximumSize
   * @see #setMaximumSize
   */
  public Dimension getMaximumSize()
  {
    if (maximumSize != null)
      return maximumSize;

    if (ui != null)
      {
        Dimension s = ui.getMaximumSize(this);
        if (s != null)
          return s;
      }

    Dimension p = super.getMaximumSize();
    return p;
  }

  /**
   * Get the component's minimum size. If the {@link #minimumSize} property
   * has been explicitly set, it is returned. If the {@link #minimumSize}
   * 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 #minimumSize
   * @see #setMinimumSize
   */
  public Dimension getMinimumSize()
  {
    if (minimumSize != null)
      return minimumSize;

    if (ui != null)
      {
        Dimension s = ui.getMinimumSize(this);
        if (s != null)
          return s;
      }

    Dimension p = super.getMinimumSize();
    return p;
  }

  /**
   * Get the component's preferred size. If the {@link #preferredSize}
   * property has been explicitly set, it is returned. If the {@link
   * #preferredSize} 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 #preferredSize
   * @see #setPreferredSize
   */
  public Dimension getPreferredSize()
  {
    Dimension prefSize = null;
    if (preferredSize != null)
      prefSize = new Dimension(preferredSize);

    else if (ui != null)
      {
        Dimension s = ui.getPreferredSize(this);
        if (s != null)
          prefSize = s;
      }

    if (prefSize == null)
      prefSize = super.getPreferredSize();

    return prefSize;
  }

  /**
   * Checks if a maximum size was explicitely set on the component.
   *
   * @return <code>true</code> if a maximum size was set,
   * <code>false</code> otherwise
   * 
   * @since 1.3
   */
  public boolean isMaximumSizeSet()
  {
    return maximumSize != null;
  }

  /**
   * Checks if a minimum size was explicitely set on the component.
   *
   * @return <code>true</code> if a minimum size was set,
   * <code>false</code> otherwise
   * 
   * @since 1.3
   */
  public boolean isMinimumSizeSet()
  {
    return minimumSize != null;
  }

  /**
   * Checks if a preferred size was explicitely set on the component.
   *
   * @return <code>true</code> if a preferred size was set,
   * <code>false</code> otherwise
   * 
   * @since 1.3
   */
  public boolean isPreferredSizeSet()
  {
    return preferredSize != null;
  }
  
  /**
   * 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);
    toolTip.setTipText(toolTipText);

    return toolTip;
  }

  /**
   * Return the location at which the {@link #toolTipText} 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 value of the {@link #toolTipText} property.
   *
   * @param text The new property value
   *
   * @see #getToolTipText()
   */
  public void setToolTipText(String text)
  {
    if (text == null)
    {
      ToolTipManager.sharedInstance().unregisterComponent(this);
      toolTipText = null;
      return;
    }

    // XXX: The tip text doesn't get updated unless you set it to null
    // and then to something not-null. This is consistent with the behaviour
    // of Sun's ToolTipManager.

    String oldText = toolTipText;
    toolTipText = text;

    if (oldText == null)
      ToolTipManager.sharedInstance().registerComponent(this);
  }

  /**
   * Get the value of the {@link #toolTipText} property.
   *
   * @return The current property value
   *
   * @see #setToolTipText
   */
  public String getToolTipText()
  {
    return toolTipText;
  }

  /**
   * Get the value of the {@link #toolTipText} property, in response to a
   * particular mouse event.
   *
   * @param event The mouse event which triggered the tooltip
   *
   * @return The current property value
   *
   * @see #setToolTipText
   */
  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);
      }
    else
      {
        if (getClientProperty("bufferedDragging") != null
            && dragBuffer == null)
          {
            initializeDragBuffer();
          }
        else if (getClientProperty("bufferedDragging") == null
            && dragBuffer != null)
          {
            dragBuffer = null;
          }

        if (g.getClip() == null)
          g.setClip(0, 0, getWidth(), getHeight());
        if (dragBuffer != null && dragBufferInitialized)
          {
            g.drawImage(dragBuffer, 0, 0, this);
          }
        else
          {
            Graphics g2 = getComponentGraphics(g);
            paintComponent(g2);
            paintBorder(g2);
            paintChildren(g2);
          }
      }
  }

  /**
   * 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())
          {
            for (int i = getComponentCount() - 1; 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))
                              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 rect the region to check
   *
   * @return <code>true</code> if the region is completely obscured by a
   *         sibling, <code>false</code> otherwise
   */
  private boolean isCompletelyObscured(int index, Rectangle rect)
  {
    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() && rect.x >= sibRect.x
                && (rect.x + rect.width) <= (sibRect.x + sibRect.width)
                && rect.y >= sibRect.y
                && (rect.y + rect.height) <= (sibRect.y + sibRect.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)
  {
    paintImmediately(new Rectangle(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)
  {
    // Try to find a root pane for this component.
    //Component root = findPaintRoot(r);
    Component root = findPaintRoot(r);
    // If no paint root is found, then this component is completely overlapped
    // by another component and we don't need repainting.
    if (root == null|| !root.isShowing())
      return;
    SwingUtilities.convertRectangleToAncestor(this, r, root);
    if (root instanceof JComponent)
      ((JComponent) root).paintImmediately2(r);
    else
      root.repaint(r.x, r.y, r.width, r.height);
  }

  /**
   * Performs the actual work of paintImmediatly on the repaint root.
   *
   * @param r the area to be repainted
   */
  void paintImmediately2(Rectangle r)
  {
    isRepainting = true;
    RepaintManager rm = RepaintManager.currentManager(this);
    if (rm.isDoubleBufferingEnabled() && isPaintingDoubleBuffered())
      paintDoubleBuffered(r);
    else
      paintSimple(r);
    isRepainting = false;
  }

  /**
   * Returns true if we must paint double buffered, that is, when this
   * component or any of it's ancestors are double buffered.
   *
   * @return true if we must paint double buffered, that is, when this
   *         component or any of it's ancestors are double buffered
   */
  private boolean isPaintingDoubleBuffered()
  {
    boolean doubleBuffered = isDoubleBuffered();
    Component parent = getParent();
    while (! doubleBuffered && parent != null)
      {
        doubleBuffered = parent instanceof JComponent
                         && ((JComponent) parent).isDoubleBuffered();
        parent = parent.getParent();
      }
    return doubleBuffered;
  }

  /**
   * Performs double buffered repainting.
   */
  private void paintDoubleBuffered(Rectangle r)
  {
    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(r.x, r.y, r.width, r.height);
    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, r);
  }

  /**
   * 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()
  {
    StringBuffer sb = new StringBuffer();
    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 = (Action) 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)
  {
    Component p = getParent();
    if (p instanceof JComponent)
      ((JComponent) p).scrollRectToVisible(r);
  }

  /**
   * 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 value of the {@link #maximumSize} property. The passed value is
   * copied, the later direct changes on the argument have no effect on the
   * property value.
   *
   * @param max The new value of the property
   */
  public void setMaximumSize(Dimension max)
  {
    Dimension oldMaximumSize = maximumSize;
    if (max != null) 
      maximumSize = new Dimension(max);
    else
      maximumSize = null;
    firePropertyChange("maximumSize", oldMaximumSize, maximumSize);
  }

  /**
   * Set the value of the {@link #minimumSize} property. The passed value is
   * copied, the later direct changes on the argument have no effect on the
   * property value.
   *
   * @param min The new value of the property
   */
  public void setMinimumSize(Dimension min)
  {
    Dimension oldMinimumSize = minimumSize;
    if (min != null)
      minimumSize = new Dimension(min);
    else
      minimumSize = null;
    firePropertyChange("minimumSize", oldMinimumSize, minimumSize);
  }

  /**
   * Set the value of the {@link #preferredSize} property. The passed value is
   * copied, the later direct changes on the argument have no effect on the
   * property value.
   *
   * @param pref The new value of the property
   */
  public void setPreferredSize(Dimension pref)
  {
    Dimension oldPreferredSize = preferredSize;
    if (pref != null)
      preferredSize = new Dimension(pref);
    else
      preferredSize = null;
    firePropertyChange("preferredSize", oldPreferredSize, preferredSize);
  }

  /**
   * 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);
      }
  }

  /**
   * Finds a suitable paint root for painting this component. This method first
   * checks if this component is overlapped using
   * {@link #findOverlapFreeParent(Rectangle)}. The returned paint root is then
   * feeded to {@link #findOpaqueParent(Component)} to find the nearest opaque
   * component for this paint root. If no paint is necessary, then we return
   * <code>null</code>.
   *
   * @param c the clip of this component
   *
   * @return the paint root or <code>null</code> if no painting is necessary
   */
  private Component findPaintRoot(Rectangle c)
  {
    Component p = findOverlapFreeParent(c);
    if (p == null)
      return null;
    Component root = findOpaqueParent(p);
    return root;
  }

  /**
   * Scans the containment hierarchy upwards for components that overlap the
   * this component in the specified clip. This method returns
   * <code>this</code>, if no component overlaps this component. It returns
   * <code>null</code> if another component completely covers this component
   * in the specified clip (no repaint necessary). If another component partly
   * overlaps this component in the specified clip, then the parent of this
   * component is returned (this is the component that must be used as repaint
   * root). For efficient lookup, the method
   * {@link #isOptimizedDrawingEnabled()} is used.
   *
   * @param clip the clip of this component
   *
   * @return the paint root, or <code>null</code> if no paint is necessary
   */
  private Component findOverlapFreeParent(Rectangle clip)
  {
    Rectangle currentClip = clip;
    Component found = this;
    Container parent = this; 

    while (parent != null && !(parent instanceof Window))
      {
        Container newParent = parent.getParent();
        if (newParent == null || newParent instanceof Window)
          break;
        // If the parent is optimizedDrawingEnabled, then its children are
        // tiled and cannot have an overlapping child. Go directly to next
        // parent.
        if ((newParent instanceof JComponent
            && ((JComponent) newParent).isOptimizedDrawingEnabled()))
          
          {
            parent = newParent;
            continue;
          }

        // If the parent is not optimizedDrawingEnabled, we must check if the
        // parent or some neighbor overlaps the current clip.

        // This is the current clip converted to the parent's coordinate
        // system. TODO: We can do this more efficiently by succesively
        // cumulating the parent-child translations.
        Rectangle target = SwingUtilities.convertRectangle(found,
                                                           currentClip,
                                                           newParent);

        // We have an overlap if either:
        // - The new parent itself doesn't completely cover the clip
        //   (this can be the case with viewports).
        // - If some higher-level (than the current) children of the new parent
        //   intersect the target rectangle.
        Rectangle parentRect = SwingUtilities.getLocalBounds(newParent);
        boolean haveOverlap =
          ! SwingUtilities.isRectangleContainingRectangle(parentRect, target);
        if (! haveOverlap)
          {
            Component child;
            for (int i = 0; (child = newParent.getComponent(i)) != parent && !haveOverlap; i++)
              {
                Rectangle childRect = child.getBounds();
                haveOverlap = target.intersects(childRect);
              }
          }
        if (haveOverlap)
          {
            found = newParent;
            currentClip = target;
          }
        parent = newParent;
      }
    //System.err.println("overlapfree parent: " + found);
    return found;
  }

  /**
   * Finds the nearest component to <code>c</code> (upwards in the containment
   * hierarchy), that is opaque. If <code>c</code> itself is opaque,
   * this returns <code>c</code> itself.
   *
   * @param c the start component for the search
   * @return the nearest component to <code>c</code> (upwards in the containment
   *         hierarchy), that is opaque; If <code>c</code> itself is opaque,
   *         this returns <code>c</code> itself
   */
  private Component findOpaqueParent(Component c)
  {
    Component found = c;
    while (true)
      {
        if ((found instanceof JComponent) && ((JComponent) found).isOpaque())
          break;
        else if (!(found instanceof JComponent) && !found.isLightweight())
          break;
        Container p = found.getParent();
        if (p == null)
          break;
        else
          found = p;
      }
    return found;
  }
  
  /**
   * 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);
      }
  }
}
