/* Component.java -- a graphics component
   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006
   Free Software Foundation

This file is part of GNU Classpath.

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

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

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

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

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


package java.awt;

//import gnu.java.awt.dnd.peer.gtk.GtkDropTargetContextPeer;

import gnu.java.awt.ComponentReshapeEvent;

import gnu.java.lang.CPStringBuilder;

import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.AdjustmentEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.HierarchyBoundsListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.InputMethodListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.PaintEvent;
import java.awt.event.WindowEvent;
import java.awt.im.InputContext;
import java.awt.im.InputMethodRequests;
import java.awt.image.BufferStrategy;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
import java.awt.peer.ComponentPeer;
import java.awt.peer.LightweightPeer;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Collections;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.Vector;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleComponent;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;

/**
 * The root of all evil. All graphical representations are subclasses of this
 * giant class, which is designed for screen display and user interaction.
 * This class can be extended directly to build a lightweight component (one
 * not associated with a native window); lightweight components must reside
 * inside a heavyweight window.
 *
 * <p>This class is Serializable, which has some big implications. A user can
 * save the state of all graphical components in one VM, and reload them in
 * another. Note that this class will only save Serializable listeners, and
 * ignore the rest, without causing any serialization exceptions. However, by
 * making a listener serializable, and adding it to another element, you link
 * in that entire element to the state of this component. To get around this,
 * use the idiom shown in the example below - make listeners non-serializable
 * in inner classes, rather than using this object itself as the listener, if
 * external objects do not need to save the state of this object.
 *
 * <pre>
 * import java.awt.*;
 * import java.awt.event.*;
 * import java.io.Serializable;
 * class MyApp implements Serializable
 * {
 *   BigObjectThatShouldNotBeSerializedWithAButton bigOne;
 *   // Serializing aButton will not suck in an instance of MyApp, with its
 *   // accompanying field bigOne.
 *   Button aButton = new Button();
 *   class MyActionListener implements ActionListener
 *   {
 *     public void actionPerformed(ActionEvent e)
 *     {
 *       System.out.println("Hello There");
 *     }
 *   }
 *   MyApp()
 *   {
 *     aButton.addActionListener(new MyActionListener());
 *   }
 * }
 * </pre>
 *
 * <p>Status: Incomplete. The event dispatch mechanism is implemented. All
 * other methods defined in the J2SE 1.3 API javadoc exist, but are mostly
 * incomplete or only stubs; except for methods relating to the Drag and
 * Drop, Input Method, and Accessibility frameworks: These methods are
 * present but commented out.
 *
 * @author original author unknown
 * @author Eric Blake (ebb9@email.byu.edu)
 * @since 1.0
 * @status still missing 1.4 support
 */
public abstract class Component
  implements ImageObserver, MenuContainer, Serializable
{
  // Word to the wise - this file is huge. Search for '\f' (^L) for logical
  // sectioning by fields, public API, private API, and nested classes.


  /**
   * Compatible with JDK 1.0+.
   */
  private static final long serialVersionUID = -7644114512714619750L;

  /**
   * Constant returned by the <code>getAlignmentY</code> method to indicate
   * that the component wishes to be aligned to the top relative to
   * other components.
   *
   * @see #getAlignmentY()
   */
  public static final float TOP_ALIGNMENT = 0;

  /**
   * Constant returned by the <code>getAlignmentY</code> and
   * <code>getAlignmentX</code> methods to indicate
   * that the component wishes to be aligned to the centdisper relative to
   * other components.
   *
   * @see #getAlignmentX()
   * @see #getAlignmentY()
   */
  public static final float CENTER_ALIGNMENT = 0.5f;

  /**
   * Constant returned by the <code>getAlignmentY</code> method to indicate
   * that the component wishes to be aligned to the bottom relative to
   * other components.
   *
   * @see #getAlignmentY()
   */
  public static final float BOTTOM_ALIGNMENT = 1;

  /**
   * Constant returned by the <code>getAlignmentX</code> method to indicate
   * that the component wishes to be aligned to the right relative to
   * other components.
   *
   * @see #getAlignmentX()
   */
  public static final float RIGHT_ALIGNMENT = 1;

  /**
   * Constant returned by the <code>getAlignmentX</code> method to indicate
   * that the component wishes to be aligned to the left relative to
   * other components.
   *
   * @see #getAlignmentX()
   */
  public static final float LEFT_ALIGNMENT = 0;

  /**
   * Make the treelock a String so that it can easily be identified
   * in debug dumps. We clone the String in order to avoid a conflict in
   * the unlikely event that some other package uses exactly the same string
   * as a lock object.
   */
  static final Object treeLock = new String("AWT_TREE_LOCK");

  /**
   * The default maximum size.
   */
  private static final Dimension DEFAULT_MAX_SIZE 
                             = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);

  // Serialized fields from the serialization spec.

  /**
   * The x position of the component in the parent's coordinate system.
   *
   * @see #getLocation()
   * @serial the x position
   */
  int x;

  /**
   * The y position of the component in the parent's coordinate system.
   *
   * @see #getLocation()
   * @serial the y position
   */
  int y;

  /**
   * The component width.
   *
   * @see #getSize()
   * @serial the width
   */
  int width;

  /**
   * The component height.
   *
   * @see #getSize()
   * @serial the height
   */
  int height;

  /**
   * The foreground color for the component. This may be null.
   *
   * @see #getForeground()
   * @see #setForeground(Color)
   * @serial the foreground color
   */
  Color foreground;

  /**
   * The background color for the component. This may be null.
   *
   * @see #getBackground()
   * @see #setBackground(Color)
   * @serial the background color
   */
  Color background;

  /**
   * The default font used in the component. This may be null.
   *
   * @see #getFont()
   * @see #setFont(Font)
   * @serial the font
   */
  Font font;

  /**
   * The font in use by the peer, or null if there is no peer.
   *
   * @serial the peer's font
   */
  Font peerFont;

  /**
   * The cursor displayed when the pointer is over this component. This may
   * be null.
   *
   * @see #getCursor()
   * @see #setCursor(Cursor)
   */
  Cursor cursor;

  /**
   * The locale for the component.
   *
   * @see #getLocale()
   * @see #setLocale(Locale)
   */
  Locale locale = Locale.getDefault ();

  /**
   * True if the object should ignore repaint events (usually because it is
   * not showing).
   *
   * @see #getIgnoreRepaint()
   * @see #setIgnoreRepaint(boolean)
   * @serial true to ignore repaints
   * @since 1.4
   */
  boolean ignoreRepaint;

  /**
   * True when the object is visible (although it is only showing if all
   * ancestors are likewise visible). For component, this defaults to true.
   *
   * @see #isVisible()
   * @see #setVisible(boolean)
   * @serial true if visible
   */
  boolean visible = true;

  /**
   * True if the object is enabled, meaning it can interact with the user.
   * For component, this defaults to true.
   *
   * @see #isEnabled()
   * @see #setEnabled(boolean)
   * @serial true if enabled
   */
  boolean enabled = true;

  /**
   * True if the object is valid. This is set to false any time a size
   * adjustment means the component need to be layed out again.
   *
   * @see #isValid()
   * @see #validate()
   * @see #invalidate()
   * @serial true if layout is valid
   */
  boolean valid;

  /**
   * The DropTarget for drag-and-drop operations.
   *
   * @see #getDropTarget()
   * @see #setDropTarget(DropTarget)
   * @serial the drop target, or null
   * @since 1.2
   */
  DropTarget dropTarget;

  /**
   * The list of popup menus for this component.
   *
   * @see #add(PopupMenu)
   * @serial the list of popups
   */
  Vector popups;

  /**
   * The component's name. May be null, in which case a default name is
   * generated on the first use.
   *
   * @see #getName()
   * @see #setName(String)
   * @serial the name
   */
  String name;

  /**
   * True once the user has set the name. Note that the user may set the name
   * to null.
   *
   * @see #name
   * @see #getName()
   * @see #setName(String)
   * @serial true if the name has been explicitly set
   */
  boolean nameExplicitlySet;

  /**
   * Indicates if the object can be focused. Defaults to true for components.
   *
   * @see #isFocusable()
   * @see #setFocusable(boolean)
   * @since 1.4
   */
  boolean focusable = true;

  /**
   * Tracks whether this component's {@link #isFocusTraversable}
   * method has been overridden.
   *
   * @since 1.4
   */
  int isFocusTraversableOverridden;

  /**
   * The focus traversal keys, if not inherited from the parent or
   * default keyboard focus manager. These sets will contain only
   * AWTKeyStrokes that represent press and release events to use as
   * focus control.
   *
   * @see #getFocusTraversalKeys(int)
   * @see #setFocusTraversalKeys(int, Set)
   * @since 1.4
   */
  Set[] focusTraversalKeys;

  /**
   * True if focus traversal keys are enabled. This defaults to true for
   * Component. If this is true, keystrokes in focusTraversalKeys are trapped
   * and processed automatically rather than being passed on to the component.
   *
   * @see #getFocusTraversalKeysEnabled()
   * @see #setFocusTraversalKeysEnabled(boolean)
   * @since 1.4
   */
  boolean focusTraversalKeysEnabled = true;

  /**
   * Cached information on the minimum size. Should have been transient.
   *
   * @serial ignore
   */
  Dimension minSize;

  /**
   * Flag indicating whether the minimum size for the component has been set
   * by a call to {@link #setMinimumSize(Dimension)} with a non-null value.
   */
  boolean minSizeSet;
  
  /**
   * The maximum size for the component.
   * @see #setMaximumSize(Dimension)
   */
  Dimension maxSize;
  
  /**
   * A flag indicating whether the maximum size for the component has been set
   * by a call to {@link #setMaximumSize(Dimension)} with a non-null value.
   */
  boolean maxSizeSet;
  
  /**
   * Cached information on the preferred size. Should have been transient.
   *
   * @serial ignore
   */
  Dimension prefSize;

  /**
   * Flag indicating whether the preferred size for the component has been set
   * by a call to {@link #setPreferredSize(Dimension)} with a non-null value.
   */
  boolean prefSizeSet;

  /**
   * Set to true if an event is to be handled by this component, false if
   * it is to be passed up the hierarcy.
   *
   * @see #dispatchEvent(AWTEvent)
   * @serial true to process event locally
   */
  boolean newEventsOnly;

  /**
   * Set by subclasses to enable event handling of particular events, and
   * left alone when modifying listeners. For component, this defaults to
   * enabling only input methods.
   *
   * @see #enableInputMethods(boolean)
   * @see AWTEvent
   * @serial the mask of events to process
   */
  long eventMask = AWTEvent.INPUT_ENABLED_EVENT_MASK;

  /**
   * Describes all registered PropertyChangeListeners.
   *
   * @see #addPropertyChangeListener(PropertyChangeListener)
   * @see #removePropertyChangeListener(PropertyChangeListener)
   * @see #firePropertyChange(String, Object, Object)
   * @serial the property change listeners
   * @since 1.2
   */
  PropertyChangeSupport changeSupport;

  /**
   * True if the component has been packed (layed out).
   *
   * @serial true if this is packed
   */
  boolean isPacked;

  /**
   * The serialization version for this class. Currently at version 4.
   *
   * XXX How do we handle prior versions?
   *
   * @serial the serialization version
   */
  int componentSerializedDataVersion = 4;

  /**
   * The accessible context associated with this component. This is only set
   * by subclasses.
   *
   * @see #getAccessibleContext()
   * @serial the accessibility context
   * @since 1.2
   */
  AccessibleContext accessibleContext;


  // Guess what - listeners are special cased in serialization. See
  // readObject and writeObject.

  /** Component listener chain. */
  transient ComponentListener componentListener;

  /** Focus listener chain. */
  transient FocusListener focusListener;

  /** Key listener chain. */
  transient KeyListener keyListener;

  /** Mouse listener chain. */
  transient MouseListener mouseListener;

  /** Mouse motion listener chain. */
  transient MouseMotionListener mouseMotionListener;

  /**
   * Mouse wheel listener chain.
   *
   * @since 1.4
   */
  transient MouseWheelListener mouseWheelListener;

  /**
   * Input method listener chain.
   *
   * @since 1.2
   */
  transient InputMethodListener inputMethodListener;

  /**
   * Hierarcy listener chain.
   *
   * @since 1.3
   */
  transient HierarchyListener hierarchyListener;

  /**
   * Hierarcy bounds listener chain.
   *
   * @since 1.3
   */
  transient HierarchyBoundsListener hierarchyBoundsListener;

  // Anything else is non-serializable, and should be declared "transient".

  /** The parent. */
  transient Container parent;

  /** The associated native peer. */
  transient ComponentPeer peer;

  /** The preferred component orientation. */
  transient ComponentOrientation componentOrientation = ComponentOrientation.UNKNOWN;

  /**
   * The associated graphics configuration.
   *
   * @since 1.4
   */
  transient GraphicsConfiguration graphicsConfig;

  /**
   * The buffer strategy for repainting.
   *
   * @since 1.4
   */
  transient BufferStrategy bufferStrategy;

  /**
   * The number of hierarchy listeners of this container plus all of its
   * children. This is needed for efficient handling of HierarchyEvents.
   * These must be propagated to all child components with HierarchyListeners
   * attached. To avoid traversal of the whole subtree, we keep track of
   * the number of HierarchyListeners here and only walk the paths that
   * actually have listeners.
   */
  int numHierarchyListeners;
  int numHierarchyBoundsListeners;

  /**
   * true if requestFocus was called on this component when its
   * top-level ancestor was not focusable.
   */
  private transient FocusEvent pendingFocusRequest = null;

  /**
   * The system properties that affect image updating.
   */
  private static transient boolean incrementalDraw;
  private static transient Long redrawRate;

  static
  {
    incrementalDraw = Boolean.getBoolean ("awt.image.incrementalDraw");
    redrawRate = Long.getLong ("awt.image.redrawrate");
  }

  // Public and protected API.

  /**
   * Default constructor for subclasses. When Component is extended directly,
   * it forms a lightweight component that must be hosted in an opaque native
   * container higher in the tree.
   */
  protected Component()
  {
    // Nothing to do here.
  }

  /**
   * Returns the name of this component.
   *
   * @return the name of this component
   * @see #setName(String)
   * @since 1.1
   */
  public String getName()
  {
    if (name == null && ! nameExplicitlySet)
      name = generateName();
    return name;
  }

  /**
   * Sets the name of this component to the specified name (this is a bound
   * property with the name 'name').
   *
   * @param name the new name (<code>null</code> permitted).
   * @see #getName()
   * @since 1.1
   */
  public void setName(String name)
  {
    nameExplicitlySet = true;
    String old = this.name;
    this.name = name;
    firePropertyChange("name", old, name);
  }

  /**
   * Returns the parent of this component.
   *
   * @return the parent of this component
   */
  public Container getParent()
  {
    return parent;
  }

  /**
   * Returns the native windowing system peer for this component. Only the
   * platform specific implementation code should call this method.
   *
   * @return the peer for this component
   * @deprecated user programs should not directly manipulate peers; use
   *             {@link #isDisplayable()} instead
   */
  // Classpath's Gtk peers rely on this.
  public ComponentPeer getPeer()
  {
    return peer;
  }

  /**
   * Set the associated drag-and-drop target, which receives events when this
   * is enabled.
   *
   * @param dt the new drop target
   * @see #isEnabled()
   */
  public void setDropTarget(DropTarget dt)
  {
    this.dropTarget = dt;
    
    if (peer != null)
      dropTarget.addNotify(peer);
  }

  /**
   * Gets the associated drag-and-drop target, if there is one.
   *
   * @return the drop target
   */
  public DropTarget getDropTarget()
  {
    return dropTarget;
  }

  /**
   * Returns the graphics configuration of this component, if there is one.
   * If it has not been set, it is inherited from the parent.
   *
   * @return the graphics configuration, or null
   * @since 1.3
   */
  public GraphicsConfiguration getGraphicsConfiguration()
  {
    GraphicsConfiguration conf = null;
    synchronized (getTreeLock())
      {
        if (graphicsConfig != null)
          {
            conf = graphicsConfig;
          }
        else
          {
            Component par = getParent();
            if (par != null)
              {
                conf = parent.getGraphicsConfiguration();
              }
          }
      }
    return conf;
  }

  /**
   * Returns the object used for synchronization locks on this component
   * when performing tree and layout functions.
   *
   * @return the synchronization lock for this component
   */
  public final Object getTreeLock()
  {
    return treeLock;
  }

  /**
   * Returns the toolkit in use for this component. The toolkit is associated
   * with the frame this component belongs to.
   *
   * @return the toolkit for this component
   */
  public Toolkit getToolkit()
  {
    // Only heavyweight peers can handle this.
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    Toolkit tk = null;
    if (p != null)
      {
        tk = peer.getToolkit();
      }
    if (tk == null)
      tk = Toolkit.getDefaultToolkit();
    return tk;
  }

  /**
   * Tests whether or not this component is valid. A invalid component needs
   * to have its layout redone.
   *
   * @return true if this component is valid
   * @see #validate()
   * @see #invalidate()
   */
  public boolean isValid()
  {
    // Tests show that components are invalid as long as they are not showing, even after validate()
    // has been called on them.
    return peer != null && valid;
  }

  /**
   * Tests if the component is displayable. It must be connected to a native
   * screen resource.  This reduces to checking that peer is not null.  A 
   * containment  hierarchy is made displayable when a window is packed or 
   * made visible.
   *
   * @return true if the component is displayable
   * @see Container#add(Component)
   * @see Container#remove(Component)
   * @see Window#pack()
   * @see Window#show()
   * @see Window#dispose()
   * @since 1.2
   */
  public boolean isDisplayable()
  {
    return peer != null;
  }

  /**
   * Tests whether or not this component is visible. Except for top-level
   * frames, components are initially visible.
   *
   * @return true if the component is visible
   * @see #setVisible(boolean)
   */
  public boolean isVisible()
  {
    return visible;
  }

  /**
   * Tests whether or not this component is actually being shown on
   * the screen. This will be true if and only if it this component is
   * visible and its parent components are all visible.
   *
   * @return true if the component is showing on the screen
   * @see #setVisible(boolean)
   */
  public boolean isShowing()
  {
    Component par = parent;
    return visible && peer != null && (par == null || par.isShowing());
  }

  /**
   * Tests whether or not this component is enabled. Components are enabled
   * by default, and must be enabled to receive user input or generate events.
   *
   * @return true if the component is enabled
   * @see #setEnabled(boolean)
   */
  public boolean isEnabled()
  {
    return enabled;
  }

  /**
   * Enables or disables this component. The component must be enabled to
   * receive events (except that lightweight components always receive mouse
   * events).
   *
   * @param enabled true to enable this component
   * 
   * @see #isEnabled()
   * @see #isLightweight()
   * 
   * @since 1.1
   */
  public void setEnabled(boolean enabled)
  {
    enable(enabled);
  }

  /**
   * Enables this component.
   *
   * @deprecated use {@link #setEnabled(boolean)} instead
   */
  public void enable()
  {
    if (! enabled)
      {
        // Need to lock the tree here, because the peers are involved.
        synchronized (getTreeLock())
          {
            enabled = true;
            ComponentPeer p = peer;
            if (p != null)
              p.enable();
          }
      }
  }

  /**
   * Enables or disables this component.
   *
   * @param enabled true to enable this component
   * 
   * @deprecated use {@link #setEnabled(boolean)} instead
   */
  public void enable(boolean enabled)
  {
    if (enabled)
      enable();
    else
      disable();
  }

  /**
   * Disables this component.
   *
   * @deprecated use {@link #setEnabled(boolean)} instead
   */
  public void disable()
  {
    if (enabled)
      {
        // Need to lock the tree here, because the peers are involved.
        synchronized (getTreeLock())
          {
            enabled = false;
            ComponentPeer p = peer;
            if (p != null)
              p.disable();
          }
      }
  }

  /**
   * Checks if this image is painted to an offscreen image buffer that is
   * later copied to screen (double buffering reduces flicker). This version
   * returns false, so subclasses must override it if they provide double
   * buffering.
   *
   * @return true if this is double buffered; defaults to false
   */
  public boolean isDoubleBuffered()
  {
    return false;
  }

  /**
   * Enables or disables input method support for this component. By default,
   * components have this enabled. Input methods are given the opportunity
   * to process key events before this component and its listeners.
   *
   * @param enable true to enable input method processing
   * @see #processKeyEvent(KeyEvent)
   * @since 1.2
   */
  public void enableInputMethods(boolean enable)
  {
    if (enable)
      eventMask |= AWTEvent.INPUT_ENABLED_EVENT_MASK;
    else
      eventMask &= ~AWTEvent.INPUT_ENABLED_EVENT_MASK;
  }

  /**
   * Makes this component visible or invisible. Note that it wtill might
   * not show the component, if a parent is invisible.
   *
   * @param visible true to make this component visible
   * 
   * @see #isVisible()
   * 
   * @since 1.1
   */
  public void setVisible(boolean visible)
  {
    // Inspection by subclassing shows that Sun's implementation calls
    // show(boolean) which then calls show() or hide(). It is the show()
    // method that is overriden in subclasses like Window.
    show(visible);
  }

  /**
   * Makes this component visible on the screen.
   *
   * @deprecated use {@link #setVisible(boolean)} instead
   */
  public void show()
  {
    // We must set visible before showing the peer.  Otherwise the
    // peer could post paint events before visible is true, in which
    // case lightweight components are not initially painted --
    // Container.paint first calls isShowing () before painting itself
    // and its children.
    if(! visible)
      {
        // Need to lock the tree here to avoid races and inconsistencies.
        synchronized (getTreeLock())
          {
            visible = true;
            // Avoid NullPointerExceptions by creating a local reference.
            ComponentPeer currentPeer = peer;
            if (currentPeer != null)
              {
                currentPeer.show();

                // Fire HierarchyEvent.
                fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
                                   this, parent,
                                   HierarchyEvent.SHOWING_CHANGED);

                // The JDK repaints the component before invalidating the parent.
                // So do we.
                if (peer instanceof LightweightPeer)
                  repaint();
              }

            // Only post an event if this component actually has a listener
            // or has this event explicitly enabled.
            if (componentListener != null
                || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
              {
                ComponentEvent ce =
                  new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
                getToolkit().getSystemEventQueue().postEvent(ce);
              }
          }

        // Invalidate the parent if we have one. The component itself must
        // not be invalidated. We also avoid NullPointerException with
        // a local reference here.
        Container currentParent = parent;
        if (currentParent != null)
          currentParent.invalidate();

      }
  }

  /**
   * Makes this component visible or invisible.
   *
   * @param visible true to make this component visible
   * 
   * @deprecated use {@link #setVisible(boolean)} instead
   */
  public void show(boolean visible)
  {
    if (visible)
      show();
    else
      hide();
  }

  /**
   * Hides this component so that it is no longer shown on the screen.
   *
   * @deprecated use {@link #setVisible(boolean)} instead
   */
  public void hide()
  {
    if (visible)
      {
        // Need to lock the tree here to avoid races and inconsistencies.
        synchronized (getTreeLock())
          {
            visible = false;

            // Avoid NullPointerExceptions by creating a local reference.
            ComponentPeer currentPeer = peer;
            if (currentPeer != null)
              {
                currentPeer.hide();

                // Fire hierarchy event.
                fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
                                   this, parent,
                                   HierarchyEvent.SHOWING_CHANGED);
                // The JDK repaints the component before invalidating the
                // parent. So do we. This only applies for lightweights.
                if (peer instanceof LightweightPeer)
                  repaint();
              }

            // Only post an event if this component actually has a listener
            // or has this event explicitly enabled.
            if (componentListener != null
                || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
              {
                ComponentEvent ce =
                  new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
                getToolkit().getSystemEventQueue().postEvent(ce);
              }
          }

        // Invalidate the parent if we have one. The component itself need
        // not be invalidated. We also avoid NullPointerException with
        // a local reference here.
        Container currentParent = parent;
        if (currentParent != null)
          currentParent.invalidate();

      }
  }

  /**
   * Returns this component's foreground color. If not set, this is inherited
   * from the parent.
   *
   * @return this component's foreground color, or null
   * @see #setForeground(Color)
   */
  public Color getForeground()
  {
    if (foreground != null)
      return foreground;
    return parent == null ? null : parent.getForeground();
  }

  /**
   * Sets this component's foreground color to the specified color. This is a
   * bound property.
   *
   * @param c the new foreground color
   * @see #getForeground()
   */
  public void setForeground(Color c)
  {
    if (peer != null)
      peer.setForeground(c);
    
    Color previous = foreground;
    foreground = c;
    firePropertyChange("foreground", previous, c);
  }

  /**
   * Tests if the foreground was explicitly set, or just inherited from the
   * parent.
   *
   * @return true if the foreground has been set
   * @since 1.4
   */
  public boolean isForegroundSet()
  {
    return foreground != null;
  }

  /**
   * Returns this component's background color. If not set, this is inherited
   * from the parent.
   *
   * @return the background color of the component, or null
   * @see #setBackground(Color)
   */
  public Color getBackground()
  {
    if (background != null)
      return background;
    return parent == null ? null : parent.getBackground();
  }

  /**
   * Sets this component's background color to the specified color. The parts
   * of the component affected by the background color may by system dependent.
   * This is a bound property.
   *
   * @param c the new background color
   * @see #getBackground()
   */
  public void setBackground(Color c)
  {
    // return if the background is already set to that color.
    if ((c != null) && c.equals(background))
      return;

    Color previous = background;
    background = c;
    if (peer != null && c != null)
      peer.setBackground(c);
    firePropertyChange("background", previous, c);
  }

  /**
   * Tests if the background was explicitly set, or just inherited from the
   * parent.
   *
   * @return true if the background has been set
   * @since 1.4
   */
  public boolean isBackgroundSet()
  {
    return background != null;
  }

  /**
   * Returns the font in use for this component. If not set, this is inherited
   * from the parent.
   *
   * @return the font for this component
   * @see #setFont(Font)
   */
  public Font getFont()
  {
    return getFontImpl();
  }

  /**
   * Implementation of getFont(). This is pulled out of getFont() to prevent
   * client programs from overriding this.
   *
   * @return the font of this component
   */
  private final Font getFontImpl()
  {
    Font f = font;
    if (f == null)
      {
        Component p = parent;
        if (p != null)
          f = p.getFontImpl();
        else
          {
            // It is important to return null here and not some kind of default
            // font, otherwise the Swing UI would not install its fonts because
            // it keeps non-UIResource fonts.
            f = null;
          }
      }
    return f;
  }

  /**
   * Sets the font for this component to the specified font. This is a bound
   * property.
   *
   * @param f the new font for this component
   * 
   * @see #getFont()
   */
  public void setFont(Font f)
  {
    Font oldFont;
    Font newFont;
    // Synchronize on the tree because getFontImpl() relies on the hierarchy
    // not beeing changed.
    synchronized (getTreeLock())
      {
        // Synchronize on this here to guarantee thread safety wrt to the
        // property values.
        synchronized (this)
          {
            oldFont = font;
            font = f;
            newFont = f;
          }
        // Create local variable here for thread safety.
        ComponentPeer p = peer;
        if (p != null)
          {
            // The peer receives the real font setting, which can depend on 
            // the parent font when this component's font has been set to null.
            f = getFont();
            if (f != null)
              {
                p.setFont(f);
                peerFont = f;
              }
          }
      }

    // Fire property change event.
    firePropertyChange("font", oldFont, newFont);

    // Invalidate when necessary as font changes can change the size of the
    // component.
    if (valid)
      invalidate();
  }

  /**
   * Tests if the font was explicitly set, or just inherited from the parent.
   *
   * @return true if the font has been set
   * @since 1.4
   */
  public boolean isFontSet()
  {
    return font != null;
  }

  /**
   * Returns the locale for this component. If this component does not
   * have a locale, the locale of the parent component is returned.
   *
   * @return the locale for this component
   * @throws IllegalComponentStateException if it has no locale or parent
   * @see #setLocale(Locale)
   * @since 1.1
   */
  public Locale getLocale()
  {
    if (locale != null)
      return locale;
    if (parent == null)
      throw new IllegalComponentStateException
        ("Component has no parent: can't determine Locale");
    return parent.getLocale();
  }

  /**
   * Sets the locale for this component to the specified locale. This is a
   * bound property.
   *
   * @param newLocale the new locale for this component
   */
  public void setLocale(Locale newLocale)
  {
    if (locale == newLocale)
      return;

    Locale oldLocale = locale;
    locale = newLocale;
    firePropertyChange("locale", oldLocale, newLocale);
    // New writing/layout direction or more/less room for localized labels.
    invalidate();
  }

  /**
   * Returns the color model of the device this componet is displayed on.
   *
   * @return this object's color model
   * @see Toolkit#getColorModel()
   */
  public ColorModel getColorModel()
  {
    GraphicsConfiguration config = getGraphicsConfiguration();
    return config != null ? config.getColorModel()
      : getToolkit().getColorModel();
  }

  /**
   * Returns the location of this component's top left corner relative to
   * its parent component. This may be outdated, so for synchronous behavior,
   * you should use a component listner.
   *
   * @return the location of this component
   * @see #setLocation(int, int)
   * @see #getLocationOnScreen()
   * @since 1.1
   */
  public Point getLocation()
  {
    return location ();
  }

  /**
   * Returns the location of this component's top left corner in screen
   * coordinates.
   *
   * @return the location of this component in screen coordinates
   * @throws IllegalComponentStateException if the component is not showing
   */
  public Point getLocationOnScreen()
  {
    if (! isShowing())
      throw new IllegalComponentStateException("component "
                                               + getClass().getName()
                                               + " not showing");

    // Need to lock the tree here. We get crazy races and explosions when
    // the tree changes while we are trying to find the location of this
    // component.
    synchronized (getTreeLock())
      {
        // Only a heavyweight peer can answer the question for the screen
        // location. So we are going through the hierarchy until we find
        // one and add up the offsets while doing so.
        int offsX = 0;
        int offsY = 0;
        ComponentPeer p = peer;
        Component comp = this;
        while (p instanceof LightweightPeer)
          {
            offsX += comp.x;
            offsY += comp.y;
            comp = comp.parent;
            p = comp == null ? null: comp.peer;
          }
        // Now we have a heavyweight component.
        assert ! (p instanceof LightweightPeer);
        Point loc = p.getLocationOnScreen();
        loc.x += offsX;
        loc.y += offsY;
        return loc;
      }
  }

  /**
   * Returns the location of this component's top left corner relative to
   * its parent component.
   *
   * @return the location of this component
   * @deprecated use {@link #getLocation()} instead
   */
  public Point location()
  {
    return new Point (x, y);
  }

  /**
   * Moves this component to the specified location, relative to the parent's
   * coordinates. The coordinates are the new upper left corner of this
   * component.
   *
   * @param x the new X coordinate of this component
   * @param y the new Y coordinate of this component
   * @see #getLocation()
   * @see #setBounds(int, int, int, int)
   */
  public void setLocation(int x, int y)
  {
    move (x, y);
  }

  /**
   * Moves this component to the specified location, relative to the parent's
   * coordinates. The coordinates are the new upper left corner of this
   * component.
   *
   * @param x the new X coordinate of this component
   * @param y the new Y coordinate of this component
   * @deprecated use {@link #setLocation(int, int)} instead
   */
  public void move(int x, int y)
  {
    setBounds(x, y, this.width, this.height);
  }

  /**
   * Moves this component to the specified location, relative to the parent's
   * coordinates. The coordinates are the new upper left corner of this
   * component.
   *
   * @param p new coordinates for this component
   * @throws NullPointerException if p is null
   * @see #getLocation()
   * @see #setBounds(int, int, int, int)
   * @since 1.1
   */
  public void setLocation(Point p)
  {
    setLocation(p.x, p.y);
  }

  /**
   * Returns the size of this object.
   *
   * @return the size of this object
   * @see #setSize(int, int)
   * @since 1.1
   */
  public Dimension getSize()
  {
    return size ();
  }

  /**
   * Returns the size of this object.
   *
   * @return the size of this object
   * @deprecated use {@link #getSize()} instead
   */
  public Dimension size()
  {
    return new Dimension (width, height);
  }

  /**
   * Sets the size of this component to the specified width and height.
   *
   * @param width the new width of this component
   * @param height the new height of this component
   * @see #getSize()
   * @see #setBounds(int, int, int, int)
   */
  public void setSize(int width, int height)
  {
    resize (width, height);
  }

  /**
   * Sets the size of this component to the specified value.
   *
   * @param width the new width of the component
   * @param height the new height of the component
   * @deprecated use {@link #setSize(int, int)} instead
   */
  public void resize(int width, int height)
  {
    setBounds(this.x, this.y, width, height);
  }

  /**
   * Sets the size of this component to the specified value.
   *
   * @param d the new size of this component
   * @throws NullPointerException if d is null
   * @see #setSize(int, int)
   * @see #setBounds(int, int, int, int)
   * @since 1.1
   */
  public void setSize(Dimension d)
  {
    resize (d);
  }

  /**
   * Sets the size of this component to the specified value.
   *
   * @param d the new size of this component
   * @throws NullPointerException if d is null
   * @deprecated use {@link #setSize(Dimension)} instead
   */
  public void resize(Dimension d)
  {
    resize (d.width, d.height);
  }

  /**
   * Returns a bounding rectangle for this component. Note that the
   * returned rectange is relative to this component's parent, not to
   * the screen.
   *
   * @return the bounding rectangle for this component
   * @see #setBounds(int, int, int, int)
   * @see #getLocation()
   * @see #getSize()
   */
  public Rectangle getBounds()
  {
    return bounds ();
  }

  /**
   * Returns a bounding rectangle for this component. Note that the
   * returned rectange is relative to this component's parent, not to
   * the screen.
   *
   * @return the bounding rectangle for this component
   * @deprecated use {@link #getBounds()} instead
   */
  public Rectangle bounds()
  {
    return new Rectangle (x, y, width, height);
  }

  /**
   * Sets the bounding rectangle for this component to the specified values.
   * Note that these coordinates are relative to the parent, not to the screen.
   *
   * @param x the X coordinate of the upper left corner of the rectangle
   * @param y the Y coordinate of the upper left corner of the rectangle
   * @param w the width of the rectangle
   * @param h the height of the rectangle
   * @see #getBounds()
   * @see #setLocation(int, int)
   * @see #setLocation(Point)
   * @see #setSize(int, int)
   * @see #setSize(Dimension)
   * @since 1.1
   */
  public void setBounds(int x, int y, int w, int h)
  {
    reshape (x, y, w, h);
  }

  /**
   * Sets the bounding rectangle for this component to the specified values.
   * Note that these coordinates are relative to the parent, not to the screen.
   *
   * @param x the X coordinate of the upper left corner of the rectangle
   * @param y the Y coordinate of the upper left corner of the rectangle
   * @param width the width of the rectangle
   * @param height the height of the rectangle
   * @deprecated use {@link #setBounds(int, int, int, int)} instead
   */
  public void reshape(int x, int y, int width, int height)
  {
    // We need to lock the tree here, otherwise we risk races and
    // inconsistencies.
    synchronized (getTreeLock())
      {
        int oldx = this.x;
        int oldy = this.y;
        int oldwidth = this.width;
        int oldheight = this.height;
    
        boolean resized = oldwidth != width || oldheight != height;
        boolean moved = oldx != x || oldy != y;

        if (resized || moved)
          {
            // Update the fields.
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;

            if (peer != null)
              {
                peer.setBounds (x, y, width, height);
                if (resized)
                  invalidate();
                if (parent != null && parent.valid)
                  parent.invalidate();
              }

            // Send some events to interested listeners.
            notifyReshape(resized, moved);

            // Repaint this component and the parent if appropriate.
            if (parent != null && peer instanceof LightweightPeer
                && isShowing())
              {
                // The parent repaints the area that we occupied before.
                parent.repaint(oldx, oldy, oldwidth, oldheight);
                // This component repaints the area that we occupy now.
                repaint();
              }
          }
      }
  }

  /**
   * Sends notification to interested listeners about resizing and/or moving
   * the component. If this component has interested
   * component listeners or the corresponding event mask enabled, then
   * COMPONENT_MOVED and/or COMPONENT_RESIZED events are posted to the event
   * queue.
   *
   * @param resized true if the component has been resized, false otherwise
   * @param moved true if the component has been moved, false otherwise
   */
  void notifyReshape(boolean resized, boolean moved)
  {
    // Only post an event if this component actually has a listener
    // or has this event explicitly enabled.
    if (componentListener != null
        || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
      {
        // Fire component event on this component.
        if (moved)
          {
            ComponentEvent ce = new ComponentEvent(this,
                                               ComponentEvent.COMPONENT_MOVED);
            getToolkit().getSystemEventQueue().postEvent(ce);
          }
        if (resized)
          {
            ComponentEvent ce = new ComponentEvent(this,
                                             ComponentEvent.COMPONENT_RESIZED);
            getToolkit().getSystemEventQueue().postEvent(ce);
          }
      }
  }

  /**
   * Sets the bounding rectangle for this component to the specified
   * rectangle. Note that these coordinates are relative to the parent, not
   * to the screen.
   *
   * @param r the new bounding rectangle
   * @throws NullPointerException if r is null
   * @see #getBounds()
   * @see #setLocation(Point)
   * @see #setSize(Dimension)
   * @since 1.1
   */
  public void setBounds(Rectangle r)
  {
    setBounds (r.x, r.y, r.width, r.height);
  }

  /**
   * Gets the x coordinate of the upper left corner. This is more efficient
   * than getBounds().x or getLocation().x.
   *
   * @return the current x coordinate
   * @since 1.2
   */
  public int getX()
  {
    return x;
  }

  /**
   * Gets the y coordinate of the upper left corner. This is more efficient
   * than getBounds().y or getLocation().y.
   *
   * @return the current y coordinate
   * @since 1.2
   */
  public int getY()
  {
    return y;
  }

  /**
   * Gets the width of the component. This is more efficient than
   * getBounds().width or getSize().width.
   *
   * @return the current width
   * @since 1.2
   */
  public int getWidth()
  {
    return width;
  }

  /**
   * Gets the height of the component. This is more efficient than
   * getBounds().height or getSize().height.
   *
   * @return the current width
   * @since 1.2
   */
  public int getHeight()
  {
    return height;
  }

  /**
   * Returns the bounds of this component. This allows reuse of an existing
   * rectangle, if r is non-null.
   *
   * @param r the rectangle to use, or null
   * @return the bounds
   */
  public Rectangle getBounds(Rectangle r)
  {
    if (r == null)
      r = new Rectangle();
    r.x = x;
    r.y = y;
    r.width = width;
    r.height = height;
    return r;
  }

  /**
   * Returns the size of this component. This allows reuse of an existing
   * dimension, if d is non-null.
   *
   * @param d the dimension to use, or null
   * @return the size
   */
  public Dimension getSize(Dimension d)
  {
    if (d == null)
      d = new Dimension();
    d.width = width;
    d.height = height;
    return d;
  }

  /**
   * Returns the location of this component. This allows reuse of an existing
   * point, if p is non-null.
   *
   * @param p the point to use, or null
   * @return the location
   */
  public Point getLocation(Point p)
  {
    if (p == null)
      p = new Point();
    p.x = x;
    p.y = y;
    return p;
  }

  /**
   * Tests if this component is opaque. All "heavyweight" (natively-drawn)
   * components are opaque. A component is opaque if it draws all pixels in
   * the bounds; a lightweight component is partially transparent if it lets
   * pixels underneath show through. Subclasses that guarantee that all pixels
   * will be drawn should override this.
   *
   * @return true if this is opaque
   * @see #isLightweight()
   * @since 1.2
   */
  public boolean isOpaque()
  {
    return ! isLightweight();
  }

  /**
   * Return whether the component is lightweight. That means the component has
   * no native peer, but is displayable. This applies to subclasses of
   * Component not in this package, such as javax.swing.
   *
   * @return true if the component has a lightweight peer
   * @see #isDisplayable()
   * @since 1.2
   */
  public boolean isLightweight()
  {
    return peer instanceof LightweightPeer;
  }

  /**
   * Returns the component's preferred size.
   *
   * @return the component's preferred size
   * @see #getMinimumSize()
   * @see #setPreferredSize(Dimension)
   * @see LayoutManager
   */
  public Dimension getPreferredSize()
  {
    return preferredSize();
  }

  /**
   * Sets the preferred size that will be returned by 
   * {@link #getPreferredSize()} always, and sends a 
   * {@link PropertyChangeEvent} (with the property name 'preferredSize') to 
   * all registered listeners.
   * 
   * @param size  the preferred size (<code>null</code> permitted).
   * 
   * @since 1.5
   * 
   * @see #getPreferredSize()
   */
  public void setPreferredSize(Dimension size)
  {
    Dimension old = prefSizeSet ? prefSize : null;
    prefSize = size;
    prefSizeSet = (size != null);
    firePropertyChange("preferredSize", old, size);
  }
  
  /**
   * Returns <code>true</code> if the current preferred size is not 
   * <code>null</code> and was set by a call to 
   * {@link #setPreferredSize(Dimension)}, otherwise returns <code>false</code>.
   * 
   * @return A boolean.
   * 
   * @since 1.5
   */
  public boolean isPreferredSizeSet()
  {
    return prefSizeSet;
  }
  
  /**
   * Returns the component's preferred size.
   *
   * @return the component's preferred size
   * @deprecated use {@link #getPreferredSize()} instead
   */
  public Dimension preferredSize()
  {
    // Create a new Dimension object, so that the application doesn't mess
    // with the actual values.
    return new Dimension(preferredSizeImpl());
  }

  /**
   * The actual calculation is pulled out of preferredSize() so that
   * we can call it from Container.preferredSize() and avoid creating a
   * new intermediate Dimension object.
   * 
   * @return the preferredSize of the component
   */
  Dimension preferredSizeImpl()
  {
    Dimension size = prefSize;
    // Try to use a cached value.
    if (size == null || !(valid || prefSizeSet))
      {
        // We need to lock here, because the calculation depends on the
        // component structure not changing.
        synchronized (getTreeLock())
          {
            ComponentPeer p = peer;
            if (p != null)
              size = peer.preferredSize();
            else
              size = minimumSizeImpl();
          }
      }
    return size;
  }

  /**
   * Returns the component's minimum size.
   * 
   * @return the component's minimum size
   * @see #getPreferredSize()
   * @see #setMinimumSize(Dimension)
   * @see LayoutManager
   */
  public Dimension getMinimumSize()
  {
    return minimumSize();
  }

  /**
   * Sets the minimum size that will be returned by {@link #getMinimumSize()}
   * always, and sends a {@link PropertyChangeEvent} (with the property name
   * 'minimumSize') to all registered listeners.
   * 
   * @param size  the minimum size (<code>null</code> permitted).
   * 
   * @since 1.5
   * 
   * @see #getMinimumSize()
   */
  public void setMinimumSize(Dimension size)
  {
    Dimension old = minSizeSet ? minSize : null;
    minSize = size;
    minSizeSet = (size != null);
    firePropertyChange("minimumSize", old, size);
  }
  
  /**
   * Returns <code>true</code> if the current minimum size is not 
   * <code>null</code> and was set by a call to 
   * {@link #setMinimumSize(Dimension)}, otherwise returns <code>false</code>.
   * 
   * @return A boolean.
   * 
   * @since 1.5
   */
  public boolean isMinimumSizeSet()
  {
    return minSizeSet;
  }
  
  /**
   * Returns the component's minimum size.
   *
   * @return the component's minimum size
   * @deprecated use {@link #getMinimumSize()} instead
   */
  public Dimension minimumSize()
  {
    // Create a new Dimension object, so that the application doesn't mess
    // with the actual values.
    return new Dimension(minimumSizeImpl());
  }

  /**
   * The actual calculation is pulled out of minimumSize() so that
   * we can call it from Container.preferredSize() and
   * Component.preferredSizeImpl and avoid creating a
   * new intermediate Dimension object.
   * 
   * @return the minimum size of the component
   */
  Dimension minimumSizeImpl()
  {
    Dimension size = minSize;
    if (size == null || !(valid || minSizeSet))
      {
        // We need to lock here, because the calculation depends on the
        // component structure not changing.
        synchronized (getTreeLock())
          {
            ComponentPeer p = peer;
            if (p != null)
              size = peer.minimumSize();
            else
              size = size();
          }
      }
    return size;
  }

  /**
   * Returns the component's maximum size.
   *
   * @return the component's maximum size
   * @see #getMinimumSize()
   * @see #setMaximumSize(Dimension)
   * @see #getPreferredSize()
   * @see LayoutManager
   */
  public Dimension getMaximumSize()
  {
    return new Dimension(maximumSizeImpl());
  }

  /**
   * This is pulled out from getMaximumSize(), so that we can access it
   * from Container.getMaximumSize() without creating an additional
   * intermediate Dimension object.
   *
   * @return the maximum size of the component
   */
  Dimension maximumSizeImpl()
  {
    Dimension size;
    if (maxSizeSet)
      size = maxSize;
    else
      size = DEFAULT_MAX_SIZE;
    return size;
  }

  /**
   * Sets the maximum size that will be returned by {@link #getMaximumSize()}
   * always, and sends a {@link PropertyChangeEvent} (with the property name
   * 'maximumSize') to all registered listeners.
   * 
   * @param size  the maximum size (<code>null</code> permitted).
   * 
   * @since 1.5
   * 
   * @see #getMaximumSize()
   */
  public void setMaximumSize(Dimension size)
  {
    Dimension old = maxSizeSet ? maxSize : null;
    maxSize = size;
    maxSizeSet = (size != null);
    firePropertyChange("maximumSize", old, size);
  }

  /**
   * Returns <code>true</code> if the current maximum size is not 
   * <code>null</code> and was set by a call to 
   * {@link #setMaximumSize(Dimension)}, otherwise returns <code>false</code>.
   * 
   * @return A boolean.
   * 
   * @since 1.5
   */
  public boolean isMaximumSizeSet()
  {
    return maxSizeSet;
  }
  
  /**
   * Returns the preferred horizontal alignment of this component. The value
   * returned will be between {@link #LEFT_ALIGNMENT} and
   * {@link #RIGHT_ALIGNMENT}, inclusive.
   *
   * @return the preferred horizontal alignment of this component
   */
  public float getAlignmentX()
  {
    return CENTER_ALIGNMENT;
  }

  /**
   * Returns the preferred vertical alignment of this component. The value
   * returned will be between {@link #TOP_ALIGNMENT} and
   * {@link #BOTTOM_ALIGNMENT}, inclusive.
   *
   * @return the preferred vertical alignment of this component
   */
  public float getAlignmentY()
  {
    return CENTER_ALIGNMENT;
  }

  /**
   * Calls the layout manager to re-layout the component. This is called
   * during validation of a container in most cases.
   *
   * @see #validate()
   * @see LayoutManager
   */
  public void doLayout()
  {
    layout ();
  }

  /**
   * Calls the layout manager to re-layout the component. This is called
   * during validation of a container in most cases.
   *
   * @deprecated use {@link #doLayout()} instead
   */
  public void layout()
  {
    // Nothing to do unless we're a container.
  }

  /**
   * Called to ensure that the layout for this component is valid. This is
   * usually called on containers.
   *
   * @see #invalidate()
   * @see #doLayout()
   * @see LayoutManager
   * @see Container#validate()
   */
  public void validate()
  {
    if (! valid)
      {
        // Synchronize on the tree here as this might change the layout
        // of the hierarchy.
        synchronized (getTreeLock())
          {
            // Create local variables for thread safety.
            ComponentPeer p = peer;
            if (p != null)
              {
                // Possibly update the peer's font.
                Font newFont = getFont();
                Font oldFont = peerFont;
                // Only update when the font really changed.
                if (newFont != oldFont
                    && (oldFont == null || ! oldFont.equals(newFont)))
                  {
                    p.setFont(newFont);
                    peerFont = newFont;
                  }
                // Let the peer perform any layout.
                p.layout();
              }
          }
        valid = true;
      }
  }

  /**
   * Invalidates this component and all of its parent components. This will
   * cause them to have their layout redone. This is called frequently, so
   * make it fast.
   */
  public void invalidate()
  {
    // Need to lock here, to avoid races and other ugly stuff when doing
    // layout or structure changes in other threads.
    synchronized (getTreeLock())
      {
        // Invalidate.
        valid = false;

        // Throw away cached layout information.
        if (! minSizeSet)
          minSize = null;
        if (! prefSizeSet)
          prefSize = null;
        if (! maxSizeSet)
          maxSize = null;

        // Also invalidate the parent, if it hasn't already been invalidated.
        if (parent != null && parent.isValid())
          parent.invalidate();
      }
  }

  /**
   * Returns a graphics object for this component. Returns <code>null</code>
   * if this component is not currently displayed on the screen.
   *
   * @return a graphics object for this component
   * @see #paint(Graphics)
   */
  public Graphics getGraphics()
  {
    // Only heavyweight peers can handle this.
    ComponentPeer p = peer;
    Graphics g = null;
    if (p instanceof LightweightPeer)
      {
        if (parent != null)
          {
            g = parent.getGraphics();
            if (g != null)
              {
                g.translate(x, y);
                g.setClip(0, 0, width, height);
                g.setFont(getFont());
              }
          }
      }
    else
      {
        if (p != null)
          g = p.getGraphics();
      }
    return g;
  }

  /**
   * Returns the font metrics for the specified font in this component.
   *
   * @param font the font to retrieve metrics for
   * @return the font metrics for the specified font
   * @throws NullPointerException if font is null
   * @see #getFont()
   * @see Toolkit#getFontMetrics(Font)
   */
  public FontMetrics getFontMetrics(Font font)
  {
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    return p == null ? getToolkit().getFontMetrics(font)
           : p.getFontMetrics(font);
  }

  /**
   * Sets the cursor for this component to the specified cursor. The cursor
   * is displayed when the point is contained by the component, and the
   * component is visible, displayable, and enabled. This is inherited by
   * subcomponents unless they set their own cursor.
   *
   * @param cursor the new cursor for this component
   * @see #isEnabled()
   * @see #isShowing()
   * @see #getCursor()
   * @see #contains(int, int)
   * @see Toolkit#createCustomCursor(Image, Point, String)
   */
  public void setCursor(Cursor cursor)
  {
    this.cursor = cursor;

    // Only heavyweight peers handle this.
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    if (p != null)
      p.setCursor(cursor);
  }

  /**
   * Returns the cursor for this component. If not set, this is inherited
   * from the parent, or from Cursor.getDefaultCursor().
   *
   * @return the cursor for this component
   */
  public Cursor getCursor()
  {
    if (cursor != null)
      return cursor;
    return parent != null ? parent.getCursor() : Cursor.getDefaultCursor();
  }

  /**
   * Tests if the cursor was explicitly set, or just inherited from the parent.
   *
   * @return true if the cursor has been set
   * @since 1.4
   */
  public boolean isCursorSet()
  {
    return cursor != null;
  }

  /**
   * Paints this component on the screen. The clipping region in the graphics
   * context will indicate the region that requires painting. This is called
   * whenever the component first shows, or needs to be repaired because
   * something was temporarily drawn on top. It is not necessary for
   * subclasses to call <code>super.paint(g)</code>. Components with no area
   * are not painted.
   *
   * @param g the graphics context for this paint job
   * @see #update(Graphics)
   */
  public void paint(Graphics g)
  {
    // This is a callback method and is meant to be overridden by subclasses
    // that want to perform custom painting.
  }

  /**
   * Updates this component. This is called for heavyweight components in
   * response to {@link #repaint()}. The default implementation simply forwards
   * to {@link #paint(Graphics)}. The coordinates of the graphics are
   * relative to this component. Subclasses should call either
   * <code>super.update(g)</code> or <code>paint(g)</code>.
   *
   * @param g the graphics context for this update
   *
   * @see #paint(Graphics)
   * @see #repaint()
   */
  public void update(Graphics g)
  {
    // Note 1: We used to clear the background here for lightweights and
    // toplevel components. Tests show that this is not what the JDK does
    // here. Note that there is some special handling and background
    // clearing code in Container.update(Graphics).

    // Note 2 (for peer implementors): The JDK doesn't seem call update() for
    // toplevel components, even when an UPDATE event is sent (as a result
    // of repaint).
    paint(g);
  }

  /**
   * Paints this entire component, including any sub-components.
   *
   * @param g the graphics context for this paint job
   * 
   * @see #paint(Graphics)
   */
  public void paintAll(Graphics g)
  {
    if (isShowing())
      {
        validate();
        if (peer instanceof LightweightPeer)
          paint(g);
        else
          peer.paint(g);
      }
  }

  /**
   * Repaint this entire component. The <code>update()</code> method
   * on this component will be called as soon as possible.
   *
   * @see #update(Graphics)
   * @see #repaint(long, int, int, int, int)
   */
  public void repaint()
  {   
    repaint(0, 0, 0, width, height);
  }

  /**
   * Repaint this entire component. The <code>update()</code> method on this
   * component will be called in approximate the specified number of
   * milliseconds.
   *
   * @param tm milliseconds before this component should be repainted
   * @see #paint(Graphics)
   * @see #repaint(long, int, int, int, int)
   */
  public void repaint(long tm)
  {
    repaint(tm, 0, 0, width, height);
  }

  /**
   * Repaints the specified rectangular region within this component. The
   * <code>update</code> method on this component will be called as soon as
   * possible. The coordinates are relative to this component.
   *
   * @param x the X coordinate of the upper left of the region to repaint
   * @param y the Y coordinate of the upper left of the region to repaint
   * @param w the width of the region to repaint
   * @param h the height of the region to repaint
   * @see #update(Graphics)
   * @see #repaint(long, int, int, int, int)
   */
  public void repaint(int x, int y, int w, int h)
  {
    repaint(0, x, y, w, h);
  }

  /**
   * Repaints the specified rectangular region within this component. The
   * <code>update</code> method on this component will be called in
   * approximately the specified number of milliseconds. The coordinates
   * are relative to this component.
   *
   * @param tm milliseconds before this component should be repainted
   * @param x the X coordinate of the upper left of the region to repaint
   * @param y the Y coordinate of the upper left of the region to repaint
   * @param width the width of the region to repaint
   * @param height the height of the region to repaint
   * @see #update(Graphics)
   */
  public void repaint(long tm, int x, int y, int width, int height)
  {
    // The repaint() call has previously been delegated to
    // {@link ComponentPeer.repaint()}. Testing on the JDK using some
    // dummy peers show that this methods is never called. I think it makes
    // sense to actually perform the tasks below here, since it's pretty
    // much peer independent anyway, and makes sure only heavyweights are
    // bothered by this.
    ComponentPeer p = peer;

    // Let the nearest heavyweight parent handle repainting for lightweight
    // components.
    // We need to recursivly call repaint() on the parent here, since
    // a (lightweight) parent component might have overridden repaint()
    // to perform additional custom tasks.

    if (p instanceof LightweightPeer)
      {
        // We perform some boundary checking to restrict the paint
        // region to this component.
        if (parent != null)
          {
            int px = this.x + Math.max(0, x); 
            int py = this.y + Math.max(0, y);
            int pw = Math.min(this.width, width);
            int ph = Math.min(this.height, height);
            parent.repaint(tm, px, py, pw, ph);
          }
      }
    else
      {
        // Now send an UPDATE event to the heavyweight component that we've found.
        if (isVisible() && p != null && width > 0 && height > 0)
          {
            PaintEvent pe = new PaintEvent(this, PaintEvent.UPDATE,
                                           new Rectangle(x, y, width, height));
            getToolkit().getSystemEventQueue().postEvent(pe);
          }
      }
  }

  /**
   * Prints this component. This method is provided so that printing can be
   * done in a different manner from painting. However, the implementation
   * in this class simply calls the <code>paint()</code> method.
   *
   * @param g the graphics context of the print device
   * 
   * @see #paint(Graphics)
   */
  public void print(Graphics g)
  {
    paint(g);
  }

  /**
   * Prints this component, including all sub-components. 
   *
   * @param g the graphics context of the print device
   * 
   * @see #paintAll(Graphics)
   */
  public void printAll(Graphics g)
  {
    if( peer != null )
      peer.print( g );
    paintAll( g );
  }

  /**
   * Called when an image has changed so that this component is repainted.
   * This incrementally draws an image as more bits are available, when
   * possible. Incremental drawing is enabled if the system property
   * <code>awt.image.incrementalDraw</code> is not present or is true, in which
   * case the redraw rate is set to 100ms or the value of the system property
   * <code>awt.image.redrawrate</code>.
   *
   * <p>The coordinate system used depends on the particular flags.
   *
   * @param img the image that has been updated
   * @param flags tlags as specified in <code>ImageObserver</code>
   * @param x the X coordinate
   * @param y the Y coordinate
   * @param w the width
   * @param h the height
   * @return false if the image is completely loaded, loading has been
   * aborted, or an error has occurred.  true if more updates are
   * required.
   * @see ImageObserver
   * @see Graphics#drawImage(Image, int, int, Color, ImageObserver)
   * @see Graphics#drawImage(Image, int, int, ImageObserver)
   * @see Graphics#drawImage(Image, int, int, int, int, Color, ImageObserver)
   * @see Graphics#drawImage(Image, int, int, int, int, ImageObserver)
   * @see ImageObserver#imageUpdate(Image, int, int, int, int, int)
   */
  public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
  {
    if ((flags & (FRAMEBITS | ALLBITS)) != 0)
      repaint();
    else if ((flags & SOMEBITS) != 0)
      {
	if (incrementalDraw)
	  {
	    if (redrawRate != null)
	      {
		long tm = redrawRate.longValue();
		if (tm < 0)
		  tm = 0;
                repaint(tm);
	      }
	    else
              repaint(100);
	  }
      }
    return (flags & (ALLBITS | ABORT | ERROR)) == 0;
  }

  /**
   * Creates an image from the specified producer.
   *
   * @param producer the image procedure to create the image from
   * @return the resulting image
   */
  public Image createImage(ImageProducer producer)
  {
    // Only heavyweight peers can handle this.
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    // Sun allows producer to be null.
    Image im;
    if (p != null)
      im = p.createImage(producer);
    else
      im = getToolkit().createImage(producer);
    return im;
  }

  /**
   * Creates an image with the specified width and height for use in
   * double buffering. Headless environments do not support images.
   *
   * @param width the width of the image
   * @param height the height of the image
   * @return the requested image, or null if it is not supported
   */
  public Image createImage (int width, int height)
  {
    Image returnValue = null;
    if (!GraphicsEnvironment.isHeadless ())
      {
        // Only heavyweight peers can handle this.
        ComponentPeer p = peer;
        Component comp = this;
        while (p instanceof LightweightPeer)
          {
            comp = comp.parent;
            p = comp == null ? null : comp.peer;
          }

        if (p != null)
          returnValue = p.createImage(width, height);
      }
    return returnValue;
  }

  /**
   * Creates an image with the specified width and height for use in
   * double buffering. Headless environments do not support images.
   *
   * @param width the width of the image
   * @param height the height of the image
   * @return the requested image, or null if it is not supported
   * @since 1.4
   */
  public VolatileImage createVolatileImage(int width, int height)
  {
    // Only heavyweight peers can handle this.
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    VolatileImage im = null;
    if (p != null)
      im = p.createVolatileImage(width, height);
    return im;
  }

  /**
   * Creates an image with the specified width and height for use in
   * double buffering. Headless environments do not support images. The image
   * will support the specified capabilities.
   *
   * @param width the width of the image
   * @param height the height of the image
   * @param caps the requested capabilities
   * @return the requested image, or null if it is not supported
   * @throws AWTException if a buffer with the capabilities cannot be created
   * @since 1.4
   */
  public VolatileImage createVolatileImage(int width, int height,
                                           ImageCapabilities caps)
    throws AWTException
  {
    // Only heavyweight peers can handle this.
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    VolatileImage im = null;
    if (p != null)
      im = peer.createVolatileImage(width, height);
    return im;
  }

  /**
   * Prepares the specified image for rendering on this component.
   *
   * @param image the image to prepare for rendering
   * @param observer the observer to notify of image preparation status
   * @return true if the image is already fully prepared
   * @throws NullPointerException if image is null
   */
  public boolean prepareImage(Image image, ImageObserver observer)
  {
    return prepareImage(image, image.getWidth(observer),
                        image.getHeight(observer), observer);
  }

  /**
   * Prepares the specified image for rendering on this component at the
   * specified scaled width and height
   *
   * @param image the image to prepare for rendering
   * @param width the scaled width of the image
   * @param height the scaled height of the image
   * @param observer the observer to notify of image preparation status
   * @return true if the image is already fully prepared
   */
  public boolean prepareImage(Image image, int width, int height,
                              ImageObserver observer)
  {
    // Only heavyweight peers handle this.
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    boolean retval;
    if (p != null)
	retval = p.prepareImage(image, width, height, observer);
    else
	retval = getToolkit().prepareImage(image, width, height, observer);
    return retval;
  }

  /**
   * Returns the status of the loading of the specified image. The value
   * returned will be those flags defined in <code>ImageObserver</code>.
   *
   * @param image the image to check on
   * @param observer the observer to notify of image loading progress
   * @return the image observer flags indicating the status of the load
   * @see #prepareImage(Image, int, int, ImageObserver)
   * @see Toolkit#checkImage(Image, int, int, ImageObserver)
   * @throws NullPointerException if image is null
   */
  public int checkImage(Image image, ImageObserver observer)
  {
    return checkImage(image, -1, -1, observer);
  }

  /**
   * Returns the status of the loading of the specified image. The value
   * returned will be those flags defined in <code>ImageObserver</code>.
   *
   * @param image the image to check on
   * @param width the scaled image width
   * @param height the scaled image height
   * @param observer the observer to notify of image loading progress
   * @return the image observer flags indicating the status of the load
   * @see #prepareImage(Image, int, int, ImageObserver)
   * @see Toolkit#checkImage(Image, int, int, ImageObserver)
   */
  public int checkImage(Image image, int width, int height,
                        ImageObserver observer)
  {
    // Only heavyweight peers handle this.
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    int retval;
    if (p != null)
      retval = p.checkImage(image, width, height, observer);
    else
      retval = getToolkit().checkImage(image, width, height, observer);
    return retval;
  }

  /**
   * Sets whether paint messages delivered by the operating system should be
   * ignored. This does not affect messages from AWT, except for those
   * triggered by OS messages. Setting this to true can allow faster
   * performance in full-screen mode or page-flipping.
   *
   * @param ignoreRepaint the new setting for ignoring repaint events
   * @see #getIgnoreRepaint()
   * @see BufferStrategy
   * @see GraphicsDevice#setFullScreenWindow(Window)
   * @since 1.4
   */
  public void setIgnoreRepaint(boolean ignoreRepaint)
  {
    this.ignoreRepaint = ignoreRepaint;
  }

  /**
   * Test whether paint events from the operating system are ignored.
   *
   * @return the status of ignoring paint events
   * @see #setIgnoreRepaint(boolean)
   * @since 1.4
   */
  public boolean getIgnoreRepaint()
  {
    return ignoreRepaint;
  }

  /**
   * Tests whether or not the specified point is contained within this
   * component. Coordinates are relative to this component.
   *
   * @param x the X coordinate of the point to test
   * @param y the Y coordinate of the point to test
   * @return true if the point is within this component
   * @see #getComponentAt(int, int)
   */
  public boolean contains(int x, int y)
  {
    return inside (x, y);
  }

  /**
   * Tests whether or not the specified point is contained within this
   * component. Coordinates are relative to this component.
   *
   * @param x the X coordinate of the point to test
   * @param y the Y coordinate of the point to test
   * @return true if the point is within this component
   * @deprecated use {@link #contains(int, int)} instead
   */
  public boolean inside(int x, int y)
  {
    return x >= 0 && y >= 0 && x < width && y < height;
  }

  /**
   * Tests whether or not the specified point is contained within this
   * component. Coordinates are relative to this component.
   *
   * @param p the point to test
   * @return true if the point is within this component
   * @throws NullPointerException if p is null
   * @see #getComponentAt(Point)
   * @since 1.1
   */
  public boolean contains(Point p)
  {
    return contains (p.x, p.y);
  }

  /**
   * Returns the component occupying the position (x,y). This will either
   * be this component, an immediate child component, or <code>null</code>
   * if neither of the first two occupies the specified location.
   *
   * @param x the X coordinate to search for components at
   * @param y the Y coordinate to search for components at
   * @return the component at the specified location, or null
   * @see #contains(int, int)
   */
  public Component getComponentAt(int x, int y)
  {
    return locate (x, y);
  }

  /**
   * Returns the component occupying the position (x,y). This will either
   * be this component, an immediate child component, or <code>null</code>
   * if neither of the first two occupies the specified location.
   *
   * @param x the X coordinate to search for components at
   * @param y the Y coordinate to search for components at
   * @return the component at the specified location, or null
   * @deprecated use {@link #getComponentAt(int, int)} instead
   */
  public Component locate(int x, int y)
  {
    return contains (x, y) ? this : null;
  }

  /**
   * Returns the component occupying the position (x,y). This will either
   * be this component, an immediate child component, or <code>null</code>
   * if neither of the first two occupies the specified location.
   *
   * @param p the point to search for components at
   * @return the component at the specified location, or null
   * @throws NullPointerException if p is null
   * @see #contains(Point)
   * @since 1.1
   */
  public Component getComponentAt(Point p)
  {
    return getComponentAt (p.x, p.y);
  }

  /**
   * AWT 1.0 event delivery.
   *
   * Deliver an AWT 1.0 event to this Component.  This method simply
   * calls {@link #postEvent}.
   *
   * @param e the event to deliver
   * @deprecated use {@link #dispatchEvent (AWTEvent)} instead
   */
  public void deliverEvent (Event e)
  {
    postEvent (e);
  }

  /**
   * Forwards AWT events to processEvent() if:<ul>
   * <li>Events have been enabled for this type of event via
   * <code>enableEvents()</code></li>,
   * <li>There is at least one registered listener for this type of event</li>
   * </ul>
   *
   * @param e the event to dispatch
   */
  public final void dispatchEvent(AWTEvent e)
  {
    // Some subclasses in the AWT package need to override this behavior,
    // hence the use of dispatchEventImpl().
    dispatchEventImpl(e);
  }

  /**
   * By default, no old mouse events should be ignored.
   * This can be overridden by subclasses.
   * 
   * @return false, no mouse events are ignored.
   */
  static boolean ignoreOldMouseEvents()
  {
    return false;
  }
  
  /**
   * AWT 1.0 event handler.
   *
   * This method simply calls handleEvent and returns the result.
   *
   * @param e the event to handle
   * @return true if the event was handled, false otherwise
   * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
   */
  public boolean postEvent (Event e)
  {
    boolean handled = handleEvent (e);

    if (!handled && getParent() != null)
      // FIXME: need to translate event coordinates to parent's
      // coordinate space.
      handled = getParent ().postEvent (e);

    return handled;
  }

  /**
   * Adds the specified listener to this component. This is harmless if the
   * listener is null, but if the listener has already been registered, it
   * will now be registered twice.
   *
   * @param listener the new listener to add
   * @see ComponentEvent
   * @see #removeComponentListener(ComponentListener)
   * @see #getComponentListeners()
   * @since 1.1
   */
  public synchronized void addComponentListener(ComponentListener listener)
  {
    if (listener != null)
      {
        componentListener = AWTEventMulticaster.add(componentListener,
                                                    listener);
        newEventsOnly = true;
      }
  }

  /**
   * Removes the specified listener from the component. This is harmless if
   * the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see ComponentEvent
   * @see #addComponentListener(ComponentListener)
   * @see #getComponentListeners()
   * @since 1.1
   */
  public synchronized void removeComponentListener(ComponentListener listener)
  {
    componentListener = AWTEventMulticaster.remove(componentListener, listener);
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addComponentListener(ComponentListener)
   * @see #removeComponentListener(ComponentListener)
   * @since 1.4
   */
  public synchronized ComponentListener[] getComponentListeners()
  {
    return (ComponentListener[])
      AWTEventMulticaster.getListeners(componentListener,
                                       ComponentListener.class);
  }

  /**
   * Adds the specified listener to this component. This is harmless if the
   * listener is null, but if the listener has already been registered, it
   * will now be registered twice.
   *
   * @param listener the new listener to add
   * @see FocusEvent
   * @see #removeFocusListener(FocusListener)
   * @see #getFocusListeners()
   * @since 1.1
   */
  public synchronized void addFocusListener(FocusListener listener)
  {
    if (listener != null)
      {
        focusListener = AWTEventMulticaster.add(focusListener, listener);
        newEventsOnly = true;
      }
  }

  /**
   * Removes the specified listener from the component. This is harmless if
   * the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see FocusEvent
   * @see #addFocusListener(FocusListener)
   * @see #getFocusListeners()
   * @since 1.1
   */
  public synchronized void removeFocusListener(FocusListener listener)
  {
    focusListener = AWTEventMulticaster.remove(focusListener, listener);
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addFocusListener(FocusListener)
   * @see #removeFocusListener(FocusListener)
   * @since 1.4
   */
  public synchronized FocusListener[] getFocusListeners()
  {
    return (FocusListener[])
      AWTEventMulticaster.getListeners(focusListener, FocusListener.class);
  }

  /**
   * Adds the specified listener to this component. This is harmless if the
   * listener is null, but if the listener has already been registered, it
   * will now be registered twice.
   *
   * @param listener the new listener to add
   * @see HierarchyEvent
   * @see #removeHierarchyListener(HierarchyListener)
   * @see #getHierarchyListeners()
   * @since 1.3
   */
  public synchronized void addHierarchyListener(HierarchyListener listener)
  {
    if (listener != null)
      {
        hierarchyListener = AWTEventMulticaster.add(hierarchyListener,
                                                    listener);
        newEventsOnly = true;
        // Need to lock the tree, otherwise we might end up inconsistent.
        synchronized (getTreeLock())
        {
          numHierarchyListeners++;
          if (parent != null)
            parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
                                                1);
        }
      }
  }

  /**
   * Removes the specified listener from the component. This is harmless if
   * the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see HierarchyEvent
   * @see #addHierarchyListener(HierarchyListener)
   * @see #getHierarchyListeners()
   * @since 1.3
   */
  public synchronized void removeHierarchyListener(HierarchyListener listener)
  {
    hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener);

    // Need to lock the tree, otherwise we might end up inconsistent.
    synchronized (getTreeLock())
      {
        numHierarchyListeners--;
        if (parent != null)
          parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
                                              -1);
      }
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addHierarchyListener(HierarchyListener)
   * @see #removeHierarchyListener(HierarchyListener)
   * @since 1.4
   */
  public synchronized HierarchyListener[] getHierarchyListeners()
  {
    return (HierarchyListener[])
      AWTEventMulticaster.getListeners(hierarchyListener,
                                       HierarchyListener.class);
  }

  /**
   * Adds the specified listener to this component. This is harmless if the
   * listener is null, but if the listener has already been registered, it
   * will now be registered twice.
   *
   * @param listener the new listener to add
   * @see HierarchyEvent
   * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
   * @see #getHierarchyBoundsListeners()
   * @since 1.3
   */
  public synchronized void
    addHierarchyBoundsListener(HierarchyBoundsListener listener)
  {
    if (listener != null)
      {
        hierarchyBoundsListener =
          AWTEventMulticaster.add(hierarchyBoundsListener, listener);
        newEventsOnly = true;

        // Need to lock the tree, otherwise we might end up inconsistent.
        synchronized (getTreeLock())
        {
          numHierarchyBoundsListeners++;
          if (parent != null)
            parent.updateHierarchyListenerCount
                                     (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1);
        }
      }
  }

  /**
   * Removes the specified listener from the component. This is harmless if
   * the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see HierarchyEvent
   * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
   * @see #getHierarchyBoundsListeners()
   * @since 1.3
   */
  public synchronized void
    removeHierarchyBoundsListener(HierarchyBoundsListener listener)
  {
    hierarchyBoundsListener =
      AWTEventMulticaster.remove(hierarchyBoundsListener, listener);

    // Need to lock the tree, otherwise we might end up inconsistent.
    synchronized (getTreeLock())
      {
        numHierarchyBoundsListeners--;
        if (parent != null)
          parent.updateHierarchyListenerCount
                                         (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                          -1);
      }
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
   * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
   * @since 1.4
   */
  public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners()
  {
    return (HierarchyBoundsListener[])
      AWTEventMulticaster.getListeners(hierarchyBoundsListener,
                                       HierarchyBoundsListener.class);
  }

  /**
   * Fires a HierarchyEvent or HierarchyChangeEvent on this component.
   *
   * @param id the event id
   * @param changed the changed component
   * @param parent the parent
   * @param flags the event flags
   */
  void fireHierarchyEvent(int id, Component changed, Container parent,
                          long flags)
  {
    boolean enabled = false;
    switch (id)
    {
      case HierarchyEvent.HIERARCHY_CHANGED:
        enabled = hierarchyListener != null
                  || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0;
        break;
      case HierarchyEvent.ANCESTOR_MOVED:
      case HierarchyEvent.ANCESTOR_RESIZED:
        enabled = hierarchyBoundsListener != null
                  || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0;
        break;
      default:
        assert false : "Should not reach here";
    }
    if (enabled)
      {
        HierarchyEvent ev = new HierarchyEvent(this, id, changed, parent,
                                               flags);
        dispatchEvent(ev);
      }
  }

  /**
   * Adds the specified listener to this component. This is harmless if the
   * listener is null, but if the listener has already been registered, it
   * will now be registered twice.
   *
   * @param listener the new listener to add
   * @see KeyEvent
   * @see #removeKeyListener(KeyListener)
   * @see #getKeyListeners()
   * @since 1.1
   */
  public synchronized void addKeyListener(KeyListener listener)
  {
    if (listener != null)
      {
        keyListener = AWTEventMulticaster.add(keyListener, listener);
        newEventsOnly = true;
      }
  }

  /**
   * Removes the specified listener from the component. This is harmless if
   * the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see KeyEvent
   * @see #addKeyListener(KeyListener)
   * @see #getKeyListeners()
   * @since 1.1
   */
  public synchronized void removeKeyListener(KeyListener listener)
  {
    keyListener = AWTEventMulticaster.remove(keyListener, listener);
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addKeyListener(KeyListener)
   * @see #removeKeyListener(KeyListener)
   * @since 1.4
   */
  public synchronized KeyListener[] getKeyListeners()
  {
    return (KeyListener[])
      AWTEventMulticaster.getListeners(keyListener, KeyListener.class);
  }

  /**
   * Adds the specified listener to this component. This is harmless if the
   * listener is null, but if the listener has already been registered, it
   * will now be registered twice.
   *
   * @param listener the new listener to add
   * @see MouseEvent
   * @see #removeMouseListener(MouseListener)
   * @see #getMouseListeners()
   * @since 1.1
   */
  public synchronized void addMouseListener(MouseListener listener)
  {
    if (listener != null)
      {
        mouseListener = AWTEventMulticaster.add(mouseListener, listener);
        newEventsOnly = true;
      }
  }

  /**
   * Removes the specified listener from the component. This is harmless if
   * the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see MouseEvent
   * @see #addMouseListener(MouseListener)
   * @see #getMouseListeners()
   * @since 1.1
   */
  public synchronized void removeMouseListener(MouseListener listener)
  {
    mouseListener = AWTEventMulticaster.remove(mouseListener, listener);
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addMouseListener(MouseListener)
   * @see #removeMouseListener(MouseListener)
   * @since 1.4
   */
  public synchronized MouseListener[] getMouseListeners()
  {
    return (MouseListener[])
      AWTEventMulticaster.getListeners(mouseListener, MouseListener.class);
  }

  /**
   * Adds the specified listener to this component. This is harmless if the
   * listener is null, but if the listener has already been registered, it
   * will now be registered twice.
   *
   * @param listener the new listener to add
   * @see MouseEvent
   * @see #removeMouseMotionListener(MouseMotionListener)
   * @see #getMouseMotionListeners()
   * @since 1.1
   */
  public synchronized void addMouseMotionListener(MouseMotionListener listener)
  {
    if (listener != null)
      {
        mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener,
                                                      listener);
        newEventsOnly = true;
      }
  }

  /**
   * Removes the specified listener from the component. This is harmless if
   * the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see MouseEvent
   * @see #addMouseMotionListener(MouseMotionListener)
   * @see #getMouseMotionListeners()
   * @since 1.1
   */
  public synchronized void removeMouseMotionListener(MouseMotionListener listener)
  {
    mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener);
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addMouseMotionListener(MouseMotionListener)
   * @see #removeMouseMotionListener(MouseMotionListener)
   * @since 1.4
   */
  public synchronized MouseMotionListener[] getMouseMotionListeners()
  {
    return (MouseMotionListener[])
      AWTEventMulticaster.getListeners(mouseMotionListener,
                                       MouseMotionListener.class);
  }

  /**
   * Adds the specified listener to this component. This is harmless if the
   * listener is null, but if the listener has already been registered, it
   * will now be registered twice.
   *
   * @param listener the new listener to add
   * @see MouseEvent
   * @see MouseWheelEvent
   * @see #removeMouseWheelListener(MouseWheelListener)
   * @see #getMouseWheelListeners()
   * @since 1.4
   */
  public synchronized void addMouseWheelListener(MouseWheelListener listener)
  {
    if (listener != null)
      {
        mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener,
                                                     listener);
        newEventsOnly = true;
      }
  }

  /**
   * Removes the specified listener from the component. This is harmless if
   * the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see MouseEvent
   * @see MouseWheelEvent
   * @see #addMouseWheelListener(MouseWheelListener)
   * @see #getMouseWheelListeners()
   * @since 1.4
   */
  public synchronized void removeMouseWheelListener(MouseWheelListener listener)
  {
    mouseWheelListener = AWTEventMulticaster.remove(mouseWheelListener, listener);
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addMouseWheelListener(MouseWheelListener)
   * @see #removeMouseWheelListener(MouseWheelListener)
   * @since 1.4
   */
  public synchronized MouseWheelListener[] getMouseWheelListeners()
  {
    return (MouseWheelListener[])
      AWTEventMulticaster.getListeners(mouseWheelListener,
                                       MouseWheelListener.class);
  }

  /**
   * Adds the specified listener to this component. This is harmless if the
   * listener is null, but if the listener has already been registered, it
   * will now be registered twice.
   *
   * @param listener the new listener to add
   * @see InputMethodEvent
   * @see #removeInputMethodListener(InputMethodListener)
   * @see #getInputMethodListeners()
   * @see #getInputMethodRequests()
   * @since 1.2
   */
  public synchronized void addInputMethodListener(InputMethodListener listener)
  {
    if (listener != null)
      {
        inputMethodListener = AWTEventMulticaster.add(inputMethodListener,
                                                      listener);
        newEventsOnly = true;
      }
  }

  /**
   * Removes the specified listener from the component. This is harmless if
   * the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see InputMethodEvent
   * @see #addInputMethodListener(InputMethodListener)
   * @see #getInputMethodRequests()
   * @since 1.2
   */
  public synchronized void removeInputMethodListener(InputMethodListener listener)
  {
    inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener);
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addInputMethodListener(InputMethodListener)
   * @see #removeInputMethodListener(InputMethodListener)
   * @since 1.4
   */
  public synchronized InputMethodListener[] getInputMethodListeners()
  {
    return (InputMethodListener[])
      AWTEventMulticaster.getListeners(inputMethodListener,
                                       InputMethodListener.class);
  }

  /**
   * 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 #getComponentListeners()
   * @see #getFocusListeners()
   * @see #getHierarchyListeners()
   * @see #getHierarchyBoundsListeners()
   * @see #getKeyListeners()
   * @see #getMouseListeners()
   * @see #getMouseMotionListeners()
   * @see #getMouseWheelListeners()
   * @see #getInputMethodListeners()
   * @see #getPropertyChangeListeners()
   * @since 1.3
   */
  public <T extends EventListener> T[] getListeners(Class<T> listenerType)
  {
    if (listenerType == ComponentListener.class)
      return (T[]) getComponentListeners();
    if (listenerType == FocusListener.class)
      return (T[]) getFocusListeners();
    if (listenerType == HierarchyListener.class)
      return (T[]) getHierarchyListeners();
    if (listenerType == HierarchyBoundsListener.class)
      return (T[]) getHierarchyBoundsListeners();
    if (listenerType == KeyListener.class)
      return (T[]) getKeyListeners();
    if (listenerType == MouseListener.class)
      return (T[]) getMouseListeners();
    if (listenerType == MouseMotionListener.class)
      return (T[]) getMouseMotionListeners();
    if (listenerType == MouseWheelListener.class)
      return (T[]) getMouseWheelListeners();
    if (listenerType == InputMethodListener.class)
      return (T[]) getInputMethodListeners();
    if (listenerType == PropertyChangeListener.class)
      return (T[]) getPropertyChangeListeners();
    return (T[]) Array.newInstance(listenerType, 0);
  }

  /**
   * Returns the input method request handler, for subclasses which support
   * on-the-spot text input. By default, input methods are handled by AWT,
   * and this returns null.
   *
   * @return the input method handler, null by default
   * @since 1.2
   */
  public InputMethodRequests getInputMethodRequests()
  {
    return null;
  }

  /**
   * Gets the input context of this component, which is inherited from the
   * parent unless this is overridden.
   *
   * @return the text input context
   * @since 1.2
   */
  public InputContext getInputContext()
  {
    return parent == null ? null : parent.getInputContext();
  }

  /**
   * Enables the specified events. The events to enable are specified
   * by OR-ing together the desired masks from <code>AWTEvent</code>.
   *
   * <p>Events are enabled by default when a listener is attached to the
   * component for that event type. This method can be used by subclasses
   * to ensure the delivery of a specified event regardless of whether
   * or not a listener is attached.
   *
   * @param eventsToEnable the desired events to enable
   * @see #processEvent(AWTEvent)
   * @see #disableEvents(long)
   * @see AWTEvent
   * @since 1.1
   */
  protected final void enableEvents(long eventsToEnable)
  {
    // Update the counter for hierarchy (bounds) listeners.
    if ((eventsToEnable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
        && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0)
      {
        // Need to lock the tree, otherwise we might end up inconsistent.
        synchronized (getTreeLock())
          {
            numHierarchyListeners++;
            if (parent != null)
              parent.updateHierarchyListenerCount
                                                (AWTEvent.HIERARCHY_EVENT_MASK,
                                                 1);
          }
      }
    if ((eventsToEnable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
        && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0)
      {
        // Need to lock the tree, otherwise we might end up inconsistent.
        synchronized (getTreeLock())
          {
            numHierarchyBoundsListeners++;
            if (parent != null)
              parent.updateHierarchyListenerCount
                                         (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                          1);
          }
      }

    eventMask |= eventsToEnable;
    newEventsOnly = true;

    // Only heavyweight peers handle this.
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    if (p != null)
      p.setEventMask(eventMask);

  }

  /**
   * Disables the specified events. The events to disable are specified
   * by OR-ing together the desired masks from <code>AWTEvent</code>.
   *
   * @param eventsToDisable the desired events to disable
   * @see #enableEvents(long)
   * @since 1.1
   */
  protected final void disableEvents(long eventsToDisable)
  {
    // Update the counter for hierarchy (bounds) listeners.
    if ((eventsToDisable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
        && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0)
      {
        // Need to lock the tree, otherwise we might end up inconsistent.
        synchronized (getTreeLock())
          {
            numHierarchyListeners--;
            if (parent != null)
              parent.updateHierarchyListenerCount
                                                (AWTEvent.HIERARCHY_EVENT_MASK,
                                                 -1);
          }
      }
    if ((eventsToDisable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
        && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0)
      {
        // Need to lock the tree, otherwise we might end up inconsistent.
        synchronized (getTreeLock())
          {
            numHierarchyBoundsListeners--;
            if (parent != null)
              parent.updateHierarchyListenerCount
                                         (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                          -1);
          }
      }

    eventMask &= ~eventsToDisable;

    // Only heavyweight peers handle this.
    ComponentPeer p = peer;
    Component comp = this;
    while (p instanceof LightweightPeer)
      {
        comp = comp.parent;
        p = comp == null ? null : comp.peer;
      }

    if (p != null)
      p.setEventMask(eventMask);

  }

  /**
   * This is called by the EventQueue if two events with the same event id
   * and owner component are queued. Returns a new combined event, or null if
   * no combining is done. The coelesced events are currently mouse moves
   * (intermediate ones are discarded) and paint events (a merged paint is
   * created in place of the two events).
   *
   * @param existingEvent the event on the queue
   * @param newEvent the new event that might be entered on the queue
   * @return null if both events are kept, or the replacement coelesced event
   */
  protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
  {
    AWTEvent coalesced = null;
    switch (existingEvent.id)
      {
      case MouseEvent.MOUSE_MOVED:
      case MouseEvent.MOUSE_DRAGGED:
        // Just drop the old (intermediate) event and return the new one.
        MouseEvent me1 = (MouseEvent) existingEvent;
        MouseEvent me2 = (MouseEvent) newEvent;
        if (me1.getModifiers() == me2.getModifiers())
          coalesced = newEvent;
        break;
      case PaintEvent.PAINT:
      case PaintEvent.UPDATE:
        // For heavyweights the EventQueue should ask the peer.
        if (peer == null || peer instanceof LightweightPeer)
          {
            PaintEvent pe1 = (PaintEvent) existingEvent;
            PaintEvent pe2 = (PaintEvent) newEvent;
            Rectangle r1 = pe1.getUpdateRect();
            Rectangle r2 = pe2.getUpdateRect();
            if (r1.contains(r2))
              coalesced = existingEvent;
            else if (r2.contains(r1))
              coalesced = newEvent;
          }
        else
          {
            // Replace the event and let the heavyweight figure out the expanding
            // of the repaint area.
            coalesced = newEvent;
          }
        break;
      default:
        coalesced = null;
      }
    return coalesced;
  }

  /**
   * Processes the specified event. In this class, this method simply
   * calls one of the more specific event handlers.
   *
   * @param e the event to process
   * @throws NullPointerException if e is null
   * @see #processComponentEvent(ComponentEvent)
   * @see #processFocusEvent(FocusEvent)
   * @see #processKeyEvent(KeyEvent)
   * @see #processMouseEvent(MouseEvent)
   * @see #processMouseMotionEvent(MouseEvent)
   * @see #processInputMethodEvent(InputMethodEvent)
   * @see #processHierarchyEvent(HierarchyEvent)
   * @see #processMouseWheelEvent(MouseWheelEvent)
   * @since 1.1
   */
  protected void processEvent(AWTEvent e)
  {
    /* Note: the order of these if statements are
       important. Subclasses must be checked first. Eg. MouseEvent
       must be checked before ComponentEvent, since a MouseEvent
       object is also an instance of a ComponentEvent. */

    if (e instanceof FocusEvent)
      processFocusEvent((FocusEvent) e);
    else if (e instanceof MouseWheelEvent)
      processMouseWheelEvent((MouseWheelEvent) e);
    else if (e instanceof MouseEvent)
      {
        if (e.id == MouseEvent.MOUSE_MOVED
            || e.id == MouseEvent.MOUSE_DRAGGED)
          processMouseMotionEvent((MouseEvent) e);
        else
          processMouseEvent((MouseEvent) e);
      }
    else if (e instanceof KeyEvent)
      processKeyEvent((KeyEvent) e);
    else if (e instanceof InputMethodEvent)
      processInputMethodEvent((InputMethodEvent) e);
    else if (e instanceof ComponentEvent)
      processComponentEvent((ComponentEvent) e);
    else if (e instanceof HierarchyEvent)
      {
        if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
          processHierarchyEvent((HierarchyEvent) e);
        else
          processHierarchyBoundsEvent((HierarchyEvent) e);
      }
  }

  /**
   * Called when a component event is dispatched and component events are
   * enabled. This method passes the event along to any listeners
   * that are attached.
   *
   * @param e the <code>ComponentEvent</code> to process
   * @throws NullPointerException if e is null
   * @see ComponentListener
   * @see #addComponentListener(ComponentListener)
   * @see #enableEvents(long)
   * @since 1.1
   */
  protected void processComponentEvent(ComponentEvent e)
  {
    if (componentListener == null)
      return;
    switch (e.id)
      {
      case ComponentEvent.COMPONENT_HIDDEN:
        componentListener.componentHidden(e);
        break;
      case ComponentEvent.COMPONENT_MOVED:
        componentListener.componentMoved(e);
        break;
      case ComponentEvent.COMPONENT_RESIZED:
        componentListener.componentResized(e);
        break;
      case ComponentEvent.COMPONENT_SHOWN:
        componentListener.componentShown(e);
        break;
      }
  }

  /**
   * Called when a focus event is dispatched and component events are
   * enabled. This method passes the event along to any listeners
   * that are attached.
   *
   * @param e the <code>FocusEvent</code> to process
   * @throws NullPointerException if e is null
   * @see FocusListener
   * @see #addFocusListener(FocusListener)
   * @see #enableEvents(long)
   * @since 1.1
   */
  protected void processFocusEvent(FocusEvent e)
  {
    if (focusListener == null)
      return;

    switch (e.id)
      {
        case FocusEvent.FOCUS_GAINED:
          focusListener.focusGained(e);
        break;
        case FocusEvent.FOCUS_LOST:
          focusListener.focusLost(e);
        break;
      }
  }

  /**
   * Called when a key event is dispatched and component events are
   * enabled. This method passes the event along to any listeners
   * that are attached.
   *
   * @param e the <code>KeyEvent</code> to process
   * @throws NullPointerException if e is null
   * @see KeyListener
   * @see #addKeyListener(KeyListener)
   * @see #enableEvents(long)
   * @since 1.1
   */
  protected void processKeyEvent(KeyEvent e)
  {
    if (keyListener == null)
      return;
    switch (e.id)
      {
        case KeyEvent.KEY_PRESSED:
          keyListener.keyPressed(e);
        break;
        case KeyEvent.KEY_RELEASED:
          keyListener.keyReleased(e);
        break;
        case KeyEvent.KEY_TYPED:
          keyListener.keyTyped(e);
        break;
      }
  }

  /**
   * Called when a regular mouse event is dispatched and component events are
   * enabled. This method passes the event along to any listeners
   * that are attached.
   *
   * @param e the <code>MouseEvent</code> to process
   * @throws NullPointerException if e is null
   * @see MouseListener
   * @see #addMouseListener(MouseListener)
   * @see #enableEvents(long)
   * @since 1.1
   */
  protected void processMouseEvent(MouseEvent e)
  {
    if (mouseListener == null)
      return;
    switch (e.id)
      {
        case MouseEvent.MOUSE_CLICKED:
          mouseListener.mouseClicked(e);
        break;
        case MouseEvent.MOUSE_ENTERED:
 	  if( isLightweight() )
 	    setCursor( getCursor() );
          mouseListener.mouseEntered(e);
        break;
        case MouseEvent.MOUSE_EXITED:
          mouseListener.mouseExited(e);
        break;
        case MouseEvent.MOUSE_PRESSED:
          mouseListener.mousePressed(e);
        break;
        case MouseEvent.MOUSE_RELEASED:
          mouseListener.mouseReleased(e);
        break;
      }
  }

  /**
   * Called when a mouse motion event is dispatched and component events are
   * enabled. This method passes the event along to any listeners
   * that are attached.
   *
   * @param e the <code>MouseMotionEvent</code> to process
   * @throws NullPointerException if e is null
   * @see MouseMotionListener
   * @see #addMouseMotionListener(MouseMotionListener)
   * @see #enableEvents(long)
   * @since 1.1
   */
  protected void processMouseMotionEvent(MouseEvent e)
  {
    if (mouseMotionListener == null)
      return;
    switch (e.id)
      {
        case MouseEvent.MOUSE_DRAGGED:
          mouseMotionListener.mouseDragged(e);
        break;
        case MouseEvent.MOUSE_MOVED:
          mouseMotionListener.mouseMoved(e);
        break;
      }
      e.consume();
  }

  /**
   * Called when a mouse wheel event is dispatched and component events are
   * enabled. This method passes the event along to any listeners that are
   * attached.
   *
   * @param e the <code>MouseWheelEvent</code> to process
   * @throws NullPointerException if e is null
   * @see MouseWheelListener
   * @see #addMouseWheelListener(MouseWheelListener)
   * @see #enableEvents(long)
   * @since 1.4
   */
  protected void processMouseWheelEvent(MouseWheelEvent e)
  {
    if (mouseWheelListener != null
        && e.id == MouseEvent.MOUSE_WHEEL)
    {
      mouseWheelListener.mouseWheelMoved(e);
      e.consume();
    }	
  }

  /**
   * Called when an input method event is dispatched and component events are
   * enabled. This method passes the event along to any listeners that are
   * attached.
   *
   * @param e the <code>InputMethodEvent</code> to process
   * @throws NullPointerException if e is null
   * @see InputMethodListener
   * @see #addInputMethodListener(InputMethodListener)
   * @see #enableEvents(long)
   * @since 1.2
   */
  protected void processInputMethodEvent(InputMethodEvent e)
  {
    if (inputMethodListener == null)
      return;
    switch (e.id)
      {
        case InputMethodEvent.CARET_POSITION_CHANGED:
          inputMethodListener.caretPositionChanged(e);
        break;
        case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
          inputMethodListener.inputMethodTextChanged(e);
        break;
      }
  }

  /**
   * Called when a hierarchy change event is dispatched and component events
   * are enabled. This method passes the event along to any listeners that are
   * attached.
   *
   * @param e the <code>HierarchyEvent</code> to process
   * @throws NullPointerException if e is null
   * @see HierarchyListener
   * @see #addHierarchyListener(HierarchyListener)
   * @see #enableEvents(long)
   * @since 1.3
   */
  protected void processHierarchyEvent(HierarchyEvent e)
  {
    if (hierarchyListener == null)
      return;
    if (e.id == HierarchyEvent.HIERARCHY_CHANGED)
      hierarchyListener.hierarchyChanged(e);
  }

  /**
   * Called when a hierarchy bounds event is dispatched and component events
   * are enabled. This method passes the event along to any listeners that are
   * attached.
   *
   * @param e the <code>HierarchyEvent</code> to process
   * @throws NullPointerException if e is null
   * @see HierarchyBoundsListener
   * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
   * @see #enableEvents(long)
   * @since 1.3
   */
  protected void processHierarchyBoundsEvent(HierarchyEvent e)
  {
    if (hierarchyBoundsListener == null)
      return;
    switch (e.id)
      {
        case HierarchyEvent.ANCESTOR_MOVED:
          hierarchyBoundsListener.ancestorMoved(e);
        break;
        case HierarchyEvent.ANCESTOR_RESIZED:
          hierarchyBoundsListener.ancestorResized(e);
        break;
      }
  }

  /**
   * AWT 1.0 event handler.
   *
   * This method calls one of the event-specific handler methods.  For
   * example for key events, either {@link #keyDown(Event,int)}
   * or {@link #keyUp(Event,int)} is called.  A derived
   * component can override one of these event-specific methods if it
   * only needs to handle certain event types.  Otherwise it can
   * override handleEvent itself and handle any event.
   *
   * @param evt the event to handle
   * @return true if the event was handled, false otherwise
   * @deprecated use {@link #processEvent(AWTEvent)} instead
   */
  public boolean handleEvent (Event evt)
  {
    switch (evt.id)
      {
	// Handle key events.
      case Event.KEY_ACTION:
      case Event.KEY_PRESS:
	return keyDown (evt, evt.key);
      case Event.KEY_ACTION_RELEASE:
      case Event.KEY_RELEASE:
	return keyUp (evt, evt.key);

	// Handle mouse events.
      case Event.MOUSE_DOWN:
	return mouseDown (evt, evt.x, evt.y);
      case Event.MOUSE_UP:
	return mouseUp (evt, evt.x, evt.y);
      case Event.MOUSE_MOVE:
	return mouseMove (evt, evt.x, evt.y);
      case Event.MOUSE_DRAG:
	return mouseDrag (evt, evt.x, evt.y);
      case Event.MOUSE_ENTER:
	return mouseEnter (evt, evt.x, evt.y);
      case Event.MOUSE_EXIT:
	return mouseExit (evt, evt.x, evt.y);

	// Handle focus events.
      case Event.GOT_FOCUS:
	return gotFocus (evt, evt.arg);
      case Event.LOST_FOCUS:
	return lostFocus (evt, evt.arg);

	// Handle action event.
      case Event.ACTION_EVENT:
	return action (evt, evt.arg);
      }
    // Unknown event.
    return false;
  }

  /**
   * AWT 1.0 MOUSE_DOWN event handler.  This method is meant to be
   * overridden by components providing their own MOUSE_DOWN handler.
   * The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param x the x coordinate, ignored
   * @param y the y coordinate, ignored
   * @return false
   * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
   */
  public boolean mouseDown(Event evt, int x, int y)
  {
    return false;
  }

  /**
   * AWT 1.0 MOUSE_DRAG event handler.  This method is meant to be
   * overridden by components providing their own MOUSE_DRAG handler.
   * The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param x the x coordinate, ignored
   * @param y the y coordinate, ignored
   * @return false
   * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
   */
  public boolean mouseDrag(Event evt, int x, int y)
  {
    return false;
  }

  /**
   * AWT 1.0 MOUSE_UP event handler.  This method is meant to be
   * overridden by components providing their own MOUSE_UP handler.
   * The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param x the x coordinate, ignored
   * @param y the y coordinate, ignored
   * @return false
   * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
   */
  public boolean mouseUp(Event evt, int x, int y)
  {
    return false;
  }

  /**
   * AWT 1.0 MOUSE_MOVE event handler.  This method is meant to be
   * overridden by components providing their own MOUSE_MOVE handler.
   * The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param x the x coordinate, ignored
   * @param y the y coordinate, ignored
   * @return false
   * @deprecated use {@link #processMouseMotionEvent(MouseEvent)} instead
   */
  public boolean mouseMove(Event evt, int x, int y)
  {
    return false;
  }

  /**
   * AWT 1.0 MOUSE_ENTER event handler.  This method is meant to be
   * overridden by components providing their own MOUSE_ENTER handler.
   * The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param x the x coordinate, ignored
   * @param y the y coordinate, ignored
   * @return false
   * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
   */
  public boolean mouseEnter(Event evt, int x, int y)
  {
    return false;
  }

  /**
   * AWT 1.0 MOUSE_EXIT event handler.  This method is meant to be
   * overridden by components providing their own MOUSE_EXIT handler.
   * The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param x the x coordinate, ignored
   * @param y the y coordinate, ignored
   * @return false
   * @deprecated use {@link #processMouseEvent(MouseEvent)} instead
   */
  public boolean mouseExit(Event evt, int x, int y)
  {
    return false;
  }

  /**
   * AWT 1.0 KEY_PRESS and KEY_ACTION event handler.  This method is
   * meant to be overridden by components providing their own key
   * press handler.  The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param key the key pressed, ignored
   * @return false
   * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
   */
  public boolean keyDown(Event evt, int key)
  {
    return false;
  }

  /**
   * AWT 1.0 KEY_RELEASE and KEY_ACTION_RELEASE event handler.  This
   * method is meant to be overridden by components providing their
   * own key release handler.  The default implementation simply
   * returns false.
   *
   * @param evt the event to handle
   * @param key the key pressed, ignored
   * @return false
   * @deprecated use {@link #processKeyEvent(KeyEvent)} instead
   */
  public boolean keyUp(Event evt, int key)
  {
    return false;
  }

  /**
   * AWT 1.0 ACTION_EVENT event handler.  This method is meant to be
   * overridden by components providing their own action event
   * handler.  The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param what the object acted on, ignored
   * @return false
   * @deprecated in classes which support actions, use
   *             <code>processActionEvent(ActionEvent)</code> instead
   */
  public boolean action(Event evt, Object what)
  {
    return false;
  }

  /**
   * Called when the parent of this Component is made visible or when
   * the Component is added to an already visible Container and needs
   * to be shown.  A native peer - if any - is created at this
   * time. This method is called automatically by the AWT system and
   * should not be called by user level code.
   *
   * @see #isDisplayable()
   * @see #removeNotify()
   */
  public void addNotify()
  {
    // We need to lock the tree here to avoid races and inconsistencies.
    synchronized (getTreeLock())
      {
        if (peer == null)
          peer = getToolkit().createComponent(this);
        else if (parent != null && parent.isLightweight())
          new HeavyweightInLightweightListener(parent);
        // Now that all the children has gotten their peers, we should
        // have the event mask needed for this component and its
        //lightweight subcomponents.
        peer.setEventMask(eventMask);

        // We used to leave the invalidate() to the peer. However, I put it
        // back here for 2 reasons: 1) The RI does call invalidate() from
        // addNotify(); 2) The peer shouldn't be bother with validation too
        // much.
        invalidate();

        if (dropTarget != null) 
          dropTarget.addNotify(peer);

        // Fetch the peerFont for later installation in validate().
        peerFont = getFont();

        // Notify hierarchy listeners.
        long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
        if (isHierarchyVisible())
          flags |= HierarchyEvent.SHOWING_CHANGED;
        fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
                           flags);
      }
  }

  /**
   * Called to inform this component is has been removed from its
   * container. Its native peer - if any - is destroyed at this time.
   * This method is called automatically by the AWT system and should
   * not be called by user level code.
   *
   * @see #isDisplayable()
   * @see #addNotify()
   */
  public void removeNotify()
  {
    // We need to lock the tree here to avoid races and inconsistencies.
    synchronized (getTreeLock())
      {
        // We null our peer field before disposing of it, such that if we're
        // not the event dispatch thread and the dispatch thread is awoken by
        // the dispose call, there will be no race checking the peer's null
        // status.

        ComponentPeer tmp = peer;
        peer = null;
        peerFont = null;
        if (tmp != null)
          {
            tmp.hide();
            tmp.dispose();
          }

        // Notify hierarchy listeners.
        long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
        if (isHierarchyVisible())
          flags |= HierarchyEvent.SHOWING_CHANGED;
        fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
                           flags);
      }
  }

  /**
   * AWT 1.0 GOT_FOCUS event handler.  This method is meant to be
   * overridden by components providing their own GOT_FOCUS handler.
   * The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param what the Object focused, ignored
   * @return false
   * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
   */
  public boolean gotFocus(Event evt, Object what)
  {
    return false;
  }

  /**
   * AWT 1.0 LOST_FOCUS event handler.  This method is meant to be
   * overridden by components providing their own LOST_FOCUS handler.
   * The default implementation simply returns false.
   *
   * @param evt the event to handle
   * @param what the Object focused, ignored
   * @return false
   * @deprecated use {@link #processFocusEvent(FocusEvent)} instead
   */
  public boolean lostFocus(Event evt, Object what)
  {
    return false;
  }

  /**
   * Tests whether or not this component is in the group that can be
   * traversed using the keyboard traversal mechanism (such as the TAB key).
   *
   * @return true if the component is traversed via the TAB key
   * @see #setFocusable(boolean)
   * @since 1.1
   * @deprecated use {@link #isFocusable()} instead
   */
  public boolean isFocusTraversable()
  {
    return enabled && visible && (peer == null || isLightweight() || peer.isFocusTraversable());
  }

  /**
   * Tests if this component can receive focus.
   *
   * @return true if this component can receive focus
   * @since 1.4
   */
  public boolean isFocusable()
  {
    return focusable;
  }

  /**
   * Specify whether this component can receive focus. This method also
   * sets the {@link #isFocusTraversableOverridden} field to 1, which
   * appears to be the undocumented way {@link
   * DefaultFocusTraversalPolicy#accept(Component)} determines whether to
   * respect the {@link #isFocusable()} method of the component.
   *
   * @param focusable the new focusable status
   * @since 1.4
   */
  public void setFocusable(boolean focusable)
  {
    firePropertyChange("focusable", this.focusable, focusable);
    this.focusable = focusable;
    this.isFocusTraversableOverridden = 1;
  }

  /**
   * Sets the focus traversal keys for one of the three focus
   * traversal directions supported by Components:
   * {@link KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS},
   * {@link KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS}, or
   * {@link KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS}. Normally, the
   * default values should match the operating system's native
   * choices. To disable a given traversal, use
   * <code>Collections.EMPTY_SET</code>. The event dispatcher will
   * consume PRESSED, RELEASED, and TYPED events for the specified
   * key, although focus can only transfer on PRESSED or RELEASED.
   *
   * <p>The defaults are:
   * <table>
   *   <th><td>Identifier</td><td>Meaning</td><td>Default</td></th>
   *   <tr><td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
   *     <td>Normal forward traversal</td>
   *     <td>TAB on KEY_PRESSED, Ctrl-TAB on KEY_PRESSED</td></tr>
   *   <tr><td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
   *     <td>Normal backward traversal</td>
   *     <td>Shift-TAB on KEY_PRESSED, Ctrl-Shift-TAB on KEY_PRESSED</td></tr>
   *   <tr><td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
   *     <td>Go up a traversal cycle</td><td>None</td></tr>
   * </table>
   *
   * If keystrokes is null, this component's focus traversal key set
   * is inherited from one of its ancestors.  If none of its ancestors
   * has its own set of focus traversal keys, the focus traversal keys
   * are set to the defaults retrieved from the current
   * KeyboardFocusManager.  If not null, the set must contain only
   * AWTKeyStrokes that are not already focus keys and are not
   * KEY_TYPED events.
   *
   * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS, or
   *        UP_CYCLE_TRAVERSAL_KEYS
   * @param keystrokes a set of keys, or null
   * @throws IllegalArgumentException if id or keystrokes is invalid
   * @see #getFocusTraversalKeys(int)
   * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
   * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
   * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
   * @since 1.4
   */
  public void setFocusTraversalKeys(int id,
				    Set<? extends AWTKeyStroke> keystrokes)
  {
    if (keystrokes == null)
      {
        Container parent = getParent ();

        while (parent != null)
          {
            if (parent.areFocusTraversalKeysSet (id))
              {
                keystrokes = parent.getFocusTraversalKeys (id);
                break;
              }
            parent = parent.getParent ();
          }

        if (keystrokes == null)
          keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
            getDefaultFocusTraversalKeys (id);
      }

    Set sa;
    Set sb;
    String name;
    switch (id)
      {
      case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
        sa = getFocusTraversalKeys
          (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
        sb = getFocusTraversalKeys
          (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
        name = "forwardFocusTraversalKeys";
        break;
      case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
        sa = getFocusTraversalKeys
          (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
        sb = getFocusTraversalKeys
          (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
        name = "backwardFocusTraversalKeys";
        break;
      case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
        sa = getFocusTraversalKeys
          (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
        sb = getFocusTraversalKeys
          (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
        name = "upCycleFocusTraversalKeys";
        break;
      default:
        throw new IllegalArgumentException ();
      }

    int i = keystrokes.size ();
    Iterator iter = keystrokes.iterator ();

    while (--i >= 0)
      {
        Object o = iter.next ();
        if (!(o instanceof AWTKeyStroke)
            || sa.contains (o) || sb.contains (o)
            || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
          throw new IllegalArgumentException ();
      }

    if (focusTraversalKeys == null)
      focusTraversalKeys = new Set[3];

    keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
    firePropertyChange (name, focusTraversalKeys[id], keystrokes);

    focusTraversalKeys[id] = keystrokes;
  }

  /**
   * Returns the set of keys for a given focus traversal action, as
   * defined in <code>setFocusTraversalKeys</code>.  If not set, this
   * is inherited from the parent component, which may have gotten it
   * from the KeyboardFocusManager.
   *
   * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
   * or UP_CYCLE_TRAVERSAL_KEYS
   *
   * @return set of traversal keys
   *
   * @throws IllegalArgumentException if id is invalid
   * 
   * @see #setFocusTraversalKeys (int, Set)
   * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
   * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
   * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
   * 
   * @since 1.4
   */
  public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
  {
    if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
      throw new IllegalArgumentException();

    Set<AWTKeyStroke> s = null;

    if (focusTraversalKeys != null)
      s = focusTraversalKeys[id];

    if (s == null && parent != null)
      s = parent.getFocusTraversalKeys (id);

    return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
                        .getDefaultFocusTraversalKeys(id)) : s;
  }

  /**
   * Tests whether the focus traversal keys for a given action are explicitly
   * set or inherited.
   *
   * @param id one of FORWARD_TRAVERSAL_KEYS, BACKWARD_TRAVERSAL_KEYS,
   * or UP_CYCLE_TRAVERSAL_KEYS
   * @return true if that set is explicitly specified
   * @throws IllegalArgumentException if id is invalid
   * @see #getFocusTraversalKeys (int)
   * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
   * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
   * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
   * @since 1.4
   */
  public boolean areFocusTraversalKeysSet (int id)
  {
    if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
      throw new IllegalArgumentException ();

    return focusTraversalKeys != null && focusTraversalKeys[id] != null;
  }

  /**
   * Enable or disable focus traversal keys on this Component.  If
   * they are, then the keyboard focus manager consumes and acts on
   * key press and release events that trigger focus traversal, and
   * discards the corresponding key typed events.  If focus traversal
   * keys are disabled, then all key events that would otherwise
   * trigger focus traversal are sent to this Component.
   *
   * @param focusTraversalKeysEnabled the new value of the flag
   * @see #getFocusTraversalKeysEnabled ()
   * @see #setFocusTraversalKeys (int, Set)
   * @see #getFocusTraversalKeys (int)
   * @since 1.4
   */
  public void setFocusTraversalKeysEnabled (boolean focusTraversalKeysEnabled)
  {
    firePropertyChange ("focusTraversalKeysEnabled",
			this.focusTraversalKeysEnabled,
			focusTraversalKeysEnabled);
    this.focusTraversalKeysEnabled = focusTraversalKeysEnabled;
  }

  /**
   * Check whether or not focus traversal keys are enabled on this
   * Component.  If they are, then the keyboard focus manager consumes
   * and acts on key press and release events that trigger focus
   * traversal, and discards the corresponding key typed events.  If
   * focus traversal keys are disabled, then all key events that would
   * otherwise trigger focus traversal are sent to this Component.
   *
   * @return true if focus traversal keys are enabled
   * @see #setFocusTraversalKeysEnabled (boolean)
   * @see #setFocusTraversalKeys (int, Set)
   * @see #getFocusTraversalKeys (int)
   * @since 1.4
   */
  public boolean getFocusTraversalKeysEnabled ()
  {
    return focusTraversalKeysEnabled;
  }

  /**
   * Request that this Component be given the keyboard input focus and
   * that its top-level ancestor become the focused Window.
   *
   * For the request to be granted, the Component must be focusable,
   * displayable and showing and the top-level Window to which it
   * belongs must be focusable.  If the request is initially denied on
   * the basis that the top-level Window is not focusable, the request
   * will be remembered and granted when the Window does become
   * focused.
   *
   * Never assume that this Component is the focus owner until it
   * receives a FOCUS_GAINED event.
   *
   * The behaviour of this method is platform-dependent.
   * {@link #requestFocusInWindow()} should be used instead.
   *
   * @see #requestFocusInWindow ()
   * @see FocusEvent
   * @see #addFocusListener (FocusListener)
   * @see #isFocusable ()
   * @see #isDisplayable ()
   * @see KeyboardFocusManager#clearGlobalFocusOwner ()
   */
  public void requestFocus ()
  {
    requestFocusImpl(false, true);
  }

  /**
   * Request that this Component be given the keyboard input focus and
   * that its top-level ancestor become the focused Window.
   *
   * For the request to be granted, the Component must be focusable,
   * displayable and showing and the top-level Window to which it
   * belongs must be focusable.  If the request is initially denied on
   * the basis that the top-level Window is not focusable, the request
   * will be remembered and granted when the Window does become
   * focused.
   *
   * Never assume that this Component is the focus owner until it
   * receives a FOCUS_GAINED event.
   *
   * The behaviour of this method is platform-dependent.
   * {@link #requestFocusInWindow()} should be used instead.
   *
   * If the return value is false, the request is guaranteed to fail.
   * If the return value is true, the request will succeed unless it
   * is vetoed or something in the native windowing system intervenes,
   * preventing this Component's top-level ancestor from becoming
   * focused.  This method is meant to be called by derived
   * lightweight Components that want to avoid unnecessary repainting
   * when they know a given focus transfer need only be temporary.
   *
   * @param temporary true if the focus request is temporary
   * @return true if the request has a chance of success
   * @see #requestFocusInWindow ()
   * @see FocusEvent
   * @see #addFocusListener (FocusListener)
   * @see #isFocusable ()
   * @see #isDisplayable ()
   * @see KeyboardFocusManager#clearGlobalFocusOwner ()
   * @since 1.4
   */
  protected boolean requestFocus (boolean temporary)
  {
    return requestFocusImpl(temporary, true);
  }

  /**
   * Request that this component be given the keyboard input focus, if
   * its top-level ancestor is the currently focused Window.  A
   * <code>FOCUS_GAINED</code> event will be fired if and only if this
   * request is successful. To be successful, the component must be
   * displayable, showing, and focusable, and its ancestor top-level
   * Window must be focused.
   *
   * If the return value is false, the request is guaranteed to fail.
   * If the return value is true, the request will succeed unless it
   * is vetoed or something in the native windowing system intervenes,
   * preventing this Component's top-level ancestor from becoming
   * focused.
   *
   * @return true if the request has a chance of success
   * @see #requestFocus ()
   * @see FocusEvent
   * @see #addFocusListener (FocusListener)
   * @see #isFocusable ()
   * @see #isDisplayable ()
   * @see KeyboardFocusManager#clearGlobalFocusOwner ()
   * @since 1.4
   */
  public boolean requestFocusInWindow ()
  {
    return requestFocusImpl(false, false);
  }

  /**
   * Request that this component be given the keyboard input focus, if
   * its top-level ancestor is the currently focused Window.  A
   * <code>FOCUS_GAINED</code> event will be fired if and only if this
   * request is successful. To be successful, the component must be
   * displayable, showing, and focusable, and its ancestor top-level
   * Window must be focused.
   *
   * If the return value is false, the request is guaranteed to fail.
   * If the return value is true, the request will succeed unless it
   * is vetoed or something in the native windowing system intervenes,
   * preventing this Component's top-level ancestor from becoming
   * focused.  This method is meant to be called by derived
   * lightweight Components that want to avoid unnecessary repainting
   * when they know a given focus transfer need only be temporary.
   *
   * @param temporary true if the focus request is temporary
   * @return true if the request has a chance of success
   * @see #requestFocus ()
   * @see FocusEvent
   * @see #addFocusListener (FocusListener)
   * @see #isFocusable ()
   * @see #isDisplayable ()
   * @see KeyboardFocusManager#clearGlobalFocusOwner ()
   * @since 1.4
   */
  protected boolean requestFocusInWindow (boolean temporary)
  {
    return requestFocusImpl(temporary, false);
  }

  /**
   * Helper method for all 4 requestFocus variants.
   *
   * @param temporary indicates if the focus change is temporary
   * @param focusWindow indicates if the window focus may be changed
   *
   * @return <code>false</code> if the request has been definitely denied,
   *         <code>true</code> otherwise
   */
  private boolean requestFocusImpl(boolean temporary, boolean focusWindow)
  {
    boolean retval = false;
 
    // Don't try to focus non-focusable and non-visible components.
    if (isFocusable() && isVisible())
      {
        ComponentPeer myPeer = peer;
        if (peer != null)
          {
            // Find Window ancestor and find out if we're showing while
            // doing this.
            boolean showing = true;
            Component window = this;
            while (! (window instanceof Window))
              {
                if (! window.isVisible())
                  showing = false;
                window = window.parent;
              }
            // Don't allow focus when there is no window or the window
            // is not focusable.
            if (window != null && ((Window) window).isFocusableWindow()
                && showing)
              {
                // Search for nearest heavy ancestor (including this
                // component).
                Component heavyweightParent = this;
                while (heavyweightParent.peer instanceof LightweightPeer)
                  heavyweightParent = heavyweightParent.parent;

                // Don't allow focus on lightweight components without
                // visible heavyweight ancestor
                if (heavyweightParent != null && heavyweightParent.isVisible())
                  {
                    // Don't allow focus when heavyweightParent has no peer.
                    myPeer = heavyweightParent.peer;
                    if (myPeer != null)
                      {
                        // Register lightweight focus request.
                        if (heavyweightParent != this)
                          {
                            KeyboardFocusManager
                            .addLightweightFocusRequest(heavyweightParent,
                                                        this);
                          }

                        // Try to focus the component.
                        long time = EventQueue.getMostRecentEventTime();
                        boolean success = myPeer.requestFocus(this, temporary,
                                                              focusWindow,
                                                              time);
                        if (! success)
                          {
                            // Dequeue key events if focus request failed.
                            KeyboardFocusManager kfm =
                              KeyboardFocusManager.getCurrentKeyboardFocusManager();
                            kfm.dequeueKeyEvents(time, this);
                          }
                        retval = success;
                      }
                  }
              }
          }
      }
    return retval;
  }

  /**
   * Transfers focus to the next component in the focus traversal
   * order, as though this were the current focus owner.
   *
   * @see #requestFocus()
   * @since 1.1
   */
  public void transferFocus ()
  {
    nextFocus ();
  }

  /**
   * Returns the root container that owns the focus cycle where this
   * component resides. A focus cycle root is in two cycles, one as
   * the ancestor, and one as the focusable element; this call always
   * returns the ancestor.
   *
   * @return the ancestor container that owns the focus cycle
   * @since 1.4
   */
  public Container getFocusCycleRootAncestor ()
  {
    Container parent = getParent ();

    while (parent != null && !parent.isFocusCycleRoot())
      parent = parent.getParent ();

    return parent;
  }

  /**
   * Tests if the container is the ancestor of the focus cycle that
   * this component belongs to.
   *
   * @param c the container to test
   * @return true if c is the focus cycle root
   * @since 1.4
   */
  public boolean isFocusCycleRoot (Container c)
  {
    return c == getFocusCycleRootAncestor ();
  }

  /**
   * AWT 1.0 focus event processor.  Transfers focus to the next
   * component in the focus traversal order, as though this were the
   * current focus owner.
   *
   * @deprecated use {@link #transferFocus ()} instead
   */
  public void nextFocus ()
  {
    // Find the nearest valid (== showing && focusable && enabled) focus
    // cycle root ancestor and the focused component in it.
    Container focusRoot = getFocusCycleRootAncestor();
    Component focusComp = this;
    while (focusRoot != null
           && ! (focusRoot.isShowing() && focusRoot.isFocusable()
                 && focusRoot.isEnabled()))
      {
        focusComp = focusRoot;
        focusRoot = focusComp.getFocusCycleRootAncestor();
      }

    if (focusRoot != null)
      {
        // First try to get the componentBefore from the policy.
        FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
        Component nextFocus = policy.getComponentAfter(focusRoot, focusComp);

        // If this fails, then ask for the defaultComponent.
        if (nextFocus == null)
          nextFocus = policy.getDefaultComponent(focusRoot);

        // Request focus on this component, if not null.
        if (nextFocus != null)
          nextFocus.requestFocus();
      }
  }

  /**
   * Transfers focus to the previous component in the focus traversal
   * order, as though this were the current focus owner.
   *
   * @see #requestFocus ()
   * @since 1.4
   */
  public void transferFocusBackward ()
  {
    // Find the nearest valid (== showing && focusable && enabled) focus
    // cycle root ancestor and the focused component in it.
    Container focusRoot = getFocusCycleRootAncestor();
    Component focusComp = this;
    while (focusRoot != null
           && ! (focusRoot.isShowing() && focusRoot.isFocusable()
                 && focusRoot.isEnabled()))
      {
        focusComp = focusRoot;
        focusRoot = focusComp.getFocusCycleRootAncestor();
      }

    if (focusRoot != null)
      {
        // First try to get the componentBefore from the policy.
        FocusTraversalPolicy policy = focusRoot.getFocusTraversalPolicy();
        Component nextFocus = policy.getComponentBefore(focusRoot, focusComp);

        // If this fails, then ask for the defaultComponent.
        if (nextFocus == null)
          nextFocus = policy.getDefaultComponent(focusRoot);

        // Request focus on this component, if not null.
        if (nextFocus != null)
          nextFocus.requestFocus();
      }
  }

  /**
   * Transfers focus to the focus cycle root of this component.
   * However, if this is a Window, the default focus owner in the
   * window in the current focus cycle is focused instead.
   *
   * @see #requestFocus()
   * @see #isFocusCycleRoot(Container)
   * @since 1.4
   */
  public void transferFocusUpCycle ()
  {
    // Find the nearest focus cycle root ancestor that is itself
    // focusable, showing and enabled.
    Container focusCycleRoot = getFocusCycleRootAncestor();
    while (focusCycleRoot != null &&
           ! (focusCycleRoot.isShowing() && focusCycleRoot.isFocusable()
              && focusCycleRoot.isEnabled()))
      {
        focusCycleRoot = focusCycleRoot.getFocusCycleRootAncestor();
      }

    KeyboardFocusManager fm =
      KeyboardFocusManager.getCurrentKeyboardFocusManager();

    if (focusCycleRoot != null)
      {
        // If we found a focus cycle root, then we make this the new
        // focused component, and make it's focus cycle root the new
        // global focus cycle root. If the found root has no focus cycle
        // root ancestor itself, then the component will be both the focused
        // component and the new global focus cycle root.
        Container focusCycleAncestor =
          focusCycleRoot.getFocusCycleRootAncestor();
        Container globalFocusCycleRoot;
        if (focusCycleAncestor == null)
          globalFocusCycleRoot = focusCycleRoot;
        else
          globalFocusCycleRoot = focusCycleAncestor;

        fm.setGlobalCurrentFocusCycleRoot(globalFocusCycleRoot);
        focusCycleRoot.requestFocus();
      }
    else
      {
        // If this component has no applicable focus cycle root, we try
        // find the nearest window and set this as the new global focus cycle
        // root and the default focus component of this window the new focused
        // component.
        Container cont;
        if (this instanceof Container)
          cont = (Container) this;
        else
          cont = getParent();

        while (cont != null && !(cont instanceof Window))
          cont = cont.getParent();

        if (cont != null)
          {
            FocusTraversalPolicy policy = cont.getFocusTraversalPolicy();
            Component focusComp = policy.getDefaultComponent(cont);
            if (focusComp != null)
              {
                fm.setGlobalCurrentFocusCycleRoot(cont);
                focusComp.requestFocus();
              }
          }
      }
  }

  /**
   * Tests if this component is the focus owner. Use {@link
   * #isFocusOwner ()} instead.
   *
   * @return true if this component owns focus
   * @since 1.2
   */
  public boolean hasFocus ()
  {
    KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();

    Component focusOwner = manager.getFocusOwner ();

    return this == focusOwner;
  }

  /**
   * Tests if this component is the focus owner.
   *
   * @return true if this component owns focus
   * @since 1.4
   */
  public boolean isFocusOwner()
  {
    return hasFocus ();
  }

  /**
   * Adds the specified popup menu to this component.
   *
   * @param popup the popup menu to be added
   * 
   * @see #remove(MenuComponent)
   * 
   * @since 1.1
   */
  public synchronized void add(PopupMenu popup)
  {
    if (popups == null)
      popups = new Vector();
    popups.add(popup);

    if (popup.parent != null)
      popup.parent.remove(popup);
    popup.parent = this;
    if (peer != null)
      popup.addNotify();
  }

  /**
   * Removes the specified popup menu from this component.
   *
   * @param popup the popup menu to remove
   * @see #add(PopupMenu)
   * @since 1.1
   */
  public synchronized void remove(MenuComponent popup)
  {
    if (popups != null)
      popups.remove(popup);
  }

  /**
   * Returns a debugging string representing this component. The string may
   * be empty but not null.
   *
   * @return a string representing this component
   */
  protected String paramString()
  {
    CPStringBuilder param = new CPStringBuilder();
    String name = getName();
    if (name != null)
      param.append(name).append(",");
    param.append(x).append(",").append(y).append(",").append(width)
      .append("x").append(height);
    if (! isValid())
      param.append(",invalid");
    if (! isVisible())
      param.append(",invisible");
    if (! isEnabled())
      param.append(",disabled");
    if (! isOpaque())
      param.append(",translucent");
    if (isDoubleBuffered())
      param.append(",doublebuffered");
    if (parent == null)
      param.append(",parent=null");
    else
      param.append(",parent=").append(parent.getName());
    return param.toString();
  }

  /**
   * Returns a string representation of this component. This is implemented
   * as <code>getClass().getName() + '[' + paramString() + ']'</code>.
   *
   * @return a string representation of this component
   */
  public String toString()
  {
    return getClass().getName() + '[' + paramString() + ']';
  }

  /**
   * Prints a listing of this component to <code>System.out</code>.
   *
   * @see #list(PrintStream)
   */
  public void list()
  {
    list(System.out, 0);
  }

  /**
   * Prints a listing of this component to the specified print stream.
   *
   * @param out the <code>PrintStream</code> to print to
   */
  public void list(PrintStream out)
  {
    list(out, 0);
  }

  /**
   * Prints a listing of this component to the specified print stream,
   * starting at the specified indentation point.
   *
   * @param out the <code>PrintStream</code> to print to
   * @param indent the indentation point
   */
  public void list(PrintStream out, int indent)
  {
    for (int i = 0; i < indent; ++i)
      out.print(' ');
    out.println(toString());
  }

  /**
   * Prints a listing of this component to the specified print writer.
   *
   * @param out the <code>PrintWrinter</code> to print to
   * @since 1.1
   */
  public void list(PrintWriter out)
  {
    list(out, 0);
  }

  /**
   * Prints a listing of this component to the specified print writer,
   * starting at the specified indentation point.
   *
   * @param out the <code>PrintWriter</code> to print to
   * @param indent the indentation point
   * @since 1.1
   */
  public void list(PrintWriter out, int indent)
  {
    for (int i = 0; i < indent; ++i)
      out.print(' ');
    out.println(toString());
  }

  /**
   * Adds the specified property listener to this component. This is harmless
   * if the listener is null, but if the listener has already been registered,
   * it will now be registered twice. The property listener ignores inherited
   * properties. Recognized properties include:<br>
   * <ul>
   * <li>the font (<code>"font"</code>)</li>
   * <li>the background color (<code>"background"</code>)</li>
   * <li>the foreground color (<code>"foreground"</code>)</li>
   * <li>the focusability (<code>"focusable"</code>)</li>
   * <li>the focus key traversal enabled state
   *     (<code>"focusTraversalKeysEnabled"</code>)</li>
   * <li>the set of forward traversal keys
   *     (<code>"forwardFocusTraversalKeys"</code>)</li>
   * <li>the set of backward traversal keys
   *     (<code>"backwardFocusTraversalKeys"</code>)</li>
   * <li>the set of up-cycle traversal keys
   *     (<code>"upCycleFocusTraversalKeys"</code>)</li>
   * </ul>
   *
   * @param listener the new listener to add
   * @see #removePropertyChangeListener(PropertyChangeListener)
   * @see #getPropertyChangeListeners()
   * @see #addPropertyChangeListener(String, PropertyChangeListener)
   * @since 1.1
   */
  public void addPropertyChangeListener(PropertyChangeListener listener)
  {
    if (changeSupport == null)
      changeSupport = new PropertyChangeSupport(this);
    changeSupport.addPropertyChangeListener(listener);
  }

  /**
   * Removes the specified property listener from the component. This is
   * harmless if the listener was not previously registered.
   *
   * @param listener the listener to remove
   * @see #addPropertyChangeListener(PropertyChangeListener)
   * @see #getPropertyChangeListeners()
   * @see #removePropertyChangeListener(String, PropertyChangeListener)
   * @since 1.1
   */
  public void removePropertyChangeListener(PropertyChangeListener listener)
  {
    if (changeSupport != null)
      changeSupport.removePropertyChangeListener(listener);
  }

  /**
   * Returns an array of all specified listeners registered on this component.
   *
   * @return an array of listeners
   * @see #addPropertyChangeListener(PropertyChangeListener)
   * @see #removePropertyChangeListener(PropertyChangeListener)
   * @see #getPropertyChangeListeners(String)
   * @since 1.4
   */
  public PropertyChangeListener[] getPropertyChangeListeners()
  {
    return changeSupport == null ? new PropertyChangeListener[0]
      : changeSupport.getPropertyChangeListeners();
  }

  /**
   * Adds the specified property listener to this component. This is harmless
   * if the listener is null, but if the listener has already been registered,
   * it will now be registered twice. The property listener ignores inherited
   * properties. The listener is keyed to a single property. Recognized
   * properties include:<br>
   * <ul>
   * <li>the font (<code>"font"</code>)</li>
   * <li>the background color (<code>"background"</code>)</li>
   * <li>the foreground color (<code>"foreground"</code>)</li>
   * <li>the focusability (<code>"focusable"</code>)</li>
   * <li>the focus key traversal enabled state
   *     (<code>"focusTraversalKeysEnabled"</code>)</li>
   * <li>the set of forward traversal keys
   *     (<code>"forwardFocusTraversalKeys"</code>)</li>
p   * <li>the set of backward traversal keys
   *     (<code>"backwardFocusTraversalKeys"</code>)</li>
   * <li>the set of up-cycle traversal keys
   *     (<code>"upCycleFocusTraversalKeys"</code>)</li>
   * </ul>
   *
   * @param propertyName the property name to filter on
   * @param listener the new listener to add
   * @see #removePropertyChangeListener(String, PropertyChangeListener)
   * @see #getPropertyChangeListeners(String)
   * @see #addPropertyChangeListener(PropertyChangeListener)
   * @since 1.1
   */
  public void addPropertyChangeListener(String propertyName,
                                        PropertyChangeListener listener)
  {
    if (changeSupport == null)
      changeSupport = new PropertyChangeSupport(this);
    changeSupport.addPropertyChangeListener(propertyName, listener);
  }

  /**
   * Removes the specified property listener on a particular property from
   * the component. This is harmless if the listener was not previously
   * registered.
   *
   * @param propertyName the property name to filter on
   * @param listener the listener to remove
   * @see #addPropertyChangeListener(String, PropertyChangeListener)
   * @see #getPropertyChangeListeners(String)
   * @see #removePropertyChangeListener(PropertyChangeListener)
   * @since 1.1
   */
  public void removePropertyChangeListener(String propertyName,
                                           PropertyChangeListener listener)
  {
    if (changeSupport != null)
      changeSupport.removePropertyChangeListener(propertyName, listener);
  }

  /**
   * Returns an array of all specified listeners on the named property that
   * are registered on this component.
   *
   * @return an array of listeners
   * @see #addPropertyChangeListener(String, PropertyChangeListener)
   * @see #removePropertyChangeListener(String, PropertyChangeListener)
   * @see #getPropertyChangeListeners()
   * @since 1.4
   */
  public PropertyChangeListener[] getPropertyChangeListeners(String property)
  {
    return changeSupport == null ? new PropertyChangeListener[0]
      : changeSupport.getPropertyChangeListeners(property);
  }

  /**
   * Report a change in a bound property to any registered property listeners.
   *
   * @param propertyName the property that changed
   * @param oldValue the old property value
   * @param newValue the new property value
   */
  protected void firePropertyChange(String propertyName, Object oldValue,
                                    Object newValue)
  {
    if (changeSupport != null)
      changeSupport.firePropertyChange(propertyName, oldValue, newValue);  
  }

  /**
   * Report a change in a bound property to any registered property listeners.
   *
   * @param propertyName the property that changed
   * @param oldValue the old property value
   * @param newValue the new property value
   */
  protected void firePropertyChange(String propertyName, boolean oldValue,
                                    boolean newValue)
  {
    if (changeSupport != null)
      changeSupport.firePropertyChange(propertyName, oldValue, newValue);
  }

  /**
   * Report a change in a bound property to any registered property listeners.
   *
   * @param propertyName the property that changed
   * @param oldValue the old property value
   * @param newValue the new property value
   */
  protected void firePropertyChange(String propertyName, int oldValue,
                                    int newValue)
  {
    if (changeSupport != null)
      changeSupport.firePropertyChange(propertyName, oldValue, newValue);
  }

  /**
   * Report a change in a bound property to any registered property listeners.
   *
   * @param propertyName the property that changed
   * @param oldValue the old property value
   * @param newValue the new property value
   *
   * @since 1.5
   */
  public void firePropertyChange(String propertyName, byte oldValue,
                                    byte newValue)
  {
    if (changeSupport != null)
      changeSupport.firePropertyChange(propertyName, new Byte(oldValue),
                                       new Byte(newValue));
  }

  /**
   * Report a change in a bound property to any registered property listeners.
   *
   * @param propertyName the property that changed
   * @param oldValue the old property value
   * @param newValue the new property value
   *
   * @since 1.5
   */
  public void firePropertyChange(String propertyName, char oldValue,
                                    char newValue)
  {
    if (changeSupport != null)
      changeSupport.firePropertyChange(propertyName, new Character(oldValue),
                                       new Character(newValue));
  }

  /**
   * Report a change in a bound property to any registered property listeners.
   *
   * @param propertyName the property that changed
   * @param oldValue the old property value
   * @param newValue the new property value
   *
   * @since 1.5
   */
  public void firePropertyChange(String propertyName, short oldValue,
                                    short newValue)
  {
    if (changeSupport != null)
      changeSupport.firePropertyChange(propertyName, new Short(oldValue),
                                       new Short(newValue));
  }

  /**
   * Report a change in a bound property to any registered property listeners.
   *
   * @param propertyName the property that changed
   * @param oldValue the old property value
   * @param newValue the new property value
   *
   * @since 1.5
   */
  public void firePropertyChange(String propertyName, long oldValue,
                                    long newValue)
  {
    if (changeSupport != null)
      changeSupport.firePropertyChange(propertyName, new Long(oldValue),
                                       new Long(newValue));
  }

  /**
   * Report a change in a bound property to any registered property listeners.
   *
   * @param propertyName the property that changed
   * @param oldValue the old property value
   * @param newValue the new property value
   *
   * @since 1.5
   */
  public void firePropertyChange(String propertyName, float oldValue,
                                    float newValue)
  {
    if (changeSupport != null)
      changeSupport.firePropertyChange(propertyName, new Float(oldValue),
                                       new Float(newValue));
  }


  /**
   * Report a change in a bound property to any registered property listeners.
   *
   * @param propertyName the property that changed
   * @param oldValue the old property value
   * @param newValue the new property value
   *
   * @since 1.5
   */
  public void firePropertyChange(String propertyName, double oldValue,
                                 double newValue)
  {
    if (changeSupport != null)
      changeSupport.firePropertyChange(propertyName, new Double(oldValue),
                                       new Double(newValue));
  }

  /**
   * Sets the text layout orientation of this component. New components default
   * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects only
   * the current component, while
   * {@link #applyComponentOrientation(ComponentOrientation)} affects the
   * entire hierarchy.
   *
   * @param o the new orientation (<code>null</code> is accepted)
   * @see #getComponentOrientation()
   */
  public void setComponentOrientation(ComponentOrientation o)
  {
 
    ComponentOrientation oldOrientation = componentOrientation;
    componentOrientation = o;
    firePropertyChange("componentOrientation", oldOrientation, o);
  }

  /**
   * Determines the text layout orientation used by this component.
   *
   * @return the component orientation (this can be <code>null</code>)
   * @see #setComponentOrientation(ComponentOrientation)
   */
  public ComponentOrientation getComponentOrientation()
  {
    return componentOrientation;
  }

  /**
   * Sets the text layout orientation of this component. New components default
   * to UNKNOWN (which behaves like LEFT_TO_RIGHT). This method affects the
   * entire hierarchy, while
   * {@link #setComponentOrientation(ComponentOrientation)} affects only the
   * current component.
   *
   * @param o the new orientation
   * @throws NullPointerException if o is null
   * @see #getComponentOrientation()
   * @since 1.4
   */
  public void applyComponentOrientation(ComponentOrientation o)
  {
    setComponentOrientation(o);
  }

  /**
   * Returns the accessibility framework context of this class. Component is
   * not accessible, so the default implementation returns null. Subclasses
   * must override this behavior, and return an appropriate subclass of
   * {@link AccessibleAWTComponent}.
   *
   * @return the accessibility context
   */
  public AccessibleContext getAccessibleContext()
  {
    return null;
  }


  // Helper methods; some are package visible for use by subclasses.

  /**
   * Subclasses should override this to return unique component names like
   * "menuitem0".
   *
   * @return the generated name for this component
   */
  String generateName()
  {
    // Component is abstract.
    return null;
  }

  /**
   * Sets the peer for this component.
   *
   * @param peer the new peer
   */
  final void setPeer(ComponentPeer peer)
  {
    this.peer = peer;
  }

  /**
   * Translate an AWT 1.1 event ({@link AWTEvent}) into an AWT 1.0
   * event ({@link Event}).
   *
   * @param e an AWT 1.1 event to translate
   *
   * @return an AWT 1.0 event representing e
   */
  static Event translateEvent (AWTEvent e)
  {
    Object target = e.getSource ();
    Event translated = null;
    
    if (e instanceof WindowEvent)
      {
        WindowEvent we = (WindowEvent) e;
        int id = we.id;
        int newId = 0;
        
        switch (id)
          {
          case WindowEvent.WINDOW_DEICONIFIED:
            newId = Event.WINDOW_DEICONIFY;
            break;
          case WindowEvent.WINDOW_CLOSED:
          case WindowEvent.WINDOW_CLOSING:
            newId = Event.WINDOW_DESTROY;
            break;
          case WindowEvent.WINDOW_ICONIFIED:
            newId = Event.WINDOW_ICONIFY;
            break;
          case WindowEvent.WINDOW_GAINED_FOCUS:
            newId = Event.GOT_FOCUS;
            break;
          case WindowEvent.WINDOW_LOST_FOCUS:
            newId = Event.LOST_FOCUS;
            break;
          default:
            return null;
          }

        translated = new Event(target, 0, newId, 0, 0, 0, 0);
      }
    else if (e instanceof InputEvent)
      {
        InputEvent ie = (InputEvent) e;
        long when = ie.getWhen ();

        int oldID = 0;
        int id = e.getID ();

        int oldMods = 0;
        int mods = ie.getModifiersEx ();

        if ((mods & InputEvent.BUTTON2_DOWN_MASK) != 0)
          oldMods |= Event.META_MASK;
        else if ((mods & InputEvent.BUTTON3_DOWN_MASK) != 0)
          oldMods |= Event.ALT_MASK;

        if ((mods & InputEvent.SHIFT_DOWN_MASK) != 0)
          oldMods |= Event.SHIFT_MASK;

        if ((mods & InputEvent.CTRL_DOWN_MASK) != 0)
          oldMods |= Event.CTRL_MASK;

        if ((mods & InputEvent.META_DOWN_MASK) != 0)
          oldMods |= Event.META_MASK;

        if ((mods & InputEvent.ALT_DOWN_MASK) != 0)
          oldMods |= Event.ALT_MASK;

        if (e instanceof MouseEvent && !ignoreOldMouseEvents())
          {
            if (id == MouseEvent.MOUSE_PRESSED)
              oldID = Event.MOUSE_DOWN;
            else if (id == MouseEvent.MOUSE_RELEASED)
              oldID = Event.MOUSE_UP;
            else if (id == MouseEvent.MOUSE_MOVED)
              oldID = Event.MOUSE_MOVE;
            else if (id == MouseEvent.MOUSE_DRAGGED)
              oldID = Event.MOUSE_DRAG;
            else if (id == MouseEvent.MOUSE_ENTERED)
              oldID = Event.MOUSE_ENTER;
            else if (id == MouseEvent.MOUSE_EXITED)
              oldID = Event.MOUSE_EXIT;
            else
              // No analogous AWT 1.0 mouse event.
              return null;

            MouseEvent me = (MouseEvent) e;

            translated = new Event (target, when, oldID,
                                    me.getX (), me.getY (), 0, oldMods);
          }
        else if (e instanceof KeyEvent)
          {
            if (id == KeyEvent.KEY_PRESSED)
              oldID = Event.KEY_PRESS;
            else if (e.getID () == KeyEvent.KEY_RELEASED)
              oldID = Event.KEY_RELEASE;
            else
              // No analogous AWT 1.0 key event.
              return null;

            int oldKey = 0;
            int newKey = ((KeyEvent) e).getKeyCode ();
            switch (newKey)
              {
              case KeyEvent.VK_BACK_SPACE:
                oldKey = Event.BACK_SPACE;
                break;
              case KeyEvent.VK_CAPS_LOCK:
                oldKey = Event.CAPS_LOCK;
                break;
              case KeyEvent.VK_DELETE:
                oldKey = Event.DELETE;
                break;
              case KeyEvent.VK_DOWN:
              case KeyEvent.VK_KP_DOWN:
                oldKey = Event.DOWN;
                break;
              case KeyEvent.VK_END:
                oldKey = Event.END;
                break;
              case KeyEvent.VK_ENTER:
                oldKey = Event.ENTER;
                break;
              case KeyEvent.VK_ESCAPE:
                oldKey = Event.ESCAPE;
                break;
              case KeyEvent.VK_F1:
                oldKey = Event.F1;
                break;
              case KeyEvent.VK_F10:
                oldKey = Event.F10;
                break;
              case KeyEvent.VK_F11:
                oldKey = Event.F11;
                break;
              case KeyEvent.VK_F12:
                oldKey = Event.F12;
                break;
              case KeyEvent.VK_F2:
                oldKey = Event.F2;
                break;
              case KeyEvent.VK_F3:
                oldKey = Event.F3;
                break;
              case KeyEvent.VK_F4:
                oldKey = Event.F4;
                break;
              case KeyEvent.VK_F5:
                oldKey = Event.F5;
                break;
              case KeyEvent.VK_F6:
                oldKey = Event.F6;
                break;
              case KeyEvent.VK_F7:
                oldKey = Event.F7;
                break;
              case KeyEvent.VK_F8:
                oldKey = Event.F8;
                break;
              case KeyEvent.VK_F9:
                oldKey = Event.F9;
                break;
              case KeyEvent.VK_HOME:
                oldKey = Event.HOME;
                break;
              case KeyEvent.VK_INSERT:
                oldKey = Event.INSERT;
                break;
              case KeyEvent.VK_LEFT:
              case KeyEvent.VK_KP_LEFT:
                oldKey = Event.LEFT;
                break;
              case KeyEvent.VK_NUM_LOCK:
                oldKey = Event.NUM_LOCK;
                break;
              case KeyEvent.VK_PAUSE:
                oldKey = Event.PAUSE;
                break;
              case KeyEvent.VK_PAGE_DOWN:
                oldKey = Event.PGDN;
                break;
              case KeyEvent.VK_PAGE_UP:
                oldKey = Event.PGUP;
                break;
              case KeyEvent.VK_PRINTSCREEN:
                oldKey = Event.PRINT_SCREEN;
                break;
              case KeyEvent.VK_RIGHT:
              case KeyEvent.VK_KP_RIGHT:
                oldKey = Event.RIGHT;
                break;
              case KeyEvent.VK_SCROLL_LOCK:
                oldKey = Event.SCROLL_LOCK;
                break;
              case KeyEvent.VK_TAB:
                oldKey = Event.TAB;
                break;
              case KeyEvent.VK_UP:
              case KeyEvent.VK_KP_UP:
                oldKey = Event.UP;
                break;
              default:
                oldKey = ((KeyEvent) e).getKeyChar();
              }

            translated = new Event (target, when, oldID,
                                    0, 0, oldKey, oldMods);
          }
      }
    else if (e instanceof AdjustmentEvent)
      {
	AdjustmentEvent ae = (AdjustmentEvent) e;
	int type = ae.getAdjustmentType();
	int oldType;
	if (type == AdjustmentEvent.BLOCK_DECREMENT)
	  oldType = Event.SCROLL_PAGE_UP;
	else if (type == AdjustmentEvent.BLOCK_INCREMENT)
	  oldType = Event.SCROLL_PAGE_DOWN;
	else if (type == AdjustmentEvent.TRACK)
	  oldType = Event.SCROLL_ABSOLUTE;
	else if (type == AdjustmentEvent.UNIT_DECREMENT)
	  oldType = Event.SCROLL_LINE_UP;
	else if (type == AdjustmentEvent.UNIT_INCREMENT)
	  oldType = Event.SCROLL_LINE_DOWN;
	else
	  oldType = type;
	translated = new Event(target, oldType, new Integer(ae.getValue()));
      }
    else if (e instanceof ActionEvent)
      translated = new Event (target, Event.ACTION_EVENT,
                              ((ActionEvent) e).getActionCommand ());

    return translated;
  }

  /**
   * Implementation of dispatchEvent. Allows trusted package classes
   * to dispatch additional events first.  This implementation first
   * translates <code>e</code> to an AWT 1.0 event and sends the
   * result to {@link #postEvent}.  If the AWT 1.0 event is not
   * handled, and events of type <code>e</code> are enabled for this
   * component, e is passed on to {@link #processEvent}.
   *
   * @param e the event to dispatch
   */
  void dispatchEventImpl(AWTEvent e)
  {
    // Update the component's knowledge about the size.
    // Important: Please look at the big comment in ComponentReshapeEvent
    // to learn why we did it this way. If you change this code, make
    // sure that the peer->AWT bounds update still works.
    // (for instance: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29448 )
    if (e instanceof ComponentReshapeEvent)
      {
        ComponentReshapeEvent reshape = (ComponentReshapeEvent) e;
        x = reshape.x;
        y = reshape.y;
        width = reshape.width;
        height = reshape.height;
        return;
      }

    // Retarget focus events before dispatching it to the KeyboardFocusManager
    // in order to handle lightweight components properly.
    boolean dispatched = false;
    if (! e.isFocusManagerEvent)
      {
        e = KeyboardFocusManager.retargetFocusEvent(e);
        dispatched = KeyboardFocusManager.getCurrentKeyboardFocusManager()
                                          .dispatchEvent(e);
      }

    if (! dispatched)
      {
        // Give toolkit a chance to dispatch the event
        // to globally registered listeners.
        Toolkit.getDefaultToolkit().globalDispatchEvent(e);

        if (newEventsOnly)
          {
            if (eventTypeEnabled(e.id))
              processEvent(e);
          }
        else
          {
            Event oldEvent = translateEvent(e);
            if (oldEvent != null)
              postEvent (oldEvent);
          }
        if (peer != null)
          peer.handleEvent(e);
      }
  }

  /**
   * Tells whether or not an event type is enabled.
   */
  boolean eventTypeEnabled (int type)
  {
    if (type > AWTEvent.RESERVED_ID_MAX)
      return true;

    switch (type)
      {
      case HierarchyEvent.HIERARCHY_CHANGED:
        return (hierarchyListener != null 
            || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0);
        
      case HierarchyEvent.ANCESTOR_MOVED:
      case HierarchyEvent.ANCESTOR_RESIZED:
        return (hierarchyBoundsListener != null 
            || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0);
        
      case ComponentEvent.COMPONENT_HIDDEN:
      case ComponentEvent.COMPONENT_MOVED:
      case ComponentEvent.COMPONENT_RESIZED:
      case ComponentEvent.COMPONENT_SHOWN:
        return (componentListener != null
                || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0);

      case KeyEvent.KEY_PRESSED:
      case KeyEvent.KEY_RELEASED:
      case KeyEvent.KEY_TYPED:
        return (keyListener != null
                || (eventMask & AWTEvent.KEY_EVENT_MASK) != 0);

      case MouseEvent.MOUSE_CLICKED:
      case MouseEvent.MOUSE_ENTERED:
      case MouseEvent.MOUSE_EXITED:
      case MouseEvent.MOUSE_PRESSED:
      case MouseEvent.MOUSE_RELEASED:
        return (mouseListener != null
                || (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
      case MouseEvent.MOUSE_MOVED:
      case MouseEvent.MOUSE_DRAGGED:
        return (mouseMotionListener != null
                || (eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0);
      case MouseEvent.MOUSE_WHEEL:
        return (mouseWheelListener != null
                || (eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0);
        
      case FocusEvent.FOCUS_GAINED:
      case FocusEvent.FOCUS_LOST:
        return (focusListener != null
                || (eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0);

      case InputMethodEvent.INPUT_METHOD_TEXT_CHANGED:
      case InputMethodEvent.CARET_POSITION_CHANGED:
        return (inputMethodListener != null
                || (eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0);
        
      case PaintEvent.PAINT:
      case PaintEvent.UPDATE:
        return (eventMask & AWTEvent.PAINT_EVENT_MASK) != 0;
        
      default:
        return false;
      }
  }

  /**
   * Returns <code>true</code> when this component and all of its ancestors
   * are visible, <code>false</code> otherwise.
   *
   * @return <code>true</code> when this component and all of its ancestors
   *         are visible, <code>false</code> otherwise
   */
  boolean isHierarchyVisible()
  {
    boolean visible = isVisible();
    Component comp = parent;
    while (comp != null && visible)
      {
        comp = comp.parent;
        if (comp != null)
          visible = visible && comp.isVisible();
      }
    return visible;
  }

  /**
   * Returns the mouse pointer position relative to this Component's
   * top-left corner.
   *
   * @return relative mouse pointer position
   *
   * @throws HeadlessException if in a headless environment
   */
  public Point getMousePosition() throws HeadlessException
  {
    return getMousePositionHelper(true);
  }

  Point getMousePositionHelper(boolean allowChildren) throws HeadlessException
  {
    if (GraphicsEnvironment.isHeadless())
      throw new HeadlessException("can't get mouse position"
                                  + " in headless environment");
    if (!isShowing())
      return null;

    Component parent = this;
    int windowRelativeXOffset = 0;
    int windowRelativeYOffset = 0;
    while (parent != null && !(parent instanceof Window))
      {
        windowRelativeXOffset += parent.getX();
        windowRelativeYOffset += parent.getY();
        parent = parent.getParent();
      }
    if (parent == null)
      return null;

    Window window = (Window) parent;
    if (!Toolkit.getDefaultToolkit()
        .getMouseInfoPeer().isWindowUnderMouse(window))
      return null;

    PointerInfo info = MouseInfo.getPointerInfo();
    Point mouseLocation = info.getLocation();
    Point windowLocation = window.getLocationOnScreen();

    int x = mouseLocation.x - windowLocation.x;
    int y = mouseLocation.y - windowLocation.y;

    if (!mouseOverComponent(window.getComponentAt(x, y), allowChildren))
      return null;

    return new Point(x - windowRelativeXOffset, y - windowRelativeYOffset);
  }

  boolean mouseOverComponent(Component component, boolean allowChildren)
  {
    return component == this;
  }

  /**
   * This method is used to implement transferFocus(). CHILD is the child
   * making the request. This is overridden by Container; when called for an
   * ordinary component there is no child and so we always return null.
   *
   * FIXME: is this still needed, in light of focus traversal policies?
   *
   * @param child the component making the request
   * @return the next component to focus on
   */
  Component findNextFocusComponent(Component child)
  {
    return null;
  }

  /**
   * Deserializes this component. This regenerates all serializable listeners
   * which were registered originally.
   *
   * @param s the stream to read from
   * @throws ClassNotFoundException if deserialization fails
   * @throws IOException if the stream fails
   */
  private void readObject(ObjectInputStream s)
    throws ClassNotFoundException, IOException
  {
    s.defaultReadObject();
    String key = (String) s.readObject();
    while (key != null)
      {
        Object listener = s.readObject();
        if ("componentL".equals(key))
          addComponentListener((ComponentListener) listener);
        else if ("focusL".equals(key))
          addFocusListener((FocusListener) listener);
        else if ("keyL".equals(key))
          addKeyListener((KeyListener) listener);
        else if ("mouseL".equals(key))
          addMouseListener((MouseListener) listener);
        else if ("mouseMotionL".equals(key))
          addMouseMotionListener((MouseMotionListener) listener);
        else if ("inputMethodL".equals(key))
          addInputMethodListener((InputMethodListener) listener);
        else if ("hierarchyL".equals(key))
          addHierarchyListener((HierarchyListener) listener);
        else if ("hierarchyBoundsL".equals(key))
          addHierarchyBoundsListener((HierarchyBoundsListener) listener);
        else if ("mouseWheelL".equals(key))
          addMouseWheelListener((MouseWheelListener) listener);
        key = (String) s.readObject();
      }
  }

  /**
   * Serializes this component. This ignores all listeners which do not
   * implement Serializable, but includes those that do.
   *
   * @param s the stream to write to
   * @throws IOException if the stream fails
   */
  private void writeObject(ObjectOutputStream s) throws IOException
  {
    s.defaultWriteObject();
    AWTEventMulticaster.save(s, "componentL", componentListener);
    AWTEventMulticaster.save(s, "focusL", focusListener);
    AWTEventMulticaster.save(s, "keyL", keyListener);
    AWTEventMulticaster.save(s, "mouseL", mouseListener);
    AWTEventMulticaster.save(s, "mouseMotionL", mouseMotionListener);
    AWTEventMulticaster.save(s, "inputMethodL", inputMethodListener);
    AWTEventMulticaster.save(s, "hierarchyL", hierarchyListener);
    AWTEventMulticaster.save(s, "hierarchyBoundsL", hierarchyBoundsListener);
    AWTEventMulticaster.save(s, "mouseWheelL", mouseWheelListener);
    s.writeObject(null);
  }

  
  // Nested classes.
  
  /**
   * This class fixes the bounds for a Heavyweight component that
   * is placed inside a Lightweight container. When the lightweight is
   * moved or resized, setBounds for the lightweight peer does nothing.
   * Therefore, it was never moved on the screen. This class is 
   * attached to the lightweight, and it adjusts the position and size
   * of the peer when notified.
   * This is the same for show and hide.
   */
  class HeavyweightInLightweightListener
      implements ComponentListener
  {
    
    /**
     * Constructor. Adds component listener to lightweight parent.
     * 
     * @param parent - the lightweight container.
     */
    public HeavyweightInLightweightListener(Container parent)
    {
      parent.addComponentListener(this);
    }
    
    /**
     * This method is called when the component is resized.
     * 
     * @param event the <code>ComponentEvent</code> indicating the resize
     */
    public void componentResized(ComponentEvent event)
    {
      // Nothing to do here, componentMoved will be called.
    }

    /**
     * This method is called when the component is moved.
     * 
     * @param event the <code>ComponentEvent</code> indicating the move
     */
    public void componentMoved(ComponentEvent event)
    {
      if (peer != null)
        peer.setBounds(x, y, width, height);
    }

    /**
     * This method is called when the component is made visible.
     * 
     * @param event the <code>ComponentEvent</code> indicating the visibility
     */
    public void componentShown(ComponentEvent event)
    {
      if (isShowing())
        peer.show();
    }

    /**
     * This method is called when the component is hidden.
     * 
     * @param event the <code>ComponentEvent</code> indicating the visibility
     */
    public void componentHidden(ComponentEvent event)
    {
      if (isShowing())
        peer.hide();
    }
  }
  
  /**
   * This class provides accessibility support for subclasses of container.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   * @since 1.3
   * @status updated to 1.4
   */
  protected abstract class AccessibleAWTComponent extends AccessibleContext
    implements Serializable, AccessibleComponent
  {
    /**
     * Compatible with JDK 1.3+.
     */
    private static final long serialVersionUID = 642321655757800191L;

    /**
     * Converts show/hide events to PropertyChange events, and is registered
     * as a component listener on this component.
     *
     * @serial the component handler
     */
    protected ComponentListener accessibleAWTComponentHandler
      = new AccessibleAWTComponentHandler();

    /**
     * Converts focus events to PropertyChange events, and is registered
     * as a focus listener on this component.
     *
     * @serial the focus handler
     */
    protected FocusListener accessibleAWTFocusHandler
      = new AccessibleAWTFocusHandler();

    /**
     * The default constructor.
     */
    protected AccessibleAWTComponent()
    {
      Component.this.addComponentListener(accessibleAWTComponentHandler);
      Component.this.addFocusListener(accessibleAWTFocusHandler);
    }

    /**
     * Adds a global property change listener to the accessible component.
     *
     * @param l the listener to add
     * @see #ACCESSIBLE_NAME_PROPERTY
     * @see #ACCESSIBLE_DESCRIPTION_PROPERTY
     * @see #ACCESSIBLE_STATE_PROPERTY
     * @see #ACCESSIBLE_VALUE_PROPERTY
     * @see #ACCESSIBLE_SELECTION_PROPERTY
     * @see #ACCESSIBLE_TEXT_PROPERTY
     * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
     */
    public void addPropertyChangeListener(PropertyChangeListener l)
    {
      Component.this.addPropertyChangeListener(l);
      super.addPropertyChangeListener(l);
    }

    /**
     * Removes a global property change listener from this accessible
     * component.
     *
     * @param l the listener to remove
     */
    public void removePropertyChangeListener(PropertyChangeListener l)
    {
      Component.this.removePropertyChangeListener(l);
      super.removePropertyChangeListener(l);
    }

    /**
     * Returns the accessible name of this component. It is almost always
     * wrong to return getName(), since it is not localized. In fact, for
     * things like buttons, this should be the text of the button, not the
     * name of the object. The tooltip text might also be appropriate.
     *
     * @return the name
     * @see #setAccessibleName(String)
     */
    public String getAccessibleName()
    {
      return accessibleName;
    }

    /**
     * Returns a brief description of this accessible context. This should
     * be localized.
     *
     * @return a description of this component
     * @see #setAccessibleDescription(String)
     */
    public String getAccessibleDescription()
    {
      return accessibleDescription;
    }

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

    /**
     * Returns a state set describing this component's state.
     *
     * @return a new state set
     * @see AccessibleState
     */
    public AccessibleStateSet getAccessibleStateSet()
    {
      AccessibleStateSet s = new AccessibleStateSet();
      if (Component.this.isEnabled())
        s.add(AccessibleState.ENABLED);
      if (isFocusable())
        s.add(AccessibleState.FOCUSABLE);
      if (isFocusOwner())
        s.add(AccessibleState.FOCUSED);
      // Note: While the java.awt.Component has an 'opaque' property, it
      // seems that it is not added to the accessible state set here, even
      // if this property is true. However, it is handled for
      // javax.swing.JComponent, so we add it there.
      if (Component.this.isShowing())
        s.add(AccessibleState.SHOWING);
      if (Component.this.isVisible())
        s.add(AccessibleState.VISIBLE);
      return s;
    }

    /**
     * Returns the parent of this component, if it is accessible.
     *
     * @return the accessible parent
     */
    public Accessible getAccessibleParent()
    {
      if (accessibleParent == null)
        {
          Container parent = getParent();
          accessibleParent = parent instanceof Accessible
            ? (Accessible) parent : null;
        }
      return accessibleParent;
    }

    /**
     * Returns the index of this component in its accessible parent.
     *
     * @return the index, or -1 if the parent is not accessible
     * @see #getAccessibleParent()
     */
    public int getAccessibleIndexInParent()
    {
      if (getAccessibleParent() == null)
        return -1;
      AccessibleContext context
        = ((Component) accessibleParent).getAccessibleContext();
      if (context == null)
        return -1;
      for (int i = context.getAccessibleChildrenCount(); --i >= 0; )
        if (context.getAccessibleChild(i) == Component.this)
          return i;
      return -1;
    }

    /**
     * Returns the number of children of this component which implement
     * Accessible. Subclasses must override this if they can have children.
     *
     * @return the number of accessible children, default 0
     */
    public int getAccessibleChildrenCount()
    {
      return 0;
    }

    /**
     * Returns the ith accessible child. Subclasses must override this if
     * they can have children.
     *
     * @return the ith accessible child, or null
     * @see #getAccessibleChildrenCount()
     */
    public Accessible getAccessibleChild(int i)
    {
      return null;
    }

    /**
     * Returns the locale of this component.
     *
     * @return the locale
     * @throws IllegalComponentStateException if the locale is unknown
     */
    public Locale getLocale()
    {
      return Component.this.getLocale();
    }

    /**
     * Returns this, since it is an accessible component.
     *
     * @return the accessible component
     */
    public AccessibleComponent getAccessibleComponent()
    {
      return this;
    }

    /**
     * Gets the background color.
     *
     * @return the background color
     * @see #setBackground(Color)
     */
    public Color getBackground()
    {
      return Component.this.getBackground();
    }

    /**
     * Sets the background color.
     *
     * @param c the background color
     * @see #getBackground()
     * @see #isOpaque()
     */
    public void setBackground(Color c)
    {
      Component.this.setBackground(c);
    }

    /**
     * Gets the foreground color.
     *
     * @return the foreground color
     * @see #setForeground(Color)
     */
    public Color getForeground()
    {
      return Component.this.getForeground();
    }

    /**
     * Sets the foreground color.
     *
     * @param c the foreground color
     * @see #getForeground()
     */
    public void setForeground(Color c)
    {
      Component.this.setForeground(c);
    }

    /**
     * Gets the cursor.
     *
     * @return the cursor
     * @see #setCursor(Cursor)
     */
    public Cursor getCursor()
    {
      return Component.this.getCursor();
    }

    /**
     * Sets the cursor.
     *
     * @param cursor the cursor
     * @see #getCursor()
     */
    public void setCursor(Cursor cursor)
    {
      Component.this.setCursor(cursor);
    }

    /**
     * Gets the font.
     *
     * @return the font
     * @see #setFont(Font)
     */
    public Font getFont()
    {
      return Component.this.getFont();
    }

    /**
     * Sets the font.
     *
     * @param f the font
     * @see #getFont()
     */
    public void setFont(Font f)
    {
      Component.this.setFont(f);
    }

    /**
     * Gets the font metrics for a font.
     *
     * @param f the font to look up
     * @return its metrics
     * @throws NullPointerException if f is null
     * @see #getFont()
     */
    public FontMetrics getFontMetrics(Font f)
    {
      return Component.this.getFontMetrics(f);
    }

    /**
     * Tests if the component is enabled.
     *
     * @return true if the component is enabled
     * @see #setEnabled(boolean)
     * @see #getAccessibleStateSet()
     * @see AccessibleState#ENABLED
     */
    public boolean isEnabled()
    {
      return Component.this.isEnabled();
    }

    /**
     * Set whether the component is enabled.
     *
     * @param b the new enabled status
     * @see #isEnabled()
     */
    public void setEnabled(boolean b)
    {
      Component.this.setEnabled(b);
    }

    /**
     * Test whether the component is visible (not necesarily showing).
     *
     * @return true if it is visible
     * @see #setVisible(boolean)
     * @see #getAccessibleStateSet()
     * @see AccessibleState#VISIBLE
     */
    public boolean isVisible()
    {
      return Component.this.isVisible();
    }

    /**
     * Sets the visibility of this component.
     *
     * @param b the desired visibility
     * @see #isVisible()
     */
    public void setVisible(boolean b)
    {
      Component.this.setVisible(b);
    }

    /**
     * Tests if the component is showing.
     *
     * @return true if this is showing
     */
    public boolean isShowing()
    {
      return Component.this.isShowing();
    }

    /**
     * Tests if the point is contained in this component.
     *
     * @param p the point to check
     * @return true if it is contained
     * @throws NullPointerException if p is null
     */
    public boolean contains(Point p)
    {
      return Component.this.contains(p.x, p.y);
    }

    /**
     * Returns the location of this object on the screen, or null if it is
     * not showing.
     *
     * @return the location relative to screen coordinates, if showing
     * @see #getBounds()
     * @see #getLocation()
     */
    public Point getLocationOnScreen()
    {
      return Component.this.isShowing() ? Component.this.getLocationOnScreen()
        : null;
    }

    /**
     * Returns the location of this object relative to its parent's coordinate
     * system, or null if it is not showing.
     *
     * @return the location
     * @see #getBounds()
     * @see #getLocationOnScreen()
     */
    public Point getLocation()
    {
      return Component.this.getLocation();
    }

    /**
     * Sets the location of this relative to its parent's coordinate system.
     *
     * @param p the location
     * @throws NullPointerException if p is null
     * @see #getLocation()
     */
    public void setLocation(Point p)
    {
      Component.this.setLocation(p.x, p.y);
    }

    /**
     * Gets the bounds of this component, or null if it is not on screen.
     *
     * @return the bounds
     * @see #contains(Point)
     * @see #setBounds(Rectangle)
     */
    public Rectangle getBounds()
    {
      return Component.this.getBounds();
    }

    /**
     * Sets the bounds of this component.
     *
     * @param r the bounds
     * @throws NullPointerException if r is null
     * @see #getBounds()
     */
    public void setBounds(Rectangle r)
    {
      Component.this.setBounds(r.x, r.y, r.width, r.height);
    }

    /**
     * Gets the size of this component, or null if it is not showing.
     *
     * @return the size
     * @see #setSize(Dimension)
     */
    public Dimension getSize()
    {
      return Component.this.getSize();
    }

    /**
     * Sets the size of this component.
     *
     * @param d the size
     * @throws NullPointerException if d is null
     * @see #getSize()
     */
    public void setSize(Dimension d)
    {
      Component.this.setSize(d.width, d.height);
    }

    /**
     * Returns the Accessible child at a point relative to the coordinate
     * system of this component, if one exists, or null. Since components
     * have no children, subclasses must override this to get anything besides
     * null.
     *
     * @param p the point to check
     * @return the accessible child at that point
     * @throws NullPointerException if p is null
     */
    public Accessible getAccessibleAt(Point p)
    {
      return null;
    }

    /**
     * Tests whether this component can accept focus.
     *
     * @return true if this is focus traversable
     * @see #getAccessibleStateSet ()
     * @see AccessibleState#FOCUSABLE
     * @see AccessibleState#FOCUSED
     */
    public boolean isFocusTraversable ()
    {
      return Component.this.isFocusTraversable ();
    }

    /**
     * Requests focus for this component.
     *
     * @see #isFocusTraversable ()
     */
    public void requestFocus ()
    {
      Component.this.requestFocus ();
    }

    /**
     * Adds a focus listener.
     *
     * @param l the listener to add
     */
    public void addFocusListener(FocusListener l)
    {
      Component.this.addFocusListener(l);
    }

    /**
     * Removes a focus listener.
     *
     * @param l the listener to remove
     */
    public void removeFocusListener(FocusListener l)
    {
      Component.this.removeFocusListener(l);
    }

    /**
     * Converts component changes into property changes.
     *
     * @author Eric Blake (ebb9@email.byu.edu)
     * @since 1.3
     * @status updated to 1.4
     */
    protected class AccessibleAWTComponentHandler implements ComponentListener
    {
      /**
       * Default constructor.
       */
      protected AccessibleAWTComponentHandler()
      {
        // Nothing to do here.
      }

      /**
       * Convert a component hidden to a property change.
       *
       * @param e the event to convert
       */
      public void componentHidden(ComponentEvent e)
      {
        AccessibleAWTComponent.this.firePropertyChange
          (ACCESSIBLE_STATE_PROPERTY, AccessibleState.VISIBLE, null);
      }

      /**
       * Convert a component shown to a property change.
       *
       * @param e the event to convert
       */
      public void componentShown(ComponentEvent e)
      {
        AccessibleAWTComponent.this.firePropertyChange
          (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.VISIBLE);
      }

      /**
       * Moving a component does not affect properties.
       *
       * @param e ignored
       */
      public void componentMoved(ComponentEvent e)
      {
        // Nothing to do here.
      }

      /**
       * Resizing a component does not affect properties.
       *
       * @param e ignored
       */
      public void componentResized(ComponentEvent e)
      {
        // Nothing to do here.
      }
    } // class AccessibleAWTComponentHandler

    /**
     * Converts focus changes into property changes.
     *
     * @author Eric Blake (ebb9@email.byu.edu)
     * @since 1.3
     * @status updated to 1.4
     */
    protected class AccessibleAWTFocusHandler implements FocusListener
    {
      /**
       * Default constructor.
       */
      protected AccessibleAWTFocusHandler()
      {
        // Nothing to do here.
      }

      /**
       * Convert a focus gained to a property change.
       *
       * @param e the event to convert
       */
      public void focusGained(FocusEvent e)
      {
        AccessibleAWTComponent.this.firePropertyChange
          (ACCESSIBLE_STATE_PROPERTY, null, AccessibleState.FOCUSED);
      }

      /**
       * Convert a focus lost to a property change.
       *
       * @param e the event to convert
       */
      public void focusLost(FocusEvent e)
      {
        AccessibleAWTComponent.this.firePropertyChange
          (ACCESSIBLE_STATE_PROPERTY, AccessibleState.FOCUSED, null);
      }
    } // class AccessibleAWTComponentHandler
  } // class AccessibleAWTComponent

  /**
   * This class provides support for blitting offscreen surfaces to a
   * component.
   *
   * @see BufferStrategy
   *
   * @since 1.4
   */
  protected class BltBufferStrategy extends BufferStrategy
  {
    /**
     * The capabilities of the image buffer.
     */
    protected BufferCapabilities caps;

    /**
     * The back buffers used in this strategy.
     */
    protected VolatileImage[] backBuffers;

    /**
     * Whether or not the image buffer resources are allocated and
     * ready to be drawn into.
     */
    protected boolean validatedContents;

    /**
     * The width of the back buffers.
     */
    protected int width;

    /**
     * The height of the back buffers.
     */
    protected int height;

    /**
     * The front buffer.
     */
    private VolatileImage frontBuffer;

    /**
     * Creates a blitting buffer strategy.
     *
     * @param numBuffers the number of buffers, including the front
     * buffer
     * @param caps the capabilities of this strategy
     */
    protected BltBufferStrategy(int numBuffers, BufferCapabilities caps)
    {
      this.caps = caps;
      createBackBuffers(numBuffers - 1);
      width = getWidth();
      height = getHeight();
    }

    /**
     * Initializes the backBuffers field with an array of numBuffers
     * VolatileImages.
     *
     * @param numBuffers the number of backbuffers to create
     */
    protected void createBackBuffers(int numBuffers)
    {
      GraphicsConfiguration c =
	GraphicsEnvironment.getLocalGraphicsEnvironment()
	.getDefaultScreenDevice().getDefaultConfiguration();

      backBuffers = new VolatileImage[numBuffers];

      for (int i = 0; i < numBuffers; i++)
	backBuffers[i] = c.createCompatibleVolatileImage(width, height);
    }

    /**
     * Retrieves the capabilities of this buffer strategy.
     *
     * @return the capabilities of this buffer strategy
     */
    public BufferCapabilities getCapabilities()
    {
      return caps;
    }

    /**
     * Retrieves a graphics object that can be used to draw into this
     * strategy's image buffer.
     *
     * @return a graphics object
     */
    public Graphics getDrawGraphics()
    {
      // Return the backmost buffer's graphics.
      return backBuffers[0].getGraphics();
    }

    /**
     * Bring the contents of the back buffer to the front buffer.
     */
    public void show()
    {
      GraphicsConfiguration c =
	GraphicsEnvironment.getLocalGraphicsEnvironment()
	.getDefaultScreenDevice().getDefaultConfiguration();

      // draw the front buffer.
      getGraphics().drawImage(backBuffers[backBuffers.length - 1],
			      width, height, null);

      BufferCapabilities.FlipContents f = getCapabilities().getFlipContents();

      // blit the back buffers.
      for (int i = backBuffers.length - 1; i > 0 ; i--)
	backBuffers[i] = backBuffers[i - 1];

      // create new backmost buffer.
      if (f == BufferCapabilities.FlipContents.UNDEFINED)
	backBuffers[0] = c.createCompatibleVolatileImage(width, height);

      // create new backmost buffer and clear it to the background
      // color.
      if (f == BufferCapabilities.FlipContents.BACKGROUND)
	{
	  backBuffers[0] = c.createCompatibleVolatileImage(width, height);
	  backBuffers[0].getGraphics().clearRect(0, 0, width, height);
	}

      // FIXME: set the backmost buffer to the prior contents of the
      // front buffer.  How do we retrieve the contents of the front
      // buffer?
      //
      //      if (f == BufferCapabilities.FlipContents.PRIOR)

      // set the backmost buffer to a copy of the new front buffer.
      if (f == BufferCapabilities.FlipContents.COPIED)
	backBuffers[0] = backBuffers[backBuffers.length - 1];
    }

    /**
     * Re-create the image buffer resources if they've been lost.
     */
    protected void revalidate()
    {
      GraphicsConfiguration c =
	GraphicsEnvironment.getLocalGraphicsEnvironment()
	.getDefaultScreenDevice().getDefaultConfiguration();

      for (int i = 0; i < backBuffers.length; i++)
	{
	  int result = backBuffers[i].validate(c);
	  if (result == VolatileImage.IMAGE_INCOMPATIBLE)
	    backBuffers[i] = c.createCompatibleVolatileImage(width, height);
	}
      validatedContents = true;
    }

    /**
     * Returns whether or not the image buffer resources have been
     * lost.
     *
     * @return true if the resources have been lost, false otherwise
     */
    public boolean contentsLost()
    {
      for (int i = 0; i < backBuffers.length; i++)
	{
	  if (backBuffers[i].contentsLost())
	    {
	      validatedContents = false;
	      return true;
	    }
	}
      // we know that the buffer resources are valid now because we
      // just checked them
      validatedContents = true;
      return false;
    }

    /**
     * Returns whether or not the image buffer resources have been
     * restored.
     *
     * @return true if the resources have been restored, false
     * otherwise
     */
    public boolean contentsRestored()
    {
      GraphicsConfiguration c =
	GraphicsEnvironment.getLocalGraphicsEnvironment()
	.getDefaultScreenDevice().getDefaultConfiguration();

      boolean imageRestored = false;

      for (int i = 0; i < backBuffers.length; i++)
	{
	  int result = backBuffers[i].validate(c);
	  if (result == VolatileImage.IMAGE_RESTORED)
	    imageRestored = true;
	  else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
	    return false;
	}
      // we know that the buffer resources are valid now because we
      // just checked them
      validatedContents = true;
      return imageRestored;
    }
  }

  /**
   * This class provides support for flipping component buffers. It
   * can only be used on Canvases and Windows.
   *
   * @since 1.4
   */
  protected class FlipBufferStrategy extends BufferStrategy
  {
    /**
     * The number of buffers.
     */
    protected int numBuffers;

    /**
     * The capabilities of this buffering strategy.
     */
    protected BufferCapabilities caps;

    /**
     * An Image reference to the drawing buffer.
     */
    protected Image drawBuffer;

    /**
     * A VolatileImage reference to the drawing buffer.
     */
    protected VolatileImage drawVBuffer;

    /**
     * Whether or not the image buffer resources are allocated and
     * ready to be drawn into.
     */
    protected boolean validatedContents;

    /**
     * The width of the back buffer.
     */
    private int width;

    /**
     * The height of the back buffer.
     */
    private int height;

    /**
     * Creates a flipping buffer strategy.  The only supported
     * strategy for FlipBufferStrategy itself is a double-buffer page
     * flipping strategy.  It forms the basis for more complex derived
     * strategies.
     *
     * @param numBuffers the number of buffers
     * @param caps the capabilities of this buffering strategy
     *
     * @throws AWTException if the requested
     * number-of-buffers/capabilities combination is not supported
     */
    protected FlipBufferStrategy(int numBuffers, BufferCapabilities caps)
      throws AWTException
    {
      this.caps = caps;
      width = getWidth();
      height = getHeight();

      if (numBuffers > 1)
	createBuffers(numBuffers, caps);
      else
	{
	  drawVBuffer = peer.createVolatileImage(width, height);
	  drawBuffer = drawVBuffer;
	}
    }

    /**
     * Creates a multi-buffer flipping strategy.  The number of
     * buffers must be greater than one and the buffer capabilities
     * must specify page flipping.
     *
     * @param numBuffers the number of flipping buffers; must be
     * greater than one
     * @param caps the buffering capabilities; caps.isPageFlipping()
     * must return true
     *
     * @throws IllegalArgumentException if numBuffers is not greater
     * than one or if the page flipping capability is not requested
     *
     * @throws AWTException if the requested flipping strategy is not
     * supported
     */
    protected void createBuffers(int numBuffers, BufferCapabilities caps)
      throws AWTException
    {
      if (numBuffers <= 1)
	throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
					   + " numBuffers must be greater than"
					   + " one.");

      if (!caps.isPageFlipping())
	throw new IllegalArgumentException("FlipBufferStrategy.createBuffers:"
					   + " flipping must be a specified"
					   + " capability.");

      peer.createBuffers(numBuffers, caps);
    }

    /**
     * Return a direct reference to the back buffer image.
     *
     * @return a direct reference to the back buffer image.
     */
    protected Image getBackBuffer()
    {
      return peer.getBackBuffer();
    }

    /**
     * Perform a flip operation to transfer the contents of the back
     * buffer to the front buffer.
     */
    protected void flip(BufferCapabilities.FlipContents flipAction)
    {
      peer.flip(flipAction);
    }

    /**
     * Release the back buffer's resources.
     */
    protected void destroyBuffers()
    {
      peer.destroyBuffers();
    }

    /**
     * Retrieves the capabilities of this buffer strategy.
     *
     * @return the capabilities of this buffer strategy
     */
    public BufferCapabilities getCapabilities()
    {
      return caps;
    }

    /**
     * Retrieves a graphics object that can be used to draw into this
     * strategy's image buffer.
     *
     * @return a graphics object
     */
    public Graphics getDrawGraphics()
    {
      return drawVBuffer.getGraphics();
    }

    /**
     * Re-create the image buffer resources if they've been lost.
     */
    protected void revalidate()
    {
      GraphicsConfiguration c =
	GraphicsEnvironment.getLocalGraphicsEnvironment()
	.getDefaultScreenDevice().getDefaultConfiguration();

      if (drawVBuffer.validate(c) == VolatileImage.IMAGE_INCOMPATIBLE)
	drawVBuffer = peer.createVolatileImage(width, height);
      validatedContents = true;
    }

    /**
     * Returns whether or not the image buffer resources have been
     * lost.
     *
     * @return true if the resources have been lost, false otherwise
     */
    public boolean contentsLost()
    {
      if (drawVBuffer.contentsLost())
	{
	  validatedContents = false;
	  return true;
	}
      // we know that the buffer resources are valid now because we
      // just checked them
      validatedContents = true;
      return false;
    }

    /**
     * Returns whether or not the image buffer resources have been
     * restored.
     *
     * @return true if the resources have been restored, false
     * otherwise
     */
    public boolean contentsRestored()
    {
      GraphicsConfiguration c =
	GraphicsEnvironment.getLocalGraphicsEnvironment()
	.getDefaultScreenDevice().getDefaultConfiguration();

      int result = drawVBuffer.validate(c);

      boolean imageRestored = false;

      if (result == VolatileImage.IMAGE_RESTORED)
	imageRestored = true;
      else if (result == VolatileImage.IMAGE_INCOMPATIBLE)
	return false;

      // we know that the buffer resources are valid now because we
      // just checked them
      validatedContents = true;
      return imageRestored;
    }

    /**
     * Bring the contents of the back buffer to the front buffer.
     */
    public void show()
    {
      flip(caps.getFlipContents());
    }
  }
}
