/* Container.java -- parent container class in AWT
   Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005  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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.peer.ContainerPeer;
import java.awt.peer.LightweightPeer;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Collections;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.accessibility.Accessible;
import javax.swing.SwingUtilities;

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

  LightweightDispatcher dispatcher;

  Dimension maxSize;

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

  int containerSerializedDataVersion;

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

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

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

  /**
   * Swaps the components at position i and j, in the container.
   */

  protected void swapComponents (int i, int j)
  {   
    synchronized (getTreeLock ())
      {
        if (i < 0 
            || i >= component.length
            || j < 0 
            || j >= component.length)
          throw new ArrayIndexOutOfBoundsException ();
        Component tmp = component[i];
        component[i] = component[j];
        component[j] = tmp;
      }
  }

  /**
   * 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 ArrayIndexOutOfBounds 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 ArrayIndexOutOfBounds 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 ArrayIndexOutOfBounds 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)
          {
            if (comp.isLightweight ())
	      {
		enableEvents (comp.eventMask);
		if (!isLightweight ())
		  enableEvents (AWTEvent.PAINT_EVENT_MASK);
	      }
          }

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

        // Notify the layout manager.
        if (layoutMgr != null)
          {
            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(null, comp);
          }

        if (isShowing ())
          {
            // Post event to notify of adding the component.
            ContainerEvent ce = new ContainerEvent(this,
                                                   ContainerEvent.COMPONENT_ADDED,
                                                   comp);
            getToolkit().getSystemEventQueue().postEvent(ce);
          }
      }
  }

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

        r.removeNotify();

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

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

  /**
   * Removes the specified component from this container.
   *
   * @return component 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 ())
      {
        while (ncomponents > 0)
          remove(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;
    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();
  }

  /**
   * 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()
  {
    for (int i = 0; i < ncomponents; i++)
      {
        Component comp = component[i];
        comp.invalidate();
        if (comp instanceof Container)
          ((Container) comp).invalidateTree();
      }
  }

  /**
   * 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)
  {
    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()
  {
    if (layoutMgr != null)
      return layoutMgr.preferredLayoutSize (this);
    else
      return super.preferredSize ();
  }

  /**
   * 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()
  {
    if (layoutMgr != null)
      return layoutMgr.minimumLayoutSize (this);
    else
      return super.minimumSize ();
  }

  /**
   * Returns the maximum size of this container.
   *
   * @return The maximum size of this container.
   */
  public Dimension getMaximumSize()
  {
    if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
      {
        LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
        return lm2.maximumLayoutSize(this);
      }
    else
      return super.getMaximumSize();
  }

  /**
   * 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()
  {
    if (layoutMgr instanceof LayoutManager2)
      {
        LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
        return lm2.getLayoutAlignmentX(this);
      }
    else
      return super.getAlignmentX();
  }

  /**
   * 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()
  {
    if (layoutMgr instanceof LayoutManager2)
      {
        LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
        return lm2.getLayoutAlignmentY(this);
      }
    else
      return super.getAlignmentY();
  }

  /**
   * 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())
      return;
    // Paint self first.
    super.paint(g);
    // Visit heavyweights as well, in case they were
    // erased when we cleared the background for this container.
    visitChildren(g, GfxPaintVisitor.INSTANCE, false);
  }

  /**
   * 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.
   */
  public void update(Graphics g)
  {
    super.update(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)
  {
    super.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 an array of all the objects currently registered as FooListeners
   * upon this Container. FooListeners are registered using the addFooListener
   * method.
   *
   * @exception ClassCastException If listenerType doesn't specify a class or
   * interface that implements @see java.util.EventListener.
   *
   * @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.
   *
   * @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.
   *
   * @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;
        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;
            if (component[i].contains (x2, y2))
              return component[i];
          }
        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.
   *
   * @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);
  }

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

  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()
  {
    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[3];

    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)
	  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.
   *
   * @return true if this is a focus cycle root, false otherwise
   *
   * @since 1.4
   */
  public void setFocusCycleRoot (boolean focusCycleRoot)
  {
    this.focusCycleRoot = focusCycleRoot;
  }

  /**
   * 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 ()
  {
    KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();

    manager.downFocusCycle (this);
  }

  /**
   * 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 ();
  }
  
  public void addPropertyChangeListener (PropertyChangeListener listener)
  {
    if (listener == null)
      return;

    if (changeSupport == null)
      changeSupport = new PropertyChangeSupport (this);

    changeSupport.addPropertyChangeListener (listener);
  }
  
  public void addPropertyChangeListener (String name,
                                         PropertyChangeListener listener)
  {
    if (listener == null)
      return;
    
    if (changeSupport == null)
      changeSupport = new PropertyChangeSupport (this);

    changeSupport.addPropertyChangeListener (name, listener);
  }

  // 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];
            // If we're visiting heavyweights as well,
            // don't recurse into Containers here. This avoids
            // painting the same nested child multiple times.
            boolean applicable = comp.isVisible()
              && (comp.isLightweight()
                  || !lightweightOnly && ! (comp instanceof Container));

            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();
    Rectangle oldClip = gfx.getClipBounds();
    if (oldClip == null)
      oldClip = bounds;

    Rectangle clip = oldClip.intersection(bounds);

    if (clip.isEmpty()) return;

    boolean clipped = false;
    boolean translated = false;
    try
      {
        gfx.setClip(clip.x, clip.y, clip.width, clip.height);
        clipped = true;
        gfx.translate(bounds.x, bounds.y);
        translated = true;
        visitor.visit(comp, gfx);
      }
    finally
      {
        if (translated)
          gfx.translate (-bounds.x, -bounds.y);
        if (clipped)
          gfx.setClip (oldClip.x, oldClip.y, oldClip.width, oldClip.height);
      }
  }

  void dispatchEventImpl(AWTEvent e)
  {
    // Give lightweight dispatcher a chance to handle it.
    if (eventTypeEnabled (e.id)
        && dispatcher != null 
        && dispatcher.handleEvent (e))
      return;
    
    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);
  }

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

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

                // If we're not lightweight, and we just got a lightweight
                // child, we need a lightweight dispatcher to feed it events.
                if (! this.isLightweight()) 
                  {
                    if (dispatcher == null)
                      dispatcher = new LightweightDispatcher (this);
                  }	
	  

		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()
      {
      }

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

/**
 * There is a helper class implied from stack traces called
 * LightweightDispatcher, but since it is not part of the public API,
 * rather than mimic it exactly we write something which does "roughly
 * the same thing".
 */

class LightweightDispatcher implements Serializable
{
  private static final long serialVersionUID = 5184291520170872969L;
  private Container nativeContainer;
  private Cursor nativeCursor;
  private long eventMask;
  
  private transient Component mouseEventTarget;
  private transient Component pressedComponent;
  private transient Component lastComponentEntered;
  private transient int pressCount;
  
  LightweightDispatcher(Container c)
  {
    nativeContainer = c;
  }

  void acquireComponentForMouseEvent(MouseEvent me)
  {
    int x = me.getX ();
    int y = me.getY ();

    // Find the candidate which should receive this event.
    Component parent = nativeContainer;
    Component candidate = null;
    Point p = me.getPoint();
    while (candidate == null && parent != null)
      {
        candidate =
          SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
        if (candidate == null || (candidate.eventMask & me.getID()) == 0)
        {
          candidate = null;
          p = SwingUtilities.convertPoint(parent, p.x, p.y, parent.parent);
          parent = parent.parent;
        }
      }

    // If the only candidate we found was the native container itself,
    // don't dispatch any event at all.  We only care about the lightweight
    // children here.
    if (candidate == nativeContainer)
      candidate = null;

    // If our candidate is new, inform the old target we're leaving.
    if (lastComponentEntered != null
        && lastComponentEntered.isShowing()
        && lastComponentEntered != candidate)
      {
        // Old candidate could have been removed from 
        // the nativeContainer so we check first.
        if (SwingUtilities.isDescendingFrom(lastComponentEntered, nativeContainer))
        {
          Point tp = 
            SwingUtilities.convertPoint(nativeContainer, 
                                        x, y, lastComponentEntered);
          MouseEvent exited = new MouseEvent (lastComponentEntered, 
                                              MouseEvent.MOUSE_EXITED,
                                              me.getWhen (), 
                                              me.getModifiersEx (), 
                                              tp.x, tp.y,
                                              me.getClickCount (),
                                              me.isPopupTrigger (),
                                              me.getButton ());
          lastComponentEntered.dispatchEvent (exited); 
        }
        lastComponentEntered = null;
      }
    // If we have a candidate, maybe enter it.
    if (candidate != null)
      {
        mouseEventTarget = candidate;
        if (candidate.isLightweight() 
            && candidate.isShowing()
            && candidate != nativeContainer
            && candidate != lastComponentEntered)
	  {			
            lastComponentEntered = mouseEventTarget;
            Point cp = SwingUtilities.convertPoint(nativeContainer, 
                                                   x, y, lastComponentEntered);
            MouseEvent entered = new MouseEvent (lastComponentEntered, 
                                                 MouseEvent.MOUSE_ENTERED,
                                                 me.getWhen (), 
                                                 me.getModifiersEx (), 
                                                 cp.x, cp.y,
                                                 me.getClickCount (),
                                                 me.isPopupTrigger (),
                                                 me.getButton ());
            lastComponentEntered.dispatchEvent (entered);
          }
      }

    if (me.getID() == MouseEvent.MOUSE_RELEASED
        || me.getID() == MouseEvent.MOUSE_PRESSED && pressCount > 0
        || me.getID() == MouseEvent.MOUSE_DRAGGED)
      // If any of the following events occur while a button is held down,
      // they should be dispatched to the same component to which the
      // original MOUSE_PRESSED event was dispatched:
      //   - MOUSE_RELEASED
      //   - MOUSE_PRESSED: another button pressed while the first is held down
      //   - MOUSE_DRAGGED
      if (SwingUtilities.isDescendingFrom(pressedComponent, nativeContainer))
        mouseEventTarget = pressedComponent;
    else if (me.getID() == MouseEvent.MOUSE_CLICKED)
      {
        // Don't dispatch CLICKED events whose target is not the same as the
        // target for the original PRESSED event.
        if (candidate != pressedComponent)
          mouseEventTarget = null;
        else if (pressCount == 0)
          pressedComponent = null;
      }
  }

  boolean handleEvent(AWTEvent e)
  {
    if (e instanceof MouseEvent)
      {
        MouseEvent me = (MouseEvent) e;

        acquireComponentForMouseEvent(me);
	
        // Avoid dispatching ENTERED and EXITED events twice.
        if (mouseEventTarget != null
            && mouseEventTarget.isShowing()
            && e.getID() != MouseEvent.MOUSE_ENTERED
            && e.getID() != MouseEvent.MOUSE_EXITED)
          {
            MouseEvent newEvt = 
              SwingUtilities.convertMouseEvent(nativeContainer, me, 
                                               mouseEventTarget);
            mouseEventTarget.dispatchEvent(newEvt);

            switch (e.getID())
              {
                case MouseEvent.MOUSE_PRESSED:
                  if (pressCount++ == 0)
                    pressedComponent = mouseEventTarget;
                  break;

                case MouseEvent.MOUSE_RELEASED:
                  // Clear our memory of the original PRESSED event, only if
                  // we're not expecting a CLICKED event after this. If
                  // there is a CLICKED event after this, it will do clean up.
                  if (--pressCount == 0
                      && mouseEventTarget != pressedComponent)
                    pressedComponent = null;
                  break;
              }
              if (newEvt.isConsumed())
                e.consume();
          }
      }
    
    return e.isConsumed();
  }

} // class LightweightDispatcher
