/*
 
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
 
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
*
 
* This code is free software; you can redistribute it and/or modify it
 
* under the terms of the GNU General Public License version 2 only, as
 
* published by the Free Software Foundation.
  
Oracle designates this
 
* particular file as subject to the "Classpath" exception as provided
 
* by Oracle in the LICENSE file that accompanied this code.
 
*
 
* This code 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
 
* version 2 for more details (a copy is included in the LICENSE file that
 
* accompanied this code).
 
*
 
* You should have received a copy of the GNU General Public License version
 
* 2 along with this work; if not, write to the Free Software Foundation,
 
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
*
 
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 
* or visit www.oracle.com if you need additional information or have any
 
* questions.
 
*/
package java.awt;

import java.awt.dnd.DropTarget;

import java.awt.event.*;

import java.awt.peer.ContainerPeer;
import java.awt.peer.ComponentPeer;
import java.awt.peer.LightweightPeer;

import java.beans.PropertyChangeListener;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.PrintStream;
import java.io.PrintWriter;

import java.lang.ref.WeakReference;
import java.security.AccessController;

import java.util.ArrayList;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Set;

import javax.accessibility.*;

import sun.util.logging.PlatformLogger;

import sun.awt.AppContext;
import sun.awt.AWTAccessor;
import sun.awt.AWTAccessor.MouseEventAccessor;
import sun.awt.CausedFocusEvent;
import sun.awt.PeerEvent;
import sun.awt.SunToolkit;

import sun.awt.dnd.SunDropTargetEvent;

import sun.java2d.pipe.Region;

import sun.security.action.GetBooleanAction;

/**
 
* A generic Abstract Window Toolkit(AWT) container object is a component
 
* that can contain other AWT components.
 
* <p>
 
* Components added to a container are tracked in a list.
  
The order
 
* of the list will define the components' front-to-back stacking order
 
* within the container.
  
If no index is specified when adding a
 
* component to a container, it will be added to the end of the list
 
* (and hence to the bottom of the stacking order).
 
* <p>
 
* <b>Note</b>: For details on the focus subsystem, see
 
* <a href=" https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
 
* How to Use the Focus Subsystem</a>,
 
* a section in <em>The Java Tutorial</em>, and the
 
*<a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
 
* for more information.
 
*
 
* @author
      
Arthur van Hoff
 
* @author
      
Sami Shaio
 
* @see
       
#add(java.awt.Component, int)
 
* @see
       
#getComponent(int)
 
* @see
       
LayoutManager
 
* @since
     
JDK1.0
 
*/

public class Container extends Component {

    
private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Container");
    
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Container");

    
private static final Component[] EMPTY_ARRAY = new Component[0];

    
/**
     
* The components in this container.
     
* @see #add
     
* @see #getComponents
     
*/
    
private java.util.List<Component> component = new ArrayList<>();

    
/**
     
* Layout manager for this container.
     
* @see #doLayout
     
* @see #setLayout
     
* @see #getLayout
     
*/

    
LayoutManager layoutMgr;

    
/**
     
* Event router for lightweight components.
  
If this container
     
* is native, this dispatcher takes care of forwarding and
     
* retargeting the events to lightweight components contained
     
* (if any).
     
*/

    
private LightweightDispatcher dispatcher;

    
/**
     
* The focus traversal policy that will manage keyboard traversal of this
     
* Container's children, if this Container is a focus cycle root. If the
     
* value is null, this Container inherits its policy from its focus-cycle-
     
* root ancestor. If all such ancestors of this Container have null
     
* policies, then the current KeyboardFocusManager's default policy is
     
* used. If the value is non-null, this policy will be inherited by all
     
* focus-cycle-root children that have no keyboard-traversal policy of
     
* their own (as will, recursively, their focus-cycle-root children).
     
* <p>
     
* If this Container is not a focus cycle root, the value will be
     
* remembered, but will not be used or inherited by this or any other
     
* Containers until this Container is made a focus cycle root.
     
*
     
* @see #setFocusTraversalPolicy
     
* @see #getFocusTraversalPolicy
     
* @since 1.4
     
*/

    
private transient FocusTraversalPolicy focusTraversalPolicy;

    
/**
     
* Indicates whether this Component is the root of a focus traversal cycle.
     
* Once focus enters a traversal cycle, typically it cannot leave it via
     
* focus traversal unless one of the up- or down-cycle keys is pressed.
     
* Normal traversal is limited to this Container, and all of this
     
* Container's descendants that are not descendants of inferior focus cycle
     
* roots.
     
*
     
* @see #setFocusCycleRoot
     
* @see #isFocusCycleRoot
     
* @since 1.4
     
*/

    
private boolean focusCycleRoot = false;


    
/**
     
* Stores the value of focusTraversalPolicyProvider property.
     
* @since 1.5
     
* @see #setFocusTraversalPolicyProvider
     
*/

    
private boolean focusTraversalPolicyProvider;

    
// keeps track of the threads that are printing this component
    
private transient Set<Thread> printingThreads;
    
// True if there is at least one thread that's printing this component
    
private transient boolean printing = false;

    
transient ContainerListener containerListener;

    
/* HierarchyListener and HierarchyBoundsListener support */
    
transient int listeningChildren;
    
transient int listeningBoundsChildren;
    
transient int descendantsCount;

    
/* Non-opaque window support -- see Window.setLayersOpaque */
    
transient Color preserveBackgroundColor = null;

    
/**
     
* JDK 1.1 serialVersionUID
     
*/
    
private static final long serialVersionUID = 4613797578919906343L;

    
/**
     
* A constant which toggles one of the controllable behaviors
     
* of <code>getMouseEventTarget</code>. It is used to specify whether
     
* the method can return the Container on which it is originally called
     
* in case if none of its children are the current mouse event targets.
     
*
     
* @see #getMouseEventTarget(int, int, boolean)
     
*/

    
static final boolean INCLUDE_SELF = true;

    
/**
     
* A constant which toggles one of the controllable behaviors
     
* of <code>getMouseEventTarget</code>. It is used to specify whether
     
* the method should search only lightweight components.
     
*
     
* @see #getMouseEventTarget(int, int, boolean)
     
*/

    
static final boolean SEARCH_HEAVYWEIGHTS = true;

    
/*
     
* Number of HW or LW components in this container (including
     
* all descendant containers).
     
*/

    
private transient int numOfHWComponents = 0;
    
private transient int numOfLWComponents = 0;

    
private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container");

    
/**
     
* @serialField ncomponents
                     
int
     
*
       
The number of components in this container.
     
*
       
This value can be null.
     
* @serialField component
                       
Component[]
     
*
       
The components in this container.
     
* @serialField layoutMgr
                       
LayoutManager
     
*
       
Layout manager for this container.
     
* @serialField dispatcher
                      
LightweightDispatcher
     
*
       
Event router for lightweight components.
  
If this container
     
*
       
is native, this dispatcher takes care of forwarding and
     
*
       
retargeting the events to lightweight components contained
     
*
       
(if any).
     
* @serialField maxSize
                         
Dimension
     
*
       
Maximum size of this Container.
     
* @serialField focusCycleRoot
                  
boolean
     
*
       
Indicates whether this Component is the root of a focus traversal cycle.
     
*
       
Once focus enters a traversal cycle, typically it cannot leave it via
     
*
       
focus traversal unless one of the up- or down-cycle keys is pressed.
     
*
       
Normal traversal is limited to this Container, and all of this
     
*
       
Container's descendants that are not descendants of inferior focus cycle
     
*
       
roots.
     
* @serialField containerSerializedDataVersion
  
int
     
*
       
Container Serial Data Version.
     
* @serialField focusTraversalPolicyProvider
    
boolean
     
*
       
Stores the value of focusTraversalPolicyProvider property.
     
*/

    
private static final ObjectStreamField[] serialPersistentFields = {
        
new ObjectStreamField("ncomponents", Integer.TYPE),
        
new ObjectStreamField("component", Component[].class),
        
new ObjectStreamField("layoutMgr", LayoutManager.class),
        
new ObjectStreamField("dispatcher", LightweightDispatcher.class),
        
new ObjectStreamField("maxSize", Dimension.class),
        
new ObjectStreamField("focusCycleRoot", Boolean.TYPE),
        
new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE),
        
new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE),
    
};

    
static {
        
/* ensure that the necessary native libraries are loaded */
        
Toolkit.loadLibraries();
        
if (!GraphicsEnvironment.isHeadless()) {
            
initIDs();
        
}

        
AWTAccessor.setContainerAccessor(new AWTAccessor.ContainerAccessor() {
            
@Override
            
public void validateUnconditionally(Container cont) {
                
cont.validateUnconditionally();
            
}

            
@Override
            
public Component findComponentAt(Container cont, int x, int y,
                    
boolean ignoreEnabled) {
                
return cont.findComponentAt(x, y, ignoreEnabled);
            
}
        
});
    
}

    
/**
     
* Initialize JNI field and method IDs for fields that may be
       
called from C.
     
*/

    
private static native void initIDs();

    
/**
     
* Constructs a new Container. Containers can be extended directly,
     
* but are lightweight in this case and must be contained by a parent
     
* somewhere higher up in the component tree that is native.
     
* (such as Frame for example).
     
*/

    
public Container() {
    
}
    
@SuppressWarnings({"unchecked","rawtypes"})
    
void initializeFocusTraversalKeys() {
        
focusTraversalKeys = new Set[4];
    
}

    
/**
     
* Gets the number of components in this panel.
     
* <p>
     
* Note: This method should be called under AWT tree lock.
     
*
     
* @return
    
the number of components in this panel.
     
* @see
       
#getComponent
     
* @sinceJDK1.1
     
* @see Component#getTreeLock()
     
*/

    
public int getComponentCount() {
        
return countComponents();
    
}

    
/**
     
* @deprecated As of JDK version 1.1,
     
* replaced by getComponentCount().
     
*/
    
@Deprecated
    
public int countComponents() {
        
// This method is not synchronized under AWT tree lock.
        
// Instead, the calling code is responsible for the
        
// synchronization. See 6784816 for details.
        
return component.size();
    
}

    
/**
     
* Gets the nth component in this container.
     
* <p>
     
* Note: This method should be called under AWT tree lock.
     
*
     
* @param
      
n
   
the index of the component to get.
     
* @returnthe n<sup>th</sup> component in this container.
     
* @exception
  
ArrayIndexOutOfBoundsException
     
*
                 
if the n<sup>th</sup> value does not exist.
     
* @see Component#getTreeLock()
     
*/

    
public Component getComponent(int n) {
        
// This method is not synchronized under AWT tree lock.
        
// Instead, the calling code is responsible for the
        
// synchronization. See 6784816 for details.
        
try {
            
return component.get(n);
        
} catch (IndexOutOfBoundsException z) {
            
throw new ArrayIndexOutOfBoundsException("No such child: " + n);
        
}
    
}

    
/**
     
* Gets all the components in this container.
     
* <p>
     
* Note: This method should be called under AWT tree lock.
     
*
     
* @return
    
an array of all the components in this container.
     
* @see Component#getTreeLock()
     
*/

    
public Component[] getComponents() {
        
// This method is not synchronized under AWT tree lock.
        
// Instead, the calling code is responsible for the
        
// synchronization. See 6784816 for details.
        
return getComponents_NoClientCode();
    
}

    
// NOTE: This method may be called by privileged threads.
    
//
       
This functionality is implemented in a package-private method
    
//
       
to insure that it cannot be overridden by client subclasses.

    
//
       
DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    
final Component[] getComponents_NoClientCode() {
        
return component.toArray(EMPTY_ARRAY);
    
}

    
/*
     
* Wrapper for getComponents() method with a proper synchronization.
     
*/

    
Component[] getComponentsSync() {
        
synchronized (getTreeLock()) {
            
return getComponents();
        
}
    
}

    
/**
     
* Determines the insets of this container, which indicate the size
     
* of the container's border.
     
* <p>
     
* A <code>Frame</code> object, for example, has a top inset that
     
* corresponds to the height of the frame's title bar.
     
* @return
    
the insets of this container.
     
* @see
       
Insets
     
* @see
       
LayoutManager
     
* @sinceJDK1.1
     
*/

    
public Insets getInsets() {
        
return insets();
    
}

    
/**
     
* @deprecated As of JDK version 1.1,
     
* replaced by <code>getInsets()</code>.
     
*/
    
@Deprecated
    
public Insets insets() {
        
ComponentPeer peer = this.peer;
        
if (peer instanceof ContainerPeer) {
            
ContainerPeer cpeer = (ContainerPeer)peer;
            
return (Insets)cpeer.getInsets().clone();
        
}
        
return new Insets(0, 0, 0, 0);
    
}

    
/**
     
* Appends the specified component to the end of this container.
     
* This is a convenience method for {@link #addImpl}.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy. If the container has already been
     
* displayed, the hierarchy must be validated thereafter in order to
     
* display the added component.
     
*
     
* @paramcomp
   
the component to be added
     
* @exception NullPointerException if {@code comp} is {@code null}
     
* @see #addImpl
     
* @see #invalidate
     
* @see #validate
     
* @see javax.swing.JComponent#revalidate()
     
* @return
    
the component argument
     
*/

    
public Component add(Component comp) {
        
addImpl(comp, null, -1);
        
return comp;
    
}

    
/**
     
* Adds the specified component to this container.
     
* This is a convenience method for {@link #addImpl}.
     
* <p>
     
* This method is obsolete as of 1.1.
  
Please use the
     
* method <code>add(Component, Object)</code> instead.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy. If the container has already been
     
* displayed, the hierarchy must be validated thereafter in order to
     
* display the added component.
     
*
     
* @exception NullPointerException if {@code comp} is {@code null}
     
* @see #add(Component, Object)
     
* @see #invalidate
     
*/

    
public Component add(String name, Component comp) {
        
addImpl(comp, name, -1);
        
return comp;
    
}

    
/**
     
* Adds the specified component to this container at the given
     
* position.
     
* This is a convenience method for {@link #addImpl}.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy. If the container has already been
     
* displayed, the hierarchy must be validated thereafter in order to
     
* display the added component.
     
*
     
*
     
* @paramcomp
   
the component to be added
     
* @paramindex
    
the position at which to insert the component,
     
*
                   
or <code>-1</code> to append the component to the end
     
* @exception NullPointerException if {@code comp} is {@code null}
     
* @exception IllegalArgumentException if {@code index} is invalid (see
     
*
            
{@link #addImpl} for details)
     
* @return
    
the component <code>comp</code>
     
* @see #addImpl
     
* @see #remove
     
* @see #invalidate
     
* @see #validate
     
* @see javax.swing.JComponent#revalidate()
     
*/

    
public Component add(Component comp, int index) {
        
addImpl(comp, null, index);
        
return comp;
    
}

    
/**
     
* Checks that the component
     
* isn't supposed to be added into itself.
     
*/

    
private void checkAddToSelf(Component comp){
        
if (comp instanceof Container) {
            
for (Container cn = this; cn != null; cn=cn.parent) {
                
if (cn == comp) {
                    
throw new IllegalArgumentException("adding container's parent to itself");
                
}
            
}
        
}
    
}

    
/**
     
* Checks that the component is not a Window instance.
     
*/
    
private void checkNotAWindow(Component comp){
        
if (comp instanceof Window) {
            
throw new IllegalArgumentException("adding a window to a container");
        
}
    
}

    
/**
     
* Checks that the component comp can be added to this container
     
* Checks :
  
index in bounds of container's size,
     
* comp is not one of this container's parents,
     
* and comp is not a window.
     
* Comp and container must be on the same GraphicsDevice.
     
* if comp is container, all sub-components must be on
     
* same GraphicsDevice.
     
*
     
* @since 1.5
     
*/

    
private void checkAdding(Component comp, int index) {
        
checkTreeLock();

        
GraphicsConfiguration thisGC = getGraphicsConfiguration();

        
if (index > component.size() || index < 0) {
            
throw new IllegalArgumentException("illegal component position");
        
}
        
if (comp.parent == this) {
            
if (index == component.size()) {
                
throw new IllegalArgumentException("illegal component position " +
                                                   
index + " should be less then " + component.size());
            
}
        
}
        
checkAddToSelf(comp);
        
checkNotAWindow(comp);

        
Window thisTopLevel = getContainingWindow();
        
Window compTopLevel = comp.getContainingWindow();
        
if (thisTopLevel != compTopLevel) {
            
throw new IllegalArgumentException("component and container should be in the same top-level window");
        
}
        
if (thisGC != null) {
            
comp.checkGD(thisGC.getDevice().getIDstring());
        
}
    
}

    
/**
     
* Removes component comp from this container without making unneccessary changes
     
* and generating unneccessary events. This function intended to perform optimized
     
* remove, for example, if newParent and current parent are the same it just changes
     
* index without calling removeNotify.
     
* Note: Should be called while holding treeLock
     
* Returns whether removeNotify was invoked
     
* @since: 1.5
     
*/

    
private boolean removeDelicately(Component comp, Container newParent, int newIndex) {
        
checkTreeLock();

        
int index = getComponentZOrder(comp);
        
boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent);
        
if (needRemoveNotify) {
            
comp.removeNotify();
        
}
        
if (newParent != this) {
            
if (layoutMgr != null) {
                
layoutMgr.removeLayoutComponent(comp);
            
}
            
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
                                    
-comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
            
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                    
-comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
            
adjustDescendants(-(comp.countHierarchyMembers()));

            
comp.parent = null;
            
if (needRemoveNotify) {
                
comp.setGraphicsConfiguration(null);
            
}
            
component.remove(index);

            
invalidateIfValid();
        
} else {
            
// We should remove component and then
            
// add it by the newIndex without newIndex decrement if even we shift components to the left
            
// after remove. Consult the rules below:
            
// 2->4: 012345 -> 013425, 2->5: 012345 -> 013452
            
// 4->2: 012345 -> 014235
            
component.remove(index);
            
component.add(newIndex, comp);
        
}
        
if (comp.parent == null) { // was actually removed
            
if (containerListener != null ||
                
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
                
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
                
ContainerEvent e = new ContainerEvent(this,
                                                      
ContainerEvent.COMPONENT_REMOVED,
                                                      
comp);
                
dispatchEvent(e);

            
}
            
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
                                       
this, HierarchyEvent.PARENT_CHANGED,
                                       
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
            
if (peer != null && layoutMgr == null && isVisible()) {
                
updateCursorImmediately();
            
}
        
}
        
return needRemoveNotify;
    
}

    
/**
     
* Checks whether this container can contain component which is focus owner.
     
* Verifies that container is enable and showing, and if it is focus cycle root
     
* its FTP allows component to be focus owner
     
* @since 1.5
     
*/

    
boolean canContainFocusOwner(Component focusOwnerCandidate) {
        
if (!(isEnabled() && isDisplayable()
              
&& isVisible() && isFocusable()))
        
{
            
return false;
        
}
        
if (isFocusCycleRoot()) {
            
FocusTraversalPolicy policy = getFocusTraversalPolicy();
            
if (policy instanceof DefaultFocusTraversalPolicy) {
                
if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) {
                    
return false;
                
}
            
}
        
}
        
synchronized(getTreeLock()) {
            
if (parent != null) {
                
return parent.canContainFocusOwner(focusOwnerCandidate);
            
}
        
}
        
return true;
    
}

    
/**
     
* Checks whether or not this container has heavyweight children.
     
* Note: Should be called while holding tree lock
     
* @return true if there is at least one heavyweight children in a container, false otherwise
     
* @since 1.5
     
*/

    
final boolean hasHeavyweightDescendants() {
        
checkTreeLock();
        
return numOfHWComponents > 0;
    
}

    
/**
     
* Checks whether or not this container has lightweight children.
     
* Note: Should be called while holding tree lock
     
* @return true if there is at least one lightweight children in a container, false otherwise
     
* @since 1.7
     
*/

    
final boolean hasLightweightDescendants() {
        
checkTreeLock();
        
return numOfLWComponents > 0;
    
}

    
/**
     
* Returns closest heavyweight component to this container. If this container is heavyweight
     
* returns this.
     
* @since 1.5
     
*/

    
Container getHeavyweightContainer() {
        
checkTreeLock();
        
if (peer != null && !(peer instanceof LightweightPeer)) {
            
return this;
        
} else {
            
return getNativeContainer();
        
}
    
}

    
/**
     
* Detects whether or not remove from current parent and adding to new parent requires call of
     
* removeNotify on the component. Since removeNotify destroys native window this might (not)
     
* be required. For example, if new container and old containers are the same we don't need to
     
* destroy native window.
     
* @since: 1.5
     
*/

    
private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) {
        
if (oldContainer == null) { // Component didn't have parent - no removeNotify
            
return false;
        
}
        
if (comp.peer == null) { // Component didn't have peer - no removeNotify
            
return false;
        
}
        
if (newContainer.peer == null) {
            
// Component has peer but new Container doesn't - call removeNotify
            
return true;
        
}

        
// If component is lightweight non-Container or lightweight Container with all but heavyweight
        
// children there is no need to call remove notify
        
if (comp.isLightweight()) {
            
boolean isContainer = comp instanceof Container;

            
if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) {
                
return false;
            
}
        
}

        
// If this point is reached, then the comp is either a HW or a LW container with HW descendants.

        
// All three components have peers, check for peer change
        
Container newNativeContainer = oldContainer.getHeavyweightContainer();
        
Container oldNativeContainer = newContainer.getHeavyweightContainer();
        
if (newNativeContainer != oldNativeContainer) {
            
// Native containers change - check whether or not current platform supports
            
// changing of widget hierarchy on native level without recreation.
            
// The current implementation forbids reparenting of LW containers with HW descendants
            
// into another native container w/o destroying the peers. Actually such an operation
            
// is quite rare. If we ever need to save the peers, we'll have to slightly change the
            
// addDelicately() method in order to handle such LW containers recursively, reparenting
            
// each HW descendant independently.
            
return !comp.peer.isReparentSupported();
        
} else {
            
return false;
        
}
    
}

    
/**
     
* Moves the specified component to the specified z-order index in
     
* the container. The z-order determines the order that components
     
* are painted; the component with the highest z-order paints first
     
* and the component with the lowest z-order paints last.
     
* Where components overlap, the component with the lower
     
* z-order paints over the component with the higher z-order.
     
* <p>
     
* If the component is a child of some other container, it is
     
* removed from that container before being added to this container.
     
* The important difference between this method and
     
* <code>java.awt.Container.add(Component, int)</code> is that this method
     
* doesn't call <code>removeNotify</code> on the component while
     
* removing it from its previous container unless necessary and when
     
* allowed by the underlying native windowing system. This way, if the
     
* component has the keyboard focus, it maintains the focus when
     
* moved to the new position.
     
* <p>
     
* This property is guaranteed to apply only to lightweight
     
* non-<code>Container</code> components.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy.
     
* <p>
     
* <b>Note</b>: Not all platforms support changing the z-order of
     
* heavyweight components from one container into another without
     
* the call to <code>removeNotify</code>. There is no way to detect
     
* whether a platform supports this, so developers shouldn't make
     
* any assumptions.
     
*
     
* @paramcomp the component to be moved
     
* @paramindex the position in the container's list to
     
*
            
insert the component, where <code>getComponentCount()</code>
     
*
            
appends to the end
     
* @exception NullPointerException if <code>comp</code> is
     
*
            
<code>null</code>
     
* @exception IllegalArgumentException if <code>comp</code> is one of the
     
*
            
container's parents
     
* @exception IllegalArgumentException if <code>index</code> is not in
     
*
            
the range <code>[0, getComponentCount()]</code> for moving
     
*
            
between containers, or not in the range
     
*
            
<code>[0, getComponentCount()-1]</code> for moving inside
     
*
            
a container
     
* @exception IllegalArgumentException if adding a container to itself
     
* @exception IllegalArgumentException if adding a <code>Window</code>
     
*
            
to a container
     
* @see #getComponentZOrder(java.awt.Component)
     
* @see #invalidate
     
* @since 1.5
     
*/

    
public void setComponentZOrder(Component comp, int index) {
         
synchronized (getTreeLock()) {
             
// Store parent because remove will clear it
             
Container curParent = comp.parent;
             
int oldZindex = getComponentZOrder(comp);

             
if (curParent == this && index == oldZindex) {
                 
return;
             
}
             
checkAdding(comp, index);

             
boolean peerRecreated = (curParent != null) ?
                 
curParent.removeDelicately(comp, this, index) : false;

             
addDelicately(comp, curParent, index);

             
// If the oldZindex == -1, the component gets inserted,
             
// rather than it changes its z-order.
             
if (!peerRecreated && oldZindex != -1) {
                 
// The new 'index' cannot be == -1.
                 
// It gets checked at the checkAdding() method.
                 
// Therefore both oldZIndex and index denote
                 
// some existing positions at this point and
                 
// this is actually a Z-order changing.
                 
comp.mixOnZOrderChanging(oldZindex, index);
             
}
         
}
    
}

    
/**
     
* Traverses the tree of components and reparents children heavyweight component
     
* to new heavyweight parent.
     
* @since 1.5
     
*/

    
private void reparentTraverse(ContainerPeer parentPeer, Container child) {
        
checkTreeLock();

        
for (int i = 0; i < child.getComponentCount(); i++) {
            
Component comp = child.getComponent(i);
            
if (comp.isLightweight()) {
                
// If components is lightweight check if it is container
                
// If it is container it might contain heavyweight children we need to reparent
                
if (comp instanceof Container) {
                    
reparentTraverse(parentPeer, (Container)comp);
                
}
            
} else {
                
// Q: Need to update NativeInLightFixer?
                
comp.getPeer().reparent(parentPeer);
            
}
        
}
    
}

    
/**
     
* Reparents child component peer to this container peer.
     
* Container must be heavyweight.
     
* @since 1.5
     
*/

    
private void reparentChild(Component comp) {
        
checkTreeLock();
        
if (comp == null) {
            
return;
        
}
        
if (comp.isLightweight()) {
            
// If component is lightweight container we need to reparent all its explicit
  
heavyweight children

            
if (comp instanceof Container) {
                
// Traverse component's tree till depth-first until encountering heavyweight component
                
reparentTraverse((ContainerPeer)getPeer(), (Container)comp);
            
}
        
} else {
            
comp.getPeer().reparent((ContainerPeer)getPeer());
        
}
    
}

    
/**
     
* Adds component to this container. Tries to minimize side effects of this adding -
     
* doesn't call remove notify if it is not required.
     
* @since 1.5
     
*/

    
private void addDelicately(Component comp, Container curParent, int index) {
        
checkTreeLock();

        
// Check if moving between containers
        
if (curParent != this) {
            
//index == -1 means add to the end.
            
if (index == -1) {
                
component.add(comp);
            
} else {
                
component.add(index, comp);
            
}
            
comp.parent = this;
            
comp.setGraphicsConfiguration(getGraphicsConfiguration());

            
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
                                    
comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
            
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                    
comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
            
adjustDescendants(comp.countHierarchyMembers());
        
} else {
            
if (index < component.size()) {
                
component.set(index, comp);
            
}
        
}

        
invalidateIfValid();
        
if (peer != null) {
            
if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one
                
comp.addNotify();
            
} else { // Both container and child have peers, it means child peer should be reparented.
                
// In both cases we need to reparent native widgets.
                
Container newNativeContainer = getHeavyweightContainer();
                
Container oldNativeContainer = curParent.getHeavyweightContainer();
                
if (oldNativeContainer != newNativeContainer) {
                    
// Native container changed - need to reparent native widgets
                    
newNativeContainer.reparentChild(comp);
                
}
                
comp.updateZOrder();

                
if (!comp.isLightweight() && isLightweight()) {
                    
// If component is heavyweight and one of the containers is lightweight
                    
// the location of the component should be fixed.
                    
comp.relocateComponent();
                
}
            
}
        
}
        
if (curParent != this) {
            
/* Notify the layout manager of the added component. */
            
if (layoutMgr != null) {
                
if (layoutMgr instanceof LayoutManager2) {
                    
((LayoutManager2)layoutMgr).addLayoutComponent(comp, null);
                
} else {
                    
layoutMgr.addLayoutComponent(null, comp);
                
}
            
}
            
if (containerListener != null ||
                
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
                
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
                
ContainerEvent e = new ContainerEvent(this,
                                                      
ContainerEvent.COMPONENT_ADDED,
                                                      
comp);
                
dispatchEvent(e);
            
}
            
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
                                       
this, HierarchyEvent.PARENT_CHANGED,
                                       
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));

            
// If component is focus owner or parent container of focus owner check that after reparenting
            
// focus owner moved out if new container prohibit this kind of focus owner.
            
if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) {
                
comp.transferFocus();
            
} else if (comp instanceof Container) {
                
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
                
if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) {
                    
focusOwner.transferFocus();
                
}
            
}
        
} else {
            
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
                                       
this, HierarchyEvent.HIERARCHY_CHANGED,
                                       
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
        
}

        
if (peer != null && layoutMgr == null && isVisible()) {
            
updateCursorImmediately();
        
}
    
}

    
/**
     
* Returns the z-order index of the component inside the container.
     
* The higher a component is in the z-order hierarchy, the lower
     
* its index.
  
The component with the lowest z-order index is
     
* painted last, above all other child components.
     
*
     
* @param comp the component being queried
     
* @return
  
the z-order index of the component; otherwise
     
*
          
returns -1 if the component is <code>null</code>
     
*
          
or doesn't belong to the container
     
* @see #setComponentZOrder(java.awt.Component, int)
     
* @since 1.5
     
*/

    
public int getComponentZOrder(Component comp) {
        
if (comp == null) {
            
return -1;
        
}
        
synchronized(getTreeLock()) {
            
// Quick check - container should be immediate parent of the component
            
if (comp.parent != this) {
                
return -1;
            
}
            
return component.indexOf(comp);
        
}
    
}

    
/**
     
* Adds the specified component to the end of this container.
     
* Also notifies the layout manager to add the component to
     
* this container's layout using the specified constraints object.
     
* This is a convenience method for {@link #addImpl}.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy. If the container has already been
     
* displayed, the hierarchy must be validated thereafter in order to
     
* display the added component.
     
*
     
*
     
* @paramcomp the component to be added
     
* @paramconstraints an object expressing
     
*
                  
layout constraints for this component
     
* @exception NullPointerException if {@code comp} is {@code null}
     
* @see #addImpl
     
* @see #invalidate
     
* @see #validate
     
* @see javax.swing.JComponent#revalidate()
     
* @see
       
LayoutManager
     
* @sinceJDK1.1
     
*/

    
public void add(Component comp, Object constraints) {
        
addImpl(comp, constraints, -1);
    
}

    
/**
     
* Adds the specified component to this container with the specified
     
* constraints at the specified index.
  
Also notifies the layout
     
* manager to add the component to the this container's layout using
     
* the specified constraints object.
     
* This is a convenience method for {@link #addImpl}.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy. If the container has already been
     
* displayed, the hierarchy must be validated thereafter in order to
     
* display the added component.
     
*
     
*
     
* @param comp the component to be added
     
* @param constraints an object expressing layout constraints for this
     
* @param index the position in the container's list at which to insert
     
* the component; <code>-1</code> means insert at the end
     
* component
     
* @exception NullPointerException if {@code comp} is {@code null}
     
* @exception IllegalArgumentException if {@code index} is invalid (see
     
*
            
{@link #addImpl} for details)
     
* @see #addImpl
     
* @see #invalidate
     
* @see #validate
     
* @see javax.swing.JComponent#revalidate()
     
* @see #remove
     
* @see LayoutManager
     
*/

    
public void add(Component comp, Object constraints, int index) {
       
addImpl(comp, constraints, index);
    
}

    
/**
     
* Adds the specified component to this container at the specified
     
* index. This method also notifies the layout manager to add
     
* the component to this container's layout using the specified
     
* constraints object via the <code>addLayoutComponent</code>
     
* method.
     
* <p>
     
* The constraints are
     
* defined by the particular layout manager being used.
  
For
     
* example, the <code>BorderLayout</code> class defines five
     
* constraints: <code>BorderLayout.NORTH</code>,
     
* <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>,
     
* <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>.
     
* <p>
     
* The <code>GridBagLayout</code> class requires a
     
* <code>GridBagConstraints</code> object.
  
Failure to pass
     
* the correct type of constraints object results in an
     
* <code>IllegalArgumentException</code>.
     
* <p>
     
* If the current layout manager implements {@code LayoutManager2}, then
     
* {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on
     
* it. If the current layout manager does not implement
     
* {@code LayoutManager2}, and constraints is a {@code String}, then
     
* {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.
     
* <p>
     
* If the component is not an ancestor of this container and has a non-null
     
* parent, it is removed from its current parent before it is added to this
     
* container.
     
* <p>
     
* This is the method to override if a program needs to track
     
* every add request to a container as all other add methods defer
     
* to this one. An overriding method should
     
* usually include a call to the superclass's version of the method:
     
*
     
* <blockquote>
     
* <code>super.addImpl(comp, constraints, index)</code>
     
* </blockquote>
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy. If the container has already been
     
* displayed, the hierarchy must be validated thereafter in order to
     
* display the added component.
     
*
     
* @paramcomp
       
the component to be added
     
* @paramconstraints an object expressing layout constraints
     
*
                 
for this component
     
* @paramindex the position in the container's list at which to
     
*
                 
insert the component, where <code>-1</code>
     
*
                 
means append to the end
     
* @exception IllegalArgumentException if {@code index} is invalid;
     
*
            
if {@code comp} is a child of this container, the valid
     
*
            
range is {@code [-1, getComponentCount()-1]}; if component is
     
*
            
not a child of this container, the valid range is
     
*
            
{@code [-1, getComponentCount()]}
     
*
     
* @exception IllegalArgumentException if {@code comp} is an ancestor of
     
*
                                     
this container
     
* @exception IllegalArgumentException if adding a window to a container
     
* @exception NullPointerException if {@code comp} is {@code null}
     
* @see
       
#add(Component)
     
* @see
       
#add(Component, int)
     
* @see
       
#add(Component, java.lang.Object)
     
* @see #invalidate
     
* @see
       
LayoutManager
     
* @see
       
LayoutManager2
     
* @sinceJDK1.1
     
*/

    
protected void addImpl(Component comp, Object constraints, int index) {
        
synchronized (getTreeLock()) {
            
/* Check for correct arguments:
  
index in bounds,
             
* comp cannot be one of this container's parents,
             
* and comp cannot be a window.
             
* comp and container must be on the same GraphicsDevice.
             
* if comp is container, all sub-components must be on
             
* same GraphicsDevice.
             
*/

            
GraphicsConfiguration thisGC = this.getGraphicsConfiguration();

            
if (index > component.size() || (index < 0 && index != -1)) {
                
throw new IllegalArgumentException(
                          
"illegal component position");
            
}
            
checkAddToSelf(comp);
            
checkNotAWindow(comp);
            
/* Reparent the component and tidy up the tree's state. */
            
if (comp.parent != null) {
                
comp.parent.remove(comp);
                
if (index > component.size()) {
                    
throw new IllegalArgumentException("illegal component position");
                
}
            
}
            
if (thisGC != null) {
                
comp.checkGD(thisGC.getDevice().getIDstring());
            
}



            
//index == -1 means add to the end.
            
if (index == -1) {
                
component.add(comp);
            
} else {
                
component.add(index, comp);
            
}
            
comp.parent = this;
            
comp.setGraphicsConfiguration(thisGC);

            
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
                
comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
            
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                
comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
            
adjustDescendants(comp.countHierarchyMembers());

            
invalidateIfValid();
            
if (peer != null) {
                
comp.addNotify();
            
}

            
/* Notify the layout manager of the added component. */
            
if (layoutMgr != null) {
                
if (layoutMgr instanceof LayoutManager2) {
                    
((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
                
} else if (constraints instanceof String) {
                    
layoutMgr.addLayoutComponent((String)constraints, comp);
                
}
            
}
            
if (containerListener != null ||
                
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
                
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
                
ContainerEvent e = new ContainerEvent(this,
                                     
ContainerEvent.COMPONENT_ADDED,
                                     
comp);
                
dispatchEvent(e);
            
}

            
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
                                       
this, HierarchyEvent.PARENT_CHANGED,
                                       
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
            
if (peer != null && layoutMgr == null && isVisible()) {
                
updateCursorImmediately();
            
}
        
}
    
}

    
@Override
    
boolean updateGraphicsData(GraphicsConfiguration gc) {
        
checkTreeLock();

        
boolean ret = super.updateGraphicsData(gc);

        
for (Component comp : component) {
            
if (comp != null) {
                
ret |= comp.updateGraphicsData(gc);
            
}
        
}
        
return ret;
    
}

    
/**
     
* Checks that all Components that this Container contains are on
     
* the same GraphicsDevice as this Container.
  
If not, throws an
     
* IllegalArgumentException.
     
*/

    
void checkGD(String stringID) {
        
for (Component comp : component) {
            
if (comp != null) {
                
comp.checkGD(stringID);
            
}
        
}
    
}

    
/**
     
* Removes the component, specified by <code>index</code>,
     
* from this container.
     
* This method also notifies the layout manager to remove the
     
* component from this container's layout via the
     
* <code>removeLayoutComponent</code> method.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy. If the container has already been
     
* displayed, the hierarchy must be validated thereafter in order to
     
* reflect the changes.
     
*
     
*
     
* @paramindex
   
the index of the component to be removed
     
* @throws ArrayIndexOutOfBoundsException if {@code index} is not in
     
*
         
range {@code [0, getComponentCount()-1]}
     
* @see #add
     
* @see #invalidate
     
* @see #validate
     
* @see #getComponentCount
     
* @since JDK1.1
     
*/

    
public void remove(int index) {
        
synchronized (getTreeLock()) {
            
if (index < 0
  
|| index >= component.size()) {
                
throw new ArrayIndexOutOfBoundsException(index);
            
}
            
Component comp = component.get(index);
            
if (peer != null) {
                
comp.removeNotify();
            
}
            
if (layoutMgr != null) {
                
layoutMgr.removeLayoutComponent(comp);
            
}

            
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
                
-comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
            
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                
-comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
            
adjustDescendants(-(comp.countHierarchyMembers()));

            
comp.parent = null;
            
component.remove(index);
            
comp.setGraphicsConfiguration(null);

            
invalidateIfValid();
            
if (containerListener != null ||
                
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
                
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
                
ContainerEvent e = new ContainerEvent(this,
                                     
ContainerEvent.COMPONENT_REMOVED,
                                     
comp);
                
dispatchEvent(e);
            
}

            
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
                                       
this, HierarchyEvent.PARENT_CHANGED,
                                       
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
            
if (peer != null && layoutMgr == null && isVisible()) {
                
updateCursorImmediately();
            
}
        
}
    
}

    
/**
     
* Removes the specified component from this container.
     
* This method also notifies the layout manager to remove the
     
* component from this container's layout via the
     
* <code>removeLayoutComponent</code> method.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy. If the container has already been
     
* displayed, the hierarchy must be validated thereafter in order to
     
* reflect the changes.
     
*
     
* @param comp the component to be removed
     
* @throws NullPointerException if {@code comp} is {@code null}
     
* @see #add
     
* @see #invalidate
     
* @see #validate
     
* @see #remove(int)
     
*/

    
public void remove(Component comp) {
        
synchronized (getTreeLock()) {
            
if (comp.parent == this)
  
{
                
int index = component.indexOf(comp);
                
if (index >= 0) {
                    
remove(index);
                
}
            
}
        
}
    
}

    
/**
     
* Removes all the components from this container.
     
* This method also notifies the layout manager to remove the
     
* components from this container's layout via the
     
* <code>removeLayoutComponent</code> method.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy. If the container has already been
     
* displayed, the hierarchy must be validated thereafter in order to
     
* reflect the changes.
     
*
     
* @see #add
     
* @see #remove
     
* @see #invalidate
     
*/

    
public void removeAll() {
        
synchronized (getTreeLock()) {
            
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
                                    
-listeningChildren);
            
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                    
-listeningBoundsChildren);
            
adjustDescendants(-descendantsCount);

            
while (!component.isEmpty()) {
                
Component comp = component.remove(component.size()-1);

                
if (peer != null) {
                    
comp.removeNotify();
                
}
                
if (layoutMgr != null) {
                    
layoutMgr.removeLayoutComponent(comp);
                
}
                
comp.parent = null;
                
comp.setGraphicsConfiguration(null);
                
if (containerListener != null ||
                   
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
                    
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
                    
ContainerEvent e = new ContainerEvent(this,
                                     
ContainerEvent.COMPONENT_REMOVED,
                                     
comp);
                    
dispatchEvent(e);
                
}

                
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
                                           
comp, this,
                                           
HierarchyEvent.PARENT_CHANGED,
                                           
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
            
}
            
if (peer != null && layoutMgr == null && isVisible()) {
                
updateCursorImmediately();
            
}
            
invalidateIfValid();
        
}
    
}

    
// Should only be called while holding tree lock
    
int numListening(long mask) {
        
int superListening = super.numListening(mask);

        
if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {
            
if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
                
// Verify listeningChildren is correct
                
int sum = 0;
                
for (Component comp : component) {
                    
sum += comp.numListening(mask);
                
}
                
if (listeningChildren != sum) {
                    
eventLog.fine("Assertion (listeningChildren == sum) failed");
                
}
            
}
            
return listeningChildren + superListening;
        
} else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
            
if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
                
// Verify listeningBoundsChildren is correct
                
int sum = 0;
                
for (Component comp : component) {
                    
sum += comp.numListening(mask);
                
}
                
if (listeningBoundsChildren != sum) {
                    
eventLog.fine("Assertion (listeningBoundsChildren == sum) failed");
                
}
            
}
            
return listeningBoundsChildren + superListening;
        
} else {
            
// assert false;
            
if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
                
eventLog.fine("This code must never be reached");
            
}
            
return superListening;
        
}
    
}

    
// Should only be called while holding tree lock
    
void adjustListeningChildren(long mask, int num) {
        
if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
            
boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK ||
                                
mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||
                                
mask == (AWTEvent.HIERARCHY_EVENT_MASK |
                                         
AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
            
if (!toAssert) {
                
eventLog.fine("Assertion failed");
            
}
        
}

        
if (num == 0)
            
return;

        
if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
            
listeningChildren += num;
        
}
        
if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
            
listeningBoundsChildren += num;
        
}

        
adjustListeningChildrenOnParent(mask, num);
    
}

    
// Should only be called while holding tree lock
    
void adjustDescendants(int num) {
        
if (num == 0)
            
return;

        
descendantsCount += num;
        
adjustDecendantsOnParent(num);
    
}

    
// Should only be called while holding tree lock
    
void adjustDecendantsOnParent(int num) {
        
if (parent != null) {
            
parent.adjustDescendants(num);
        
}
    
}

    
// Should only be called while holding tree lock
    
int countHierarchyMembers() {
        
if (log.isLoggable(PlatformLogger.Level.FINE)) {
            
// Verify descendantsCount is correct
            
int sum = 0;
            
for (Component comp : component) {
                
sum += comp.countHierarchyMembers();
            
}
            
if (descendantsCount != sum) {
                
log.fine("Assertion (descendantsCount == sum) failed");
            
}
        
}
        
return descendantsCount + 1;
    
}

    
private int getListenersCount(int id, boolean enabledOnToolkit) {
        
checkTreeLock();
        
if (enabledOnToolkit) {
            
return descendantsCount;
        
}
        
switch (id) {
          
case HierarchyEvent.HIERARCHY_CHANGED:
            
return listeningChildren;
          
case HierarchyEvent.ANCESTOR_MOVED:
          
case HierarchyEvent.ANCESTOR_RESIZED:
            
return listeningBoundsChildren;
          
default:
            
return 0;
        
}
    
}

    
final int createHierarchyEvents(int id, Component changed,
        
Container changedParent, long changeFlags, boolean enabledOnToolkit)
    
{
        
checkTreeLock();
        
int listeners = getListenersCount(id, enabledOnToolkit);

        
for (int count = listeners, i = 0; count > 0; i++) {
            
count -= component.get(i).createHierarchyEvents(id, changed,
                
changedParent, changeFlags, enabledOnToolkit);
        
}
        
return listeners +
            
super.createHierarchyEvents(id, changed, changedParent,
                                        
changeFlags, enabledOnToolkit);
    
}

    
final void createChildHierarchyEvents(int id, long changeFlags,
        
boolean enabledOnToolkit)
    
{
        
checkTreeLock();
        
if (component.isEmpty()) {
            
return;
        
}
        
int listeners = getListenersCount(id, enabledOnToolkit);

        
for (int count = listeners, i = 0; count > 0; i++) {
            
count -= component.get(i).createHierarchyEvents(id, this, parent,
                
changeFlags, enabledOnToolkit);
        
}
    
}

    
/**
     
* Gets the layout manager for this container.
     
* @see #doLayout
     
* @see #setLayout
     
*/

    
public LayoutManager getLayout() {
        
return layoutMgr;
    
}

    
/**
     
* Sets the layout manager for this container.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy.
     
*
     
* @param mgr the specified layout manager
     
* @see #doLayout
     
* @see #getLayout
     
* @see #invalidate
     
*/

    
public void setLayout(LayoutManager mgr) {
        
layoutMgr = mgr;
        
invalidateIfValid();
    
}

    
/**
     
* Causes this container to lay out its components.
  
Most programs
     
* should not call this method directly, but should invoke
     
* the <code>validate</code> method instead.
     
* @see LayoutManager#layoutContainer
     
* @see #setLayout
     
* @see #validate
     
* @since JDK1.1
     
*/

    
public void doLayout() {
        
layout();
    
}

    
/**
     
* @deprecated As of JDK version 1.1,
     
* replaced by <code>doLayout()</code>.
     
*/
    
@Deprecated
    
public void layout() {
        
LayoutManager layoutMgr = this.layoutMgr;
        
if (layoutMgr != null) {
            
layoutMgr.layoutContainer(this);
        
}
    
}

    
/**
     
* Indicates if this container is a <i>validate root</i>.
     
* <p>
     
* Layout-related changes, such as bounds of the validate root descendants,
     
* do not affect the layout of the validate root parent. This peculiarity
     
* enables the {@code invalidate()} method to stop invalidating the
     
* component hierarchy when the method encounters a validate root. However,
     
* to preserve backward compatibility this new optimized behavior is
     
* enabled only when the {@code java.awt.smartInvalidate} system property
     
* value is set to {@code true}.
     
* <p>
     
* If a component hierarchy contains validate roots and the new optimized
     
* {@code invalidate()} behavior is enabled, the {@code validate()} method
     
* must be invoked on the validate root of a previously invalidated
     
* component to restore the validity of the hierarchy later. Otherwise,
     
* calling the {@code validate()} method on the top-level container (such
     
* as a {@code Frame} object) should be used to restore the validity of the
     
* component hierarchy.
     
* <p>
     
* The {@code Window} class and the {@code Applet} class are the validate
     
* roots in AWT.
  
Swing introduces more validate roots.
     
*
     
* @return whether this container is a validate root
     
* @see #invalidate
     
* @see java.awt.Component#invalidate
     
* @see javax.swing.JComponent#isValidateRoot
     
* @see javax.swing.JComponent#revalidate
     
* @since 1.7
     
*/

    
public boolean isValidateRoot() {
        
return false;
    
}

    
private static final boolean isJavaAwtSmartInvalidate;
    
static {
        
// Don't lazy-read because every app uses invalidate()
        
isJavaAwtSmartInvalidate = AccessController.doPrivileged(
                
new GetBooleanAction("java.awt.smartInvalidate"));
    
}

    
/**
     
* Invalidates the parent of the container unless the container
     
* is a validate root.
     
*/

    
@Override
    
void invalidateParent() {
        
if (!isJavaAwtSmartInvalidate || !isValidateRoot()) {
            
super.invalidateParent();
        
}
    
}

    
/**
     
* Invalidates the container.
     
* <p>
     
* If the {@code LayoutManager} installed on this container is an instance
     
* of the {@code LayoutManager2} interface, then
     
* the {@link LayoutManager2#invalidateLayout(Container)} method is invoked
     
* on it supplying this {@code Container} as the argument.
     
* <p>
     
* Afterwards this method marks this container invalid, and invalidates its
     
* ancestors. See the {@link Component#invalidate} method for more details.
     
*
     
* @see #validate
     
* @see #layout
     
* @see LayoutManager2
     
*/

    
@Override
    
public void invalidate() {
        
LayoutManager layoutMgr = this.layoutMgr;
        
if (layoutMgr instanceof LayoutManager2) {
            
LayoutManager2 lm = (LayoutManager2) layoutMgr;
            
lm.invalidateLayout(this);
        
}
        
super.invalidate();
    
}

    
/**
     
* Validates this container and all of its subcomponents.
     
* <p>
     
* Validating a container means laying out its subcomponents.
     
* Layout-related changes, such as setting the bounds of a component, or
     
* adding a component to the container, invalidate the container
     
* automatically.
  
Note that the ancestors of the container may be
     
* invalidated also (see {@link Component#invalidate} for details.)
     
* Therefore, to restore the validity of the hierarchy, the {@code
     
* validate()} method should be invoked on the top-most invalid
     
* container of the hierarchy.
     
* <p>
     
* Validating the container may be a quite time-consuming operation. For
     
* performance reasons a developer may postpone the validation of the
     
* hierarchy till a set of layout-related operations completes, e.g. after
     
* adding all the children to the container.
     
* <p>
     
* If this {@code Container} is not valid, this method invokes
     
* the {@code validateTree} method and marks this {@code Container}
     
* as valid. Otherwise, no action is performed.
     
*
     
* @see #add(java.awt.Component)
     
* @see #invalidate
     
* @see Container#isValidateRoot
     
* @see javax.swing.JComponent#revalidate()
     
* @see #validateTree
     
*/

    
public void validate() {
        
boolean updateCur = false;
        
synchronized (getTreeLock()) {
            
if ((!isValid() || descendUnconditionallyWhenValidating)
                    
&& peer != null)
            
{
                
ContainerPeer p = null;
                
if (peer instanceof ContainerPeer) {
                    
p = (ContainerPeer) peer;
                
}
                
if (p != null) {
                    
p.beginValidate();
                
}
                
validateTree();
                
if (p != null) {
                    
p.endValidate();
                    
// Avoid updating cursor if this is an internal call.
                    
// See validateUnconditionally() for details.
                    
if (!descendUnconditionallyWhenValidating) {
                        
updateCur = isVisible();
                    
}
                
}
            
}
        
}
        
if (updateCur) {
            
updateCursorImmediately();
        
}
    
}

    
/**
     
* Indicates whether valid containers should also traverse their
     
* children and call the validateTree() method on them.
     
*
     
* Synchronization: TreeLock.
     
*
     
* The field is allowed to be static as long as the TreeLock itself is
     
* static.
     
*
     
*
 

     
*/

    
private static boolean descendUnconditionallyWhenValidating = false;

    
/**
     
* Unconditionally validate the component hierarchy.
     
*/
    
final void validateUnconditionally() {
        
boolean updateCur = false;
        
synchronized (getTreeLock()) {
            
descendUnconditionallyWhenValidating = true;

            
validate();
            
if (peer instanceof ContainerPeer) {
                
updateCur = isVisible();
            
}

            
descendUnconditionallyWhenValidating = false;
        
}
        
if (updateCur) {
            
updateCursorImmediately();
        
}
    
}

    
/**
     
* Recursively descends the container tree and recomputes the
     
* layout for any subtrees marked as needing it (those marked as
     
* invalid).
  
Synchronization should be provided by the method
     
* that calls this one:
  
<code>validate</code>.
     
*
     
* @see #doLayout
     
* @see #validate
     
*/

    
protected void validateTree() {
        
checkTreeLock();
        
if (!isValid() || descendUnconditionallyWhenValidating) {
            
if (peer instanceof ContainerPeer) {
                
((ContainerPeer)peer).beginLayout();
            
}
            
if (!isValid()) {
                
doLayout();
            
}
            
for (int i = 0; i < component.size(); i++) {
                
Component comp = component.get(i);
                
if (
   
(comp instanceof Container)
                       
&& !(comp instanceof Window)
                       
&& (!comp.isValid() ||
                           
descendUnconditionallyWhenValidating))
                
{
                    
((Container)comp).validateTree();
                
} else {
                    
comp.validate();
                
}
            
}
            
if (peer instanceof ContainerPeer) {
                
((ContainerPeer)peer).endLayout();
            
}
        
}
        
super.validate();
    
}

    
/**
     
* Recursively descends the container tree and invalidates all
     
* contained components.
     
*/

    
void invalidateTree() {
        
synchronized (getTreeLock()) {
            
for (int i = 0; i < component.size(); i++) {
                
Component comp = component.get(i);
                
if (comp instanceof Container) {
                    
((Container)comp).invalidateTree();
                
}
                
else {
                    
comp.invalidateIfValid();
                
}
            
}
            
invalidateIfValid();
        
}
    
}

    
/**
     
* Sets the font of this container.
     
* <p>
     
* This method changes layout-related information, and therefore,
     
* invalidates the component hierarchy.
     
*
     
* @param f The font to become this container's font.
     
* @see Component#getFont
     
* @see #invalidate
     
* @since JDK1.0
     
*/

    
public void setFont(Font f) {
        
boolean shouldinvalidate = false;

        
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.
  
If the preferred size has
     
* not been set explicitly by {@link Component#setPreferredSize(Dimension)}
     
* and this {@code Container} has a {@code non-null} {@link LayoutManager},
     
* then {@link LayoutManager#preferredLayoutSize(Container)}
     
* is used to calculate the preferred size.
     
*
     
* <p>Note: some implementations may cache the value returned from the
     
* {@code LayoutManager}.
  
Implementations that cache need not invoke
     
* {@code preferredLayoutSize} on the {@code LayoutManager} every time
     
* this method is invoked, rather the {@code LayoutManager} will only
     
* be queried after the {@code Container} becomes invalid.
     
*
     
* @return
    
an instance of <code>Dimension</code> that represents
     
*
                
the preferred size of this container.
     
* @see
       
#getMinimumSize
     
* @see
       
#getMaximumSize
     
* @see
       
#getLayout
     
* @see
       
LayoutManager#preferredLayoutSize(Container)
     
* @see
       
Component#getPreferredSize
     
*/

    
public Dimension getPreferredSize() {
        
return preferredSize();
    
}

    
/**
     
* @deprecated As of JDK version 1.1,
     
* replaced by <code>getPreferredSize()</code>.
     
*/
    
@Deprecated
    
public Dimension preferredSize() {
        
/* Avoid grabbing the lock if a reasonable cached size value
         
* is available.
         
*/

        
Dimension dim = prefSize;
        
if (dim == null || !(isPreferredSizeSet() || isValid())) {
            
synchronized (getTreeLock()) {
                
prefSize = (layoutMgr != null) ?
                    
layoutMgr.preferredLayoutSize(this) :
                    
super.preferredSize();
                
dim = prefSize;
            
}
        
}
        
if (dim != null){
            
return new Dimension(dim);
        
}
        
else{
            
return dim;
        
}
    
}

    
/**
     
* Returns the minimum size of this container.
  
If the minimum size has
     
* not been set explicitly by {@link Component#setMinimumSize(Dimension)}
     
* and this {@code Container} has a {@code non-null} {@link LayoutManager},
     
* then {@link LayoutManager#minimumLayoutSize(Container)}
     
* is used to calculate the minimum size.
     
*
     
* <p>Note: some implementations may cache the value returned from the
     
* {@code LayoutManager}.
  
Implementations that cache need not invoke
     
* {@code minimumLayoutSize} on the {@code LayoutManager} every time
     
* this method is invoked, rather the {@code LayoutManager} will only
     
* be queried after the {@code Container} becomes invalid.
     
*
     
* @return
    
an instance of <code>Dimension</code> that represents
     
*
                
the minimum size of this container.
     
* @see
       
#getPreferredSize
     
* @see
       
#getMaximumSize
     
* @see
       
#getLayout
     
* @see
       
LayoutManager#minimumLayoutSize(Container)
     
* @see
       
Component#getMinimumSize
     
* @sinceJDK1.1
     
*/

    
public Dimension getMinimumSize() {
        
return minimumSize();
    
}

    
/**
     
* @deprecated As of JDK version 1.1,
     
* replaced by <code>getMinimumSize()</code>.
     
*/
    
@Deprecated
    
public Dimension minimumSize() {
        
/* Avoid grabbing the lock if a reasonable cached size value
         
* is available.
         
*/

        
Dimension dim = minSize;
        
if (dim == null || !(isMinimumSizeSet() || isValid())) {
            
synchronized (getTreeLock()) {
                
minSize = (layoutMgr != null) ?
                    
layoutMgr.minimumLayoutSize(this) :
                    
super.minimumSize();
                
dim = minSize;
            
}
        
}
        
if (dim != null){
            
return new Dimension(dim);
        
}
        
else{
            
return dim;
        
}
    
}

    
/**
     
* Returns the maximum size of this container.
  
If the maximum size has
     
* not been set explicitly by {@link Component#setMaximumSize(Dimension)}
     
* and the {@link LayoutManager} installed on this {@code Container}
     
* is an instance of {@link LayoutManager2}, then
     
* {@link LayoutManager2#maximumLayoutSize(Container)}
     
* is used to calculate the maximum size.
     
*
     
* <p>Note: some implementations may cache the value returned from the
     
* {@code LayoutManager2}.
  
Implementations that cache need not invoke
     
* {@code maximumLayoutSize} on the {@code LayoutManager2} every time
     
* this method is invoked, rather the {@code LayoutManager2} will only
     
* be queried after the {@code Container} becomes invalid.
     
*
     
* @return
    
an instance of <code>Dimension</code> that represents
     
*
                
the maximum size of this container.
     
* @see
       
#getPreferredSize
     
* @see
       
#getMinimumSize
     
* @see
       
#getLayout
     
* @see
       
LayoutManager2#maximumLayoutSize(Container)
     
* @see
       
Component#getMaximumSize
     
*/

    
public Dimension getMaximumSize() {
        
/* Avoid grabbing the lock if a reasonable cached size value
         
* is available.
         
*/

        
Dimension dim = maxSize;
        
if (dim == null || !(isMaximumSizeSet() || isValid())) {
            
synchronized (getTreeLock()) {
               
if (layoutMgr instanceof LayoutManager2) {
                    
LayoutManager2 lm = (LayoutManager2) layoutMgr;
                    
maxSize = lm.maximumLayoutSize(this);
               
} else {
                    
maxSize = super.getMaximumSize();
               
}
               
dim = maxSize;
            
}
        
}
        
if (dim != null){
            
return new Dimension(dim);
        
}
        
else{
            
return dim;
        
}
    
}

    
/**
     
* Returns the alignment along the x axis.
  
This specifies how
     
* the component would like to be aligned relative to other
     
* components.
  
The value should be a number between 0 and 1
     
* where 0 represents alignment along the origin, 1 is aligned
     
* the furthest away from the origin, 0.5 is centered, etc.
     
*/

    
public float getAlignmentX() {
        
float xAlign;
        
if (layoutMgr instanceof LayoutManager2) {
            
synchronized (getTreeLock()) {
                
LayoutManager2 lm = (LayoutManager2) layoutMgr;
                
xAlign = lm.getLayoutAlignmentX(this);
            
}
        
} else {
            
xAlign = super.getAlignmentX();
        
}
        
return xAlign;
    
}

    
/**
     
* Returns the alignment along the y axis.
  
This specifies how
     
* the component would like to be aligned relative to other
     
* components.
  
The value should be a number between 0 and 1
     
* where 0 represents alignment along the origin, 1 is aligned
     
* the furthest away from the origin, 0.5 is centered, etc.
     
*/

    
public float getAlignmentY() {
        
float yAlign;
        
if (layoutMgr instanceof LayoutManager2) {
            
synchronized (getTreeLock()) {
                
LayoutManager2 lm = (LayoutManager2) layoutMgr;
                
yAlign = lm.getLayoutAlignmentY(this);
            
}
        
} else {
            
yAlign = super.getAlignmentY();
        
}
        
return yAlign;
    
}

    
/**
     
* Paints the container. This forwards the paint to any lightweight
     
* components that are children of this container. If this method is
     
* reimplemented, super.paint(g) should be called so that lightweight
     
* components are properly rendered. If a child component is entirely
     
* clipped by the current clipping setting in g, paint() will not be
     
* forwarded to that child.
     
*
     
* @param g the specified Graphics window
     
* @see
   
Component#update(Graphics)
     
*/

    
public void paint(Graphics g) {
        
if (isShowing()) {
            
synchronized (getObjectLock()) {
                
if (printing) {
                    
if (printingThreads.contains(Thread.currentThread())) {
                        
return;
                    
}
                
}
            
}

            
// The container is showing on screen and
            
// this paint() is not called from print().
            
// Paint self and forward the paint to lightweight subcomponents.

            
// super.paint(); -- Don't bother, since it's a NOP.

            
GraphicsCallback.PaintCallback.getInstance().
                
runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
        
}
    
}

    
/**
     
* Updates the container.
  
This forwards the update to any lightweight
     
* components that are children of this container.
  
If this method is
     
* reimplemented, super.update(g) should be called so that lightweight
     
* components are properly rendered.
  
If a child component is entirely
     
* clipped by the current clipping setting in g, update() will not be
     
* forwarded to that child.
     
*
     
* @param g the specified Graphics window
     
* @see
   
Component#update(Graphics)
     
*/

    
public void update(Graphics g) {
        
if (isShowing()) {
            
if (! (peer instanceof LightweightPeer)) {
                
g.clearRect(0, 0, width, height);
            
}
            
paint(g);
        
}
    
}

    
/**
     
* Prints the container. This forwards the print to any lightweight
     
* components that are children of this container. If this method is
     
* reimplemented, super.print(g) should be called so that lightweight
     
* components are properly rendered. If a child component is entirely
     
* clipped by the current clipping setting in g, print() will not be
     
* forwarded to that child.
     
*
     
* @param g the specified Graphics window
     
* @see
   
Component#update(Graphics)
     
*/

    
public void print(Graphics g) {
        
if (isShowing()) {
            
Thread t = Thread.currentThread();
            
try {
                
synchronized (getObjectLock()) {
                    
if (printingThreads == null) {
                        
printingThreads = new HashSet<>();
                    
}
                    
printingThreads.add(t);
                    
printing = true;
                
}
                
super.print(g);
  
// By default, Component.print() calls paint()
            
} finally {
                
synchronized (getObjectLock()) {
                    
printingThreads.remove(t);
                    
printing = !printingThreads.isEmpty();
                
}
            
}

            
GraphicsCallback.PrintCallback.getInstance().
                
runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
        
}
    
}

    
/**
     
* Paints each of the components in this container.
     
* @paramg
   
the graphics context.
     
* @see
       
Component#paint
     
* @see
       
Component#paintAll
     
*/

    
public void paintComponents(Graphics g) {
        
if (isShowing()) {
            
GraphicsCallback.PaintAllCallback.getInstance().
                
runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
        
}
    
}

    
/**
     
* Simulates the peer callbacks into java.awt for printing of
     
* lightweight Containers.
     
* @paramg
   
the graphics context to use for printing.
     
* @see
       
Component#printAll
     
* @see
       
#printComponents
     
*/

    
void lightweightPaint(Graphics g) {
        
super.lightweightPaint(g);
        
paintHeavyweightComponents(g);
    
}

    
/**
     
* Prints all the heavyweight subcomponents.
     
*/
    
void paintHeavyweightComponents(Graphics g) {
        
if (isShowing()) {
            
GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
                
runComponents(getComponentsSync(), g,
                              
GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
        
}
    
}

    
/**
     
* Prints each of the components in this container.
     
* @paramg
   
the graphics context.
     
* @see
       
Component#print
     
* @see
       
Component#printAll
     
*/

    
public void printComponents(Graphics g) {
        
if (isShowing()) {
            
GraphicsCallback.PrintAllCallback.getInstance().
                
runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
        
}
    
}

    
/**
     
* Simulates the peer callbacks into java.awt for printing of
     
* lightweight Containers.
     
* @paramg
   
the graphics context to use for printing.
     
* @see
       
Component#printAll
     
* @see
       
#printComponents
     
*/

    
void lightweightPrint(Graphics g) {
        
super.lightweightPrint(g);
        
printHeavyweightComponents(g);
    
}

    
/**
     
* Prints all the heavyweight subcomponents.
     
*/
    
void printHeavyweightComponents(Graphics g) {
        
if (isShowing()) {
            
GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
                
runComponents(getComponentsSync(), g,
                              
GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
        
}
    
}

    
/**
     
* Adds the specified container listener to receive container events
     
* from this container.
     
* If l is null, no exception is thrown and no action is performed.
     
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
     
* >AWT Threading Issues</a> for details on AWT's threading model.
     
*
     
* @param
    
l the container listener
     
*
     
* @see #removeContainerListener
     
* @see #getContainerListeners
     
*/

    
public synchronized void addContainerListener(ContainerListener l) {
        
if (l == null) {
            
return;
        
}
        
containerListener = AWTEventMulticaster.add(containerListener, l);
        
newEventsOnly = true;
    
}

    
/**
     
* Removes the specified container listener so it no longer receives
     
* container events from this container.
     
* If l is null, no exception is thrown and no action is performed.
     
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
     
* >AWT Threading Issues</a> for details on AWT's threading model.
     
*
     
* @param
   
l the container listener
     
*
     
* @see #addContainerListener
     
* @see #getContainerListeners
     
*/

    
public synchronized void removeContainerListener(ContainerListener l) {
        
if (l == null) {
            
return;
        
}
        
containerListener = AWTEventMulticaster.remove(containerListener, l);
    
}

    
/**
     
* Returns an array of all the container listeners
     
* registered on this container.
     
*
     
* @return all of this container's <code>ContainerListener</code>s
     
*
         
or an empty array if no container
     
*
         
listeners are currently registered
     
*
     
* @see #addContainerListener
     
* @see #removeContainerListener
     
* @since 1.4
     
*/

    
public synchronized ContainerListener[] getContainerListeners() {
        
return getListeners(ContainerListener.class);
    
}

    
/**
     
* Returns an array of all the objects currently registered
     
* as <code><em>Foo</em>Listener</code>s
     
* upon this <code>Container</code>.
     
* <code><em>Foo</em>Listener</code>s are registered using the
     
* <code>add<em>Foo</em>Listener</code> method.
     
*
     
* <p>
     
* You can specify the <code>listenerType</code> argument
     
* with a class literal, such as
     
* <code><em>Foo</em>Listener.class</code>.
     
* For example, you can query a
     
* <code>Container</code> <code>c</code>
     
* for its container listeners with the following code:
     
*
     
* <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>
     
*
     
* If no such listeners exist, this method returns an empty array.
     
*
     
* @param listenerType the type of listeners requested; this parameter
     
*
          
should specify an interface that descends from
     
*
          
<code>java.util.EventListener</code>
     
* @return an array of all objects registered as
     
*
          
<code><em>Foo</em>Listener</code>s on this container,
     
*
          
or an empty array if no such listeners have been added
     
* @exception ClassCastException if <code>listenerType</code>
     
*
          
doesn't specify a class or interface that implements
     
*
          
<code>java.util.EventListener</code>
     
* @exception NullPointerException if {@code listenerType} is {@code null}
     
*
     
* @see #getContainerListeners
     
*
     
* @since 1.3
     
*/

    
public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
        
EventListener l = null;
        
if
  
(listenerType == ContainerListener.class) {
            
l = containerListener;
        
} else {
            
return super.getListeners(listenerType);
        
}
        
return AWTEventMulticaster.getListeners(l, listenerType);
    
}

    
// REMIND: remove when filtering is done at lower level
    
boolean eventEnabled(AWTEvent e) {
        
int id = e.getID();

        
if (id == ContainerEvent.COMPONENT_ADDED ||
            
id == ContainerEvent.COMPONENT_REMOVED) {
            
if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
                
containerListener != null) {
                
return true;
            
}
            
return false;
        
}
        
return super.eventEnabled(e);
    
}

    
/**
     
* Processes events on this container. If the event is a
     
* <code>ContainerEvent</code>, it invokes the
     
* <code>processContainerEvent</code> method, else it invokes
     
* its superclass's <code>processEvent</code>.
     
* <p>Note that if the event parameter is <code>null</code>
     
* the behavior is unspecified and may result in an
     
* exception.
     
*
     
* @param e the event
     
*/

    
protected void processEvent(AWTEvent e) {
        
if (e instanceof ContainerEvent) {
            
processContainerEvent((ContainerEvent)e);
            
return;
        
}
        
super.processEvent(e);
    
}

    
/**
     
* Processes container events occurring on this container by
     
* dispatching them to any registered ContainerListener objects.
     
* NOTE: This method will not be called unless container events
     
* are enabled for this component; this happens when one of the
     
* following occurs:
     
* <ul>
     
* <li>A ContainerListener object is registered via
     
*<code>addContainerListener</code>
     
* <li>Container events are enabled via <code>enableEvents</code>
     
* </ul>
     
* <p>Note that if the event parameter is <code>null</code>
     
* the behavior is unspecified and may result in an
     
* exception.
     
*
     
* @param e the container event
     
* @see Component#enableEvents
     
*/

    
protected void processContainerEvent(ContainerEvent e) {
        
ContainerListener listener = containerListener;
        
if (listener != null) {
            
switch(e.getID()) {
              
case ContainerEvent.COMPONENT_ADDED:
                
listener.componentAdded(e);
                
break;
              
case ContainerEvent.COMPONENT_REMOVED:
                
listener.componentRemoved(e);
                
break;
            
}
        
}
    
}

    
/*
     
* Dispatches an event to this component or one of its sub components.
     
* Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to
     
* COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this
     
* here instead of in processComponentEvent because ComponentEvents
     
* may not be enabled for this Container.
     
* @param e the event
     
*/

    
void dispatchEventImpl(AWTEvent e) {
        
if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
            
// event was sent to a lightweight component.
  
The
            
// native-produced event sent to the native container
            
// must be properly disposed of by the peer, so it
            
// gets forwarded.
  
If the native host has been removed
            
// as a result of the sending the lightweight event,
            
// the peer reference will be null.
            
e.consume();
            
if (peer != null) {
                
peer.handleEvent(e);
            
}
            
return;
        
}

        
super.dispatchEventImpl(e);

        
synchronized (getTreeLock()) {
            
switch (e.getID()) {
              
case ComponentEvent.COMPONENT_RESIZED:
                
createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0,
                                           
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
                
break;
              
case ComponentEvent.COMPONENT_MOVED:
                
createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0,
                                       
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
                
break;
              
default:
                
break;
            
}
        
}
    
}

    
/*
     
* Dispatches an event to this component, without trying to forward
     
* it to any subcomponents
     
* @param e the event
     
*/

    
void dispatchEventToSelf(AWTEvent e) {
        
super.dispatchEventImpl(e);
    
}

    
/**
     
* Fetchs the top-most (deepest) lightweight component that is interested
     
* in receiving mouse events.
     
*/

    
Component getMouseEventTarget(int x, int y, boolean includeSelf) {
        
return getMouseEventTarget(x, y, includeSelf,
                                   
MouseEventTargetFilter.FILTER,
                                   
!SEARCH_HEAVYWEIGHTS);
    
}

    
/**
     
* Fetches the top-most (deepest) component to receive SunDropTargetEvents.
     
*/

    
Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {
        
return getMouseEventTarget(x, y, includeSelf,
                                   
DropTargetEventTargetFilter.FILTER,
                                   
SEARCH_HEAVYWEIGHTS);
    
}

    
/**
     
* A private version of getMouseEventTarget which has two additional
     
* controllable behaviors. This method searches for the top-most
     
* descendant of this container that contains the given coordinates
     
* and is accepted by the given filter. The search will be constrained to
     
* lightweight descendants if the last argument is <code>false</code>.
     
*
     
* @param filter EventTargetFilter instance to determine whether the
     
*
        
given component is a valid target for this event.
     
* @param searchHeavyweights if <code>false</code>, the method
     
*
        
will bypass heavyweight components during the search.
     
*/

    
private Component getMouseEventTarget(int x, int y, boolean includeSelf,
                                          
EventTargetFilter filter,
                                          
boolean searchHeavyweights) {
        
Component comp = null;
        
if (searchHeavyweights) {
            
comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
                                           
SEARCH_HEAVYWEIGHTS,
                                           
searchHeavyweights);
        
}

        
if (comp == null || comp == this) {
            
comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
                                           
!SEARCH_HEAVYWEIGHTS,
                                           
searchHeavyweights);
        
}

        
return comp;
    
}

    
/**
     
* A private version of getMouseEventTarget which has three additional
     
* controllable behaviors. This method searches for the top-most
     
* descendant of this container that contains the given coordinates
     
* and is accepted by the given filter. The search will be constrained to
     
* descendants of only lightweight children or only heavyweight children
     
* of this container depending on searchHeavyweightChildren. The search will
     
* be constrained to only lightweight descendants of the searched children
     
* of this container if searchHeavyweightDescendants is <code>false</code>.
     
*
     
* @param filter EventTargetFilter instance to determine whether the
     
*
        
selected component is a valid target for this event.
     
* @param searchHeavyweightChildren if <code>true</code>, the method
     
*
        
will bypass immediate lightweight children during the search.
     
*
        
If <code>false</code>, the methods will bypass immediate
     
*
        
heavyweight children during the search.
     
* @param searchHeavyweightDescendants if <code>false</code>, the method
     
*
        
will bypass heavyweight descendants which are not immediate
     
*
        
children during the search. If <code>true</code>, the method
     
*
        
will traverse both lightweight and heavyweight descendants during
     
*
        
the search.
     
*/

    
private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,
                                         
EventTargetFilter filter,
                                         
boolean searchHeavyweightChildren,
                                         
boolean searchHeavyweightDescendants) {
        
synchronized (getTreeLock()) {

            
for (int i = 0; i < component.size(); i++) {
                
Component comp = component.get(i);
                
if (comp != null && comp.visible &&
                    
((!searchHeavyweightChildren &&
                      
comp.peer instanceof LightweightPeer) ||
                     
(searchHeavyweightChildren &&
                      
!(comp.peer instanceof LightweightPeer))) &&
                    
comp.contains(x - comp.x, y - comp.y)) {

                    
// found a component that intersects the point, see if there
                    
// is a deeper possibility.
                    
if (comp instanceof Container) {
                        
Container child = (Container) comp;
                        
Component deeper = child.getMouseEventTarget(
                                
x - child.x,
                                
y - child.y,
                                
includeSelf,
                                
filter,
                                
searchHeavyweightDescendants);
                        
if (deeper != null) {
                            
return deeper;
                        
}
                    
} else {
                        
if (filter.accept(comp)) {
                            
// there isn't a deeper target, but this component
                            
// is a target
                            
return comp;
                        
}
                    
}
                
}
            
}

            
boolean isPeerOK;
            
boolean isMouseOverMe;

            
isPeerOK = (peer instanceof LightweightPeer) || includeSelf;
            
isMouseOverMe = contains(x,y);

            
// didn't find a child target, return this component if it's
            
// a possible target
            
if (isMouseOverMe && isPeerOK && filter.accept(this)) {
                
return this;
            
}
            
// no possible target
            
return null;
        
}
    
}

    
static interface EventTargetFilter {
        
boolean accept(final Component comp);
    
}

    
static class MouseEventTargetFilter implements EventTargetFilter {
        
static final EventTargetFilter FILTER = new MouseEventTargetFilter();

        
private MouseEventTargetFilter() {}

        
public boolean accept(final Component comp) {
            
return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
                
|| (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
                
|| (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0
                
|| comp.mouseListener != null
                
|| comp.mouseMotionListener != null
                
|| comp.mouseWheelListener != null;
        
}
    
}

    
static class DropTargetEventTargetFilter implements EventTargetFilter {
        
static final EventTargetFilter FILTER = new DropTargetEventTargetFilter();

        
private DropTargetEventTargetFilter() {}

        
public boolean accept(final Component comp) {
            
DropTarget dt = comp.getDropTarget();