|  | /* Container.java -- parent container class in AWT | 
|  | Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006 | 
|  | Free Software Foundation | 
|  |  | 
|  | This file is part of GNU Classpath. | 
|  |  | 
|  | GNU Classpath is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 2, or (at your option) | 
|  | any later version. | 
|  |  | 
|  | GNU Classpath is distributed in the hope that it will be useful, but | 
|  | WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with GNU Classpath; see the file COPYING.  If not, write to the | 
|  | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 
|  | 02110-1301 USA. | 
|  |  | 
|  | Linking this library statically or dynamically with other modules is | 
|  | making a combined work based on this library.  Thus, the terms and | 
|  | conditions of the GNU General Public License cover the whole | 
|  | combination. | 
|  |  | 
|  | As a special exception, the copyright holders of this library give you | 
|  | permission to link this library with independent modules to produce an | 
|  | executable, regardless of the license terms of these independent | 
|  | modules, and to copy and distribute the resulting executable under | 
|  | terms of your choice, provided that you also meet, for each linked | 
|  | independent module, the terms and conditions of the license of that | 
|  | module.  An independent module is a module which is not derived from | 
|  | or based on this library.  If you modify this library, you may extend | 
|  | this exception to your version of the library, but you are not | 
|  | obligated to do so.  If you do not wish to do so, delete this | 
|  | exception statement from your version. */ | 
|  |  | 
|  |  | 
|  | package java.awt; | 
|  |  | 
|  | import gnu.java.lang.CPStringBuilder; | 
|  |  | 
|  | import java.awt.event.ContainerEvent; | 
|  | import java.awt.event.ContainerListener; | 
|  | import java.awt.event.HierarchyEvent; | 
|  | import java.awt.event.KeyEvent; | 
|  | import java.awt.event.MouseEvent; | 
|  | import java.awt.peer.ComponentPeer; | 
|  | import java.awt.peer.ContainerPeer; | 
|  | import java.awt.peer.LightweightPeer; | 
|  | import java.beans.PropertyChangeListener; | 
|  | import java.io.IOException; | 
|  | import java.io.ObjectInputStream; | 
|  | import java.io.ObjectOutputStream; | 
|  | import java.io.PrintStream; | 
|  | import java.io.PrintWriter; | 
|  | import java.io.Serializable; | 
|  | import java.util.Collections; | 
|  | import java.util.EventListener; | 
|  | import java.util.HashSet; | 
|  | import java.util.Iterator; | 
|  | import java.util.Set; | 
|  |  | 
|  | import javax.accessibility.Accessible; | 
|  |  | 
|  | /** | 
|  | * A generic window toolkit object that acts as a container for other objects. | 
|  | * Components are tracked in a list, and new elements are at the end of the | 
|  | * list or bottom of the stacking order. | 
|  | * | 
|  | * @author original author unknown | 
|  | * @author Eric Blake (ebb9@email.byu.edu) | 
|  | * @author Andrew John Hughes (gnu_andrew@member.fsf.org) | 
|  | * | 
|  | * @since 1.0 | 
|  | * | 
|  | * @status still missing 1.4 support, some generics from 1.5 | 
|  | */ | 
|  | public class Container extends Component | 
|  | { | 
|  | /** | 
|  | * Compatible with JDK 1.0+. | 
|  | */ | 
|  | private static final long serialVersionUID = 4613797578919906343L; | 
|  |  | 
|  | /* Serialized fields from the serialization spec. */ | 
|  | int ncomponents; | 
|  | Component[] component; | 
|  | LayoutManager layoutMgr; | 
|  |  | 
|  | /** | 
|  | * @since 1.4 | 
|  | */ | 
|  | boolean focusCycleRoot; | 
|  |  | 
|  | /** | 
|  | * Indicates if this container provides a focus traversal policy. | 
|  | * | 
|  | * @since 1.5 | 
|  | */ | 
|  | private boolean focusTraversalPolicyProvider; | 
|  |  | 
|  | int containerSerializedDataVersion; | 
|  |  | 
|  | /* Anything else is non-serializable, and should be declared "transient". */ | 
|  | transient ContainerListener containerListener; | 
|  |  | 
|  | /** The focus traversal policy that determines how focus is | 
|  | transferred between this Container and its children. */ | 
|  | private FocusTraversalPolicy focusTraversalPolicy; | 
|  |  | 
|  | /** | 
|  | * The focus traversal keys, if not inherited from the parent or default | 
|  | * keyboard manager. These sets will contain only AWTKeyStrokes that | 
|  | * represent press and release events to use as focus control. | 
|  | * | 
|  | * @see #getFocusTraversalKeys(int) | 
|  | * @see #setFocusTraversalKeys(int, Set) | 
|  | * @since 1.4 | 
|  | */ | 
|  | transient Set[] focusTraversalKeys; | 
|  |  | 
|  | /** | 
|  | * Default constructor for subclasses. | 
|  | */ | 
|  | public Container() | 
|  | { | 
|  | // Nothing to do here. | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the number of components in this container. | 
|  | * | 
|  | * @return The number of components in this container. | 
|  | */ | 
|  | public int getComponentCount() | 
|  | { | 
|  | return countComponents (); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the number of components in this container. | 
|  | * | 
|  | * @return The number of components in this container. | 
|  | * | 
|  | * @deprecated use {@link #getComponentCount()} instead | 
|  | */ | 
|  | public int countComponents() | 
|  | { | 
|  | return ncomponents; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the component at the specified index. | 
|  | * | 
|  | * @param n The index of the component to retrieve. | 
|  | * | 
|  | * @return The requested component. | 
|  | * | 
|  | * @throws ArrayIndexOutOfBoundsException If the specified index is invalid | 
|  | */ | 
|  | public Component getComponent(int n) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | if (n < 0 || n >= ncomponents) | 
|  | throw new ArrayIndexOutOfBoundsException("no such component"); | 
|  |  | 
|  | return component[n]; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns an array of the components in this container. | 
|  | * | 
|  | * @return The components in this container. | 
|  | */ | 
|  | public Component[] getComponents() | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | Component[] result = new Component[ncomponents]; | 
|  |  | 
|  | if (ncomponents > 0) | 
|  | System.arraycopy(component, 0, result, 0, ncomponents); | 
|  |  | 
|  | return result; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the insets for this container, which is the space used for | 
|  | * borders, the margin, etc. | 
|  | * | 
|  | * @return The insets for this container. | 
|  | */ | 
|  | public Insets getInsets() | 
|  | { | 
|  | return insets (); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the insets for this container, which is the space used for | 
|  | * borders, the margin, etc. | 
|  | * | 
|  | * @return The insets for this container. | 
|  | * @deprecated use {@link #getInsets()} instead | 
|  | */ | 
|  | public Insets insets() | 
|  | { | 
|  | Insets i; | 
|  | if (peer == null || peer instanceof LightweightPeer) | 
|  | i = new Insets (0, 0, 0, 0); | 
|  | else | 
|  | i = ((ContainerPeer) peer).getInsets (); | 
|  | return i; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Adds the specified component to this container at the end of the | 
|  | * component list. | 
|  | * | 
|  | * @param comp The component to add to the container. | 
|  | * | 
|  | * @return The same component that was added. | 
|  | */ | 
|  | public Component add(Component comp) | 
|  | { | 
|  | addImpl(comp, null, -1); | 
|  | return comp; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Adds the specified component to the container at the end of the | 
|  | * component list.  This method should not be used. Instead, use | 
|  | * <code>add(Component, Object)</code>. | 
|  | * | 
|  | * @param name The name of the component to be added. | 
|  | * @param comp The component to be added. | 
|  | * | 
|  | * @return The same component that was added. | 
|  | * | 
|  | * @see #add(Component,Object) | 
|  | */ | 
|  | public Component add(String name, Component comp) | 
|  | { | 
|  | addImpl(comp, name, -1); | 
|  | return comp; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Adds the specified component to this container at the specified index | 
|  | * in the component list. | 
|  | * | 
|  | * @param comp The component to be added. | 
|  | * @param index The index in the component list to insert this child | 
|  | * at, or -1 to add at the end of the list. | 
|  | * | 
|  | * @return The same component that was added. | 
|  | * | 
|  | * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. | 
|  | */ | 
|  | public Component add(Component comp, int index) | 
|  | { | 
|  | addImpl(comp, null, index); | 
|  | return comp; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Adds the specified component to this container at the end of the | 
|  | * component list.  The layout manager will use the specified constraints | 
|  | * when laying out this component. | 
|  | * | 
|  | * @param comp The component to be added to this container. | 
|  | * @param constraints The layout constraints for this component. | 
|  | */ | 
|  | public void add(Component comp, Object constraints) | 
|  | { | 
|  | addImpl(comp, constraints, -1); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Adds the specified component to this container at the specified index | 
|  | * in the component list.  The layout manager will use the specified | 
|  | * constraints when layout out this component. | 
|  | * | 
|  | * @param comp The component to be added. | 
|  | * @param constraints The layout constraints for this component. | 
|  | * @param index The index in the component list to insert this child | 
|  | * at, or -1 to add at the end of the list. | 
|  | * | 
|  | * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. | 
|  | */ | 
|  | public void add(Component comp, Object constraints, int index) | 
|  | { | 
|  | addImpl(comp, constraints, index); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * This method is called by all the <code>add()</code> methods to perform | 
|  | * the actual adding of the component.  Subclasses who wish to perform | 
|  | * their own processing when a component is added should override this | 
|  | * method.  Any subclass doing this must call the superclass version of | 
|  | * this method in order to ensure proper functioning of the container. | 
|  | * | 
|  | * @param comp The component to be added. | 
|  | * @param constraints The layout constraints for this component, or | 
|  | * <code>null</code> if there are no constraints. | 
|  | * @param index The index in the component list to insert this child | 
|  | * at, or -1 to add at the end of the list. | 
|  | * | 
|  | * @throws ArrayIndexOutOfBoundsException If the specified index is invalid. | 
|  | */ | 
|  | protected void addImpl(Component comp, Object constraints, int index) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | if (index > ncomponents | 
|  | || (index < 0 && index != -1) | 
|  | || comp instanceof Window | 
|  | || (comp instanceof Container | 
|  | && ((Container) comp).isAncestorOf(this))) | 
|  | throw new IllegalArgumentException(); | 
|  |  | 
|  | // Reparent component, and make sure component is instantiated if | 
|  | // we are. | 
|  | if (comp.parent != null) | 
|  | comp.parent.remove(comp); | 
|  |  | 
|  | if (component == null) | 
|  | component = new Component[4]; // FIXME, better initial size? | 
|  |  | 
|  | // This isn't the most efficient implementation.  We could do less | 
|  | // copying when growing the array.  It probably doesn't matter. | 
|  | if (ncomponents >= component.length) | 
|  | { | 
|  | int nl = component.length * 2; | 
|  | Component[] c = new Component[nl]; | 
|  | System.arraycopy(component, 0, c, 0, ncomponents); | 
|  | component = c; | 
|  | } | 
|  |  | 
|  | if (index == -1) | 
|  | component[ncomponents++] = comp; | 
|  | else | 
|  | { | 
|  | System.arraycopy(component, index, component, index + 1, | 
|  | ncomponents - index); | 
|  | component[index] = comp; | 
|  | ++ncomponents; | 
|  | } | 
|  |  | 
|  | // Give the new component a parent. | 
|  | comp.parent = this; | 
|  |  | 
|  | // Update the counter for Hierarchy(Bounds)Listeners. | 
|  | int childHierarchyListeners = comp.numHierarchyListeners; | 
|  | if (childHierarchyListeners > 0) | 
|  | updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, | 
|  | childHierarchyListeners); | 
|  | int childHierarchyBoundsListeners = comp.numHierarchyBoundsListeners; | 
|  | if (childHierarchyBoundsListeners > 0) | 
|  | updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, | 
|  | childHierarchyListeners); | 
|  |  | 
|  | // Invalidate the layout of this container. | 
|  | if (valid) | 
|  | invalidate(); | 
|  |  | 
|  | // Create the peer _after_ the component has been added, so that | 
|  | // the peer gets to know about the component hierarchy. | 
|  | if (peer != null) | 
|  | { | 
|  | // Notify the component that it has a new parent. | 
|  | comp.addNotify(); | 
|  | } | 
|  |  | 
|  | // Notify the layout manager. | 
|  | if (layoutMgr != null) | 
|  | { | 
|  | // If we have a LayoutManager2 the constraints are "real", | 
|  | // otherwise they are the "name" of the Component to add. | 
|  | if (layoutMgr instanceof LayoutManager2) | 
|  | { | 
|  | LayoutManager2 lm2 = (LayoutManager2) layoutMgr; | 
|  | lm2.addLayoutComponent(comp, constraints); | 
|  | } | 
|  | else if (constraints instanceof String) | 
|  | layoutMgr.addLayoutComponent((String) constraints, comp); | 
|  | else | 
|  | layoutMgr.addLayoutComponent("", comp); | 
|  | } | 
|  |  | 
|  | // We previously only sent an event when this container is showing. | 
|  | // Also, the event was posted to the event queue. A Mauve test shows | 
|  | // that this event is not delivered using the event queue and it is | 
|  | // also sent when the container is not showing. | 
|  | if (containerListener != null | 
|  | || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) | 
|  | { | 
|  | ContainerEvent ce = new ContainerEvent(this, | 
|  | ContainerEvent.COMPONENT_ADDED, | 
|  | comp); | 
|  | dispatchEvent(ce); | 
|  | } | 
|  |  | 
|  | // Notify hierarchy listeners. | 
|  | comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp, | 
|  | this, HierarchyEvent.PARENT_CHANGED); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Removes the component at the specified index from this container. | 
|  | * | 
|  | * @param index The index of the component to remove. | 
|  | */ | 
|  | public void remove(int index) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | if (index < 0 || index >= ncomponents) | 
|  | throw new ArrayIndexOutOfBoundsException(); | 
|  |  | 
|  | Component r = component[index]; | 
|  | if (peer != null) | 
|  | r.removeNotify(); | 
|  |  | 
|  | if (layoutMgr != null) | 
|  | layoutMgr.removeLayoutComponent(r); | 
|  |  | 
|  | // Update the counter for Hierarchy(Bounds)Listeners. | 
|  | int childHierarchyListeners = r.numHierarchyListeners; | 
|  | if (childHierarchyListeners > 0) | 
|  | updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, | 
|  | -childHierarchyListeners); | 
|  | int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners; | 
|  | if (childHierarchyBoundsListeners > 0) | 
|  | updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, | 
|  | -childHierarchyListeners); | 
|  |  | 
|  | r.parent = null; | 
|  |  | 
|  | System.arraycopy(component, index + 1, component, index, | 
|  | ncomponents - index - 1); | 
|  | component[--ncomponents] = null; | 
|  |  | 
|  | if (valid) | 
|  | invalidate(); | 
|  |  | 
|  | if (containerListener != null | 
|  | || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) | 
|  | { | 
|  | // Post event to notify of removing the component. | 
|  | ContainerEvent ce = new ContainerEvent(this, | 
|  | ContainerEvent.COMPONENT_REMOVED, | 
|  | r); | 
|  | dispatchEvent(ce); | 
|  | } | 
|  |  | 
|  | // Notify hierarchy listeners. | 
|  | r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, | 
|  | this, HierarchyEvent.PARENT_CHANGED); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Removes the specified component from this container. | 
|  | * | 
|  | * @param comp The component to remove from this container. | 
|  | */ | 
|  | public void remove(Component comp) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | for (int i = 0; i < ncomponents; ++i) | 
|  | { | 
|  | if (component[i] == comp) | 
|  | { | 
|  | remove(i); | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Removes all components from this container. | 
|  | */ | 
|  | public void removeAll() | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | // In order to allow the same bad tricks to be used as in RI | 
|  | // this code has to stay exactly that way: In a real-life app | 
|  | // a Container subclass implemented its own vector for | 
|  | // subcomponents, supplied additional addXYZ() methods | 
|  | // and overrode remove(int) and removeAll (the latter calling | 
|  | // super.removeAll() ). | 
|  | // By doing it this way, user code cannot prevent the correct | 
|  | // removal of components. | 
|  | while (ncomponents > 0) | 
|  | { | 
|  | ncomponents--; | 
|  | Component r = component[ncomponents]; | 
|  | component[ncomponents] = null; | 
|  |  | 
|  | if (peer != null) | 
|  | r.removeNotify(); | 
|  |  | 
|  | if (layoutMgr != null) | 
|  | layoutMgr.removeLayoutComponent(r); | 
|  |  | 
|  | r.parent = null; | 
|  |  | 
|  | // Send ContainerEvent if necessary. | 
|  | if (containerListener != null | 
|  | || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0) | 
|  | { | 
|  | // Post event to notify of removing the component. | 
|  | ContainerEvent ce | 
|  | = new ContainerEvent(this, | 
|  | ContainerEvent.COMPONENT_REMOVED, | 
|  | r); | 
|  | dispatchEvent(ce); | 
|  | } | 
|  |  | 
|  | // Update the counter for Hierarchy(Bounds)Listeners. | 
|  | int childHierarchyListeners = r.numHierarchyListeners; | 
|  | if (childHierarchyListeners > 0) | 
|  | updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, | 
|  | -childHierarchyListeners); | 
|  | int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners; | 
|  | if (childHierarchyBoundsListeners > 0) | 
|  | updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, | 
|  | -childHierarchyListeners); | 
|  |  | 
|  |  | 
|  | // Send HierarchyEvent if necessary. | 
|  | fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this, | 
|  | HierarchyEvent.PARENT_CHANGED); | 
|  |  | 
|  | } | 
|  |  | 
|  | if (valid) | 
|  | invalidate(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the current layout manager for this container. | 
|  | * | 
|  | * @return The layout manager for this container. | 
|  | */ | 
|  | public LayoutManager getLayout() | 
|  | { | 
|  | return layoutMgr; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the layout manager for this container to the specified layout | 
|  | * manager. | 
|  | * | 
|  | * @param mgr The new layout manager for this container. | 
|  | */ | 
|  | public void setLayout(LayoutManager mgr) | 
|  | { | 
|  | layoutMgr = mgr; | 
|  | if (valid) | 
|  | invalidate(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Layout the components in this container. | 
|  | */ | 
|  | public void doLayout() | 
|  | { | 
|  | layout (); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Layout the components in this container. | 
|  | * | 
|  | * @deprecated use {@link #doLayout()} instead | 
|  | */ | 
|  | public void layout() | 
|  | { | 
|  | if (layoutMgr != null) | 
|  | layoutMgr.layoutContainer (this); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Invalidates this container to indicate that it (and all parent | 
|  | * containers) need to be laid out. | 
|  | */ | 
|  | public void invalidate() | 
|  | { | 
|  | super.invalidate(); | 
|  | if (layoutMgr != null && layoutMgr instanceof LayoutManager2) | 
|  | { | 
|  | LayoutManager2 lm2 = (LayoutManager2) layoutMgr; | 
|  | lm2.invalidateLayout(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Re-lays out the components in this container. | 
|  | */ | 
|  | public void validate() | 
|  | { | 
|  | ComponentPeer p = peer; | 
|  | if (! valid && p != null) | 
|  | { | 
|  | ContainerPeer cPeer = null; | 
|  | if (p instanceof ContainerPeer) | 
|  | cPeer = (ContainerPeer) peer; | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | if (cPeer != null) | 
|  | cPeer.beginValidate(); | 
|  | validateTree(); | 
|  | valid = true; | 
|  | if (cPeer != null) | 
|  | cPeer.endValidate(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Recursively invalidates the container tree. | 
|  | */ | 
|  | private final void invalidateTree() | 
|  | { | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | for (int i = 0; i < ncomponents; i++) | 
|  | { | 
|  | Component comp = component[i]; | 
|  | if (comp instanceof Container) | 
|  | ((Container) comp).invalidateTree(); | 
|  | else if (comp.valid) | 
|  | comp.invalidate(); | 
|  | } | 
|  | if (valid) | 
|  | invalidate(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Recursively validates the container tree, recomputing any invalid | 
|  | * layouts. | 
|  | */ | 
|  | protected void validateTree() | 
|  | { | 
|  | if (!valid) | 
|  | { | 
|  | ContainerPeer cPeer = null; | 
|  | if (peer instanceof ContainerPeer) | 
|  | { | 
|  | cPeer = (ContainerPeer) peer; | 
|  | cPeer.beginLayout(); | 
|  | } | 
|  |  | 
|  | doLayout (); | 
|  | for (int i = 0; i < ncomponents; ++i) | 
|  | { | 
|  | Component comp = component[i]; | 
|  |  | 
|  | if (comp instanceof Container && ! (comp instanceof Window) | 
|  | && ! comp.valid) | 
|  | { | 
|  | ((Container) comp).validateTree(); | 
|  | } | 
|  | else | 
|  | { | 
|  | comp.validate(); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (cPeer != null) | 
|  | { | 
|  | cPeer = (ContainerPeer) peer; | 
|  | cPeer.endLayout(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* children will call invalidate() when they are layed out. It | 
|  | is therefore important that valid is not set to true | 
|  | until after the children have been layed out. */ | 
|  | valid = true; | 
|  |  | 
|  | } | 
|  |  | 
|  | public void setFont(Font f) | 
|  | { | 
|  | Font oldFont = getFont(); | 
|  | super.setFont(f); | 
|  | Font newFont = getFont(); | 
|  | if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont))) | 
|  | { | 
|  | invalidateTree(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the preferred size of this container. | 
|  | * | 
|  | * @return The preferred size of this container. | 
|  | */ | 
|  | public Dimension getPreferredSize() | 
|  | { | 
|  | return preferredSize (); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the preferred size of this container. | 
|  | * | 
|  | * @return The preferred size of this container. | 
|  | * | 
|  | * @deprecated use {@link #getPreferredSize()} instead | 
|  | */ | 
|  | public Dimension preferredSize() | 
|  | { | 
|  | Dimension size = prefSize; | 
|  | // Try to return cached value if possible. | 
|  | if (size == null || !(prefSizeSet || valid)) | 
|  | { | 
|  | // Need to lock here. | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | LayoutManager l = layoutMgr; | 
|  | if (l != null) | 
|  | prefSize = l.preferredLayoutSize(this); | 
|  | else | 
|  | prefSize = super.preferredSizeImpl(); | 
|  | size = prefSize; | 
|  | } | 
|  | } | 
|  | if (size != null) | 
|  | return new Dimension(size); | 
|  | else | 
|  | return size; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the minimum size of this container. | 
|  | * | 
|  | * @return The minimum size of this container. | 
|  | */ | 
|  | public Dimension getMinimumSize() | 
|  | { | 
|  | return minimumSize (); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the minimum size of this container. | 
|  | * | 
|  | * @return The minimum size of this container. | 
|  | * | 
|  | * @deprecated use {@link #getMinimumSize()} instead | 
|  | */ | 
|  | public Dimension minimumSize() | 
|  | { | 
|  | Dimension size = minSize; | 
|  | // Try to return cached value if possible. | 
|  | if (size == null || !(minSizeSet || valid)) | 
|  | { | 
|  | // Need to lock here. | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | LayoutManager l = layoutMgr; | 
|  | if (l != null) | 
|  | minSize = l.minimumLayoutSize(this); | 
|  | else | 
|  | minSize = super.minimumSizeImpl(); | 
|  | size = minSize; | 
|  | } | 
|  | } | 
|  | if (size != null) | 
|  | return new Dimension(size); | 
|  | else | 
|  | return size; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the maximum size of this container. | 
|  | * | 
|  | * @return The maximum size of this container. | 
|  | */ | 
|  | public Dimension getMaximumSize() | 
|  | { | 
|  | Dimension size = maxSize; | 
|  | // Try to return cached value if possible. | 
|  | if (size == null || !(maxSizeSet || valid)) | 
|  | { | 
|  | // Need to lock here. | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | LayoutManager l = layoutMgr; | 
|  | if (l instanceof LayoutManager2) | 
|  | maxSize = ((LayoutManager2) l).maximumLayoutSize(this); | 
|  | else { | 
|  | maxSize = super.maximumSizeImpl(); | 
|  | } | 
|  | size = maxSize; | 
|  | } | 
|  | } | 
|  | if (size != null) | 
|  | return new Dimension(size); | 
|  | else | 
|  | return size; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the preferred alignment along the X axis.  This is a value | 
|  | * between 0 and 1 where 0 represents alignment flush left and | 
|  | * 1 means alignment flush right, and 0.5 means centered. | 
|  | * | 
|  | * @return The preferred alignment along the X axis. | 
|  | */ | 
|  | public float getAlignmentX() | 
|  | { | 
|  | LayoutManager layout = getLayout(); | 
|  | float alignmentX = 0.0F; | 
|  | if (layout != null && layout instanceof LayoutManager2) | 
|  | { | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | LayoutManager2 lm2 = (LayoutManager2) layout; | 
|  | alignmentX = lm2.getLayoutAlignmentX(this); | 
|  | } | 
|  | } | 
|  | else | 
|  | alignmentX = super.getAlignmentX(); | 
|  | return alignmentX; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the preferred alignment along the Y axis.  This is a value | 
|  | * between 0 and 1 where 0 represents alignment flush top and | 
|  | * 1 means alignment flush bottom, and 0.5 means centered. | 
|  | * | 
|  | * @return The preferred alignment along the Y axis. | 
|  | */ | 
|  | public float getAlignmentY() | 
|  | { | 
|  | LayoutManager layout = getLayout(); | 
|  | float alignmentY = 0.0F; | 
|  | if (layout != null && layout instanceof LayoutManager2) | 
|  | { | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | LayoutManager2 lm2 = (LayoutManager2) layout; | 
|  | alignmentY = lm2.getLayoutAlignmentY(this); | 
|  | } | 
|  | } | 
|  | else | 
|  | alignmentY = super.getAlignmentY(); | 
|  | return alignmentY; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Paints this container.  The implementation of this method in this | 
|  | * class forwards to any lightweight components in this container.  If | 
|  | * this method is subclassed, this method should still be invoked as | 
|  | * a superclass method so that lightweight components are properly | 
|  | * drawn. | 
|  | * | 
|  | * @param g - The graphics context for this paint job. | 
|  | */ | 
|  | public void paint(Graphics g) | 
|  | { | 
|  | if (isShowing()) | 
|  | { | 
|  | visitChildren(g, GfxPaintVisitor.INSTANCE, true); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Updates this container.  The implementation of this method in this | 
|  | * class forwards to any lightweight components in this container.  If | 
|  | * this method is subclassed, this method should still be invoked as | 
|  | * a superclass method so that lightweight components are properly | 
|  | * drawn. | 
|  | * | 
|  | * @param g The graphics context for this update. | 
|  | * | 
|  | * @specnote The specification suggests that this method forwards the | 
|  | *           update() call to all its lightweight children. Tests show | 
|  | *           that this is not done either in the JDK. The exact behaviour | 
|  | *           seems to be that the background is cleared in heavyweight | 
|  | *           Containers, and all other containers | 
|  | *           directly call paint(), causing the (lightweight) children to | 
|  | *           be painted. | 
|  | */ | 
|  | public void update(Graphics g) | 
|  | { | 
|  | // It seems that the JDK clears the background of containers like Panel | 
|  | // and Window (within this method) but not of 'plain' Containers or | 
|  | // JComponents. This could | 
|  | // lead to the assumption that it only clears heavyweight containers. | 
|  | // However that is not quite true. In a test with a custom Container | 
|  | // that overrides isLightweight() to return false, the background is | 
|  | // also not cleared. So we do a check on !(peer instanceof LightweightPeer) | 
|  | // instead. | 
|  | if (isShowing()) | 
|  | { | 
|  | ComponentPeer p = peer; | 
|  | if (! (p instanceof LightweightPeer)) | 
|  | { | 
|  | g.clearRect(0, 0, getWidth(), getHeight()); | 
|  | } | 
|  | paint(g); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Prints this container.  The implementation of this method in this | 
|  | * class forwards to any lightweight components in this container.  If | 
|  | * this method is subclassed, this method should still be invoked as | 
|  | * a superclass method so that lightweight components are properly | 
|  | * drawn. | 
|  | * | 
|  | * @param g The graphics context for this print job. | 
|  | */ | 
|  | public void print(Graphics g) | 
|  | { | 
|  | super.print(g); | 
|  | visitChildren(g, GfxPrintVisitor.INSTANCE, true); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Paints all of the components in this container. | 
|  | * | 
|  | * @param g The graphics context for this paint job. | 
|  | */ | 
|  | public void paintComponents(Graphics g) | 
|  | { | 
|  | if (isShowing()) | 
|  | visitChildren(g, GfxPaintAllVisitor.INSTANCE, false); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Prints all of the components in this container. | 
|  | * | 
|  | * @param g The graphics context for this print job. | 
|  | */ | 
|  | public void printComponents(Graphics g) | 
|  | { | 
|  | super.paint(g); | 
|  | visitChildren(g, GfxPrintAllVisitor.INSTANCE, true); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Adds the specified container listener to this object's list of | 
|  | * container listeners. | 
|  | * | 
|  | * @param listener The listener to add. | 
|  | */ | 
|  | public synchronized void addContainerListener(ContainerListener listener) | 
|  | { | 
|  | if (listener != null) | 
|  | { | 
|  | containerListener = AWTEventMulticaster.add(containerListener, | 
|  | listener); | 
|  | newEventsOnly = true; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Removes the specified container listener from this object's list of | 
|  | * container listeners. | 
|  | * | 
|  | * @param listener The listener to remove. | 
|  | */ | 
|  | public synchronized void removeContainerListener(ContainerListener listener) | 
|  | { | 
|  | containerListener = AWTEventMulticaster.remove(containerListener, listener); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @since 1.4 | 
|  | */ | 
|  | public synchronized ContainerListener[] getContainerListeners() | 
|  | { | 
|  | return (ContainerListener[]) | 
|  | AWTEventMulticaster.getListeners(containerListener, | 
|  | ContainerListener.class); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns all registered {@link EventListener}s of the given | 
|  | * <code>listenerType</code>. | 
|  | * | 
|  | * @param listenerType the class of listeners to filter (<code>null</code> | 
|  | *                     not permitted). | 
|  | * | 
|  | * @return An array of registered listeners. | 
|  | * | 
|  | * @throws ClassCastException if <code>listenerType</code> does not implement | 
|  | *                            the {@link EventListener} interface. | 
|  | * @throws NullPointerException if <code>listenerType</code> is | 
|  | *                              <code>null</code>. | 
|  | * | 
|  | * @see #getContainerListeners() | 
|  | * | 
|  | * @since 1.3 | 
|  | */ | 
|  | public <T extends EventListener> T[] getListeners(Class<T> listenerType) | 
|  | { | 
|  | if (listenerType == ContainerListener.class) | 
|  | return (T[]) getContainerListeners(); | 
|  | return super.getListeners(listenerType); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Processes the specified event.  This method calls | 
|  | * <code>processContainerEvent()</code> if this method is a | 
|  | * <code>ContainerEvent</code>, otherwise it calls the superclass | 
|  | * method. | 
|  | * | 
|  | * @param e The event to be processed. | 
|  | */ | 
|  | protected void processEvent(AWTEvent e) | 
|  | { | 
|  | if (e instanceof ContainerEvent) | 
|  | processContainerEvent((ContainerEvent) e); | 
|  | else | 
|  | super.processEvent(e); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Called when a container event occurs if container events are enabled. | 
|  | * This method calls any registered listeners. | 
|  | * | 
|  | * @param e The event that occurred. | 
|  | */ | 
|  | protected void processContainerEvent(ContainerEvent e) | 
|  | { | 
|  | if (containerListener == null) | 
|  | return; | 
|  | switch (e.id) | 
|  | { | 
|  | case ContainerEvent.COMPONENT_ADDED: | 
|  | containerListener.componentAdded(e); | 
|  | break; | 
|  |  | 
|  | case ContainerEvent.COMPONENT_REMOVED: | 
|  | containerListener.componentRemoved(e); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * AWT 1.0 event processor. | 
|  | * | 
|  | * @param e The event that occurred. | 
|  | * | 
|  | * @deprecated use {@link #dispatchEvent(AWTEvent)} instead | 
|  | */ | 
|  | public void deliverEvent(Event e) | 
|  | { | 
|  | if (!handleEvent (e)) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | Component parent = getParent (); | 
|  |  | 
|  | if (parent != null) | 
|  | parent.deliverEvent (e); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the component located at the specified point.  This is done | 
|  | * by checking whether or not a child component claims to contain this | 
|  | * point.  The first child component that does is returned.  If no | 
|  | * child component claims the point, the container itself is returned, | 
|  | * unless the point does not exist within this container, in which | 
|  | * case <code>null</code> is returned. | 
|  | * | 
|  | * When components overlap, the first component is returned. The component | 
|  | * that is closest to (x, y), containing that location, is returned. | 
|  | * Heavyweight components take precedence of lightweight components. | 
|  | * | 
|  | * This function does not ignore invisible components. If there is an invisible | 
|  | * component at (x,y), it will be returned. | 
|  | * | 
|  | * @param x The X coordinate of the point. | 
|  | * @param y The Y coordinate of the point. | 
|  | * | 
|  | * @return The component containing the specified point, or | 
|  | * <code>null</code> if there is no such point. | 
|  | */ | 
|  | public Component getComponentAt(int x, int y) | 
|  | { | 
|  | return locate (x, y); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the mouse pointer position relative to this Container's | 
|  | * top-left corner.  If allowChildren is false, the mouse pointer | 
|  | * must be directly over this container.  If allowChildren is true, | 
|  | * the mouse pointer may be over this container or any of its | 
|  | * descendents. | 
|  | * | 
|  | * @param allowChildren true to allow descendents, false if pointer | 
|  | * must be directly over Container. | 
|  | * | 
|  | * @return relative mouse pointer position | 
|  | * | 
|  | * @throws HeadlessException if in a headless environment | 
|  | */ | 
|  | public Point getMousePosition(boolean allowChildren) throws HeadlessException | 
|  | { | 
|  | return super.getMousePositionHelper(allowChildren); | 
|  | } | 
|  |  | 
|  | boolean mouseOverComponent(Component component, boolean allowChildren) | 
|  | { | 
|  | if (allowChildren) | 
|  | return isAncestorOf(component); | 
|  | else | 
|  | return component == this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the component located at the specified point.  This is done | 
|  | * by checking whether or not a child component claims to contain this | 
|  | * point.  The first child component that does is returned.  If no | 
|  | * child component claims the point, the container itself is returned, | 
|  | * unless the point does not exist within this container, in which | 
|  | * case <code>null</code> is returned. | 
|  | * | 
|  | * When components overlap, the first component is returned. The component | 
|  | * that is closest to (x, y), containing that location, is returned. | 
|  | * Heavyweight components take precedence of lightweight components. | 
|  | * | 
|  | * This function does not ignore invisible components. If there is an invisible | 
|  | * component at (x,y), it will be returned. | 
|  | * | 
|  | * @param x The x position of the point to return the component at. | 
|  | * @param y The y position of the point to return the component at. | 
|  | * | 
|  | * @return The component containing the specified point, or <code>null</code> | 
|  | * if there is no such point. | 
|  | * | 
|  | * @deprecated use {@link #getComponentAt(int, int)} instead | 
|  | */ | 
|  | public Component locate(int x, int y) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | if (!contains (x, y)) | 
|  | return null; | 
|  |  | 
|  | // First find the component closest to (x,y) that is a heavyweight. | 
|  | for (int i = 0; i < ncomponents; ++i) | 
|  | { | 
|  | Component comp = component[i]; | 
|  | int x2 = x - comp.x; | 
|  | int y2 = y - comp.y; | 
|  | if (comp.contains (x2, y2) && !comp.isLightweight()) | 
|  | return comp; | 
|  | } | 
|  |  | 
|  | // if a heavyweight component is not found, look for a lightweight | 
|  | // closest to (x,y). | 
|  | for (int i = 0; i < ncomponents; ++i) | 
|  | { | 
|  | Component comp = component[i]; | 
|  | int x2 = x - comp.x; | 
|  | int y2 = y - comp.y; | 
|  | if (comp.contains (x2, y2) && comp.isLightweight()) | 
|  | return comp; | 
|  | } | 
|  |  | 
|  | return this; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the component located at the specified point.  This is done | 
|  | * by checking whether or not a child component claims to contain this | 
|  | * point.  The first child component that does is returned.  If no | 
|  | * child component claims the point, the container itself is returned, | 
|  | * unless the point does not exist within this container, in which | 
|  | * case <code>null</code> is returned. | 
|  | * | 
|  | * The top-most child component is returned in the case where components overlap. | 
|  | * This is determined by finding the component closest to (x,y) and contains | 
|  | * that location. Heavyweight components take precedence of lightweight components. | 
|  | * | 
|  | * This function does not ignore invisible components. If there is an invisible | 
|  | * component at (x,y), it will be returned. | 
|  | * | 
|  | * @param p The point to return the component at. | 
|  | * @return The component containing the specified point, or <code>null</code> | 
|  | * if there is no such point. | 
|  | */ | 
|  | public Component getComponentAt(Point p) | 
|  | { | 
|  | return getComponentAt (p.x, p.y); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Locates the visible child component that contains the specified position. | 
|  | * The top-most child component is returned in the case where there is overlap | 
|  | * in the components. If the containing child component is a Container, | 
|  | * this method will continue searching for the deepest nested child | 
|  | * component. Components which are not visible are ignored during the search. | 
|  | * | 
|  | * findComponentAt differs from getComponentAt, because it recursively | 
|  | * searches a Container's children. | 
|  | * | 
|  | * @param x - x coordinate | 
|  | * @param y - y coordinate | 
|  | * @return null if the component does not contain the position. | 
|  | * If there is no child component at the requested point and the point is | 
|  | * within the bounds of the container the container itself is returned. | 
|  | */ | 
|  | public Component findComponentAt(int x, int y) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | if (! contains(x, y)) | 
|  | return null; | 
|  |  | 
|  | for (int i = 0; i < ncomponents; ++i) | 
|  | { | 
|  | // Ignore invisible children... | 
|  | if (!component[i].isVisible()) | 
|  | continue; | 
|  |  | 
|  | int x2 = x - component[i].x; | 
|  | int y2 = y - component[i].y; | 
|  | // We don't do the contains() check right away because | 
|  | // findComponentAt would redundantly do it first thing. | 
|  | if (component[i] instanceof Container) | 
|  | { | 
|  | Container k = (Container) component[i]; | 
|  | Component r = k.findComponentAt(x2, y2); | 
|  | if (r != null) | 
|  | return r; | 
|  | } | 
|  | else if (component[i].contains(x2, y2)) | 
|  | return component[i]; | 
|  | } | 
|  |  | 
|  | return this; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Locates the visible child component that contains the specified position. | 
|  | * The top-most child component is returned in the case where there is overlap | 
|  | * in the components. If the containing child component is a Container, | 
|  | * this method will continue searching for the deepest nested child | 
|  | * component. Components which are not visible are ignored during the search. | 
|  | * | 
|  | * findComponentAt differs from getComponentAt, because it recursively | 
|  | * searches a Container's children. | 
|  | * | 
|  | * @param p - the component's location | 
|  | * @return null if the component does not contain the position. | 
|  | * If there is no child component at the requested point and the point is | 
|  | * within the bounds of the container the container itself is returned. | 
|  | */ | 
|  | public Component findComponentAt(Point p) | 
|  | { | 
|  | return findComponentAt(p.x, p.y); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Called when this container is added to another container to inform it | 
|  | * to create its peer.  Peers for any child components will also be | 
|  | * created. | 
|  | */ | 
|  | public void addNotify() | 
|  | { | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | super.addNotify(); | 
|  | addNotifyContainerChildren(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Called when this container is removed from its parent container to | 
|  | * inform it to destroy its peer.  This causes the peers of all child | 
|  | * component to be destroyed as well. | 
|  | */ | 
|  | public void removeNotify() | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | int ncomps = ncomponents; | 
|  | Component[] comps = component; | 
|  | for (int i = ncomps - 1; i >= 0; --i) | 
|  | { | 
|  | Component comp = comps[i]; | 
|  | if (comp != null) | 
|  | comp.removeNotify(); | 
|  | } | 
|  | super.removeNotify(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Tests whether or not the specified component is contained within | 
|  | * this components subtree. | 
|  | * | 
|  | * @param comp The component to test. | 
|  | * | 
|  | * @return <code>true</code> if this container is an ancestor of the | 
|  | * specified component, <code>false</code> otherwise. | 
|  | */ | 
|  | public boolean isAncestorOf(Component comp) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | while (true) | 
|  | { | 
|  | if (comp == null) | 
|  | return false; | 
|  | comp = comp.getParent(); | 
|  | if (comp == this) | 
|  | return true; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns a string representing the state of this container for | 
|  | * debugging purposes. | 
|  | * | 
|  | * @return A string representing the state of this container. | 
|  | */ | 
|  | protected String paramString() | 
|  | { | 
|  | if (layoutMgr == null) | 
|  | return super.paramString(); | 
|  |  | 
|  | CPStringBuilder sb = new CPStringBuilder(); | 
|  | sb.append(super.paramString()); | 
|  | sb.append(",layout="); | 
|  | sb.append(layoutMgr.getClass().getName()); | 
|  | return sb.toString(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Writes a listing of this container to the specified stream starting | 
|  | * at the specified indentation point. | 
|  | * | 
|  | * @param out The <code>PrintStream</code> to write to. | 
|  | * @param indent The indentation point. | 
|  | */ | 
|  | public void list(PrintStream out, int indent) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | super.list(out, indent); | 
|  | for (int i = 0; i < ncomponents; ++i) | 
|  | component[i].list(out, indent + 2); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Writes a listing of this container to the specified stream starting | 
|  | * at the specified indentation point. | 
|  | * | 
|  | * @param out The <code>PrintWriter</code> to write to. | 
|  | * @param indent The indentation point. | 
|  | */ | 
|  | public void list(PrintWriter out, int indent) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | super.list(out, indent); | 
|  | for (int i = 0; i < ncomponents; ++i) | 
|  | component[i].list(out, indent + 2); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the focus traversal keys for a given traversal operation for this | 
|  | * Container. | 
|  | * | 
|  | * @exception IllegalArgumentException If id is not one of | 
|  | * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, | 
|  | * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, | 
|  | * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, | 
|  | * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, | 
|  | * or if keystrokes contains null, or if any Object in keystrokes is not an | 
|  | * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any | 
|  | * keystroke already maps to another focus traversal operation for this | 
|  | * Container. | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public void setFocusTraversalKeys(int id, | 
|  | Set<? extends AWTKeyStroke> keystrokes) | 
|  | { | 
|  | if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && | 
|  | id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && | 
|  | id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && | 
|  | id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) | 
|  | throw new IllegalArgumentException (); | 
|  |  | 
|  | if (keystrokes == null) | 
|  | { | 
|  | Container parent = getParent (); | 
|  |  | 
|  | while (parent != null) | 
|  | { | 
|  | if (parent.areFocusTraversalKeysSet (id)) | 
|  | { | 
|  | keystrokes = parent.getFocusTraversalKeys (id); | 
|  | break; | 
|  | } | 
|  | parent = parent.getParent (); | 
|  | } | 
|  |  | 
|  | if (keystrokes == null) | 
|  | keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager (). | 
|  | getDefaultFocusTraversalKeys (id); | 
|  | } | 
|  |  | 
|  | Set sa; | 
|  | Set sb; | 
|  | Set sc; | 
|  | String name; | 
|  | switch (id) | 
|  | { | 
|  | case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS: | 
|  | sa = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); | 
|  | sb = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); | 
|  | sc = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); | 
|  | name = "forwardFocusTraversalKeys"; | 
|  | break; | 
|  | case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS: | 
|  | sa = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); | 
|  | sb = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); | 
|  | sc = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); | 
|  | name = "backwardFocusTraversalKeys"; | 
|  | break; | 
|  | case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS: | 
|  | sa = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); | 
|  | sb = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); | 
|  | sc = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS); | 
|  | name = "upCycleFocusTraversalKeys"; | 
|  | break; | 
|  | case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS: | 
|  | sa = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS); | 
|  | sb = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS); | 
|  | sc = getFocusTraversalKeys | 
|  | (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS); | 
|  | name = "downCycleFocusTraversalKeys"; | 
|  | break; | 
|  | default: | 
|  | throw new IllegalArgumentException (); | 
|  | } | 
|  |  | 
|  | int i = keystrokes.size (); | 
|  | Iterator iter = keystrokes.iterator (); | 
|  |  | 
|  | while (--i >= 0) | 
|  | { | 
|  | Object o = iter.next (); | 
|  | if (!(o instanceof AWTKeyStroke) | 
|  | || sa.contains (o) || sb.contains (o) || sc.contains (o) | 
|  | || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED) | 
|  | throw new IllegalArgumentException (); | 
|  | } | 
|  |  | 
|  | if (focusTraversalKeys == null) | 
|  | focusTraversalKeys = new Set[4]; | 
|  |  | 
|  | keystrokes = | 
|  | Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes)); | 
|  | firePropertyChange (name, focusTraversalKeys[id], keystrokes); | 
|  |  | 
|  | focusTraversalKeys[id] = keystrokes; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the Set of focus traversal keys for a given traversal operation for | 
|  | * this Container. | 
|  | * | 
|  | * @exception IllegalArgumentException If id is not one of | 
|  | * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, | 
|  | * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, | 
|  | * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, | 
|  | * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public Set<AWTKeyStroke> getFocusTraversalKeys (int id) | 
|  | { | 
|  | if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && | 
|  | id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && | 
|  | id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && | 
|  | id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) | 
|  | throw new IllegalArgumentException (); | 
|  |  | 
|  | Set s = null; | 
|  |  | 
|  | if (focusTraversalKeys != null) | 
|  | s = focusTraversalKeys[id]; | 
|  |  | 
|  | if (s == null && parent != null) | 
|  | s = parent.getFocusTraversalKeys (id); | 
|  |  | 
|  | return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager() | 
|  | .getDefaultFocusTraversalKeys(id)) : s; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns whether the Set of focus traversal keys for the given focus | 
|  | * traversal operation has been explicitly defined for this Container. | 
|  | * If this method returns false, this Container is inheriting the Set from | 
|  | * an ancestor, or from the current KeyboardFocusManager. | 
|  | * | 
|  | * @exception IllegalArgumentException If id is not one of | 
|  | * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, | 
|  | * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, | 
|  | * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, | 
|  | * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public boolean areFocusTraversalKeysSet (int id) | 
|  | { | 
|  | if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS && | 
|  | id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS && | 
|  | id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS && | 
|  | id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS) | 
|  | throw new IllegalArgumentException (); | 
|  |  | 
|  | return focusTraversalKeys != null && focusTraversalKeys[id] != null; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Check whether the given Container is the focus cycle root of this | 
|  | * Container's focus traversal cycle.  If this Container is a focus | 
|  | * cycle root itself, then it will be in two different focus cycles | 
|  | * -- it's own, and that of its ancestor focus cycle root's.  In | 
|  | * that case, if <code>c</code> is either of those containers, this | 
|  | * method will return true. | 
|  | * | 
|  | * @param c the candidate Container | 
|  | * | 
|  | * @return true if c is the focus cycle root of the focus traversal | 
|  | * cycle to which this Container belongs, false otherwise | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public boolean isFocusCycleRoot (Container c) | 
|  | { | 
|  | if (this == c | 
|  | && isFocusCycleRoot ()) | 
|  | return true; | 
|  |  | 
|  | Container ancestor = getFocusCycleRootAncestor (); | 
|  |  | 
|  | if (c == ancestor) | 
|  | return true; | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * If this Container is a focus cycle root, set the focus traversal | 
|  | * policy that determines the focus traversal order for its | 
|  | * children.  If non-null, this policy will be inherited by all | 
|  | * inferior focus cycle roots.  If <code>policy</code> is null, this | 
|  | * Container will inherit its policy from the closest ancestor focus | 
|  | * cycle root that's had its policy set. | 
|  | * | 
|  | * @param policy the new focus traversal policy for this Container or null | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public void setFocusTraversalPolicy (FocusTraversalPolicy policy) | 
|  | { | 
|  | focusTraversalPolicy = policy; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return the focus traversal policy that determines the focus | 
|  | * traversal order for this Container's children.  This method | 
|  | * returns null if this Container is not a focus cycle root.  If the | 
|  | * focus traversal policy has not been set explicitly, then this | 
|  | * method will return an ancestor focus cycle root's policy instead. | 
|  | * | 
|  | * @return this Container's focus traversal policy or null | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public FocusTraversalPolicy getFocusTraversalPolicy () | 
|  | { | 
|  | if (!isFocusCycleRoot ()) | 
|  | return null; | 
|  |  | 
|  | if (focusTraversalPolicy == null) | 
|  | { | 
|  | Container ancestor = getFocusCycleRootAncestor (); | 
|  |  | 
|  | if (ancestor != this && ancestor !=  null) | 
|  | return ancestor.getFocusTraversalPolicy (); | 
|  | else | 
|  | { | 
|  | KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager (); | 
|  |  | 
|  | return manager.getDefaultFocusTraversalPolicy (); | 
|  | } | 
|  | } | 
|  | else | 
|  | return focusTraversalPolicy; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Check whether this Container's focus traversal policy has been | 
|  | * explicitly set.  If it has not, then this Container will inherit | 
|  | * its focus traversal policy from one of its ancestor focus cycle | 
|  | * roots. | 
|  | * | 
|  | * @return true if focus traversal policy is set, false otherwise | 
|  | */ | 
|  | public boolean isFocusTraversalPolicySet () | 
|  | { | 
|  | return focusTraversalPolicy == null; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Set whether or not this Container is the root of a focus | 
|  | * traversal cycle.  This Container's focus traversal policy | 
|  | * determines the order of focus traversal.  Some policies prevent | 
|  | * the focus from being transferred between two traversal cycles | 
|  | * until an up or down traversal operation is performed.  In that | 
|  | * case, normal traversal (not up or down) is limited to this | 
|  | * Container and all of this Container's descendents that are not | 
|  | * descendents of inferior focus cycle roots.  In the default case | 
|  | * however, ContainerOrderFocusTraversalPolicy is in effect, and it | 
|  | * supports implicit down-cycle traversal operations. | 
|  | * | 
|  | * @param focusCycleRoot true if this is a focus cycle root, false otherwise | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public void setFocusCycleRoot (boolean focusCycleRoot) | 
|  | { | 
|  | this.focusCycleRoot = focusCycleRoot; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Set to <code>true</code> if this container provides a focus traversal | 
|  | * policy, <code>false</code> when the root container's focus | 
|  | * traversal policy should be used. | 
|  | * | 
|  | * @return <code>true</code> if this container provides a focus traversal | 
|  | *        policy, <code>false</code> when the root container's focus | 
|  | *        traversal policy should be used | 
|  | * | 
|  | * @see #setFocusTraversalPolicyProvider(boolean) | 
|  | * | 
|  | * @since 1.5 | 
|  | */ | 
|  | public final boolean isFocusTraversalPolicyProvider() | 
|  | { | 
|  | return focusTraversalPolicyProvider; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Set to <code>true</code> if this container provides a focus traversal | 
|  | * policy, <code>false</code> when the root container's focus | 
|  | * traversal policy should be used. | 
|  | * | 
|  | * @param b <code>true</code> if this container provides a focus traversal | 
|  | *        policy, <code>false</code> when the root container's focus | 
|  | *        traversal policy should be used | 
|  | * | 
|  | * @see #isFocusTraversalPolicyProvider() | 
|  | * | 
|  | * @since 1.5 | 
|  | */ | 
|  | public final void setFocusTraversalPolicyProvider(boolean b) | 
|  | { | 
|  | focusTraversalPolicyProvider = b; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Check whether this Container is a focus cycle root. | 
|  | * | 
|  | * @return true if this is a focus cycle root, false otherwise | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public boolean isFocusCycleRoot () | 
|  | { | 
|  | return focusCycleRoot; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Transfer focus down one focus traversal cycle.  If this Container | 
|  | * is a focus cycle root, then its default component becomes the | 
|  | * focus owner, and this Container becomes the current focus cycle | 
|  | * root.  No traversal will occur if this Container is not a focus | 
|  | * cycle root. | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public void transferFocusDownCycle () | 
|  | { | 
|  | if (isFocusCycleRoot()) | 
|  | { | 
|  | KeyboardFocusManager fm = | 
|  | KeyboardFocusManager.getCurrentKeyboardFocusManager(); | 
|  | fm.setGlobalCurrentFocusCycleRoot(this); | 
|  | FocusTraversalPolicy policy = getFocusTraversalPolicy(); | 
|  | Component defaultComponent = policy.getDefaultComponent(this); | 
|  | if (defaultComponent != null) | 
|  | defaultComponent.requestFocus(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the ComponentOrientation property of this container and all components | 
|  | * contained within it. | 
|  | * | 
|  | * @exception NullPointerException If orientation is null | 
|  | * | 
|  | * @since 1.4 | 
|  | */ | 
|  | public void applyComponentOrientation (ComponentOrientation orientation) | 
|  | { | 
|  | if (orientation == null) | 
|  | throw new NullPointerException(); | 
|  |  | 
|  | setComponentOrientation(orientation); | 
|  | for (int i = 0; i < ncomponents; i++) | 
|  | { | 
|  | if (component[i] instanceof Container) | 
|  | ((Container) component[i]).applyComponentOrientation(orientation); | 
|  | else | 
|  | component[i].setComponentOrientation(orientation); | 
|  | } | 
|  | } | 
|  |  | 
|  | public void addPropertyChangeListener (PropertyChangeListener listener) | 
|  | { | 
|  | // TODO: Why is this overridden? | 
|  | super.addPropertyChangeListener(listener); | 
|  | } | 
|  |  | 
|  | public void addPropertyChangeListener (String propertyName, | 
|  | PropertyChangeListener listener) | 
|  | { | 
|  | // TODO: Why is this overridden? | 
|  | super.addPropertyChangeListener(propertyName, listener); | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Sets the Z ordering for the component <code>comp</code> to | 
|  | * <code>index</code>. Components with lower Z order paint above components | 
|  | * with higher Z order. | 
|  | * | 
|  | * @param comp the component for which to change the Z ordering | 
|  | * @param index the index to set | 
|  | * | 
|  | * @throws NullPointerException if <code>comp == null</code> | 
|  | * @throws IllegalArgumentException if comp is an ancestor of this container | 
|  | * @throws IllegalArgumentException if <code>index</code> is not in | 
|  | *         <code>[0, getComponentCount()]</code> for moving between | 
|  | *         containers or <code>[0, getComponentCount() - 1]</code> for moving | 
|  | *         inside this container | 
|  | * @throws IllegalArgumentException if <code>comp == this</code> | 
|  | * @throws IllegalArgumentException if <code>comp</code> is a | 
|  | *         <code>Window</code> | 
|  | * | 
|  | * @see #getComponentZOrder(Component) | 
|  | * | 
|  | * @since 1.5 | 
|  | */ | 
|  | public final void setComponentZOrder(Component comp, int index) | 
|  | { | 
|  | if (comp == null) | 
|  | throw new NullPointerException("comp must not be null"); | 
|  | if (comp instanceof Container && ((Container) comp).isAncestorOf(this)) | 
|  | throw new IllegalArgumentException("comp must not be an ancestor of " | 
|  | + "this"); | 
|  | if (comp instanceof Window) | 
|  | throw new IllegalArgumentException("comp must not be a Window"); | 
|  |  | 
|  | if (comp == this) | 
|  | throw new IllegalArgumentException("cannot add component to itself"); | 
|  |  | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | // FIXME: Implement reparenting. | 
|  | if ( comp.getParent() != this) | 
|  | throw new AssertionError("Reparenting is not implemented yet"); | 
|  | else | 
|  | { | 
|  | // Find current component index. | 
|  | int currentIndex = getComponentZOrder(comp); | 
|  | if (currentIndex < index) | 
|  | { | 
|  | System.arraycopy(component, currentIndex + 1, component, | 
|  | currentIndex, index - currentIndex); | 
|  | } | 
|  | else | 
|  | { | 
|  | System.arraycopy(component, index, component, index + 1, | 
|  | currentIndex - index); | 
|  | } | 
|  | component[index] = comp; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the Z ordering index of <code>comp</code>. If <code>comp</code> | 
|  | * is not a child component of this Container, this returns <code>-1</code>. | 
|  | * | 
|  | * @param comp the component for which to query the Z ordering | 
|  | * | 
|  | * @return the Z ordering index of <code>comp</code> or <code>-1</code> if | 
|  | *         <code>comp</code> is not a child of this Container | 
|  | * | 
|  | * @see #setComponentZOrder(Component, int) | 
|  | * | 
|  | * @since 1.5 | 
|  | */ | 
|  | public final int getComponentZOrder(Component comp) | 
|  | { | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | int index = -1; | 
|  | if (component != null) | 
|  | { | 
|  | for (int i = 0; i < ncomponents; i++) | 
|  | { | 
|  | if (component[i] == comp) | 
|  | { | 
|  | index = i; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  | return index; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Hidden helper methods. | 
|  |  | 
|  | /** | 
|  | * Perform a graphics operation on the children of this container. | 
|  | * For each applicable child, the visitChild() method will be called | 
|  | * to perform the graphics operation. | 
|  | * | 
|  | * @param gfx The graphics object that will be used to derive new | 
|  | * graphics objects for the children. | 
|  | * | 
|  | * @param visitor Object encapsulating the graphics operation that | 
|  | * should be performed. | 
|  | * | 
|  | * @param lightweightOnly If true, only lightweight components will | 
|  | * be visited. | 
|  | */ | 
|  | private void visitChildren(Graphics gfx, GfxVisitor visitor, | 
|  | boolean lightweightOnly) | 
|  | { | 
|  | synchronized (getTreeLock()) | 
|  | { | 
|  | for (int i = ncomponents - 1; i >= 0; --i) | 
|  | { | 
|  | Component comp = component[i]; | 
|  | boolean applicable = comp.isVisible() | 
|  | && (comp.isLightweight() || ! lightweightOnly); | 
|  |  | 
|  | if (applicable) | 
|  | visitChild(gfx, visitor, comp); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Perform a graphics operation on a child. A translated and clipped | 
|  | * graphics object will be created, and the visit() method of the | 
|  | * visitor will be called to perform the operation. | 
|  | * | 
|  | * @param gfx The graphics object that will be used to derive new | 
|  | * graphics objects for the child. | 
|  | * | 
|  | * @param visitor Object encapsulating the graphics operation that | 
|  | * should be performed. | 
|  | * | 
|  | * @param comp The child component that should be visited. | 
|  | */ | 
|  | private void visitChild(Graphics gfx, GfxVisitor visitor, | 
|  | Component comp) | 
|  | { | 
|  | Rectangle bounds = comp.getBounds(); | 
|  |  | 
|  | if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height)) | 
|  | return; | 
|  | Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width, | 
|  | bounds.height); | 
|  | try | 
|  | { | 
|  | g2.setFont(comp.getFont()); | 
|  | visitor.visit(comp, g2); | 
|  | } | 
|  | finally | 
|  | { | 
|  | g2.dispose(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Overridden to dispatch events to lightweight descendents. | 
|  | * | 
|  | * @param e the event to dispatch. | 
|  | */ | 
|  | void dispatchEventImpl(AWTEvent e) | 
|  | { | 
|  | LightweightDispatcher dispatcher = LightweightDispatcher.getInstance(); | 
|  | if (! isLightweight() && dispatcher.dispatchEvent(e)) | 
|  | { | 
|  | // Some lightweight descendent got this event dispatched. Consume | 
|  | // it and let the peer handle it. | 
|  | e.consume(); | 
|  | ComponentPeer p = peer; | 
|  | if (p != null) | 
|  | p.handleEvent(e); | 
|  | } | 
|  | else | 
|  | { | 
|  | super.dispatchEventImpl(e); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * This is called by the lightweight dispatcher to avoid recursivly | 
|  | * calling into the lightweight dispatcher. | 
|  | * | 
|  | * @param e the event to dispatch | 
|  | * | 
|  | * @see LightweightDispatcher#redispatch(MouseEvent, Component, int) | 
|  | */ | 
|  | void dispatchNoLightweight(AWTEvent e) | 
|  | { | 
|  | super.dispatchEventImpl(e); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Tests if this container has an interest in the given event id. | 
|  | * | 
|  | * @param eventId The event id to check. | 
|  | * | 
|  | * @return <code>true</code> if a listener for the event id exists or | 
|  | *         if the eventMask is set for the event id. | 
|  | * | 
|  | * @see java.awt.Component#eventTypeEnabled(int) | 
|  | */ | 
|  | boolean eventTypeEnabled(int eventId) | 
|  | { | 
|  | if(eventId <= ContainerEvent.CONTAINER_LAST | 
|  | && eventId >= ContainerEvent.CONTAINER_FIRST) | 
|  | return containerListener != null | 
|  | || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0; | 
|  | else | 
|  | return super.eventTypeEnabled(eventId); | 
|  | } | 
|  |  | 
|  | // This is used to implement Component.transferFocus. | 
|  | Component findNextFocusComponent(Component child) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | int start, end; | 
|  | if (child != null) | 
|  | { | 
|  | for (start = 0; start < ncomponents; ++start) | 
|  | { | 
|  | if (component[start] == child) | 
|  | break; | 
|  | } | 
|  | end = start; | 
|  | // This special case lets us be sure to terminate. | 
|  | if (end == 0) | 
|  | end = ncomponents; | 
|  | ++start; | 
|  | } | 
|  | else | 
|  | { | 
|  | start = 0; | 
|  | end = ncomponents; | 
|  | } | 
|  |  | 
|  | for (int j = start; j != end; ++j) | 
|  | { | 
|  | if (j >= ncomponents) | 
|  | { | 
|  | // The JCL says that we should wrap here.  However, that | 
|  | // seems wrong.  To me it seems that focus order should be | 
|  | // global within in given window.  So instead if we reach | 
|  | // the end we try to look in our parent, if we have one. | 
|  | if (parent != null) | 
|  | return parent.findNextFocusComponent(this); | 
|  | j -= ncomponents; | 
|  | } | 
|  | if (component[j] instanceof Container) | 
|  | { | 
|  | Component c = component[j]; | 
|  | c = c.findNextFocusComponent(null); | 
|  | if (c != null) | 
|  | return c; | 
|  | } | 
|  | else if (component[j].isFocusTraversable()) | 
|  | return component[j]; | 
|  | } | 
|  |  | 
|  | return null; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Fires hierarchy events to the children of this container and this | 
|  | * container itself. This overrides {@link Component#fireHierarchyEvent} | 
|  | * in order to forward this event to all children. | 
|  | */ | 
|  | void fireHierarchyEvent(int id, Component changed, Container parent, | 
|  | long flags) | 
|  | { | 
|  | // Only propagate event if there is actually a listener waiting for it. | 
|  | if ((id == HierarchyEvent.HIERARCHY_CHANGED && numHierarchyListeners > 0) | 
|  | || ((id == HierarchyEvent.ANCESTOR_MOVED | 
|  | || id == HierarchyEvent.ANCESTOR_RESIZED) | 
|  | && numHierarchyBoundsListeners > 0)) | 
|  | { | 
|  | for (int i = 0; i < ncomponents; i++) | 
|  | component[i].fireHierarchyEvent(id, changed, parent, flags); | 
|  | super.fireHierarchyEvent(id, changed, parent, flags); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Adjusts the number of hierarchy listeners of this container and all of | 
|  | * its parents. This is called by the add/remove listener methods and | 
|  | * structure changing methods in Container. | 
|  | * | 
|  | * @param type the type, either {@link AWTEvent#HIERARCHY_BOUNDS_EVENT_MASK} | 
|  | *        or {@link AWTEvent#HIERARCHY_EVENT_MASK} | 
|  | * @param delta the number of listeners added or removed | 
|  | */ | 
|  | void updateHierarchyListenerCount(long type, int delta) | 
|  | { | 
|  | if (type == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) | 
|  | numHierarchyBoundsListeners += delta; | 
|  | else if (type == AWTEvent.HIERARCHY_EVENT_MASK) | 
|  | numHierarchyListeners += delta; | 
|  | else | 
|  | assert false : "Should not reach here"; | 
|  |  | 
|  | if (parent != null) | 
|  | parent.updateHierarchyListenerCount(type, delta); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Notifies interested listeners about resizing or moving the container. | 
|  | * This performs the super behaviour (sending component events) and | 
|  | * additionally notifies any hierarchy bounds listeners on child components. | 
|  | * | 
|  | * @param resized true if the component has been resized, false otherwise | 
|  | * @param moved true if the component has been moved, false otherwise | 
|  | */ | 
|  | void notifyReshape(boolean resized, boolean moved) | 
|  | { | 
|  | // Notify component listeners. | 
|  | super.notifyReshape(resized, moved); | 
|  |  | 
|  | if (ncomponents > 0) | 
|  | { | 
|  | // Notify hierarchy bounds listeners. | 
|  | if (resized) | 
|  | { | 
|  | for (int i = 0; i < getComponentCount(); i++) | 
|  | { | 
|  | Component child = getComponent(i); | 
|  | child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED, | 
|  | this, parent, 0); | 
|  | } | 
|  | } | 
|  | if (moved) | 
|  | { | 
|  | for (int i = 0; i < getComponentCount(); i++) | 
|  | { | 
|  | Component child = getComponent(i); | 
|  | child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED, | 
|  | this, parent, 0); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | private void addNotifyContainerChildren() | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | for (int i = ncomponents;  --i >= 0; ) | 
|  | { | 
|  | component[i].addNotify(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Deserialize this Container: | 
|  | * <ol> | 
|  | * <li>Read from the stream the default serializable fields.</li> | 
|  | * <li>Read a list of serializable ContainerListeners as optional | 
|  | * data.  If the list is null, no listeners will be registered.</li> | 
|  | * <li>Read this Container's FocusTraversalPolicy as optional data. | 
|  | * If this is null, then this Container will use a | 
|  | * DefaultFocusTraversalPolicy.</li> | 
|  | * </ol> | 
|  | * | 
|  | * @param s the stream to read from | 
|  | * @throws ClassNotFoundException if deserialization fails | 
|  | * @throws IOException if the stream fails | 
|  | */ | 
|  | private void readObject (ObjectInputStream s) | 
|  | throws ClassNotFoundException, IOException | 
|  | { | 
|  | s.defaultReadObject (); | 
|  | String key = (String) s.readObject (); | 
|  | while (key != null) | 
|  | { | 
|  | Object object = s.readObject (); | 
|  | if ("containerL".equals (key)) | 
|  | addContainerListener((ContainerListener) object); | 
|  | // FIXME: under what key is the focus traversal policy stored? | 
|  | else if ("focusTraversalPolicy".equals (key)) | 
|  | setFocusTraversalPolicy ((FocusTraversalPolicy) object); | 
|  |  | 
|  | key = (String) s.readObject(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Serialize this Container: | 
|  | * <ol> | 
|  | * <li>Write to the stream the default serializable fields.</li> | 
|  | * <li>Write the list of serializable ContainerListeners as optional | 
|  | * data.</li> | 
|  | * <li>Write this Container's FocusTraversalPolicy as optional data.</li> | 
|  | * </ol> | 
|  | * | 
|  | * @param s the stream to write to | 
|  | * @throws IOException if the stream fails | 
|  | */ | 
|  | private void writeObject (ObjectOutputStream s) throws IOException | 
|  | { | 
|  | s.defaultWriteObject (); | 
|  | AWTEventMulticaster.save (s, "containerL", containerListener); | 
|  | if (focusTraversalPolicy instanceof Serializable) | 
|  | s.writeObject (focusTraversalPolicy); | 
|  | else | 
|  | s.writeObject (null); | 
|  | } | 
|  |  | 
|  | // Nested classes. | 
|  |  | 
|  | /* The following classes are used in concert with the | 
|  | visitChildren() method to implement all the graphics operations | 
|  | that requires traversal of the containment hierarchy. */ | 
|  |  | 
|  | abstract static class GfxVisitor | 
|  | { | 
|  | public abstract void visit(Component c, Graphics gfx); | 
|  | } | 
|  |  | 
|  | static class GfxPaintVisitor extends GfxVisitor | 
|  | { | 
|  | public static final GfxVisitor INSTANCE = new GfxPaintVisitor(); | 
|  |  | 
|  | public void visit(Component c, Graphics gfx) | 
|  | { | 
|  | c.paint(gfx); | 
|  | } | 
|  | } | 
|  |  | 
|  | static class GfxPrintVisitor extends GfxVisitor | 
|  | { | 
|  | public static final GfxVisitor INSTANCE = new GfxPrintVisitor(); | 
|  |  | 
|  | public void visit(Component c, Graphics gfx) | 
|  | { | 
|  | c.print(gfx); | 
|  | } | 
|  | } | 
|  |  | 
|  | static class GfxPaintAllVisitor extends GfxVisitor | 
|  | { | 
|  | public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor(); | 
|  |  | 
|  | public void visit(Component c, Graphics gfx) | 
|  | { | 
|  | c.paintAll(gfx); | 
|  | } | 
|  | } | 
|  |  | 
|  | static class GfxPrintAllVisitor extends GfxVisitor | 
|  | { | 
|  | public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor(); | 
|  |  | 
|  | public void visit(Component c, Graphics gfx) | 
|  | { | 
|  | c.printAll(gfx); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * This class provides accessibility support for subclasses of container. | 
|  | * | 
|  | * @author Eric Blake (ebb9@email.byu.edu) | 
|  | * | 
|  | * @since 1.3 | 
|  | */ | 
|  | protected class AccessibleAWTContainer extends AccessibleAWTComponent | 
|  | { | 
|  | /** | 
|  | * Compatible with JDK 1.4+. | 
|  | */ | 
|  | private static final long serialVersionUID = 5081320404842566097L; | 
|  |  | 
|  | /** | 
|  | * The handler to fire PropertyChange when children are added or removed. | 
|  | * | 
|  | * @serial the handler for property changes | 
|  | */ | 
|  | protected ContainerListener accessibleContainerHandler | 
|  | = new AccessibleContainerHandler(); | 
|  |  | 
|  | /** | 
|  | * The default constructor. | 
|  | */ | 
|  | protected AccessibleAWTContainer() | 
|  | { | 
|  | Container.this.addContainerListener(accessibleContainerHandler); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return the number of accessible children of the containing accessible | 
|  | * object (at most the total number of its children). | 
|  | * | 
|  | * @return the number of accessible children | 
|  | */ | 
|  | public int getAccessibleChildrenCount() | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | int count = 0; | 
|  | int i = component == null ? 0 : component.length; | 
|  | while (--i >= 0) | 
|  | if (component[i] instanceof Accessible) | 
|  | count++; | 
|  | return count; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return the nth accessible child of the containing accessible object. | 
|  | * | 
|  | * @param i the child to grab, zero-based | 
|  | * @return the accessible child, or null | 
|  | */ | 
|  | public Accessible getAccessibleChild(int i) | 
|  | { | 
|  | synchronized (getTreeLock ()) | 
|  | { | 
|  | if (component == null) | 
|  | return null; | 
|  | int index = -1; | 
|  | while (i >= 0 && ++index < component.length) | 
|  | if (component[index] instanceof Accessible) | 
|  | i--; | 
|  | if (i < 0) | 
|  | return (Accessible) component[index]; | 
|  | return null; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return the accessible child located at point (in the parent's | 
|  | * coordinates), if one exists. | 
|  | * | 
|  | * @param p the point to look at | 
|  | * | 
|  | * @return an accessible object at that point, or null | 
|  | * | 
|  | * @throws NullPointerException if p is null | 
|  | */ | 
|  | public Accessible getAccessibleAt(Point p) | 
|  | { | 
|  | Component c = getComponentAt(p.x, p.y); | 
|  | return c != Container.this && c instanceof Accessible ? (Accessible) c | 
|  | : null; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * This class fires a <code>PropertyChange</code> listener, if registered, | 
|  | * when children are added or removed from the enclosing accessible object. | 
|  | * | 
|  | * @author Eric Blake (ebb9@email.byu.edu) | 
|  | * | 
|  | * @since 1.3 | 
|  | */ | 
|  | protected class AccessibleContainerHandler implements ContainerListener | 
|  | { | 
|  | /** | 
|  | * Default constructor. | 
|  | */ | 
|  | protected AccessibleContainerHandler() | 
|  | { | 
|  | // Nothing to do here. | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Fired when a component is added; forwards to the PropertyChange | 
|  | * listener. | 
|  | * | 
|  | * @param e the container event for adding | 
|  | */ | 
|  | public void componentAdded(ContainerEvent e) | 
|  | { | 
|  | AccessibleAWTContainer.this.firePropertyChange | 
|  | (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild()); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Fired when a component is removed; forwards to the PropertyChange | 
|  | * listener. | 
|  | * | 
|  | * @param e the container event for removing | 
|  | */ | 
|  | public void componentRemoved(ContainerEvent e) | 
|  | { | 
|  | AccessibleAWTContainer.this.firePropertyChange | 
|  | (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null); | 
|  | } | 
|  | } // class AccessibleContainerHandler | 
|  | } // class AccessibleAWTContainer | 
|  | } // class Container |