/* 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 java.awt.event.ComponentListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.KeyEvent;
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)
 *
 * @since 1.0
 *
 * @status still missing 1.4 support
 */
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;

  Dimension maxSize;

  /**
   * @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()
  {
    if (peer == null)
      return new Insets (0, 0, 0, 0);

    return ((ContainerPeer) peer).getInsets ();
  }

  /**
   * 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);
        comp.parent = this;

        if (peer != null)
          {
	    // Notify the component that it has a new parent.
	    comp.addNotify();

            if (comp.isLightweight ())
	      {
		enableEvents (comp.eventMask);
		if (!isLightweight ())
		  enableEvents (AWTEvent.PAINT_EVENT_MASK);
	      }
          }

        // Invalidate the layout of the added component and its ancestors.
        comp.invalidate();

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

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

        // 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. 
        ContainerEvent ce = new ContainerEvent(this,
                                               ContainerEvent.COMPONENT_ADDED,
                                               comp);
        ContainerListener[] listeners = getContainerListeners();
        for (int i = 0; i < listeners.length; i++)
          listeners[i].componentAdded(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 ())
      {
        Component r = component[index];

        ComponentListener[] list = r.getComponentListeners();
        for (int j = 0; j < list.length; j++)
              r.removeComponentListener(list[j]);
        
        r.removeNotify();

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

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

        invalidate();

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

        r.parent = null;

        if (isShowing ())
          {
            // Post event to notify of removing the component.
            ContainerEvent ce = new ContainerEvent(this,
                                               ContainerEvent.COMPONENT_REMOVED,
                                               r);
            getToolkit().getSystemEventQueue().postEvent(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.
        for ( int index = 0; index < ncomponents; index++)
          {
            Component r = component[index];

            ComponentListener[] list = r.getComponentListeners();
            for (int j = 0; j < list.length; j++)
              r.removeComponentListener(list[j]);
            
            r.removeNotify();

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

            r.parent = null;

            if (isShowing ())
              {
                // Post event to notify of removing the component.
                ContainerEvent ce
                  = new ContainerEvent(this,
                                       ContainerEvent.COMPONENT_REMOVED,
                                       r);
                
                getToolkit().getSystemEventQueue().postEvent(ce);
              }
            }
          
          invalidate();
        
          ncomponents = 0;
      }
  }

  /**
   * 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()
  {
    synchronized (getTreeLock ())
      {
        if (! isValid() && peer != null)
          {
            validateTree();
          }
      }
  }

  /**
   * Recursively invalidates the container tree.
   */
  void invalidateTree()
  {
    synchronized (getTreeLock())
      {
        super.invalidate();  // Clean cached layout state.
        for (int i = 0; i < ncomponents; i++)
          {
            Component comp = component[i];
            comp.invalidate();
            if (comp instanceof Container)
              ((Container) comp).invalidateTree();
          }

        if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
          {
            LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
            lm2.invalidateLayout(this);
          }
      }
  }

  /**
   * Recursively validates the container tree, recomputing any invalid
   * layouts.
   */
  protected void validateTree()
  {
    if (valid)
      return;

    ContainerPeer cPeer = null;
    if (peer != null && ! (peer instanceof LightweightPeer))
      {
        cPeer = (ContainerPeer) peer;
        cPeer.beginValidate();
      }

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

        if (comp.getPeer () == null)
          comp.addNotify();
      }

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

        if (! comp.isValid())
          {
            if (comp instanceof Container)
              {
                ((Container) comp).validateTree();
              }
            else
              {
                component[i].validate();
              }
          }
      }

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

    if (cPeer != null)
      cPeer.endValidate();
  }

  public void setFont(Font f)
  {
    if( (f != null && (font == null || !font.equals(f)))
        || f == null)
      {
        super.setFont(f);
        // FIXME: Although it might make more sense to invalidate only
        // those children whose font == null, Sun invalidates all children.
        // So we'll do the same.
        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)
  {
    paint(g);
    visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
  }

  /**
   * 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)
  {
    containerListener = AWTEventMulticaster.add(containerListener, listener);
  }

  /**
   * 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 EventListener[] getListeners(Class listenerType)
  {
    if (listenerType == ContainerListener.class)
      return 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 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 ())
      {
        for (int i = 0; i < ncomponents; ++i)
          component[i].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;
            if (comp == this)
              return true;
            comp = comp.getParent();
          }
      }
  }

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

    StringBuffer sb = new StringBuffer();
    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 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 (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 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
      {
        visitor.visit(comp, g2);
      }
    finally
      {
        g2.dispose();
      }
  }

  void dispatchEventImpl(AWTEvent e)
  {
    boolean dispatched =
      LightweightDispatcher.getInstance().dispatchEvent(e);
    if (! dispatched)
      {
        if ((e.id <= ContainerEvent.CONTAINER_LAST
            && e.id >= ContainerEvent.CONTAINER_FIRST)
            && (containerListener != null
                || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
          processEvent(e);
        else
          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);
  }

  private void addNotifyContainerChildren()
  {
    synchronized (getTreeLock ())
      {
        for (int i = ncomponents;  --i >= 0; )
          {
            component[i].addNotify();
            if (component[i].isLightweight ())
	      {
		enableEvents(component[i].eventMask);
		if (peer != null && !isLightweight ())
		  enableEvents (AWTEvent.PAINT_EVENT_MASK);
	      }
          }
      }
  }

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