/* Container.java -- parent container class in AWT
   Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 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.lang.CPStringBuilder;

import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.peer.LightweightPeer;
import java.beans.PropertyChangeListener;
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.util.Collections;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.accessibility.Accessible;

/**
 * A generic window toolkit object that acts as a container for other objects.
 * Components are tracked in a list, and new elements are at the end of the
 * list or bottom of the stacking order.
 *
 * @author original author unknown
 * @author Eric Blake (ebb9@email.byu.edu)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 *
 * @since 1.0
 *
 * @status still missing 1.4 support, some generics from 1.5
 */
public class Container extends Component
{
  /**
   * Compatible with JDK 1.0+.
   */
  private static final long serialVersionUID = 4613797578919906343L;

  /* Serialized fields from the serialization spec. */
  int ncomponents;
  Component[] component;
  LayoutManager layoutMgr;

  /**
   * @since 1.4
   */
  boolean focusCycleRoot;

  /**
   * Indicates if this container provides a focus traversal policy.
   *
   * @since 1.5
   */
  private boolean focusTraversalPolicyProvider;

  int containerSerializedDataVersion;

  /* Anything else is non-serializable, and should be declared "transient". */
  transient ContainerListener containerListener;

  /** The focus traversal policy that determines how focus is
      transferred between this Container and its children. */
  private FocusTraversalPolicy focusTraversalPolicy;

  /**
   * The focus traversal keys, if not inherited from the parent or default
   * keyboard 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
   */
  transient Set[] focusTraversalKeys;

  /**
   * Default constructor for subclasses.
   */
  public Container()
  {
    // Nothing to do here.
  }

  /**
   * Returns the number of components in this container.
   *
   * @return The number of components in this container.
   */
  public int getComponentCount()
  {
    return countComponents ();
  }

  /**
   * Returns the number of components in this container.
   *
   * @return The number of components in this container.
   *
   * @deprecated use {@link #getComponentCount()} instead
   */
  public int countComponents()
  {
    return ncomponents;
  }

  /**
   * Returns the component at the specified index.
   *
   * @param n The index of the component to retrieve.
   *
   * @return The requested component.
   *
   * @throws ArrayIndexOutOfBoundsException If the specified index is invalid
   */
  public Component getComponent(int n)
  {
    synchronized (getTreeLock ())
      {
        if (n < 0 || n >= ncomponents)
          throw new ArrayIndexOutOfBoundsException("no such component");

        return component[n];
      }
  }

  /**
   * Returns an array of the components in this container.
   *
   * @return The components in this container.
   */
  public Component[] getComponents()
  {
    synchronized (getTreeLock ())
      {
        Component[] result = new Component[ncomponents];

        if (ncomponents > 0)
          System.arraycopy(component, 0, result, 0, ncomponents);

        return result;
      }
  }

  /**
   * Returns the insets for this container, which is the space used for
   * borders, the margin, etc.
   *
   * @return The insets for this container.
   */
  public Insets getInsets()
  {
    return insets ();
  }

  /**
   * Returns the insets for this container, which is the space used for
   * borders, the margin, etc.
   *
   * @return The insets for this container.
   * @deprecated use {@link #getInsets()} instead
   */
  public Insets insets()
  {
    Insets i;
    if (peer == null || peer instanceof LightweightPeer)
      i = new Insets (0, 0, 0, 0);
    else
      i = ((ContainerPeer) peer).getInsets ();
    return i;
  }

  /**
   * Adds the specified component to this container at the end of the
   * component list.
   *
   * @param comp The component to add to the container.
   *
   * @return The same component that was added.
   */
  public Component add(Component comp)
  {
    addImpl(comp, null, -1);
    return comp;
  }

  /**
   * Adds the specified component to the container at the end of the
   * component list.  This method should not be used. Instead, use
   * <code>add(Component, Object)</code>.
   *
   * @param name The name of the component to be added.
   * @param comp The component to be added.
   *
   * @return The same component that was added.
   *
   * @see #add(Component,Object)
   */
  public Component add(String name, Component comp)
  {
    addImpl(comp, name, -1);
    return comp;
  }

  /**
   * Adds the specified component to this container at the specified index
   * in the component list.
   *
   * @param comp The component to be added.
   * @param index The index in the component list to insert this child
   * at, or -1 to add at the end of the list.
   *
   * @return The same component that was added.
   *
   * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
   */
  public Component add(Component comp, int index)
  {
    addImpl(comp, null, index);
    return comp;
  }

  /**
   * Adds the specified component to this container at the end of the
   * component list.  The layout manager will use the specified constraints
   * when laying out this component.
   *
   * @param comp The component to be added to this container.
   * @param constraints The layout constraints for this component.
   */
  public void add(Component comp, Object constraints)
  {
    addImpl(comp, constraints, -1);
  }

  /**
   * Adds the specified component to this container at the specified index
   * in the component list.  The layout manager will use the specified
   * constraints when layout out this component.
   *
   * @param comp The component to be added.
   * @param constraints The layout constraints for this component.
   * @param index The index in the component list to insert this child
   * at, or -1 to add at the end of the list.
   *
   * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
   */
  public void add(Component comp, Object constraints, int index)
  {
    addImpl(comp, constraints, index);
  }

  /**
   * This method is called by all the <code>add()</code> methods to perform
   * the actual adding of the component.  Subclasses who wish to perform
   * their own processing when a component is added should override this
   * method.  Any subclass doing this must call the superclass version of
   * this method in order to ensure proper functioning of the container.
   *
   * @param comp The component to be added.
   * @param constraints The layout constraints for this component, or
   * <code>null</code> if there are no constraints.
   * @param index The index in the component list to insert this child
   * at, or -1 to add at the end of the list.
   *
   * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
   */
  protected void addImpl(Component comp, Object constraints, int index)
  {
    synchronized (getTreeLock ())
      {
        if (index > ncomponents
            || (index < 0 && index != -1)
            || comp instanceof Window
            || (comp instanceof Container
                && ((Container) comp).isAncestorOf(this)))
          throw new IllegalArgumentException();

        // Reparent component, and make sure component is instantiated if
        // we are.
        if (comp.parent != null)
          comp.parent.remove(comp);

        if (component == null)
          component = new Component[4]; // FIXME, better initial size?

        // This isn't the most efficient implementation.  We could do less
        // copying when growing the array.  It probably doesn't matter.
        if (ncomponents >= component.length)
          {
            int nl = component.length * 2;
            Component[] c = new Component[nl];
            System.arraycopy(component, 0, c, 0, ncomponents);
            component = c;
          }

        if (index == -1)
          component[ncomponents++] = comp;
        else
          {
            System.arraycopy(component, index, component, index + 1,
                             ncomponents - index);
            component[index] = comp;
            ++ncomponents;
          }

        // Give the new component a parent.
        comp.parent = this;

        // Update the counter for Hierarchy(Bounds)Listeners.
        int childHierarchyListeners = comp.numHierarchyListeners;
        if (childHierarchyListeners > 0)
          updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
                                       childHierarchyListeners);
        int childHierarchyBoundsListeners = comp.numHierarchyBoundsListeners;
        if (childHierarchyBoundsListeners > 0)
          updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                       childHierarchyListeners);

        // Invalidate the layout of this container.
        if (valid)
          invalidate();

        // Create the peer _after_ the component has been added, so that
        // the peer gets to know about the component hierarchy.
        if (peer != null)
          {
            // Notify the component that it has a new parent.
            comp.addNotify();
          }

        // Notify the layout manager.
        if (layoutMgr != null)
          {
            // If we have a LayoutManager2 the constraints are "real",
            // otherwise they are the "name" of the Component to add.
            if (layoutMgr instanceof LayoutManager2)
              {
                LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
                lm2.addLayoutComponent(comp, constraints);
              }
            else if (constraints instanceof String)
              layoutMgr.addLayoutComponent((String) constraints, comp);
            else
              layoutMgr.addLayoutComponent("", comp);
          }

        // We previously only sent an event when this container is showing.
        // Also, the event was posted to the event queue. A Mauve test shows
        // that this event is not delivered using the event queue and it is
        // also sent when the container is not showing.
        if (containerListener != null
            || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
          {
            ContainerEvent ce = new ContainerEvent(this,
                                                ContainerEvent.COMPONENT_ADDED,
                                                comp);
            dispatchEvent(ce);
          }

        // Notify hierarchy listeners.
        comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp,
                                this, HierarchyEvent.PARENT_CHANGED);
      }
  }

  /**
   * Removes the component at the specified index from this container.
   *
   * @param index The index of the component to remove.
   */
  public void remove(int index)
  {
    synchronized (getTreeLock ())
      {
        if (index < 0 || index >= ncomponents)
          throw new ArrayIndexOutOfBoundsException();

        Component r = component[index];
        if (peer != null)
          r.removeNotify();

        if (layoutMgr != null)
          layoutMgr.removeLayoutComponent(r);

        // Update the counter for Hierarchy(Bounds)Listeners.
        int childHierarchyListeners = r.numHierarchyListeners;
        if (childHierarchyListeners > 0)
          updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
                                       -childHierarchyListeners);
        int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
        if (childHierarchyBoundsListeners > 0)
          updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                       -childHierarchyListeners);

        r.parent = null;

        System.arraycopy(component, index + 1, component, index,
                         ncomponents - index - 1);
        component[--ncomponents] = null;

        if (valid)
          invalidate();

        if (containerListener != null
            || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
          {
            // Post event to notify of removing the component.
            ContainerEvent ce = new ContainerEvent(this,
                                              ContainerEvent.COMPONENT_REMOVED,
                                              r);
            dispatchEvent(ce);
          }

        // Notify hierarchy listeners.
        r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r,
                             this, HierarchyEvent.PARENT_CHANGED);
      }
  }

  /**
   * Removes the specified component from this container.
   *
   * @param comp The component to remove from this container.
   */
  public void remove(Component comp)
  {
    synchronized (getTreeLock ())
      {
        for (int i = 0; i < ncomponents; ++i)
          {
            if (component[i] == comp)
              {
                remove(i);
                break;
              }
          }
      }
  }

  /**
   * Removes all components from this container.
   */
  public void removeAll()
  {
    synchronized (getTreeLock ())
      {
        // In order to allow the same bad tricks to be used as in RI
        // this code has to stay exactly that way: In a real-life app
        // a Container subclass implemented its own vector for
        // subcomponents, supplied additional addXYZ() methods
        // and overrode remove(int) and removeAll (the latter calling
        // super.removeAll() ).
        // By doing it this way, user code cannot prevent the correct
        // removal of components.
        while (ncomponents > 0)
          {
            ncomponents--;
            Component r = component[ncomponents];
            component[ncomponents] = null;

            if (peer != null)
              r.removeNotify();

            if (layoutMgr != null)
              layoutMgr.removeLayoutComponent(r);

            r.parent = null;

            // Send ContainerEvent if necessary.
            if (containerListener != null
                || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
              {
                // Post event to notify of removing the component.
                ContainerEvent ce
                  = new ContainerEvent(this,
                                       ContainerEvent.COMPONENT_REMOVED,
                                       r);
                dispatchEvent(ce);
              }

            // Update the counter for Hierarchy(Bounds)Listeners.
            int childHierarchyListeners = r.numHierarchyListeners;
            if (childHierarchyListeners > 0)
              updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
                                           -childHierarchyListeners);
            int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
            if (childHierarchyBoundsListeners > 0)
              updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                           -childHierarchyListeners);


            // Send HierarchyEvent if necessary.
            fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this,
                               HierarchyEvent.PARENT_CHANGED);

          }

        if (valid)
          invalidate();
      }
  }

  /**
   * Returns the current layout manager for this container.
   *
   * @return The layout manager for this container.
   */
  public LayoutManager getLayout()
  {
    return layoutMgr;
  }

  /**
   * Sets the layout manager for this container to the specified layout
   * manager.
   *
   * @param mgr The new layout manager for this container.
   */
  public void setLayout(LayoutManager mgr)
  {
    layoutMgr = mgr;
    if (valid)
      invalidate();
  }

  /**
   * Layout the components in this container.
   */
  public void doLayout()
  {
    layout ();
  }

  /**
   * Layout the components in this container.
   *
   * @deprecated use {@link #doLayout()} instead
   */
  public void layout()
  {
    if (layoutMgr != null)
      layoutMgr.layoutContainer (this);
  }

  /**
   * Invalidates this container to indicate that it (and all parent
   * containers) need to be laid out.
   */
  public void invalidate()
  {
    super.invalidate();
    if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
      {
        LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
        lm2.invalidateLayout(this);
      }
  }

  /**
   * Re-lays out the components in this container.
   */
  public void validate()
  {
    ComponentPeer p = peer;
    if (! valid && p != null)
      {
        ContainerPeer cPeer = null;
        if (p instanceof ContainerPeer)
          cPeer = (ContainerPeer) peer;
        synchronized (getTreeLock ())
          {
            if (cPeer != null)
              cPeer.beginValidate();
            validateTree();
            valid = true;
            if (cPeer != null)
              cPeer.endValidate();
          }
      }
  }

  /**
   * Recursively invalidates the container tree.
   */
  private final void invalidateTree()
  {
    synchronized (getTreeLock())
      {
        for (int i = 0; i < ncomponents; i++)
          {
            Component comp = component[i];
            if (comp instanceof Container)
              ((Container) comp).invalidateTree();
            else if (comp.valid)
              comp.invalidate();
          }
        if (valid)
          invalidate();
      }
  }

  /**
   * Recursively validates the container tree, recomputing any invalid
   * layouts.
   */
  protected void validateTree()
  {
    if (!valid)
      {
        ContainerPeer cPeer = null;
        if (peer instanceof ContainerPeer)
          {
            cPeer = (ContainerPeer) peer;
            cPeer.beginLayout();
          }

        doLayout ();
        for (int i = 0; i < ncomponents; ++i)
          {
            Component comp = component[i];

            if (comp instanceof Container && ! (comp instanceof Window)
                && ! comp.valid)
              {
                ((Container) comp).validateTree();
              }
            else
              {
                comp.validate();
              }
          }

        if (cPeer != null)
          {
            cPeer = (ContainerPeer) peer;
            cPeer.endLayout();
          }
      }

    /* children will call invalidate() when they are layed out. It
       is therefore important that valid is not set to true
       until after the children have been layed out. */
    valid = true;

  }

  public void setFont(Font f)
  {
    Font oldFont = getFont();
    super.setFont(f);
    Font newFont = getFont();
    if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont)))
      {
        invalidateTree();
      }
  }

  /**
   * Returns the preferred size of this container.
   *
   * @return The preferred size of this container.
   */
  public Dimension getPreferredSize()
  {
    return preferredSize ();
  }

  /**
   * Returns the preferred size of this container.
   *
   * @return The preferred size of this container.
   *
   * @deprecated use {@link #getPreferredSize()} instead
   */
  public Dimension preferredSize()
  {
    Dimension size = prefSize;
    // Try to return cached value if possible.
    if (size == null || !(prefSizeSet || valid))
      {
        // Need to lock here.
        synchronized (getTreeLock())
          {
            LayoutManager l = layoutMgr;
            if (l != null)
              prefSize = l.preferredLayoutSize(this);
            else
              prefSize = super.preferredSizeImpl();
            size = prefSize;
          }
      }
    if (size != null)
      return new Dimension(size);
    else
      return size;
  }

  /**
   * Returns the minimum size of this container.
   *
   * @return The minimum size of this container.
   */
  public Dimension getMinimumSize()
  {
    return minimumSize ();
  }

  /**
   * Returns the minimum size of this container.
   *
   * @return The minimum size of this container.
   *
   * @deprecated use {@link #getMinimumSize()} instead
   */
  public Dimension minimumSize()
  {
    Dimension size = minSize;
    // Try to return cached value if possible.
    if (size == null || !(minSizeSet || valid))
      {
        // Need to lock here.
        synchronized (getTreeLock())
          {
            LayoutManager l = layoutMgr;
            if (l != null)
              minSize = l.minimumLayoutSize(this);
            else
              minSize = super.minimumSizeImpl();
            size = minSize;
          }
      }
    if (size != null)
      return new Dimension(size);
    else
      return size;
  }

  /**
   * Returns the maximum size of this container.
   *
   * @return The maximum size of this container.
   */
  public Dimension getMaximumSize()
  {
    Dimension size = maxSize;
    // Try to return cached value if possible.
    if (size == null || !(maxSizeSet || valid))
      {
        // Need to lock here.
        synchronized (getTreeLock())
          {
            LayoutManager l = layoutMgr;
            if (l instanceof LayoutManager2)
              maxSize = ((LayoutManager2) l).maximumLayoutSize(this);
            else {
              maxSize = super.maximumSizeImpl();
            }
            size = maxSize;
          }
      }
    if (size != null)
      return new Dimension(size);
    else
      return size;
  }

  /**
   * Returns the preferred alignment along the X axis.  This is a value
   * between 0 and 1 where 0 represents alignment flush left and
   * 1 means alignment flush right, and 0.5 means centered.
   *
   * @return The preferred alignment along the X axis.
   */
  public float getAlignmentX()
  {
    LayoutManager layout = getLayout();
    float alignmentX = 0.0F;
    if (layout != null && layout instanceof LayoutManager2)
      {
        synchronized (getTreeLock())
          {
            LayoutManager2 lm2 = (LayoutManager2) layout;
            alignmentX = lm2.getLayoutAlignmentX(this);
          }
      }
    else
      alignmentX = super.getAlignmentX();
    return alignmentX;
  }

  /**
   * Returns the preferred alignment along the Y axis.  This is a value
   * between 0 and 1 where 0 represents alignment flush top and
   * 1 means alignment flush bottom, and 0.5 means centered.
   *
   * @return The preferred alignment along the Y axis.
   */
  public float getAlignmentY()
  {
    LayoutManager layout = getLayout();
    float alignmentY = 0.0F;
    if (layout != null && layout instanceof LayoutManager2)
      {
        synchronized (getTreeLock())
          {
            LayoutManager2 lm2 = (LayoutManager2) layout;
            alignmentY = lm2.getLayoutAlignmentY(this);
          }
      }
    else
      alignmentY = super.getAlignmentY();
    return alignmentY;
  }

  /**
   * Paints this container.  The implementation of this method in this
   * class forwards to any lightweight components in this container.  If
   * this method is subclassed, this method should still be invoked as
   * a superclass method so that lightweight components are properly
   * drawn.
   *
   * @param g - The graphics context for this paint job.
   */
  public void paint(Graphics g)
  {
    if (isShowing())
      {
        visitChildren(g, GfxPaintVisitor.INSTANCE, true);
      }
  }

  /**
   * Updates this container.  The implementation of this method in this
   * class forwards to any lightweight components in this container.  If
   * this method is subclassed, this method should still be invoked as
   * a superclass method so that lightweight components are properly
   * drawn.
   *
   * @param g The graphics context for this update.
   *
   * @specnote The specification suggests that this method forwards the
   *           update() call to all its lightweight children. Tests show
   *           that this is not done either in the JDK. The exact behaviour
   *           seems to be that the background is cleared in heavyweight
   *           Containers, and all other containers
   *           directly call paint(), causing the (lightweight) children to
   *           be painted.
   */
  public void update(Graphics g)
  {
    // It seems that the JDK clears the background of containers like Panel
    // and Window (within this method) but not of 'plain' Containers or
    // JComponents. This could
    // lead to the assumption that it only clears heavyweight containers.
    // However that is not quite true. In a test with a custom Container
    // that overrides isLightweight() to return false, the background is
    // also not cleared. So we do a check on !(peer instanceof LightweightPeer)
    // instead.
    if (isShowing())
      {
        ComponentPeer p = peer;
        if (! (p instanceof LightweightPeer))
          {
            g.clearRect(0, 0, getWidth(), getHeight());
          }
        paint(g);
      }
  }

  /**
   * Prints this container.  The implementation of this method in this
   * class forwards to any lightweight components in this container.  If
   * this method is subclassed, this method should still be invoked as
   * a superclass method so that lightweight components are properly
   * drawn.
   *
   * @param g The graphics context for this print job.
   */
  public void print(Graphics g)
  {
    super.print(g);
    visitChildren(g, GfxPrintVisitor.INSTANCE, true);
  }

  /**
   * Paints all of the components in this container.
   *
   * @param g The graphics context for this paint job.
   */
  public void paintComponents(Graphics g)
  {
    if (isShowing())
      visitChildren(g, GfxPaintAllVisitor.INSTANCE, false);
  }

  /**
   * Prints all of the components in this container.
   *
   * @param g The graphics context for this print job.
   */
  public void printComponents(Graphics g)
  {
    super.paint(g);
    visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
  }

  /**
   * Adds the specified container listener to this object's list of
   * container listeners.
   *
   * @param listener The listener to add.
   */
  public synchronized void addContainerListener(ContainerListener listener)
  {
    if (listener != null)
      {
        containerListener = AWTEventMulticaster.add(containerListener,
                                                    listener);
        newEventsOnly = true;
      }
  }

  /**
   * Removes the specified container listener from this object's list of
   * container listeners.
   *
   * @param listener The listener to remove.
   */
  public synchronized void removeContainerListener(ContainerListener listener)
  {
    containerListener = AWTEventMulticaster.remove(containerListener, listener);
  }

  /**
   * @since 1.4
   */
  public synchronized ContainerListener[] getContainerListeners()
  {
    return (ContainerListener[])
      AWTEventMulticaster.getListeners(containerListener,
                                       ContainerListener.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 #getContainerListeners()
   *
   * @since 1.3
   */
  public <T extends EventListener> T[] getListeners(Class<T> listenerType)
  {
    if (listenerType == ContainerListener.class)
      return (T[]) getContainerListeners();
    return super.getListeners(listenerType);
  }

  /**
   * Processes the specified event.  This method calls
   * <code>processContainerEvent()</code> if this method is a
   * <code>ContainerEvent</code>, otherwise it calls the superclass
   * method.
   *
   * @param e The event to be processed.
   */
  protected void processEvent(AWTEvent e)
  {
    if (e instanceof ContainerEvent)
      processContainerEvent((ContainerEvent) e);
    else
      super.processEvent(e);
  }

  /**
   * Called when a container event occurs if container events are enabled.
   * This method calls any registered listeners.
   *
   * @param e The event that occurred.
   */
  protected void processContainerEvent(ContainerEvent e)
  {
    if (containerListener == null)
      return;
    switch (e.id)
      {
      case ContainerEvent.COMPONENT_ADDED:
        containerListener.componentAdded(e);
        break;

      case ContainerEvent.COMPONENT_REMOVED:
        containerListener.componentRemoved(e);
        break;
      }
  }

  /**
   * AWT 1.0 event processor.
   *
   * @param e The event that occurred.
   *
   * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
   */
  public void deliverEvent(Event e)
  {
    if (!handleEvent (e))
      {
        synchronized (getTreeLock ())
          {
            Component parent = getParent ();

            if (parent != null)
              parent.deliverEvent (e);
          }
      }
  }

  /**
   * Returns the component located at the specified point.  This is done
   * by checking whether or not a child component claims to contain this
   * point.  The first child component that does is returned.  If no
   * child component claims the point, the container itself is returned,
   * unless the point does not exist within this container, in which
   * case <code>null</code> is returned.
   *
   * When components overlap, the first component is returned. The component
   * that is closest to (x, y), containing that location, is returned.
   * Heavyweight components take precedence of lightweight components.
   *
   * This function does not ignore invisible components. If there is an invisible
   * component at (x,y), it will be returned.
   *
   * @param x The X coordinate of the point.
   * @param y The Y coordinate of the point.
   *
   * @return The component containing the specified point, or
   * <code>null</code> if there is no such point.
   */
  public Component getComponentAt(int x, int y)
  {
    return locate (x, y);
  }

  /**
   * Returns the mouse pointer position relative to this Container's
   * top-left corner.  If allowChildren is false, the mouse pointer
   * must be directly over this container.  If allowChildren is true,
   * the mouse pointer may be over this container or any of its
   * descendents.
   *
   * @param allowChildren true to allow descendents, false if pointer
   * must be directly over Container.
   *
   * @return relative mouse pointer position
   *
   * @throws HeadlessException if in a headless environment
   */
  public Point getMousePosition(boolean allowChildren) throws HeadlessException
  {
    return super.getMousePositionHelper(allowChildren);
  }

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

  /**
   * Returns the component located at the specified point.  This is done
   * by checking whether or not a child component claims to contain this
   * point.  The first child component that does is returned.  If no
   * child component claims the point, the container itself is returned,
   * unless the point does not exist within this container, in which
   * case <code>null</code> is returned.
   *
   * When components overlap, the first component is returned. The component
   * that is closest to (x, y), containing that location, is returned.
   * Heavyweight components take precedence of lightweight components.
   *
   * This function does not ignore invisible components. If there is an invisible
   * component at (x,y), it will be returned.
   *
   * @param x The x position of the point to return the component at.
   * @param y The y position of the point to return the component at.
   *
   * @return The component containing the specified point, or <code>null</code>
   * if there is no such point.
   *
   * @deprecated use {@link #getComponentAt(int, int)} instead
   */
  public Component locate(int x, int y)
  {
    synchronized (getTreeLock ())
      {
        if (!contains (x, y))
          return null;

        // First find the component closest to (x,y) that is a heavyweight.
        for (int i = 0; i < ncomponents; ++i)
          {
            Component comp = component[i];
            int x2 = x - comp.x;
            int y2 = y - comp.y;
            if (comp.contains (x2, y2) && !comp.isLightweight())
              return comp;
          }

        // if a heavyweight component is not found, look for a lightweight
        // closest to (x,y).
        for (int i = 0; i < ncomponents; ++i)
          {
            Component comp = component[i];
            int x2 = x - comp.x;
            int y2 = y - comp.y;
            if (comp.contains (x2, y2) && comp.isLightweight())
              return comp;
          }

        return this;
      }
  }

  /**
   * Returns the component located at the specified point.  This is done
   * by checking whether or not a child component claims to contain this
   * point.  The first child component that does is returned.  If no
   * child component claims the point, the container itself is returned,
   * unless the point does not exist within this container, in which
   * case <code>null</code> is returned.
   *
   * The top-most child component is returned in the case where components overlap.
   * This is determined by finding the component closest to (x,y) and contains
   * that location. Heavyweight components take precedence of lightweight components.
   *
   * This function does not ignore invisible components. If there is an invisible
   * component at (x,y), it will be returned.
   *
   * @param p The point to return the component at.
   * @return The component containing the specified point, or <code>null</code>
   * if there is no such point.
   */
  public Component getComponentAt(Point p)
  {
    return getComponentAt (p.x, p.y);
  }

  /**
   * Locates the visible child component that contains the specified position.
   * The top-most child component is returned in the case where there is overlap
   * in the components. If the containing child component is a Container,
   * this method will continue searching for the deepest nested child
   * component. Components which are not visible are ignored during the search.
   *
   * findComponentAt differs from getComponentAt, because it recursively
   * searches a Container's children.
   *
   * @param x - x coordinate
   * @param y - y coordinate
   * @return null if the component does not contain the position.
   * If there is no child component at the requested point and the point is
   * within the bounds of the container the container itself is returned.
   */
  public Component findComponentAt(int x, int y)
  {
    synchronized (getTreeLock ())
      {
        if (! contains(x, y))
          return null;

        for (int i = 0; i < ncomponents; ++i)
          {
            // Ignore invisible children...
            if (!component[i].isVisible())
              continue;

            int x2 = x - component[i].x;
            int y2 = y - component[i].y;
            // We don't do the contains() check right away because
            // findComponentAt would redundantly do it first thing.
            if (component[i] instanceof Container)
              {
                Container k = (Container) component[i];
                Component r = k.findComponentAt(x2, y2);
                if (r != null)
                  return r;
              }
            else if (component[i].contains(x2, y2))
              return component[i];
          }

        return this;
      }
  }

  /**
   * Locates the visible child component that contains the specified position.
   * The top-most child component is returned in the case where there is overlap
   * in the components. If the containing child component is a Container,
   * this method will continue searching for the deepest nested child
   * component. Components which are not visible are ignored during the search.
   *
   * findComponentAt differs from getComponentAt, because it recursively
   * searches a Container's children.
   *
   * @param p - the component's location
   * @return null if the component does not contain the position.
   * If there is no child component at the requested point and the point is
   * within the bounds of the container the container itself is returned.
   */
  public Component findComponentAt(Point p)
  {
    return findComponentAt(p.x, p.y);
  }

  /**
   * Called when this container is added to another container to inform it
   * to create its peer.  Peers for any child components will also be
   * created.
   */
  public void addNotify()
  {
    synchronized (getTreeLock())
      {
        super.addNotify();
        addNotifyContainerChildren();
      }
  }

  /**
   * Called when this container is removed from its parent container to
   * inform it to destroy its peer.  This causes the peers of all child
   * component to be destroyed as well.
   */
  public void removeNotify()
  {
    synchronized (getTreeLock ())
      {
        int ncomps = ncomponents;
        Component[] comps = component;
        for (int i = ncomps - 1; i >= 0; --i)
          {
            Component comp = comps[i];
            if (comp != null)
              comp.removeNotify();
          }
        super.removeNotify();
      }
  }

  /**
   * Tests whether or not the specified component is contained within
   * this components subtree.
   *
   * @param comp The component to test.
   *
   * @return <code>true</code> if this container is an ancestor of the
   * specified component, <code>false</code> otherwise.
   */
  public boolean isAncestorOf(Component comp)
  {
    synchronized (getTreeLock ())
      {
        while (true)
          {
            if (comp == null)
              return false;
            comp = comp.getParent();
            if (comp == this)
              return true;
          }
      }
  }

  /**
   * Returns a string representing the state of this container for
   * debugging purposes.
   *
   * @return A string representing the state of this container.
   */
  protected String paramString()
  {
    if (layoutMgr == null)
      return super.paramString();

    CPStringBuilder sb = new CPStringBuilder();
    sb.append(super.paramString());
    sb.append(",layout=");
    sb.append(layoutMgr.getClass().getName());
    return sb.toString();
  }

  /**
   * Writes a listing of this container to the specified stream starting
   * at the specified indentation point.
   *
   * @param out The <code>PrintStream</code> to write to.
   * @param indent The indentation point.
   */
  public void list(PrintStream out, int indent)
  {
    synchronized (getTreeLock ())
      {
        super.list(out, indent);
        for (int i = 0; i < ncomponents; ++i)
          component[i].list(out, indent + 2);
      }
  }

  /**
   * Writes a listing of this container to the specified stream starting
   * at the specified indentation point.
   *
   * @param out The <code>PrintWriter</code> to write to.
   * @param indent The indentation point.
   */
  public void list(PrintWriter out, int indent)
  {
    synchronized (getTreeLock ())
      {
        super.list(out, indent);
        for (int i = 0; i < ncomponents; ++i)
          component[i].list(out, indent + 2);
      }
  }

  /**
   * Sets the focus traversal keys for a given traversal operation for this
   * Container.
   *
   * @exception IllegalArgumentException If id is not one of
   * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
   * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
   * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
   * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS,
   * or if keystrokes contains null, or if any Object in keystrokes is not an
   * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any
   * keystroke already maps to another focus traversal operation for this
   * Container.
   *
   * @since 1.4
   */
  public void setFocusTraversalKeys(int id,
                                    Set<? extends AWTKeyStroke> keystrokes)
  {
    if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
      throw new IllegalArgumentException ();

    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;
    Set sc;
    String name;
    switch (id)
      {
      case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
        sa = getFocusTraversalKeys
          (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
        sb = getFocusTraversalKeys
          (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
        sc = getFocusTraversalKeys
          (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
        name = "forwardFocusTraversalKeys";
        break;
      case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
        sa = getFocusTraversalKeys
          (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
        sb = getFocusTraversalKeys
          (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
        sc = getFocusTraversalKeys
          (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
        name = "backwardFocusTraversalKeys";
        break;
      case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
        sa = getFocusTraversalKeys
          (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
        sb = getFocusTraversalKeys
          (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
        sc = getFocusTraversalKeys
          (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
        name = "upCycleFocusTraversalKeys";
        break;
      case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS:
        sa = getFocusTraversalKeys
          (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
        sb = getFocusTraversalKeys
          (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
        sc = getFocusTraversalKeys
          (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
        name = "downCycleFocusTraversalKeys";
        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) || sc.contains (o)
            || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
          throw new IllegalArgumentException ();
      }

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

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

    focusTraversalKeys[id] = keystrokes;
  }

  /**
   * Returns the Set of focus traversal keys for a given traversal operation for
   * this Container.
   *
   * @exception IllegalArgumentException If id is not one of
   * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
   * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
   * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
   * or KeyboardFocusManager.DOWN_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 &&
        id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
      throw new IllegalArgumentException ();

    Set 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;
  }

  /**
   * Returns whether the Set of focus traversal keys for the given focus
   * traversal operation has been explicitly defined for this Container.
   * If this method returns false, this Container is inheriting the Set from
   * an ancestor, or from the current KeyboardFocusManager.
   *
   * @exception IllegalArgumentException If id is not one of
   * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
   * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
   * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
   * or KeyboardFocusManager.DOWN_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 &&
        id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
      throw new IllegalArgumentException ();

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

  /**
   * Check whether the given Container is the focus cycle root of this
   * Container's focus traversal cycle.  If this Container is a focus
   * cycle root itself, then it will be in two different focus cycles
   * -- it's own, and that of its ancestor focus cycle root's.  In
   * that case, if <code>c</code> is either of those containers, this
   * method will return true.
   *
   * @param c the candidate Container
   *
   * @return true if c is the focus cycle root of the focus traversal
   * cycle to which this Container belongs, false otherwise
   *
   * @since 1.4
   */
  public boolean isFocusCycleRoot (Container c)
  {
    if (this == c
        && isFocusCycleRoot ())
      return true;

    Container ancestor = getFocusCycleRootAncestor ();

    if (c == ancestor)
      return true;

    return false;
  }

  /**
   * If this Container is a focus cycle root, set the focus traversal
   * policy that determines the focus traversal order for its
   * children.  If non-null, this policy will be inherited by all
   * inferior focus cycle roots.  If <code>policy</code> is null, this
   * Container will inherit its policy from the closest ancestor focus
   * cycle root that's had its policy set.
   *
   * @param policy the new focus traversal policy for this Container or null
   *
   * @since 1.4
   */
  public void setFocusTraversalPolicy (FocusTraversalPolicy policy)
  {
    focusTraversalPolicy = policy;
  }

  /**
   * Return the focus traversal policy that determines the focus
   * traversal order for this Container's children.  This method
   * returns null if this Container is not a focus cycle root.  If the
   * focus traversal policy has not been set explicitly, then this
   * method will return an ancestor focus cycle root's policy instead.
   *
   * @return this Container's focus traversal policy or null
   *
   * @since 1.4
   */
  public FocusTraversalPolicy getFocusTraversalPolicy ()
  {
    if (!isFocusCycleRoot ())
      return null;

    if (focusTraversalPolicy == null)
      {
        Container ancestor = getFocusCycleRootAncestor ();

        if (ancestor != this && ancestor !=  null)
          return ancestor.getFocusTraversalPolicy ();
        else
          {
            KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();

            return manager.getDefaultFocusTraversalPolicy ();
          }
      }
    else
      return focusTraversalPolicy;
  }

  /**
   * Check whether this Container's focus traversal policy has been
   * explicitly set.  If it has not, then this Container will inherit
   * its focus traversal policy from one of its ancestor focus cycle
   * roots.
   *
   * @return true if focus traversal policy is set, false otherwise
  */
  public boolean isFocusTraversalPolicySet ()
  {
    return focusTraversalPolicy == null;
  }

  /**
   * Set whether or not this Container is the root of a focus
   * traversal cycle.  This Container's focus traversal policy
   * determines the order of focus traversal.  Some policies prevent
   * the focus from being transferred between two traversal cycles
   * until an up or down traversal operation is performed.  In that
   * case, normal traversal (not up or down) is limited to this
   * Container and all of this Container's descendents that are not
   * descendents of inferior focus cycle roots.  In the default case
   * however, ContainerOrderFocusTraversalPolicy is in effect, and it
   * supports implicit down-cycle traversal operations.
   *
   * @param focusCycleRoot true if this is a focus cycle root, false otherwise
   *
   * @since 1.4
   */
  public void setFocusCycleRoot (boolean focusCycleRoot)
  {
    this.focusCycleRoot = focusCycleRoot;
  }

  /**
   * Set to <code>true</code> if this container provides a focus traversal
   * policy, <code>false</code> when the root container's focus
   * traversal policy should be used.
   *
   * @return <code>true</code> if this container provides a focus traversal
   *        policy, <code>false</code> when the root container's focus
   *        traversal policy should be used
   *
   * @see #setFocusTraversalPolicyProvider(boolean)
   *
   * @since 1.5
   */
  public final boolean isFocusTraversalPolicyProvider()
  {
    return focusTraversalPolicyProvider;
  }

  /**
   * Set to <code>true</code> if this container provides a focus traversal
   * policy, <code>false</code> when the root container's focus
   * traversal policy should be used.
   *
   * @param b <code>true</code> if this container provides a focus traversal
   *        policy, <code>false</code> when the root container's focus
   *        traversal policy should be used
   *
   * @see #isFocusTraversalPolicyProvider()
   *
   * @since 1.5
   */
  public final void setFocusTraversalPolicyProvider(boolean b)
  {
    focusTraversalPolicyProvider = b;
  }

  /**
   * Check whether this Container is a focus cycle root.
   *
   * @return true if this is a focus cycle root, false otherwise
   *
   * @since 1.4
   */
  public boolean isFocusCycleRoot ()
  {
    return focusCycleRoot;
  }

  /**
   * Transfer focus down one focus traversal cycle.  If this Container
   * is a focus cycle root, then its default component becomes the
   * focus owner, and this Container becomes the current focus cycle
   * root.  No traversal will occur if this Container is not a focus
   * cycle root.
   *
   * @since 1.4
   */
  public void transferFocusDownCycle ()
  {
    if (isFocusCycleRoot())
      {
        KeyboardFocusManager fm =
          KeyboardFocusManager.getCurrentKeyboardFocusManager();
        fm.setGlobalCurrentFocusCycleRoot(this);
        FocusTraversalPolicy policy = getFocusTraversalPolicy();
        Component defaultComponent = policy.getDefaultComponent(this);
        if (defaultComponent != null)
          defaultComponent.requestFocus();
      }
  }

  /**
   * Sets the ComponentOrientation property of this container and all components
   * contained within it.
   *
   * @exception NullPointerException If orientation is null
   *
   * @since 1.4
   */
  public void applyComponentOrientation (ComponentOrientation orientation)
  {
    if (orientation == null)
      throw new NullPointerException();

    setComponentOrientation(orientation);
    for (int i = 0; i < ncomponents; i++)
      {
        if (component[i] instanceof Container)
             ((Container) component[i]).applyComponentOrientation(orientation);
          else
             component[i].setComponentOrientation(orientation);
      }
  }

  public void addPropertyChangeListener (PropertyChangeListener listener)
  {
    // TODO: Why is this overridden?
    super.addPropertyChangeListener(listener);
  }

  public void addPropertyChangeListener (String propertyName,
                                         PropertyChangeListener listener)
  {
    // TODO: Why is this overridden?
    super.addPropertyChangeListener(propertyName, listener);
  }


  /**
   * Sets the Z ordering for the component <code>comp</code> to
   * <code>index</code>. Components with lower Z order paint above components
   * with higher Z order.
   *
   * @param comp the component for which to change the Z ordering
   * @param index the index to set
   *
   * @throws NullPointerException if <code>comp == null</code>
   * @throws IllegalArgumentException if comp is an ancestor of this container
   * @throws IllegalArgumentException if <code>index</code> is not in
   *         <code>[0, getComponentCount()]</code> for moving between
   *         containers or <code>[0, getComponentCount() - 1]</code> for moving
   *         inside this container
   * @throws IllegalArgumentException if <code>comp == this</code>
   * @throws IllegalArgumentException if <code>comp</code> is a
   *         <code>Window</code>
   *
   * @see #getComponentZOrder(Component)
   *
   * @since 1.5
   */
  public final void setComponentZOrder(Component comp, int index)
  {
    if (comp == null)
      throw new NullPointerException("comp must not be null");
    if (comp instanceof Container && ((Container) comp).isAncestorOf(this))
      throw new IllegalArgumentException("comp must not be an ancestor of "
                                         + "this");
    if (comp instanceof Window)
      throw new IllegalArgumentException("comp must not be a Window");

    if (comp == this)
      throw new IllegalArgumentException("cannot add component to itself");

    synchronized (getTreeLock())
      {
        // FIXME: Implement reparenting.
        if ( comp.getParent() != this)
          throw new AssertionError("Reparenting is not implemented yet");
        else
          {
            // Find current component index.
            int currentIndex = getComponentZOrder(comp);
            if (currentIndex < index)
              {
                System.arraycopy(component, currentIndex + 1, component,
                                 currentIndex, index - currentIndex);
              }
            else
              {
                System.arraycopy(component, index, component, index + 1,
                                 currentIndex - index);
              }
            component[index] = comp;
          }
      }
  }

  /**
   * Returns the Z ordering index of <code>comp</code>. If <code>comp</code>
   * is not a child component of this Container, this returns <code>-1</code>.
   *
   * @param comp the component for which to query the Z ordering
   *
   * @return the Z ordering index of <code>comp</code> or <code>-1</code> if
   *         <code>comp</code> is not a child of this Container
   *
   * @see #setComponentZOrder(Component, int)
   *
   * @since 1.5
   */
  public final int getComponentZOrder(Component comp)
  {
    synchronized (getTreeLock())
      {
        int index = -1;
        if (component != null)
          {
            for (int i = 0; i < ncomponents; i++)
              {
                if (component[i] == comp)
                  {
                    index = i;
                    break;
                  }
              }
          }
        return index;
      }
  }

  // Hidden helper methods.

  /**
   * Perform a graphics operation on the children of this container.
   * For each applicable child, the visitChild() method will be called
   * to perform the graphics operation.
   *
   * @param gfx The graphics object that will be used to derive new
   * graphics objects for the children.
   *
   * @param visitor Object encapsulating the graphics operation that
   * should be performed.
   *
   * @param lightweightOnly If true, only lightweight components will
   * be visited.
   */
  private void visitChildren(Graphics gfx, GfxVisitor visitor,
                             boolean lightweightOnly)
  {
    synchronized (getTreeLock())
      {
        for (int i = ncomponents - 1; i >= 0; --i)
          {
            Component comp = component[i];
            boolean applicable = comp.isVisible()
                                 && (comp.isLightweight() || ! lightweightOnly);

            if (applicable)
              visitChild(gfx, visitor, comp);
          }
      }
  }

  /**
   * Perform a graphics operation on a child. A translated and clipped
   * graphics object will be created, and the visit() method of the
   * visitor will be called to perform the operation.
   *
   * @param gfx The graphics object that will be used to derive new
   * graphics objects for the child.
   *
   * @param visitor Object encapsulating the graphics operation that
   * should be performed.
   *
   * @param comp The child component that should be visited.
   */
  private void visitChild(Graphics gfx, GfxVisitor visitor,
                          Component comp)
  {
    Rectangle bounds = comp.getBounds();

    if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height))
      return;
    Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width,
                             bounds.height);
    try
      {
        g2.setFont(comp.getFont());
        visitor.visit(comp, g2);
      }
    finally
      {
        g2.dispose();
      }
  }

  /**
   * Overridden to dispatch events to lightweight descendents.
   *
   * @param e the event to dispatch.
   */
  void dispatchEventImpl(AWTEvent e)
  {
    LightweightDispatcher dispatcher = LightweightDispatcher.getInstance();
    if (! isLightweight() && dispatcher.dispatchEvent(e))
      {
        // Some lightweight descendent got this event dispatched. Consume
        // it and let the peer handle it.
        e.consume();
        ComponentPeer p = peer;
        if (p != null)
          p.handleEvent(e);
      }
    else
      {
        super.dispatchEventImpl(e);
      }
  }

  /**
   * This is called by the lightweight dispatcher to avoid recursivly
   * calling into the lightweight dispatcher.
   *
   * @param e the event to dispatch
   *
   * @see LightweightDispatcher#redispatch(MouseEvent, Component, int)
   */
  void dispatchNoLightweight(AWTEvent e)
  {
    super.dispatchEventImpl(e);
  }

  /**
   * Tests if this container has an interest in the given event id.
   *
   * @param eventId The event id to check.
   *
   * @return <code>true</code> if a listener for the event id exists or
   *         if the eventMask is set for the event id.
   *
   * @see java.awt.Component#eventTypeEnabled(int)
   */
  boolean eventTypeEnabled(int eventId)
  {
    if(eventId <= ContainerEvent.CONTAINER_LAST
       && eventId >= ContainerEvent.CONTAINER_FIRST)
      return containerListener != null
        || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0;
      else
        return super.eventTypeEnabled(eventId);
  }

  // This is used to implement Component.transferFocus.
  Component findNextFocusComponent(Component child)
  {
    synchronized (getTreeLock ())
      {
        int start, end;
        if (child != null)
          {
            for (start = 0; start < ncomponents; ++start)
              {
                if (component[start] == child)
                  break;
              }
            end = start;
            // This special case lets us be sure to terminate.
            if (end == 0)
              end = ncomponents;
            ++start;
          }
        else
          {
            start = 0;
            end = ncomponents;
          }

        for (int j = start; j != end; ++j)
          {
            if (j >= ncomponents)
              {
                // The JCL says that we should wrap here.  However, that
                // seems wrong.  To me it seems that focus order should be
                // global within in given window.  So instead if we reach
                // the end we try to look in our parent, if we have one.
                if (parent != null)
                  return parent.findNextFocusComponent(this);
                j -= ncomponents;
              }
            if (component[j] instanceof Container)
              {
                Component c = component[j];
                c = c.findNextFocusComponent(null);
                if (c != null)
                  return c;
              }
            else if (component[j].isFocusTraversable())
              return component[j];
          }

        return null;
      }
  }

  /**
   * Fires hierarchy events to the children of this container and this
   * container itself. This overrides {@link Component#fireHierarchyEvent}
   * in order to forward this event to all children.
   */
  void fireHierarchyEvent(int id, Component changed, Container parent,
                          long flags)
  {
    // Only propagate event if there is actually a listener waiting for it.
    if ((id == HierarchyEvent.HIERARCHY_CHANGED && numHierarchyListeners > 0)
        || ((id == HierarchyEvent.ANCESTOR_MOVED
             || id == HierarchyEvent.ANCESTOR_RESIZED)
            && numHierarchyBoundsListeners > 0))
      {
        for (int i = 0; i < ncomponents; i++)
          component[i].fireHierarchyEvent(id, changed, parent, flags);
        super.fireHierarchyEvent(id, changed, parent, flags);
      }
  }

  /**
   * Adjusts the number of hierarchy listeners of this container and all of
   * its parents. This is called by the add/remove listener methods and
   * structure changing methods in Container.
   *
   * @param type the type, either {@link AWTEvent#HIERARCHY_BOUNDS_EVENT_MASK}
   *        or {@link AWTEvent#HIERARCHY_EVENT_MASK}
   * @param delta the number of listeners added or removed
   */
  void updateHierarchyListenerCount(long type, int delta)
  {
    if (type == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)
      numHierarchyBoundsListeners += delta;
    else if (type == AWTEvent.HIERARCHY_EVENT_MASK)
      numHierarchyListeners += delta;
    else
      assert false : "Should not reach here";

    if (parent != null)
      parent.updateHierarchyListenerCount(type, delta);
  }

  /**
   * Notifies interested listeners about resizing or moving the container.
   * This performs the super behaviour (sending component events) and
   * additionally notifies any hierarchy bounds listeners on child components.
   *
   * @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)
  {
    // Notify component listeners.
    super.notifyReshape(resized, moved);

    if (ncomponents > 0)
      {
        // Notify hierarchy bounds listeners.
        if (resized)
          {
            for (int i = 0; i < getComponentCount(); i++)
              {
                Component child = getComponent(i);
                child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
                                         this, parent, 0);
              }
          }
        if (moved)
          {
            for (int i = 0; i < getComponentCount(); i++)
              {
                Component child = getComponent(i);
                child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
                                         this, parent, 0);
              }
          }
      }
  }

  private void addNotifyContainerChildren()
  {
    synchronized (getTreeLock ())
      {
        for (int i = ncomponents;  --i >= 0; )
          {
            component[i].addNotify();
          }
      }
  }

  /**
   * Deserialize this Container:
   * <ol>
   * <li>Read from the stream the default serializable fields.</li>
   * <li>Read a list of serializable ContainerListeners as optional
   * data.  If the list is null, no listeners will be registered.</li>
   * <li>Read this Container's FocusTraversalPolicy as optional data.
   * If this is null, then this Container will use a
   * DefaultFocusTraversalPolicy.</li>
   * </ol>
   *
   * @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 object = s.readObject ();
        if ("containerL".equals (key))
          addContainerListener((ContainerListener) object);
        // FIXME: under what key is the focus traversal policy stored?
        else if ("focusTraversalPolicy".equals (key))
          setFocusTraversalPolicy ((FocusTraversalPolicy) object);

        key = (String) s.readObject();
      }
  }

  /**
   * Serialize this Container:
   * <ol>
   * <li>Write to the stream the default serializable fields.</li>
   * <li>Write the list of serializable ContainerListeners as optional
   * data.</li>
   * <li>Write this Container's FocusTraversalPolicy as optional data.</li>
   * </ol>
   *
   * @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, "containerL", containerListener);
    if (focusTraversalPolicy instanceof Serializable)
      s.writeObject (focusTraversalPolicy);
    else
      s.writeObject (null);
  }

  // Nested classes.

  /* The following classes are used in concert with the
     visitChildren() method to implement all the graphics operations
     that requires traversal of the containment hierarchy. */

  abstract static class GfxVisitor
  {
    public abstract void visit(Component c, Graphics gfx);
  }

  static class GfxPaintVisitor extends GfxVisitor
  {
    public static final GfxVisitor INSTANCE = new GfxPaintVisitor();

    public void visit(Component c, Graphics gfx)
    {
      c.paint(gfx);
    }
  }

  static class GfxPrintVisitor extends GfxVisitor
  {
    public static final GfxVisitor INSTANCE = new GfxPrintVisitor();

    public void visit(Component c, Graphics gfx)
    {
      c.print(gfx);
    }
  }

  static class GfxPaintAllVisitor extends GfxVisitor
  {
    public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();

    public void visit(Component c, Graphics gfx)
    {
      c.paintAll(gfx);
    }
  }

  static class GfxPrintAllVisitor extends GfxVisitor
  {
    public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();

    public void visit(Component c, Graphics gfx)
    {
      c.printAll(gfx);
    }
  }

  /**
   * This class provides accessibility support for subclasses of container.
   *
   * @author Eric Blake (ebb9@email.byu.edu)
   *
   * @since 1.3
   */
  protected class AccessibleAWTContainer extends AccessibleAWTComponent
  {
    /**
     * Compatible with JDK 1.4+.
     */
    private static final long serialVersionUID = 5081320404842566097L;

    /**
     * The handler to fire PropertyChange when children are added or removed.
     *
     * @serial the handler for property changes
     */
    protected ContainerListener accessibleContainerHandler
      = new AccessibleContainerHandler();

    /**
     * The default constructor.
     */
    protected AccessibleAWTContainer()
    {
      Container.this.addContainerListener(accessibleContainerHandler);
    }

    /**
     * Return the number of accessible children of the containing accessible
     * object (at most the total number of its children).
     *
     * @return the number of accessible children
     */
    public int getAccessibleChildrenCount()
    {
      synchronized (getTreeLock ())
        {
          int count = 0;
          int i = component == null ? 0 : component.length;
          while (--i >= 0)
            if (component[i] instanceof Accessible)
              count++;
          return count;
        }
    }

    /**
     * Return the nth accessible child of the containing accessible object.
     *
     * @param i the child to grab, zero-based
     * @return the accessible child, or null
     */
    public Accessible getAccessibleChild(int i)
    {
      synchronized (getTreeLock ())
        {
          if (component == null)
            return null;
          int index = -1;
          while (i >= 0 && ++index < component.length)
            if (component[index] instanceof Accessible)
              i--;
          if (i < 0)
            return (Accessible) component[index];
          return null;
        }
    }

    /**
     * Return the accessible child located at point (in the parent's
     * coordinates), if one exists.
     *
     * @param p the point to look at
     *
     * @return an accessible object at that point, or null
     *
     * @throws NullPointerException if p is null
     */
    public Accessible getAccessibleAt(Point p)
    {
      Component c = getComponentAt(p.x, p.y);
      return c != Container.this && c instanceof Accessible ? (Accessible) c
        : null;
    }

    /**
     * This class fires a <code>PropertyChange</code> listener, if registered,
     * when children are added or removed from the enclosing accessible object.
     *
     * @author Eric Blake (ebb9@email.byu.edu)
     *
     * @since 1.3
     */
    protected class AccessibleContainerHandler implements ContainerListener
    {
      /**
       * Default constructor.
       */
      protected AccessibleContainerHandler()
      {
        // Nothing to do here.
      }

      /**
       * Fired when a component is added; forwards to the PropertyChange
       * listener.
       *
       * @param e the container event for adding
       */
      public void componentAdded(ContainerEvent e)
      {
        AccessibleAWTContainer.this.firePropertyChange
          (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild());
      }

      /**
       * Fired when a component is removed; forwards to the PropertyChange
       * listener.
       *
       * @param e the container event for removing
       */
      public void componentRemoved(ContainerEvent e)
      {
        AccessibleAWTContainer.this.firePropertyChange
          (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null);
      }
    } // class AccessibleContainerHandler
  } // class AccessibleAWTContainer
} // class Container
