Save This Page
Home » openjdk-7 » java » awt » [javadoc | source]
    1   /*
    2    * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   package java.awt;
   26   
   27   import java.awt.dnd.DropTarget;
   28   
   29   import java.awt.event;
   30   
   31   import java.awt.peer.ContainerPeer;
   32   import java.awt.peer.ComponentPeer;
   33   import java.awt.peer.LightweightPeer;
   34   
   35   import java.beans.PropertyChangeListener;
   36   
   37   import java.io.IOException;
   38   import java.io.ObjectInputStream;
   39   import java.io.ObjectOutputStream;
   40   import java.io.ObjectStreamField;
   41   import java.io.PrintStream;
   42   import java.io.PrintWriter;
   43   
   44   import java.security.AccessController;
   45   
   46   import java.util.Arrays;
   47   import java.util.EventListener;
   48   import java.util.HashSet;
   49   import java.util.Set;
   50   
   51   import javax.accessibility;
   52   
   53   import sun.util.logging.PlatformLogger;
   54   
   55   import sun.awt.AppContext;
   56   import sun.awt.AWTAccessor;
   57   import sun.awt.CausedFocusEvent;
   58   import sun.awt.PeerEvent;
   59   import sun.awt.SunToolkit;
   60   
   61   import sun.awt.dnd.SunDropTargetEvent;
   62   
   63   import sun.java2d.pipe.Region;
   64   
   65   import sun.security.action.GetBooleanAction;
   66   
   67   /**
   68    * A generic Abstract Window Toolkit(AWT) container object is a component
   69    * that can contain other AWT components.
   70    * <p>
   71    * Components added to a container are tracked in a list.  The order
   72    * of the list will define the components' front-to-back stacking order
   73    * within the container.  If no index is specified when adding a
   74    * component to a container, it will be added to the end of the list
   75    * (and hence to the bottom of the stacking order).
   76    * <p>
   77    * <b>Note</b>: For details on the focus subsystem, see
   78    * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
   79    * How to Use the Focus Subsystem</a>,
   80    * a section in <em>The Java Tutorial</em>, and the
   81    * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
   82    * for more information.
   83    *
   84    * @author      Arthur van Hoff
   85    * @author      Sami Shaio
   86    * @see       #add(java.awt.Component, int)
   87    * @see       #getComponent(int)
   88    * @see       LayoutManager
   89    * @since     JDK1.0
   90    */
   91   public class Container extends Component {
   92   
   93       private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Container");
   94       private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Container");
   95   
   96       private static final Component[] EMPTY_ARRAY = new Component[0];
   97   
   98       /**
   99        * The components in this container.
  100        * @see #add
  101        * @see #getComponents
  102        */
  103       private java.util.List<Component> component = new java.util.ArrayList<Component>();
  104   
  105       /**
  106        * Layout manager for this container.
  107        * @see #doLayout
  108        * @see #setLayout
  109        * @see #getLayout
  110        */
  111       LayoutManager layoutMgr;
  112   
  113       /**
  114        * Event router for lightweight components.  If this container
  115        * is native, this dispatcher takes care of forwarding and
  116        * retargeting the events to lightweight components contained
  117        * (if any).
  118        */
  119       private LightweightDispatcher dispatcher;
  120   
  121       /**
  122        * The focus traversal policy that will manage keyboard traversal of this
  123        * Container's children, if this Container is a focus cycle root. If the
  124        * value is null, this Container inherits its policy from its focus-cycle-
  125        * root ancestor. If all such ancestors of this Container have null
  126        * policies, then the current KeyboardFocusManager's default policy is
  127        * used. If the value is non-null, this policy will be inherited by all
  128        * focus-cycle-root children that have no keyboard-traversal policy of
  129        * their own (as will, recursively, their focus-cycle-root children).
  130        * <p>
  131        * If this Container is not a focus cycle root, the value will be
  132        * remembered, but will not be used or inherited by this or any other
  133        * Containers until this Container is made a focus cycle root.
  134        *
  135        * @see #setFocusTraversalPolicy
  136        * @see #getFocusTraversalPolicy
  137        * @since 1.4
  138        */
  139       private transient FocusTraversalPolicy focusTraversalPolicy;
  140   
  141       /**
  142        * Indicates whether this Component is the root of a focus traversal cycle.
  143        * Once focus enters a traversal cycle, typically it cannot leave it via
  144        * focus traversal unless one of the up- or down-cycle keys is pressed.
  145        * Normal traversal is limited to this Container, and all of this
  146        * Container's descendants that are not descendants of inferior focus cycle
  147        * roots.
  148        *
  149        * @see #setFocusCycleRoot
  150        * @see #isFocusCycleRoot
  151        * @since 1.4
  152        */
  153       private boolean focusCycleRoot = false;
  154   
  155   
  156       /**
  157        * Stores the value of focusTraversalPolicyProvider property.
  158        * @since 1.5
  159        * @see #setFocusTraversalPolicyProvider
  160        */
  161       private boolean focusTraversalPolicyProvider;
  162   
  163       // keeps track of the threads that are printing this component
  164       private transient Set printingThreads;
  165       // True if there is at least one thread that's printing this component
  166       private transient boolean printing = false;
  167   
  168       transient ContainerListener containerListener;
  169   
  170       /* HierarchyListener and HierarchyBoundsListener support */
  171       transient int listeningChildren;
  172       transient int listeningBoundsChildren;
  173       transient int descendantsCount;
  174   
  175       /* Non-opaque window support -- see Window.setLayersOpaque */
  176       transient Color preserveBackgroundColor = null;
  177   
  178       /**
  179        * JDK 1.1 serialVersionUID
  180        */
  181       private static final long serialVersionUID = 4613797578919906343L;
  182   
  183       /**
  184        * A constant which toggles one of the controllable behaviors
  185        * of <code>getMouseEventTarget</code>. It is used to specify whether
  186        * the method can return the Container on which it is originally called
  187        * in case if none of its children are the current mouse event targets.
  188        *
  189        * @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
  190        */
  191       static final boolean INCLUDE_SELF = true;
  192   
  193       /**
  194        * A constant which toggles one of the controllable behaviors
  195        * of <code>getMouseEventTarget</code>. It is used to specify whether
  196        * the method should search only lightweight components.
  197        *
  198        * @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
  199        */
  200       static final boolean SEARCH_HEAVYWEIGHTS = true;
  201   
  202       /*
  203        * Number of HW or LW components in this container (including
  204        * all descendant containers).
  205        */
  206       private transient int numOfHWComponents = 0;
  207       private transient int numOfLWComponents = 0;
  208   
  209       private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container");
  210   
  211       /**
  212        * @serialField ncomponents                     int
  213        *       The number of components in this container.
  214        *       This value can be null.
  215        * @serialField component                       Component[]
  216        *       The components in this container.
  217        * @serialField layoutMgr                       LayoutManager
  218        *       Layout manager for this container.
  219        * @serialField dispatcher                      LightweightDispatcher
  220        *       Event router for lightweight components.  If this container
  221        *       is native, this dispatcher takes care of forwarding and
  222        *       retargeting the events to lightweight components contained
  223        *       (if any).
  224        * @serialField maxSize                         Dimension
  225        *       Maximum size of this Container.
  226        * @serialField focusCycleRoot                  boolean
  227        *       Indicates whether this Component is the root of a focus traversal cycle.
  228        *       Once focus enters a traversal cycle, typically it cannot leave it via
  229        *       focus traversal unless one of the up- or down-cycle keys is pressed.
  230        *       Normal traversal is limited to this Container, and all of this
  231        *       Container's descendants that are not descendants of inferior focus cycle
  232        *       roots.
  233        * @serialField containerSerializedDataVersion  int
  234        *       Container Serial Data Version.
  235        * @serialField focusTraversalPolicyProvider    boolean
  236        *       Stores the value of focusTraversalPolicyProvider property.
  237        */
  238       private static final ObjectStreamField[] serialPersistentFields = {
  239           new ObjectStreamField("ncomponents", Integer.TYPE),
  240           new ObjectStreamField("component", Component[].class),
  241           new ObjectStreamField("layoutMgr", LayoutManager.class),
  242           new ObjectStreamField("dispatcher", LightweightDispatcher.class),
  243           new ObjectStreamField("maxSize", Dimension.class),
  244           new ObjectStreamField("focusCycleRoot", Boolean.TYPE),
  245           new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE),
  246           new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE),
  247       };
  248   
  249       static {
  250           /* ensure that the necessary native libraries are loaded */
  251           Toolkit.loadLibraries();
  252           if (!GraphicsEnvironment.isHeadless()) {
  253               initIDs();
  254           }
  255   
  256           AWTAccessor.setContainerAccessor(new AWTAccessor.ContainerAccessor() {
  257               @Override
  258               public void validateUnconditionally(Container cont) {
  259                   cont.validateUnconditionally();
  260               }
  261           });
  262       }
  263   
  264       /**
  265        * Initialize JNI field and method IDs for fields that may be
  266          called from C.
  267        */
  268       private static native void initIDs();
  269   
  270       /**
  271        * Constructs a new Container. Containers can be extended directly,
  272        * but are lightweight in this case and must be contained by a parent
  273        * somewhere higher up in the component tree that is native.
  274        * (such as Frame for example).
  275        */
  276       public Container() {
  277       }
  278   
  279       void initializeFocusTraversalKeys() {
  280           focusTraversalKeys = new Set[4];
  281       }
  282   
  283       /**
  284        * Gets the number of components in this panel.
  285        * <p>
  286        * Note: This method should be called under AWT tree lock.
  287        *
  288        * @return    the number of components in this panel.
  289        * @see       #getComponent
  290        * @since     JDK1.1
  291        * @see Component#getTreeLock()
  292        */
  293       public int getComponentCount() {
  294           return countComponents();
  295       }
  296   
  297       /**
  298        * @deprecated As of JDK version 1.1,
  299        * replaced by getComponentCount().
  300        */
  301       @Deprecated
  302       public int countComponents() {
  303           // This method is not synchronized under AWT tree lock.
  304           // Instead, the calling code is responsible for the
  305           // synchronization. See 6784816 for details.
  306           return component.size();
  307       }
  308   
  309       /**
  310        * Gets the nth component in this container.
  311        * <p>
  312        * Note: This method should be called under AWT tree lock.
  313        *
  314        * @param      n   the index of the component to get.
  315        * @return     the n<sup>th</sup> component in this container.
  316        * @exception  ArrayIndexOutOfBoundsException
  317        *                 if the n<sup>th</sup> value does not exist.
  318        * @see Component#getTreeLock()
  319        */
  320       public Component getComponent(int n) {
  321           // This method is not synchronized under AWT tree lock.
  322           // Instead, the calling code is responsible for the
  323           // synchronization. See 6784816 for details.
  324           try {
  325               return component.get(n);
  326           } catch (IndexOutOfBoundsException z) {
  327               throw new ArrayIndexOutOfBoundsException("No such child: " + n);
  328           }
  329       }
  330   
  331       /**
  332        * Gets all the components in this container.
  333        * <p>
  334        * Note: This method should be called under AWT tree lock.
  335        *
  336        * @return    an array of all the components in this container.
  337        * @see Component#getTreeLock()
  338        */
  339       public Component[] getComponents() {
  340           // This method is not synchronized under AWT tree lock.
  341           // Instead, the calling code is responsible for the
  342           // synchronization. See 6784816 for details.
  343           return getComponents_NoClientCode();
  344       }
  345   
  346       // NOTE: This method may be called by privileged threads.
  347       //       This functionality is implemented in a package-private method
  348       //       to insure that it cannot be overridden by client subclasses.
  349       //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
  350       final Component[] getComponents_NoClientCode() {
  351           return component.toArray(EMPTY_ARRAY);
  352       }
  353   
  354       /*
  355        * Wrapper for getComponents() method with a proper synchronization.
  356        */
  357       Component[] getComponentsSync() {
  358           synchronized (getTreeLock()) {
  359               return getComponents();
  360           }
  361       }
  362   
  363       /**
  364        * Determines the insets of this container, which indicate the size
  365        * of the container's border.
  366        * <p>
  367        * A <code>Frame</code> object, for example, has a top inset that
  368        * corresponds to the height of the frame's title bar.
  369        * @return    the insets of this container.
  370        * @see       Insets
  371        * @see       LayoutManager
  372        * @since     JDK1.1
  373        */
  374       public Insets getInsets() {
  375           return insets();
  376       }
  377   
  378       /**
  379        * @deprecated As of JDK version 1.1,
  380        * replaced by <code>getInsets()</code>.
  381        */
  382       @Deprecated
  383       public Insets insets() {
  384           ComponentPeer peer = this.peer;
  385           if (peer instanceof ContainerPeer) {
  386               ContainerPeer cpeer = (ContainerPeer)peer;
  387               return (Insets)cpeer.getInsets().clone();
  388           }
  389           return new Insets(0, 0, 0, 0);
  390       }
  391   
  392       /**
  393        * Appends the specified component to the end of this container.
  394        * This is a convenience method for {@link #addImpl}.
  395        * <p>
  396        * This method changes layout-related information, and therefore,
  397        * invalidates the component hierarchy. If the container has already been
  398        * displayed, the hierarchy must be validated thereafter in order to
  399        * display the added component.
  400        *
  401        * @param     comp   the component to be added
  402        * @exception NullPointerException if {@code comp} is {@code null}
  403        * @see #addImpl
  404        * @see #invalidate
  405        * @see #validate
  406        * @see javax.swing.JComponent#revalidate()
  407        * @return    the component argument
  408        */
  409       public Component add(Component comp) {
  410           addImpl(comp, null, -1);
  411           return comp;
  412       }
  413   
  414       /**
  415        * Adds the specified component to this container.
  416        * This is a convenience method for {@link #addImpl}.
  417        * <p>
  418        * This method is obsolete as of 1.1.  Please use the
  419        * method <code>add(Component, Object)</code> instead.
  420        * <p>
  421        * This method changes layout-related information, and therefore,
  422        * invalidates the component hierarchy. If the container has already been
  423        * displayed, the hierarchy must be validated thereafter in order to
  424        * display the added component.
  425        *
  426        * @exception NullPointerException if {@code comp} is {@code null}
  427        * @see #add(Component, Object)
  428        * @see #invalidate
  429        */
  430       public Component add(String name, Component comp) {
  431           addImpl(comp, name, -1);
  432           return comp;
  433       }
  434   
  435       /**
  436        * Adds the specified component to this container at the given
  437        * position.
  438        * This is a convenience method for {@link #addImpl}.
  439        * <p>
  440        * This method changes layout-related information, and therefore,
  441        * invalidates the component hierarchy. If the container has already been
  442        * displayed, the hierarchy must be validated thereafter in order to
  443        * display the added component.
  444        *
  445        *
  446        * @param     comp   the component to be added
  447        * @param     index    the position at which to insert the component,
  448        *                   or <code>-1</code> to append the component to the end
  449        * @exception NullPointerException if {@code comp} is {@code null}
  450        * @exception IllegalArgumentException if {@code index} is invalid (see
  451        *            {@link #addImpl} for details)
  452        * @return    the component <code>comp</code>
  453        * @see #addImpl
  454        * @see #remove
  455        * @see #invalidate
  456        * @see #validate
  457        * @see javax.swing.JComponent#revalidate()
  458        */
  459       public Component add(Component comp, int index) {
  460           addImpl(comp, null, index);
  461           return comp;
  462       }
  463   
  464       /**
  465        * Checks that the component
  466        * isn't supposed to be added into itself.
  467        */
  468       private void checkAddToSelf(Component comp){
  469           if (comp instanceof Container) {
  470               for (Container cn = this; cn != null; cn=cn.parent) {
  471                   if (cn == comp) {
  472                       throw new IllegalArgumentException("adding container's parent to itself");
  473                   }
  474               }
  475           }
  476       }
  477   
  478       /**
  479        * Checks that the component is not a Window instance.
  480        */
  481       private void checkNotAWindow(Component comp){
  482           if (comp instanceof Window) {
  483               throw new IllegalArgumentException("adding a window to a container");
  484           }
  485       }
  486   
  487       /**
  488        * Checks that the component comp can be added to this container
  489        * Checks :  index in bounds of container's size,
  490        * comp is not one of this container's parents,
  491        * and comp is not a window.
  492        * Comp and container must be on the same GraphicsDevice.
  493        * if comp is container, all sub-components must be on
  494        * same GraphicsDevice.
  495        *
  496        * @since 1.5
  497        */
  498       private void checkAdding(Component comp, int index) {
  499           checkTreeLock();
  500   
  501           GraphicsConfiguration thisGC = getGraphicsConfiguration();
  502   
  503           if (index > component.size() || index < 0) {
  504               throw new IllegalArgumentException("illegal component position");
  505           }
  506           if (comp.parent == this) {
  507               if (index == component.size()) {
  508                   throw new IllegalArgumentException("illegal component position " +
  509                                                      index + " should be less then " + component.size());
  510               }
  511           }
  512           checkAddToSelf(comp);
  513           checkNotAWindow(comp);
  514   
  515           Window thisTopLevel = getContainingWindow();
  516           Window compTopLevel = comp.getContainingWindow();
  517           if (thisTopLevel != compTopLevel) {
  518               throw new IllegalArgumentException("component and container should be in the same top-level window");
  519           }
  520           if (thisGC != null) {
  521               comp.checkGD(thisGC.getDevice().getIDstring());
  522           }
  523       }
  524   
  525       /**
  526        * Removes component comp from this container without making unneccessary changes
  527        * and generating unneccessary events. This function intended to perform optimized
  528        * remove, for example, if newParent and current parent are the same it just changes
  529        * index without calling removeNotify.
  530        * Note: Should be called while holding treeLock
  531        * Returns whether removeNotify was invoked
  532        * @since: 1.5
  533        */
  534       private boolean removeDelicately(Component comp, Container newParent, int newIndex) {
  535           checkTreeLock();
  536   
  537           int index = getComponentZOrder(comp);
  538           boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent);
  539           if (needRemoveNotify) {
  540               comp.removeNotify();
  541           }
  542           if (newParent != this) {
  543               if (layoutMgr != null) {
  544                   layoutMgr.removeLayoutComponent(comp);
  545               }
  546               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  547                                       -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  548               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  549                                       -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  550               adjustDescendants(-(comp.countHierarchyMembers()));
  551   
  552               comp.parent = null;
  553               if (needRemoveNotify) {
  554                   comp.setGraphicsConfiguration(null);
  555               }
  556               component.remove(index);
  557   
  558               invalidateIfValid();
  559           } else {
  560               // We should remove component and then
  561               // add it by the newIndex without newIndex decrement if even we shift components to the left
  562               // after remove. Consult the rules below:
  563               // 2->4: 012345 -> 013425, 2->5: 012345 -> 013452
  564               // 4->2: 012345 -> 014235
  565               component.remove(index);
  566               component.add(newIndex, comp);
  567           }
  568           if (comp.parent == null) { // was actually removed
  569               if (containerListener != null ||
  570                   (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  571                   Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
  572                   ContainerEvent e = new ContainerEvent(this,
  573                                                         ContainerEvent.COMPONENT_REMOVED,
  574                                                         comp);
  575                   dispatchEvent(e);
  576   
  577               }
  578               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  579                                          this, HierarchyEvent.PARENT_CHANGED,
  580                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  581               if (peer != null && layoutMgr == null && isVisible()) {
  582                   updateCursorImmediately();
  583               }
  584           }
  585           return needRemoveNotify;
  586       }
  587   
  588       /**
  589        * Checks whether this container can contain component which is focus owner.
  590        * Verifies that container is enable and showing, and if it is focus cycle root
  591        * its FTP allows component to be focus owner
  592        * @since 1.5
  593        */
  594       boolean canContainFocusOwner(Component focusOwnerCandidate) {
  595           if (!(isEnabled() && isDisplayable()
  596                 && isVisible() && isFocusable()))
  597           {
  598               return false;
  599           }
  600           if (isFocusCycleRoot()) {
  601               FocusTraversalPolicy policy = getFocusTraversalPolicy();
  602               if (policy instanceof DefaultFocusTraversalPolicy) {
  603                   if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) {
  604                       return false;
  605                   }
  606               }
  607           }
  608           synchronized(getTreeLock()) {
  609               if (parent != null) {
  610                   return parent.canContainFocusOwner(focusOwnerCandidate);
  611               }
  612           }
  613           return true;
  614       }
  615   
  616       /**
  617        * Checks whether or not this container has heavyweight children.
  618        * Note: Should be called while holding tree lock
  619        * @return true if there is at least one heavyweight children in a container, false otherwise
  620        * @since 1.5
  621        */
  622       final boolean hasHeavyweightDescendants() {
  623           checkTreeLock();
  624           return numOfHWComponents > 0;
  625       }
  626   
  627       /**
  628        * Checks whether or not this container has lightweight children.
  629        * Note: Should be called while holding tree lock
  630        * @return true if there is at least one lightweight children in a container, false otherwise
  631        * @since 1.7
  632        */
  633       final boolean hasLightweightDescendants() {
  634           checkTreeLock();
  635           return numOfLWComponents > 0;
  636       }
  637   
  638       /**
  639        * Returns closest heavyweight component to this container. If this container is heavyweight
  640        * returns this.
  641        * @since 1.5
  642        */
  643       Container getHeavyweightContainer() {
  644           checkTreeLock();
  645           if (peer != null && !(peer instanceof LightweightPeer)) {
  646               return this;
  647           } else {
  648               return getNativeContainer();
  649           }
  650       }
  651   
  652       /**
  653        * Detects whether or not remove from current parent and adding to new parent requires call of
  654        * removeNotify on the component. Since removeNotify destroys native window this might (not)
  655        * be required. For example, if new container and old containers are the same we don't need to
  656        * destroy native window.
  657        * @since: 1.5
  658        */
  659       private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) {
  660           if (oldContainer == null) { // Component didn't have parent - no removeNotify
  661               return false;
  662           }
  663           if (comp.peer == null) { // Component didn't have peer - no removeNotify
  664               return false;
  665           }
  666           if (newContainer.peer == null) {
  667               // Component has peer but new Container doesn't - call removeNotify
  668               return true;
  669           }
  670   
  671           // If component is lightweight non-Container or lightweight Container with all but heavyweight
  672           // children there is no need to call remove notify
  673           if (comp.isLightweight()) {
  674               boolean isContainer = comp instanceof Container;
  675   
  676               if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) {
  677                   return false;
  678               }
  679           }
  680   
  681           // If this point is reached, then the comp is either a HW or a LW container with HW descendants.
  682   
  683           // All three components have peers, check for peer change
  684           Container newNativeContainer = oldContainer.getHeavyweightContainer();
  685           Container oldNativeContainer = newContainer.getHeavyweightContainer();
  686           if (newNativeContainer != oldNativeContainer) {
  687               // Native containers change - check whether or not current platform supports
  688               // changing of widget hierarchy on native level without recreation.
  689               // The current implementation forbids reparenting of LW containers with HW descendants
  690               // into another native container w/o destroying the peers. Actually such an operation
  691               // is quite rare. If we ever need to save the peers, we'll have to slightly change the
  692               // addDelicately() method in order to handle such LW containers recursively, reparenting
  693               // each HW descendant independently.
  694               return !comp.peer.isReparentSupported();
  695           } else {
  696               return false;
  697           }
  698       }
  699   
  700       /**
  701        * Moves the specified component to the specified z-order index in
  702        * the container. The z-order determines the order that components
  703        * are painted; the component with the highest z-order paints first
  704        * and the component with the lowest z-order paints last.
  705        * Where components overlap, the component with the lower
  706        * z-order paints over the component with the higher z-order.
  707        * <p>
  708        * If the component is a child of some other container, it is
  709        * removed from that container before being added to this container.
  710        * The important difference between this method and
  711        * <code>java.awt.Container.add(Component, int)</code> is that this method
  712        * doesn't call <code>removeNotify</code> on the component while
  713        * removing it from its previous container unless necessary and when
  714        * allowed by the underlying native windowing system. This way, if the
  715        * component has the keyboard focus, it maintains the focus when
  716        * moved to the new position.
  717        * <p>
  718        * This property is guaranteed to apply only to lightweight
  719        * non-<code>Container</code> components.
  720        * <p>
  721        * This method changes layout-related information, and therefore,
  722        * invalidates the component hierarchy.
  723        * <p>
  724        * <b>Note</b>: Not all platforms support changing the z-order of
  725        * heavyweight components from one container into another without
  726        * the call to <code>removeNotify</code>. There is no way to detect
  727        * whether a platform supports this, so developers shouldn't make
  728        * any assumptions.
  729        *
  730        * @param     comp the component to be moved
  731        * @param     index the position in the container's list to
  732        *            insert the component, where <code>getComponentCount()</code>
  733        *            appends to the end
  734        * @exception NullPointerException if <code>comp</code> is
  735        *            <code>null</code>
  736        * @exception IllegalArgumentException if <code>comp</code> is one of the
  737        *            container's parents
  738        * @exception IllegalArgumentException if <code>index</code> is not in
  739        *            the range <code>[0, getComponentCount()]</code> for moving
  740        *            between containers, or not in the range
  741        *            <code>[0, getComponentCount()-1]</code> for moving inside
  742        *            a container
  743        * @exception IllegalArgumentException if adding a container to itself
  744        * @exception IllegalArgumentException if adding a <code>Window</code>
  745        *            to a container
  746        * @see #getComponentZOrder(java.awt.Component)
  747        * @see #invalidate
  748        * @since 1.5
  749        */
  750       public void setComponentZOrder(Component comp, int index) {
  751            synchronized (getTreeLock()) {
  752                // Store parent because remove will clear it
  753                Container curParent = comp.parent;
  754                int oldZindex = getComponentZOrder(comp);
  755   
  756                if (curParent == this && index == oldZindex) {
  757                    return;
  758                }
  759                checkAdding(comp, index);
  760   
  761                boolean peerRecreated = (curParent != null) ?
  762                    curParent.removeDelicately(comp, this, index) : false;
  763   
  764                addDelicately(comp, curParent, index);
  765   
  766                // If the oldZindex == -1, the component gets inserted,
  767                // rather than it changes its z-order.
  768                if (!peerRecreated && oldZindex != -1) {
  769                    // The new 'index' cannot be == -1.
  770                    // It gets checked at the checkAdding() method.
  771                    // Therefore both oldZIndex and index denote
  772                    // some existing positions at this point and
  773                    // this is actually a Z-order changing.
  774                    comp.mixOnZOrderChanging(oldZindex, index);
  775                }
  776            }
  777       }
  778   
  779       /**
  780        * Traverses the tree of components and reparents children heavyweight component
  781        * to new heavyweight parent.
  782        * @since 1.5
  783        */
  784       private void reparentTraverse(ContainerPeer parentPeer, Container child) {
  785           checkTreeLock();
  786   
  787           for (int i = 0; i < child.getComponentCount(); i++) {
  788               Component comp = child.getComponent(i);
  789               if (comp.isLightweight()) {
  790                   // If components is lightweight check if it is container
  791                   // If it is container it might contain heavyweight children we need to reparent
  792                   if (comp instanceof Container) {
  793                       reparentTraverse(parentPeer, (Container)comp);
  794                   }
  795               } else {
  796                   // Q: Need to update NativeInLightFixer?
  797                   comp.getPeer().reparent(parentPeer);
  798               }
  799           }
  800       }
  801   
  802       /**
  803        * Reparents child component peer to this container peer.
  804        * Container must be heavyweight.
  805        * @since 1.5
  806        */
  807       private void reparentChild(Component comp) {
  808           checkTreeLock();
  809           if (comp == null) {
  810               return;
  811           }
  812           if (comp.isLightweight()) {
  813               // If component is lightweight container we need to reparent all its explicit  heavyweight children
  814               if (comp instanceof Container) {
  815                   // Traverse component's tree till depth-first until encountering heavyweight component
  816                   reparentTraverse((ContainerPeer)getPeer(), (Container)comp);
  817               }
  818           } else {
  819               comp.getPeer().reparent((ContainerPeer)getPeer());
  820           }
  821       }
  822   
  823       /**
  824        * Adds component to this container. Tries to minimize side effects of this adding -
  825        * doesn't call remove notify if it is not required.
  826        * @since 1.5
  827        */
  828       private void addDelicately(Component comp, Container curParent, int index) {
  829           checkTreeLock();
  830   
  831           // Check if moving between containers
  832           if (curParent != this) {
  833               //index == -1 means add to the end.
  834               if (index == -1) {
  835                   component.add(comp);
  836               } else {
  837                   component.add(index, comp);
  838               }
  839               comp.parent = this;
  840               comp.setGraphicsConfiguration(getGraphicsConfiguration());
  841   
  842               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
  843                                       comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
  844               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
  845                                       comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
  846               adjustDescendants(comp.countHierarchyMembers());
  847           } else {
  848               if (index < component.size()) {
  849                   component.set(index, comp);
  850               }
  851           }
  852   
  853           invalidateIfValid();
  854           if (peer != null) {
  855               if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one
  856                   comp.addNotify();
  857               } else { // Both container and child have peers, it means child peer should be reparented.
  858                   // In both cases we need to reparent native widgets.
  859                   Container newNativeContainer = getHeavyweightContainer();
  860                   Container oldNativeContainer = curParent.getHeavyweightContainer();
  861                   if (oldNativeContainer != newNativeContainer) {
  862                       // Native container changed - need to reparent native widgets
  863                       newNativeContainer.reparentChild(comp);
  864                   }
  865                   comp.updateZOrder();
  866   
  867                   if (!comp.isLightweight() && isLightweight()) {
  868                       // If component is heavyweight and one of the containers is lightweight
  869                       // the location of the component should be fixed.
  870                       comp.relocateComponent();
  871                   }
  872               }
  873           }
  874           if (curParent != this) {
  875               /* Notify the layout manager of the added component. */
  876               if (layoutMgr != null) {
  877                   if (layoutMgr instanceof LayoutManager2) {
  878                       ((LayoutManager2)layoutMgr).addLayoutComponent(comp, null);
  879                   } else {
  880                       layoutMgr.addLayoutComponent(null, comp);
  881                   }
  882               }
  883               if (containerListener != null ||
  884                   (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
  885                   Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
  886                   ContainerEvent e = new ContainerEvent(this,
  887                                                         ContainerEvent.COMPONENT_ADDED,
  888                                                         comp);
  889                   dispatchEvent(e);
  890               }
  891               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  892                                          this, HierarchyEvent.PARENT_CHANGED,
  893                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  894   
  895               // If component is focus owner or parent container of focus owner check that after reparenting
  896               // focus owner moved out if new container prohibit this kind of focus owner.
  897               if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) {
  898                   comp.transferFocus();
  899               } else if (comp instanceof Container) {
  900                   Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
  901                   if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) {
  902                       focusOwner.transferFocus();
  903                   }
  904               }
  905           } else {
  906               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
  907                                          this, HierarchyEvent.HIERARCHY_CHANGED,
  908                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
  909           }
  910   
  911           if (peer != null && layoutMgr == null && isVisible()) {
  912               updateCursorImmediately();
  913           }
  914       }
  915   
  916       /**
  917        * Returns the z-order index of the component inside the container.
  918        * The higher a component is in the z-order hierarchy, the lower
  919        * its index.  The component with the lowest z-order index is
  920        * painted last, above all other child components.
  921        *
  922        * @param comp the component being queried
  923        * @return  the z-order index of the component; otherwise
  924        *          returns -1 if the component is <code>null</code>
  925        *          or doesn't belong to the container
  926        * @see #setComponentZOrder(java.awt.Component, int)
  927        * @since 1.5
  928        */
  929       public int getComponentZOrder(Component comp) {
  930           if (comp == null) {
  931               return -1;
  932           }
  933           synchronized(getTreeLock()) {
  934               // Quick check - container should be immediate parent of the component
  935               if (comp.parent != this) {
  936                   return -1;
  937               }
  938               return component.indexOf(comp);
  939           }
  940       }
  941   
  942       /**
  943        * Adds the specified component to the end of this container.
  944        * Also notifies the layout manager to add the component to
  945        * this container's layout using the specified constraints object.
  946        * This is a convenience method for {@link #addImpl}.
  947        * <p>
  948        * This method changes layout-related information, and therefore,
  949        * invalidates the component hierarchy. If the container has already been
  950        * displayed, the hierarchy must be validated thereafter in order to
  951        * display the added component.
  952        *
  953        *
  954        * @param     comp the component to be added
  955        * @param     constraints an object expressing
  956        *                  layout contraints for this component
  957        * @exception NullPointerException if {@code comp} is {@code null}
  958        * @see #addImpl
  959        * @see #invalidate
  960        * @see #validate
  961        * @see javax.swing.JComponent#revalidate()
  962        * @see       LayoutManager
  963        * @since     JDK1.1
  964        */
  965       public void add(Component comp, Object constraints) {
  966           addImpl(comp, constraints, -1);
  967       }
  968   
  969       /**
  970        * Adds the specified component to this container with the specified
  971        * constraints at the specified index.  Also notifies the layout
  972        * manager to add the component to the this container's layout using
  973        * the specified constraints object.
  974        * This is a convenience method for {@link #addImpl}.
  975        * <p>
  976        * This method changes layout-related information, and therefore,
  977        * invalidates the component hierarchy. If the container has already been
  978        * displayed, the hierarchy must be validated thereafter in order to
  979        * display the added component.
  980        *
  981        *
  982        * @param comp the component to be added
  983        * @param constraints an object expressing layout contraints for this
  984        * @param index the position in the container's list at which to insert
  985        * the component; <code>-1</code> means insert at the end
  986        * component
  987        * @exception NullPointerException if {@code comp} is {@code null}
  988        * @exception IllegalArgumentException if {@code index} is invalid (see
  989        *            {@link #addImpl} for details)
  990        * @see #addImpl
  991        * @see #invalidate
  992        * @see #validate
  993        * @see javax.swing.JComponent#revalidate()
  994        * @see #remove
  995        * @see LayoutManager
  996        */
  997       public void add(Component comp, Object constraints, int index) {
  998          addImpl(comp, constraints, index);
  999       }
 1000   
 1001       /**
 1002        * Adds the specified component to this container at the specified
 1003        * index. This method also notifies the layout manager to add
 1004        * the component to this container's layout using the specified
 1005        * constraints object via the <code>addLayoutComponent</code>
 1006        * method.
 1007        * <p>
 1008        * The constraints are
 1009        * defined by the particular layout manager being used.  For
 1010        * example, the <code>BorderLayout</code> class defines five
 1011        * constraints: <code>BorderLayout.NORTH</code>,
 1012        * <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>,
 1013        * <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>.
 1014        * <p>
 1015        * The <code>GridBagLayout</code> class requires a
 1016        * <code>GridBagConstraints</code> object.  Failure to pass
 1017        * the correct type of constraints object results in an
 1018        * <code>IllegalArgumentException</code>.
 1019        * <p>
 1020        * If the current layout manager implements {@code LayoutManager2}, then
 1021        * {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on
 1022        * it. If the current layout manager does not implement
 1023        * {@code LayoutManager2}, and constraints is a {@code String}, then
 1024        * {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.
 1025        * <p>
 1026        * If the component is not an ancestor of this container and has a non-null
 1027        * parent, it is removed from its current parent before it is added to this
 1028        * container.
 1029        * <p>
 1030        * This is the method to override if a program needs to track
 1031        * every add request to a container as all other add methods defer
 1032        * to this one. An overriding method should
 1033        * usually include a call to the superclass's version of the method:
 1034        * <p>
 1035        * <blockquote>
 1036        * <code>super.addImpl(comp, constraints, index)</code>
 1037        * </blockquote>
 1038        * <p>
 1039        * This method changes layout-related information, and therefore,
 1040        * invalidates the component hierarchy. If the container has already been
 1041        * displayed, the hierarchy must be validated thereafter in order to
 1042        * display the added component.
 1043        *
 1044        * @param     comp       the component to be added
 1045        * @param     constraints an object expressing layout constraints
 1046        *                 for this component
 1047        * @param     index the position in the container's list at which to
 1048        *                 insert the component, where <code>-1</code>
 1049        *                 means append to the end
 1050        * @exception IllegalArgumentException if {@code index} is invalid;
 1051        *            if {@code comp} is a child of this container, the valid
 1052        *            range is {@code [-1, getComponentCount()-1]}; if component is
 1053        *            not a child of this container, the valid range is
 1054        *            {@code [-1, getComponentCount()]}
 1055        *
 1056        * @exception IllegalArgumentException if {@code comp} is an ancestor of
 1057        *                                     this container
 1058        * @exception IllegalArgumentException if adding a window to a container
 1059        * @exception NullPointerException if {@code comp} is {@code null}
 1060        * @see       #add(Component)
 1061        * @see       #add(Component, int)
 1062        * @see       #add(Component, java.lang.Object)
 1063        * @see #invalidate
 1064        * @see       LayoutManager
 1065        * @see       LayoutManager2
 1066        * @since     JDK1.1
 1067        */
 1068       protected void addImpl(Component comp, Object constraints, int index) {
 1069           synchronized (getTreeLock()) {
 1070               /* Check for correct arguments:  index in bounds,
 1071                * comp cannot be one of this container's parents,
 1072                * and comp cannot be a window.
 1073                * comp and container must be on the same GraphicsDevice.
 1074                * if comp is container, all sub-components must be on
 1075                * same GraphicsDevice.
 1076                */
 1077               GraphicsConfiguration thisGC = this.getGraphicsConfiguration();
 1078   
 1079               if (index > component.size() || (index < 0 && index != -1)) {
 1080                   throw new IllegalArgumentException(
 1081                             "illegal component position");
 1082               }
 1083               checkAddToSelf(comp);
 1084               checkNotAWindow(comp);
 1085               if (thisGC != null) {
 1086                   comp.checkGD(thisGC.getDevice().getIDstring());
 1087               }
 1088   
 1089               /* Reparent the component and tidy up the tree's state. */
 1090               if (comp.parent != null) {
 1091                   comp.parent.remove(comp);
 1092                       if (index > component.size()) {
 1093                           throw new IllegalArgumentException("illegal component position");
 1094                       }
 1095               }
 1096   
 1097               //index == -1 means add to the end.
 1098               if (index == -1) {
 1099                   component.add(comp);
 1100               } else {
 1101                   component.add(index, comp);
 1102               }
 1103               comp.parent = this;
 1104               comp.setGraphicsConfiguration(thisGC);
 1105   
 1106               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 1107                   comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
 1108               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 1109                   comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 1110               adjustDescendants(comp.countHierarchyMembers());
 1111   
 1112               invalidateIfValid();
 1113               if (peer != null) {
 1114                   comp.addNotify();
 1115               }
 1116   
 1117               /* Notify the layout manager of the added component. */
 1118               if (layoutMgr != null) {
 1119                   if (layoutMgr instanceof LayoutManager2) {
 1120                       ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
 1121                   } else if (constraints instanceof String) {
 1122                       layoutMgr.addLayoutComponent((String)constraints, comp);
 1123                   }
 1124               }
 1125               if (containerListener != null ||
 1126                   (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 1127                   Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
 1128                   ContainerEvent e = new ContainerEvent(this,
 1129                                        ContainerEvent.COMPONENT_ADDED,
 1130                                        comp);
 1131                   dispatchEvent(e);
 1132               }
 1133   
 1134               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
 1135                                          this, HierarchyEvent.PARENT_CHANGED,
 1136                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
 1137               if (peer != null && layoutMgr == null && isVisible()) {
 1138                   updateCursorImmediately();
 1139               }
 1140           }
 1141       }
 1142   
 1143       @Override
 1144       boolean updateGraphicsData(GraphicsConfiguration gc) {
 1145           checkTreeLock();
 1146   
 1147           boolean ret = super.updateGraphicsData(gc);
 1148   
 1149           for (Component comp : component) {
 1150               if (comp != null) {
 1151                   ret |= comp.updateGraphicsData(gc);
 1152               }
 1153           }
 1154           return ret;
 1155       }
 1156   
 1157       /**
 1158        * Checks that all Components that this Container contains are on
 1159        * the same GraphicsDevice as this Container.  If not, throws an
 1160        * IllegalArgumentException.
 1161        */
 1162       void checkGD(String stringID) {
 1163           for (Component comp : component) {
 1164               if (comp != null) {
 1165                   comp.checkGD(stringID);
 1166               }
 1167           }
 1168       }
 1169   
 1170       /**
 1171        * Removes the component, specified by <code>index</code>,
 1172        * from this container.
 1173        * This method also notifies the layout manager to remove the
 1174        * component from this container's layout via the
 1175        * <code>removeLayoutComponent</code> method.
 1176        * <p>
 1177        * This method changes layout-related information, and therefore,
 1178        * invalidates the component hierarchy. If the container has already been
 1179        * displayed, the hierarchy must be validated thereafter in order to
 1180        * reflect the changes.
 1181        *
 1182        *
 1183        * @param     index   the index of the component to be removed
 1184        * @throws ArrayIndexOutOfBoundsException if {@code index} is not in
 1185        *         range {@code [0, getComponentCount()-1]}
 1186        * @see #add
 1187        * @see #invalidate
 1188        * @see #validate
 1189        * @see #getComponentCount
 1190        * @since JDK1.1
 1191        */
 1192       public void remove(int index) {
 1193           synchronized (getTreeLock()) {
 1194               if (index < 0  || index >= component.size()) {
 1195                   throw new ArrayIndexOutOfBoundsException(index);
 1196               }
 1197               Component comp = component.get(index);
 1198               if (peer != null) {
 1199                   comp.removeNotify();
 1200               }
 1201               if (layoutMgr != null) {
 1202                   layoutMgr.removeLayoutComponent(comp);
 1203               }
 1204   
 1205               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 1206                   -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
 1207               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 1208                   -comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 1209               adjustDescendants(-(comp.countHierarchyMembers()));
 1210   
 1211               comp.parent = null;
 1212               component.remove(index);
 1213               comp.setGraphicsConfiguration(null);
 1214   
 1215               invalidateIfValid();
 1216               if (containerListener != null ||
 1217                   (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 1218                   Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
 1219                   ContainerEvent e = new ContainerEvent(this,
 1220                                        ContainerEvent.COMPONENT_REMOVED,
 1221                                        comp);
 1222                   dispatchEvent(e);
 1223               }
 1224   
 1225               comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
 1226                                          this, HierarchyEvent.PARENT_CHANGED,
 1227                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
 1228               if (peer != null && layoutMgr == null && isVisible()) {
 1229                   updateCursorImmediately();
 1230               }
 1231           }
 1232       }
 1233   
 1234       /**
 1235        * Removes the specified component from this container.
 1236        * This method also notifies the layout manager to remove the
 1237        * component from this container's layout via the
 1238        * <code>removeLayoutComponent</code> method.
 1239        * <p>
 1240        * This method changes layout-related information, and therefore,
 1241        * invalidates the component hierarchy. If the container has already been
 1242        * displayed, the hierarchy must be validated thereafter in order to
 1243        * reflect the changes.
 1244        *
 1245        * @param comp the component to be removed
 1246        * @throws NullPointerException if {@code comp} is {@code null}
 1247        * @see #add
 1248        * @see #invalidate
 1249        * @see #validate
 1250        * @see #remove(int)
 1251        */
 1252       public void remove(Component comp) {
 1253           synchronized (getTreeLock()) {
 1254               if (comp.parent == this)  {
 1255                   int index = component.indexOf(comp);
 1256                   if (index >= 0) {
 1257                       remove(index);
 1258                   }
 1259               }
 1260           }
 1261       }
 1262   
 1263       /**
 1264        * Removes all the components from this container.
 1265        * This method also notifies the layout manager to remove the
 1266        * components from this container's layout via the
 1267        * <code>removeLayoutComponent</code> method.
 1268        * <p>
 1269        * This method changes layout-related information, and therefore,
 1270        * invalidates the component hierarchy. If the container has already been
 1271        * displayed, the hierarchy must be validated thereafter in order to
 1272        * reflect the changes.
 1273        *
 1274        * @see #add
 1275        * @see #remove
 1276        * @see #invalidate
 1277        */
 1278       public void removeAll() {
 1279           synchronized (getTreeLock()) {
 1280               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 1281                                       -listeningChildren);
 1282               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 1283                                       -listeningBoundsChildren);
 1284               adjustDescendants(-descendantsCount);
 1285   
 1286               while (!component.isEmpty()) {
 1287                   Component comp = component.remove(component.size()-1);
 1288   
 1289                   if (peer != null) {
 1290                       comp.removeNotify();
 1291                   }
 1292                   if (layoutMgr != null) {
 1293                       layoutMgr.removeLayoutComponent(comp);
 1294                   }
 1295                   comp.parent = null;
 1296                   comp.setGraphicsConfiguration(null);
 1297                   if (containerListener != null ||
 1298                      (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 1299                       Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
 1300                       ContainerEvent e = new ContainerEvent(this,
 1301                                        ContainerEvent.COMPONENT_REMOVED,
 1302                                        comp);
 1303                       dispatchEvent(e);
 1304                   }
 1305   
 1306                   comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
 1307                                              comp, this,
 1308                                              HierarchyEvent.PARENT_CHANGED,
 1309                                              Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
 1310               }
 1311               if (peer != null && layoutMgr == null && isVisible()) {
 1312                   updateCursorImmediately();
 1313               }
 1314               invalidateIfValid();
 1315           }
 1316       }
 1317   
 1318       // Should only be called while holding tree lock
 1319       int numListening(long mask) {
 1320           int superListening = super.numListening(mask);
 1321   
 1322           if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {
 1323               if (eventLog.isLoggable(PlatformLogger.FINE)) {
 1324                   // Verify listeningChildren is correct
 1325                   int sum = 0;
 1326                   for (Component comp : component) {
 1327                       sum += comp.numListening(mask);
 1328                   }
 1329                   if (listeningChildren != sum) {
 1330                       eventLog.fine("Assertion (listeningChildren == sum) failed");
 1331                   }
 1332               }
 1333               return listeningChildren + superListening;
 1334           } else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
 1335               if (eventLog.isLoggable(PlatformLogger.FINE)) {
 1336                   // Verify listeningBoundsChildren is correct
 1337                   int sum = 0;
 1338                   for (Component comp : component) {
 1339                       sum += comp.numListening(mask);
 1340                   }
 1341                   if (listeningBoundsChildren != sum) {
 1342                       eventLog.fine("Assertion (listeningBoundsChildren == sum) failed");
 1343                   }
 1344               }
 1345               return listeningBoundsChildren + superListening;
 1346           } else {
 1347               // assert false;
 1348               if (eventLog.isLoggable(PlatformLogger.FINE)) {
 1349                   eventLog.fine("This code must never be reached");
 1350               }
 1351               return superListening;
 1352           }
 1353       }
 1354   
 1355       // Should only be called while holding tree lock
 1356       void adjustListeningChildren(long mask, int num) {
 1357           if (eventLog.isLoggable(PlatformLogger.FINE)) {
 1358               boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK ||
 1359                                   mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||
 1360                                   mask == (AWTEvent.HIERARCHY_EVENT_MASK |
 1361                                            AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 1362               if (!toAssert) {
 1363                   eventLog.fine("Assertion failed");
 1364               }
 1365           }
 1366   
 1367           if (num == 0)
 1368               return;
 1369   
 1370           if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
 1371               listeningChildren += num;
 1372           }
 1373           if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
 1374               listeningBoundsChildren += num;
 1375           }
 1376   
 1377           adjustListeningChildrenOnParent(mask, num);
 1378       }
 1379   
 1380       // Should only be called while holding tree lock
 1381       void adjustDescendants(int num) {
 1382           if (num == 0)
 1383               return;
 1384   
 1385           descendantsCount += num;
 1386           adjustDecendantsOnParent(num);
 1387       }
 1388   
 1389       // Should only be called while holding tree lock
 1390       void adjustDecendantsOnParent(int num) {
 1391           if (parent != null) {
 1392               parent.adjustDescendants(num);
 1393           }
 1394       }
 1395   
 1396       // Should only be called while holding tree lock
 1397       int countHierarchyMembers() {
 1398           if (log.isLoggable(PlatformLogger.FINE)) {
 1399               // Verify descendantsCount is correct
 1400               int sum = 0;
 1401               for (Component comp : component) {
 1402                   sum += comp.countHierarchyMembers();
 1403               }
 1404               if (descendantsCount != sum) {
 1405                   log.fine("Assertion (descendantsCount == sum) failed");
 1406               }
 1407           }
 1408           return descendantsCount + 1;
 1409       }
 1410   
 1411       private int getListenersCount(int id, boolean enabledOnToolkit) {
 1412           checkTreeLock();
 1413           if (enabledOnToolkit) {
 1414               return descendantsCount;
 1415           }
 1416           switch (id) {
 1417             case HierarchyEvent.HIERARCHY_CHANGED:
 1418               return listeningChildren;
 1419             case HierarchyEvent.ANCESTOR_MOVED:
 1420             case HierarchyEvent.ANCESTOR_RESIZED:
 1421               return listeningBoundsChildren;
 1422             default:
 1423               return 0;
 1424           }
 1425       }
 1426   
 1427       final int createHierarchyEvents(int id, Component changed,
 1428           Container changedParent, long changeFlags, boolean enabledOnToolkit)
 1429       {
 1430           checkTreeLock();
 1431           int listeners = getListenersCount(id, enabledOnToolkit);
 1432   
 1433           for (int count = listeners, i = 0; count > 0; i++) {
 1434               count -= component.get(i).createHierarchyEvents(id, changed,
 1435                   changedParent, changeFlags, enabledOnToolkit);
 1436           }
 1437           return listeners +
 1438               super.createHierarchyEvents(id, changed, changedParent,
 1439                                           changeFlags, enabledOnToolkit);
 1440       }
 1441   
 1442       final void createChildHierarchyEvents(int id, long changeFlags,
 1443           boolean enabledOnToolkit)
 1444       {
 1445           checkTreeLock();
 1446           if (component.isEmpty()) {
 1447               return;
 1448           }
 1449           int listeners = getListenersCount(id, enabledOnToolkit);
 1450   
 1451           for (int count = listeners, i = 0; count > 0; i++) {
 1452               count -= component.get(i).createHierarchyEvents(id, this, parent,
 1453                   changeFlags, enabledOnToolkit);
 1454           }
 1455       }
 1456   
 1457       /**
 1458        * Gets the layout manager for this container.
 1459        * @see #doLayout
 1460        * @see #setLayout
 1461        */
 1462       public LayoutManager getLayout() {
 1463           return layoutMgr;
 1464       }
 1465   
 1466       /**
 1467        * Sets the layout manager for this container.
 1468        * <p>
 1469        * This method changes layout-related information, and therefore,
 1470        * invalidates the component hierarchy.
 1471        *
 1472        * @param mgr the specified layout manager
 1473        * @see #doLayout
 1474        * @see #getLayout
 1475        * @see #invalidate
 1476        */
 1477       public void setLayout(LayoutManager mgr) {
 1478           layoutMgr = mgr;
 1479           invalidateIfValid();
 1480       }
 1481   
 1482       /**
 1483        * Causes this container to lay out its components.  Most programs
 1484        * should not call this method directly, but should invoke
 1485        * the <code>validate</code> method instead.
 1486        * @see LayoutManager#layoutContainer
 1487        * @see #setLayout
 1488        * @see #validate
 1489        * @since JDK1.1
 1490        */
 1491       public void doLayout() {
 1492           layout();
 1493       }
 1494   
 1495       /**
 1496        * @deprecated As of JDK version 1.1,
 1497        * replaced by <code>doLayout()</code>.
 1498        */
 1499       @Deprecated
 1500       public void layout() {
 1501           LayoutManager layoutMgr = this.layoutMgr;
 1502           if (layoutMgr != null) {
 1503               layoutMgr.layoutContainer(this);
 1504           }
 1505       }
 1506   
 1507       /**
 1508        * Indicates if this container is a <i>validate root</i>.
 1509        * <p>
 1510        * Layout-related changes, such as bounds of the validate root descendants,
 1511        * do not affect the layout of the validate root parent. This peculiarity
 1512        * enables the {@code invalidate()} method to stop invalidating the
 1513        * component hierarchy when the method encounters a validate root. However,
 1514        * to preserve backward compatibility this new optimized behavior is
 1515        * enabled only when the {@code java.awt.smartInvalidate} system property
 1516        * value is set to {@code true}.
 1517        * <p>
 1518        * If a component hierarchy contains validate roots and the new optimized
 1519        * {@code invalidate()} behavior is enabled, the {@code validate()} method
 1520        * must be invoked on the validate root of a previously invalidated
 1521        * component to restore the validity of the hierarchy later. Otherwise,
 1522        * calling the {@code validate()} method on the top-level container (such
 1523        * as a {@code Frame} object) should be used to restore the validity of the
 1524        * component hierarchy.
 1525        * <p>
 1526        * The {@code Window} class and the {@code Applet} class are the validate
 1527        * roots in AWT.  Swing introduces more validate roots.
 1528        *
 1529        * @return whether this container is a validate root
 1530        * @see #invalidate
 1531        * @see java.awt.Component#invalidate
 1532        * @see javax.swing.JComponent#isValidateRoot
 1533        * @see javax.swing.JComponent#revalidate
 1534        * @since 1.7
 1535        */
 1536       public boolean isValidateRoot() {
 1537           return false;
 1538       }
 1539   
 1540       private static final boolean isJavaAwtSmartInvalidate;
 1541       static {
 1542           // Don't lazy-read because every app uses invalidate()
 1543           isJavaAwtSmartInvalidate = AccessController.doPrivileged(
 1544                   new GetBooleanAction("java.awt.smartInvalidate"));
 1545       }
 1546   
 1547       /**
 1548        * Invalidates the parent of the container unless the container
 1549        * is a validate root.
 1550        */
 1551       @Override
 1552       void invalidateParent() {
 1553           if (!isJavaAwtSmartInvalidate || !isValidateRoot()) {
 1554               super.invalidateParent();
 1555           }
 1556       }
 1557   
 1558       /**
 1559        * Invalidates the container.
 1560        * <p>
 1561        * If the {@code LayoutManager} installed on this container is an instance
 1562        * of the {@code LayoutManager2} interface, then
 1563        * the {@link LayoutManager2#invalidateLayout(Container)} method is invoked
 1564        * on it supplying this {@code Container} as the argument.
 1565        * <p>
 1566        * Afterwards this method marks this container invalid, and invalidates its
 1567        * ancestors. See the {@link Component#invalidate} method for more details.
 1568        *
 1569        * @see #validate
 1570        * @see #layout
 1571        * @see LayoutManager2
 1572        */
 1573       @Override
 1574       public void invalidate() {
 1575           LayoutManager layoutMgr = this.layoutMgr;
 1576           if (layoutMgr instanceof LayoutManager2) {
 1577               LayoutManager2 lm = (LayoutManager2) layoutMgr;
 1578               lm.invalidateLayout(this);
 1579           }
 1580           super.invalidate();
 1581       }
 1582   
 1583       /**
 1584        * Validates this container and all of its subcomponents.
 1585        * <p>
 1586        * Validating a container means laying out its subcomponents.
 1587        * Layout-related changes, such as setting the bounds of a component, or
 1588        * adding a component to the container, invalidate the container
 1589        * automatically.  Note that the ancestors of the container may be
 1590        * invalidated also (see {@link Component#invalidate} for details.)
 1591        * Therefore, to restore the validity of the hierarchy, the {@code
 1592        * validate()} method should be invoked on the top-most invalid
 1593        * container of the hierarchy.
 1594        * <p>
 1595        * Validating the container may be a quite time-consuming operation. For
 1596        * performance reasons a developer may postpone the validation of the
 1597        * hierarchy till a set of layout-related operations completes, e.g. after
 1598        * adding all the children to the container.
 1599        * <p>
 1600        * If this {@code Container} is not valid, this method invokes
 1601        * the {@code validateTree} method and marks this {@code Container}
 1602        * as valid. Otherwise, no action is performed.
 1603        *
 1604        * @see #add(java.awt.Component)
 1605        * @see #invalidate
 1606        * @see Container#isValidateRoot
 1607        * @see javax.swing.JComponent#revalidate()
 1608        * @see #validateTree
 1609        */
 1610       public void validate() {
 1611           boolean updateCur = false;
 1612           synchronized (getTreeLock()) {
 1613               if ((!isValid() || descendUnconditionallyWhenValidating)
 1614                       && peer != null)
 1615               {
 1616                   ContainerPeer p = null;
 1617                   if (peer instanceof ContainerPeer) {
 1618                       p = (ContainerPeer) peer;
 1619                   }
 1620                   if (p != null) {
 1621                       p.beginValidate();
 1622                   }
 1623                   validateTree();
 1624                   if (p != null) {
 1625                       p.endValidate();
 1626                       // Avoid updating cursor if this is an internal call.
 1627                       // See validateUnconditionally() for details.
 1628                       if (!descendUnconditionallyWhenValidating) {
 1629                           updateCur = isVisible();
 1630                       }
 1631                   }
 1632               }
 1633           }
 1634           if (updateCur) {
 1635               updateCursorImmediately();
 1636           }
 1637       }
 1638   
 1639       /**
 1640        * Indicates whether valid containers should also traverse their
 1641        * children and call the validateTree() method on them.
 1642        *
 1643        * Synchronization: TreeLock.
 1644        *
 1645        * The field is allowed to be static as long as the TreeLock itself is
 1646        * static.
 1647        *
 1648        * @see #validateUnconditionally()
 1649        */
 1650       private static boolean descendUnconditionallyWhenValidating = false;
 1651   
 1652       /**
 1653        * Unconditionally validate the component hierarchy.
 1654        */
 1655       final void validateUnconditionally() {
 1656           boolean updateCur = false;
 1657           synchronized (getTreeLock()) {
 1658               descendUnconditionallyWhenValidating = true;
 1659   
 1660               validate();
 1661               if (peer instanceof ContainerPeer) {
 1662                   updateCur = isVisible();
 1663               }
 1664   
 1665               descendUnconditionallyWhenValidating = false;
 1666           }
 1667           if (updateCur) {
 1668               updateCursorImmediately();
 1669           }
 1670       }
 1671   
 1672       /**
 1673        * Recursively descends the container tree and recomputes the
 1674        * layout for any subtrees marked as needing it (those marked as
 1675        * invalid).  Synchronization should be provided by the method
 1676        * that calls this one:  <code>validate</code>.
 1677        *
 1678        * @see #doLayout
 1679        * @see #validate
 1680        */
 1681       protected void validateTree() {
 1682           checkTreeLock();
 1683           if (!isValid() || descendUnconditionallyWhenValidating) {
 1684               if (peer instanceof ContainerPeer) {
 1685                   ((ContainerPeer)peer).beginLayout();
 1686               }
 1687               if (!isValid()) {
 1688                   doLayout();
 1689               }
 1690               for (int i = 0; i < component.size(); i++) {
 1691                   Component comp = component.get(i);
 1692                   if (   (comp instanceof Container)
 1693                          && !(comp instanceof Window)
 1694                          && (!comp.isValid() ||
 1695                              descendUnconditionallyWhenValidating))
 1696                   {
 1697                       ((Container)comp).validateTree();
 1698                   } else {
 1699                       comp.validate();
 1700                   }
 1701               }
 1702               if (peer instanceof ContainerPeer) {
 1703                   ((ContainerPeer)peer).endLayout();
 1704               }
 1705           }
 1706           super.validate();
 1707       }
 1708   
 1709       /**
 1710        * Recursively descends the container tree and invalidates all
 1711        * contained components.
 1712        */
 1713       void invalidateTree() {
 1714           synchronized (getTreeLock()) {
 1715               for (int i = 0; i < component.size(); i++) {
 1716                   Component comp = component.get(i);
 1717                   if (comp instanceof Container) {
 1718                       ((Container)comp).invalidateTree();
 1719                   }
 1720                   else {
 1721                       comp.invalidateIfValid();
 1722                   }
 1723               }
 1724               invalidateIfValid();
 1725           }
 1726       }
 1727   
 1728       /**
 1729        * Sets the font of this container.
 1730        * <p>
 1731        * This method changes layout-related information, and therefore,
 1732        * invalidates the component hierarchy.
 1733        *
 1734        * @param f The font to become this container's font.
 1735        * @see Component#getFont
 1736        * @see #invalidate
 1737        * @since JDK1.0
 1738        */
 1739       public void setFont(Font f) {
 1740           boolean shouldinvalidate = false;
 1741   
 1742           Font oldfont = getFont();
 1743           super.setFont(f);
 1744           Font newfont = getFont();
 1745           if (newfont != oldfont && (oldfont == null ||
 1746                                      !oldfont.equals(newfont))) {
 1747               invalidateTree();
 1748           }
 1749       }
 1750   
 1751       /**
 1752        * Returns the preferred size of this container.  If the preferred size has
 1753        * not been set explicitly by {@link Component#setPreferredSize(Dimension)}
 1754        * and this {@code Container} has a {@code non-null} {@link LayoutManager},
 1755        * then {@link LayoutManager#preferredLayoutSize(Container)}
 1756        * is used to calculate the preferred size.
 1757        *
 1758        * <p>Note: some implementations may cache the value returned from the
 1759        * {@code LayoutManager}.  Implementations that cache need not invoke
 1760        * {@code preferredLayoutSize} on the {@code LayoutManager} every time
 1761        * this method is invoked, rather the {@code LayoutManager} will only
 1762        * be queried after the {@code Container} becomes invalid.
 1763        *
 1764        * @return    an instance of <code>Dimension</code> that represents
 1765        *                the preferred size of this container.
 1766        * @see       #getMinimumSize
 1767        * @see       #getMaximumSize
 1768        * @see       #getLayout
 1769        * @see       LayoutManager#preferredLayoutSize(Container)
 1770        * @see       Component#getPreferredSize
 1771        */
 1772       public Dimension getPreferredSize() {
 1773           return preferredSize();
 1774       }
 1775   
 1776       /**
 1777        * @deprecated As of JDK version 1.1,
 1778        * replaced by <code>getPreferredSize()</code>.
 1779        */
 1780       @Deprecated
 1781       public Dimension preferredSize() {
 1782           /* Avoid grabbing the lock if a reasonable cached size value
 1783            * is available.
 1784            */
 1785           Dimension dim = prefSize;
 1786           if (dim == null || !(isPreferredSizeSet() || isValid())) {
 1787               synchronized (getTreeLock()) {
 1788                   prefSize = (layoutMgr != null) ?
 1789                       layoutMgr.preferredLayoutSize(this) :
 1790                       super.preferredSize();
 1791                   dim = prefSize;
 1792               }
 1793           }
 1794           if (dim != null){
 1795               return new Dimension(dim);
 1796           }
 1797           else{
 1798               return dim;
 1799           }
 1800       }
 1801   
 1802       /**
 1803        * Returns the minimum size of this container.  If the minimum size has
 1804        * not been set explicitly by {@link Component#setMinimumSize(Dimension)}
 1805        * and this {@code Container} has a {@code non-null} {@link LayoutManager},
 1806        * then {@link LayoutManager#minimumLayoutSize(Container)}
 1807        * is used to calculate the minimum size.
 1808        *
 1809        * <p>Note: some implementations may cache the value returned from the
 1810        * {@code LayoutManager}.  Implementations that cache need not invoke
 1811        * {@code minimumLayoutSize} on the {@code LayoutManager} every time
 1812        * this method is invoked, rather the {@code LayoutManager} will only
 1813        * be queried after the {@code Container} becomes invalid.
 1814        *
 1815        * @return    an instance of <code>Dimension</code> that represents
 1816        *                the minimum size of this container.
 1817        * @see       #getPreferredSize
 1818        * @see       #getMaximumSize
 1819        * @see       #getLayout
 1820        * @see       LayoutManager#minimumLayoutSize(Container)
 1821        * @see       Component#getMinimumSize
 1822        * @since     JDK1.1
 1823        */
 1824       public Dimension getMinimumSize() {
 1825           return minimumSize();
 1826       }
 1827   
 1828       /**
 1829        * @deprecated As of JDK version 1.1,
 1830        * replaced by <code>getMinimumSize()</code>.
 1831        */
 1832       @Deprecated
 1833       public Dimension minimumSize() {
 1834           /* Avoid grabbing the lock if a reasonable cached size value
 1835            * is available.
 1836            */
 1837           Dimension dim = minSize;
 1838           if (dim == null || !(isMinimumSizeSet() || isValid())) {
 1839               synchronized (getTreeLock()) {
 1840                   minSize = (layoutMgr != null) ?
 1841                       layoutMgr.minimumLayoutSize(this) :
 1842                       super.minimumSize();
 1843                   dim = minSize;
 1844               }
 1845           }
 1846           if (dim != null){
 1847               return new Dimension(dim);
 1848           }
 1849           else{
 1850               return dim;
 1851           }
 1852       }
 1853   
 1854       /**
 1855        * Returns the maximum size of this container.  If the maximum size has
 1856        * not been set explicitly by {@link Component#setMaximumSize(Dimension)}
 1857        * and the {@link LayoutManager} installed on this {@code Container}
 1858        * is an instance of {@link LayoutManager2}, then
 1859        * {@link LayoutManager2#maximumLayoutSize(Container)}
 1860        * is used to calculate the maximum size.
 1861        *
 1862        * <p>Note: some implementations may cache the value returned from the
 1863        * {@code LayoutManager2}.  Implementations that cache need not invoke
 1864        * {@code maximumLayoutSize} on the {@code LayoutManager2} every time
 1865        * this method is invoked, rather the {@code LayoutManager2} will only
 1866        * be queried after the {@code Container} becomes invalid.
 1867        *
 1868        * @return    an instance of <code>Dimension</code> that represents
 1869        *                the maximum size of this container.
 1870        * @see       #getPreferredSize
 1871        * @see       #getMinimumSize
 1872        * @see       #getLayout
 1873        * @see       LayoutManager2#maximumLayoutSize(Container)
 1874        * @see       Component#getMaximumSize
 1875        */
 1876       public Dimension getMaximumSize() {
 1877           /* Avoid grabbing the lock if a reasonable cached size value
 1878            * is available.
 1879            */
 1880           Dimension dim = maxSize;
 1881           if (dim == null || !(isMaximumSizeSet() || isValid())) {
 1882               synchronized (getTreeLock()) {
 1883                  if (layoutMgr instanceof LayoutManager2) {
 1884                       LayoutManager2 lm = (LayoutManager2) layoutMgr;
 1885                       maxSize = lm.maximumLayoutSize(this);
 1886                  } else {
 1887                       maxSize = super.getMaximumSize();
 1888                  }
 1889                  dim = maxSize;
 1890               }
 1891           }
 1892           if (dim != null){
 1893               return new Dimension(dim);
 1894           }
 1895           else{
 1896               return dim;
 1897           }
 1898       }
 1899   
 1900       /**
 1901        * Returns the alignment along the x axis.  This specifies how
 1902        * the component would like to be aligned relative to other
 1903        * components.  The value should be a number between 0 and 1
 1904        * where 0 represents alignment along the origin, 1 is aligned
 1905        * the furthest away from the origin, 0.5 is centered, etc.
 1906        */
 1907       public float getAlignmentX() {
 1908           float xAlign;
 1909           if (layoutMgr instanceof LayoutManager2) {
 1910               synchronized (getTreeLock()) {
 1911                   LayoutManager2 lm = (LayoutManager2) layoutMgr;
 1912                   xAlign = lm.getLayoutAlignmentX(this);
 1913               }
 1914           } else {
 1915               xAlign = super.getAlignmentX();
 1916           }
 1917           return xAlign;
 1918       }
 1919   
 1920       /**
 1921        * Returns the alignment along the y axis.  This specifies how
 1922        * the component would like to be aligned relative to other
 1923        * components.  The value should be a number between 0 and 1
 1924        * where 0 represents alignment along the origin, 1 is aligned
 1925        * the furthest away from the origin, 0.5 is centered, etc.
 1926        */
 1927       public float getAlignmentY() {
 1928           float yAlign;
 1929           if (layoutMgr instanceof LayoutManager2) {
 1930               synchronized (getTreeLock()) {
 1931                   LayoutManager2 lm = (LayoutManager2) layoutMgr;
 1932                   yAlign = lm.getLayoutAlignmentY(this);
 1933               }
 1934           } else {
 1935               yAlign = super.getAlignmentY();
 1936           }
 1937           return yAlign;
 1938       }
 1939   
 1940       /**
 1941        * Paints the container. This forwards the paint to any lightweight
 1942        * components that are children of this container. If this method is
 1943        * reimplemented, super.paint(g) should be called so that lightweight
 1944        * components are properly rendered. If a child component is entirely
 1945        * clipped by the current clipping setting in g, paint() will not be
 1946        * forwarded to that child.
 1947        *
 1948        * @param g the specified Graphics window
 1949        * @see   Component#update(Graphics)
 1950        */
 1951       public void paint(Graphics g) {
 1952           if (isShowing()) {
 1953               synchronized (this) {
 1954                   if (printing) {
 1955                       if (printingThreads.contains(Thread.currentThread())) {
 1956                           return;
 1957                       }
 1958                   }
 1959               }
 1960   
 1961               // The container is showing on screen and
 1962               // this paint() is not called from print().
 1963               // Paint self and forward the paint to lightweight subcomponents.
 1964   
 1965               // super.paint(); -- Don't bother, since it's a NOP.
 1966   
 1967               GraphicsCallback.PaintCallback.getInstance().
 1968                   runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
 1969           }
 1970       }
 1971   
 1972       /**
 1973        * Updates the container.  This forwards the update to any lightweight
 1974        * components that are children of this container.  If this method is
 1975        * reimplemented, super.update(g) should be called so that lightweight
 1976        * components are properly rendered.  If a child component is entirely
 1977        * clipped by the current clipping setting in g, update() will not be
 1978        * forwarded to that child.
 1979        *
 1980        * @param g the specified Graphics window
 1981        * @see   Component#update(Graphics)
 1982        */
 1983       public void update(Graphics g) {
 1984           if (isShowing()) {
 1985               if (! (peer instanceof LightweightPeer)) {
 1986                   g.clearRect(0, 0, width, height);
 1987               }
 1988               paint(g);
 1989           }
 1990       }
 1991   
 1992       /**
 1993        * Prints the container. This forwards the print to any lightweight
 1994        * components that are children of this container. If this method is
 1995        * reimplemented, super.print(g) should be called so that lightweight
 1996        * components are properly rendered. If a child component is entirely
 1997        * clipped by the current clipping setting in g, print() will not be
 1998        * forwarded to that child.
 1999        *
 2000        * @param g the specified Graphics window
 2001        * @see   Component#update(Graphics)
 2002        */
 2003       public void print(Graphics g) {
 2004           if (isShowing()) {
 2005               Thread t = Thread.currentThread();
 2006               try {
 2007                   synchronized (this) {
 2008                       if (printingThreads == null) {
 2009                           printingThreads = new HashSet();
 2010                       }
 2011                       printingThreads.add(t);
 2012                       printing = true;
 2013                   }
 2014                   super.print(g);  // By default, Component.print() calls paint()
 2015               } finally {
 2016                   synchronized (this) {
 2017                       printingThreads.remove(t);
 2018                       printing = !printingThreads.isEmpty();
 2019                   }
 2020               }
 2021   
 2022               GraphicsCallback.PrintCallback.getInstance().
 2023                   runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
 2024           }
 2025       }
 2026   
 2027       /**
 2028        * Paints each of the components in this container.
 2029        * @param     g   the graphics context.
 2030        * @see       Component#paint
 2031        * @see       Component#paintAll
 2032        */
 2033       public void paintComponents(Graphics g) {
 2034           if (isShowing()) {
 2035               GraphicsCallback.PaintAllCallback.getInstance().
 2036                   runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
 2037           }
 2038       }
 2039   
 2040       /**
 2041        * Simulates the peer callbacks into java.awt for printing of
 2042        * lightweight Containers.
 2043        * @param     g   the graphics context to use for printing.
 2044        * @see       Component#printAll
 2045        * @see       #printComponents
 2046        */
 2047       void lightweightPaint(Graphics g) {
 2048           super.lightweightPaint(g);
 2049           paintHeavyweightComponents(g);
 2050       }
 2051   
 2052       /**
 2053        * Prints all the heavyweight subcomponents.
 2054        */
 2055       void paintHeavyweightComponents(Graphics g) {
 2056           if (isShowing()) {
 2057               GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
 2058                   runComponents(getComponentsSync(), g,
 2059                                 GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
 2060           }
 2061       }
 2062   
 2063       /**
 2064        * Prints each of the components in this container.
 2065        * @param     g   the graphics context.
 2066        * @see       Component#print
 2067        * @see       Component#printAll
 2068        */
 2069       public void printComponents(Graphics g) {
 2070           if (isShowing()) {
 2071               GraphicsCallback.PrintAllCallback.getInstance().
 2072                   runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
 2073           }
 2074       }
 2075   
 2076       /**
 2077        * Simulates the peer callbacks into java.awt for printing of
 2078        * lightweight Containers.
 2079        * @param     g   the graphics context to use for printing.
 2080        * @see       Component#printAll
 2081        * @see       #printComponents
 2082        */
 2083       void lightweightPrint(Graphics g) {
 2084           super.lightweightPrint(g);
 2085           printHeavyweightComponents(g);
 2086       }
 2087   
 2088       /**
 2089        * Prints all the heavyweight subcomponents.
 2090        */
 2091       void printHeavyweightComponents(Graphics g) {
 2092           if (isShowing()) {
 2093               GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
 2094                   runComponents(getComponentsSync(), g,
 2095                                 GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
 2096           }
 2097       }
 2098   
 2099       /**
 2100        * Adds the specified container listener to receive container events
 2101        * from this container.
 2102        * If l is null, no exception is thrown and no action is performed.
 2103        * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 2104        * >AWT Threading Issues</a> for details on AWT's threading model.
 2105        *
 2106        * @param    l the container listener
 2107        *
 2108        * @see #removeContainerListener
 2109        * @see #getContainerListeners
 2110        */
 2111       public synchronized void addContainerListener(ContainerListener l) {
 2112           if (l == null) {
 2113               return;
 2114           }
 2115           containerListener = AWTEventMulticaster.add(containerListener, l);
 2116           newEventsOnly = true;
 2117       }
 2118   
 2119       /**
 2120        * Removes the specified container listener so it no longer receives
 2121        * container events from this container.
 2122        * If l is null, no exception is thrown and no action is performed.
 2123        * <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 2124        * >AWT Threading Issues</a> for details on AWT's threading model.
 2125        *
 2126        * @param   l the container listener
 2127        *
 2128        * @see #addContainerListener
 2129        * @see #getContainerListeners
 2130        */
 2131       public synchronized void removeContainerListener(ContainerListener l) {
 2132           if (l == null) {
 2133               return;
 2134           }
 2135           containerListener = AWTEventMulticaster.remove(containerListener, l);
 2136       }
 2137   
 2138       /**
 2139        * Returns an array of all the container listeners
 2140        * registered on this container.
 2141        *
 2142        * @return all of this container's <code>ContainerListener</code>s
 2143        *         or an empty array if no container
 2144        *         listeners are currently registered
 2145        *
 2146        * @see #addContainerListener
 2147        * @see #removeContainerListener
 2148        * @since 1.4
 2149        */
 2150       public synchronized ContainerListener[] getContainerListeners() {
 2151           return (ContainerListener[]) (getListeners(ContainerListener.class));
 2152       }
 2153   
 2154       /**
 2155        * Returns an array of all the objects currently registered
 2156        * as <code><em>Foo</em>Listener</code>s
 2157        * upon this <code>Container</code>.
 2158        * <code><em>Foo</em>Listener</code>s are registered using the
 2159        * <code>add<em>Foo</em>Listener</code> method.
 2160        *
 2161        * <p>
 2162        * You can specify the <code>listenerType</code> argument
 2163        * with a class literal, such as
 2164        * <code><em>Foo</em>Listener.class</code>.
 2165        * For example, you can query a
 2166        * <code>Container</code> <code>c</code>
 2167        * for its container listeners with the following code:
 2168        *
 2169        * <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>
 2170        *
 2171        * If no such listeners exist, this method returns an empty array.
 2172        *
 2173        * @param listenerType the type of listeners requested; this parameter
 2174        *          should specify an interface that descends from
 2175        *          <code>java.util.EventListener</code>
 2176        * @return an array of all objects registered as
 2177        *          <code><em>Foo</em>Listener</code>s on this container,
 2178        *          or an empty array if no such listeners have been added
 2179        * @exception ClassCastException if <code>listenerType</code>
 2180        *          doesn't specify a class or interface that implements
 2181        *          <code>java.util.EventListener</code>
 2182        * @exception NullPointerException if {@code listenerType} is {@code null}
 2183        *
 2184        * @see #getContainerListeners
 2185        *
 2186        * @since 1.3
 2187        */
 2188       public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
 2189           EventListener l = null;
 2190           if  (listenerType == ContainerListener.class) {
 2191               l = containerListener;
 2192           } else {
 2193               return super.getListeners(listenerType);
 2194           }
 2195           return AWTEventMulticaster.getListeners(l, listenerType);
 2196       }
 2197   
 2198       // REMIND: remove when filtering is done at lower level
 2199       boolean eventEnabled(AWTEvent e) {
 2200           int id = e.getID();
 2201   
 2202           if (id == ContainerEvent.COMPONENT_ADDED ||
 2203               id == ContainerEvent.COMPONENT_REMOVED) {
 2204               if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
 2205                   containerListener != null) {
 2206                   return true;
 2207               }
 2208               return false;
 2209           }
 2210           return super.eventEnabled(e);
 2211       }
 2212   
 2213       /**
 2214        * Processes events on this container. If the event is a
 2215        * <code>ContainerEvent</code>, it invokes the
 2216        * <code>processContainerEvent</code> method, else it invokes
 2217        * its superclass's <code>processEvent</code>.
 2218        * <p>Note that if the event parameter is <code>null</code>
 2219        * the behavior is unspecified and may result in an
 2220        * exception.
 2221        *
 2222        * @param e the event
 2223        */
 2224       protected void processEvent(AWTEvent e) {
 2225           if (e instanceof ContainerEvent) {
 2226               processContainerEvent((ContainerEvent)e);
 2227               return;
 2228           }
 2229           super.processEvent(e);
 2230       }
 2231   
 2232       /**
 2233        * Processes container events occurring on this container by
 2234        * dispatching them to any registered ContainerListener objects.
 2235        * NOTE: This method will not be called unless container events
 2236        * are enabled for this component; this happens when one of the
 2237        * following occurs:
 2238        * <ul>
 2239        * <li>A ContainerListener object is registered via
 2240        *     <code>addContainerListener</code>
 2241        * <li>Container events are enabled via <code>enableEvents</code>
 2242        * </ul>
 2243        * <p>Note that if the event parameter is <code>null</code>
 2244        * the behavior is unspecified and may result in an
 2245        * exception.
 2246        *
 2247        * @param e the container event
 2248        * @see Component#enableEvents
 2249        */
 2250       protected void processContainerEvent(ContainerEvent e) {
 2251           ContainerListener listener = containerListener;
 2252           if (listener != null) {
 2253               switch(e.getID()) {
 2254                 case ContainerEvent.COMPONENT_ADDED:
 2255                   listener.componentAdded(e);
 2256                   break;
 2257                 case ContainerEvent.COMPONENT_REMOVED:
 2258                   listener.componentRemoved(e);
 2259                   break;
 2260               }
 2261           }
 2262       }
 2263   
 2264       /*
 2265        * Dispatches an event to this component or one of its sub components.
 2266        * Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to
 2267        * COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this
 2268        * here instead of in processComponentEvent because ComponentEvents
 2269        * may not be enabled for this Container.
 2270        * @param e the event
 2271        */
 2272       void dispatchEventImpl(AWTEvent e) {
 2273           if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
 2274               // event was sent to a lightweight component.  The
 2275               // native-produced event sent to the native container
 2276               // must be properly disposed of by the peer, so it
 2277               // gets forwarded.  If the native host has been removed
 2278               // as a result of the sending the lightweight event,
 2279               // the peer reference will be null.
 2280               e.consume();
 2281               if (peer != null) {
 2282                   peer.handleEvent(e);
 2283               }
 2284               return;
 2285           }
 2286   
 2287           super.dispatchEventImpl(e);
 2288   
 2289           synchronized (getTreeLock()) {
 2290               switch (e.getID()) {
 2291                 case ComponentEvent.COMPONENT_RESIZED:
 2292                   createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0,
 2293                                              Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 2294                   break;
 2295                 case ComponentEvent.COMPONENT_MOVED:
 2296                   createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0,
 2297                                          Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 2298                   break;
 2299                 default:
 2300                   break;
 2301               }
 2302           }
 2303       }
 2304   
 2305       /*
 2306        * Dispatches an event to this component, without trying to forward
 2307        * it to any subcomponents
 2308        * @param e the event
 2309        */
 2310       void dispatchEventToSelf(AWTEvent e) {
 2311           super.dispatchEventImpl(e);
 2312       }
 2313   
 2314       /**
 2315        * Fetchs the top-most (deepest) lightweight component that is interested
 2316        * in receiving mouse events.
 2317        */
 2318       Component getMouseEventTarget(int x, int y, boolean includeSelf) {
 2319           return getMouseEventTarget(x, y, includeSelf,
 2320                                      MouseEventTargetFilter.FILTER,
 2321                                      !SEARCH_HEAVYWEIGHTS);
 2322       }
 2323   
 2324       /**
 2325        * Fetches the top-most (deepest) component to receive SunDropTargetEvents.
 2326        */
 2327       Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {
 2328           return getMouseEventTarget(x, y, includeSelf,
 2329                                      DropTargetEventTargetFilter.FILTER,
 2330                                      SEARCH_HEAVYWEIGHTS);
 2331       }
 2332   
 2333       /**
 2334        * A private version of getMouseEventTarget which has two additional
 2335        * controllable behaviors. This method searches for the top-most
 2336        * descendant of this container that contains the given coordinates
 2337        * and is accepted by the given filter. The search will be constrained to
 2338        * lightweight descendants if the last argument is <code>false</code>.
 2339        *
 2340        * @param filter EventTargetFilter instance to determine whether the
 2341        *        given component is a valid target for this event.
 2342        * @param searchHeavyweights if <code>false</code>, the method
 2343        *        will bypass heavyweight components during the search.
 2344        */
 2345       private Component getMouseEventTarget(int x, int y, boolean includeSelf,
 2346                                             EventTargetFilter filter,
 2347                                             boolean searchHeavyweights) {
 2348           Component comp = null;
 2349           if (searchHeavyweights) {
 2350               comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
 2351                                              SEARCH_HEAVYWEIGHTS,
 2352                                              searchHeavyweights);
 2353           }
 2354   
 2355           if (comp == null || comp == this) {
 2356               comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
 2357                                              !SEARCH_HEAVYWEIGHTS,
 2358                                              searchHeavyweights);
 2359           }
 2360   
 2361           return comp;
 2362       }
 2363   
 2364       /**
 2365        * A private version of getMouseEventTarget which has three additional
 2366        * controllable behaviors. This method searches for the top-most
 2367        * descendant of this container that contains the given coordinates
 2368        * and is accepted by the given filter. The search will be constrained to
 2369        * descendants of only lightweight children or only heavyweight children
 2370        * of this container depending on searchHeavyweightChildren. The search will
 2371        * be constrained to only lightweight descendants of the searched children
 2372        * of this container if searchHeavyweightDescendants is <code>false</code>.
 2373        *
 2374        * @param filter EventTargetFilter instance to determine whether the
 2375        *        selected component is a valid target for this event.
 2376        * @param searchHeavyweightChildren if <code>true</code>, the method
 2377        *        will bypass immediate lightweight children during the search.
 2378        *        If <code>false</code>, the methods will bypass immediate
 2379        *        heavyweight children during the search.
 2380        * @param searchHeavyweightDescendants if <code>false</code>, the method
 2381        *        will bypass heavyweight descendants which are not immediate
 2382        *        children during the search. If <code>true</code>, the method
 2383        *        will traverse both lightweight and heavyweight descendants during
 2384        *        the search.
 2385        */
 2386       private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,
 2387                                            EventTargetFilter filter,
 2388                                            boolean searchHeavyweightChildren,
 2389                                            boolean searchHeavyweightDescendants) {
 2390           synchronized (getTreeLock()) {
 2391   
 2392               for (int i = 0; i < component.size(); i++) {
 2393                   Component comp = component.get(i);
 2394                   if (comp != null && comp.visible &&
 2395                       ((!searchHeavyweightChildren &&
 2396                         comp.peer instanceof LightweightPeer) ||
 2397                        (searchHeavyweightChildren &&
 2398                         !(comp.peer instanceof LightweightPeer))) &&
 2399                       comp.contains(x - comp.x, y - comp.y)) {
 2400   
 2401                       // found a component that intersects the point, see if there
 2402                       // is a deeper possibility.
 2403                       if (comp instanceof Container) {
 2404                           Container child = (Container) comp;
 2405                           Component deeper = child.getMouseEventTarget(
 2406                                   x - child.x,
 2407                                   y - child.y,
 2408                                   includeSelf,
 2409                                   filter,
 2410                                   searchHeavyweightDescendants);
 2411                           if (deeper != null) {
 2412                               return deeper;
 2413                           }
 2414                       } else {
 2415                           if (filter.accept(comp)) {
 2416                               // there isn't a deeper target, but this component
 2417                               // is a target
 2418                               return comp;
 2419                           }
 2420                       }
 2421                   }
 2422               }
 2423   
 2424               boolean isPeerOK;
 2425               boolean isMouseOverMe;
 2426   
 2427               isPeerOK = (peer instanceof LightweightPeer) || includeSelf;
 2428               isMouseOverMe = contains(x,y);
 2429   
 2430               // didn't find a child target, return this component if it's
 2431               // a possible target
 2432               if (isMouseOverMe && isPeerOK && filter.accept(this)) {
 2433                   return this;
 2434               }
 2435               // no possible target
 2436               return null;
 2437           }
 2438       }
 2439   
 2440       static interface EventTargetFilter {
 2441           boolean accept(final Component comp);
 2442       }
 2443   
 2444       static class MouseEventTargetFilter implements EventTargetFilter {
 2445           static final EventTargetFilter FILTER = new MouseEventTargetFilter();
 2446   
 2447           private MouseEventTargetFilter() {}
 2448   
 2449           public boolean accept(final Component comp) {
 2450               return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
 2451                   || (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
 2452                   || (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0
 2453                   || comp.mouseListener != null
 2454                   || comp.mouseMotionListener != null
 2455                   || comp.mouseWheelListener != null;
 2456           }
 2457       }
 2458   
 2459       static class DropTargetEventTargetFilter implements EventTargetFilter {
 2460           static final EventTargetFilter FILTER = new DropTargetEventTargetFilter();
 2461   
 2462           private DropTargetEventTargetFilter() {}
 2463   
 2464           public boolean accept(final Component comp) {
 2465               DropTarget dt = comp.getDropTarget();
 2466               return dt != null && dt.isActive();
 2467           }
 2468       }
 2469   
 2470       /**
 2471        * This is called by lightweight components that want the containing
 2472        * windowed parent to enable some kind of events on their behalf.
 2473        * This is needed for events that are normally only dispatched to
 2474        * windows to be accepted so that they can be forwarded downward to
 2475        * the lightweight component that has enabled them.
 2476        */
 2477       void proxyEnableEvents(long events) {
 2478           if (peer instanceof LightweightPeer) {
 2479               // this container is lightweight.... continue sending it
 2480               // upward.
 2481               if (parent != null) {
 2482                   parent.proxyEnableEvents(events);
 2483               }
 2484           } else {
 2485               // This is a native container, so it needs to host
 2486               // one of it's children.  If this function is called before
 2487               // a peer has been created we don't yet have a dispatcher
 2488               // because it has not yet been determined if this instance
 2489               // is lightweight.
 2490               if (dispatcher != null) {
 2491                   dispatcher.enableEvents(events);
 2492               }
 2493           }
 2494       }
 2495   
 2496       /**
 2497        * @deprecated As of JDK version 1.1,
 2498        * replaced by <code>dispatchEvent(AWTEvent e)</code>
 2499        */
 2500       @Deprecated
 2501       public void deliverEvent(Event e) {
 2502           Component comp = getComponentAt(e.x, e.y);
 2503           if ((comp != null) && (comp != this)) {
 2504               e.translate(-comp.x, -comp.y);
 2505               comp.deliverEvent(e);
 2506           } else {
 2507               postEvent(e);
 2508           }
 2509       }
 2510   
 2511       /**
 2512        * Locates the component that contains the x,y position.  The
 2513        * top-most child component is returned in the case where there
 2514        * is overlap in the components.  This is determined by finding
 2515        * the component closest to the index 0 that claims to contain
 2516        * the given point via Component.contains(), except that Components
 2517        * which have native peers take precedence over those which do not
 2518        * (i.e., lightweight Components).
 2519        *
 2520        * @param x the <i>x</i> coordinate
 2521        * @param y the <i>y</i> coordinate
 2522        * @return null if the component does not contain the position.
 2523        * If there is no child component at the requested point and the
 2524        * point is within the bounds of the container the container itself
 2525        * is returned; otherwise the top-most child is returned.
 2526        * @see Component#contains
 2527        * @since JDK1.1
 2528        */
 2529       public Component getComponentAt(int x, int y) {
 2530           return locate(x, y);
 2531       }
 2532   
 2533       /**
 2534        * @deprecated As of JDK version 1.1,
 2535        * replaced by <code>getComponentAt(int, int)</code>.
 2536        */
 2537       @Deprecated
 2538       public Component locate(int x, int y) {
 2539           if (!contains(x, y)) {
 2540               return null;
 2541           }
 2542           synchronized (getTreeLock()) {
 2543               // Two passes: see comment in sun.awt.SunGraphicsCallback
 2544               for (int i = 0; i < component.size(); i++) {
 2545                   Component comp = component.get(i);
 2546                   if (comp != null &&
 2547                       !(comp.peer instanceof LightweightPeer)) {
 2548                       if (comp.contains(x - comp.x, y - comp.y)) {
 2549                           return comp;
 2550                       }
 2551                   }
 2552               }
 2553               for (int i = 0; i < component.size(); i++) {
 2554                   Component comp = component.get(i);
 2555                   if (comp != null &&
 2556                       comp.peer instanceof LightweightPeer) {
 2557                       if (comp.contains(x - comp.x, y - comp.y)) {
 2558                           return comp;
 2559                       }
 2560                   }
 2561               }
 2562           }
 2563           return this;
 2564       }
 2565   
 2566       /**
 2567        * Gets the component that contains the specified point.
 2568        * @param      p   the point.
 2569        * @return     returns the component that contains the point,
 2570        *                 or <code>null</code> if the component does
 2571        *                 not contain the point.
 2572        * @see        Component#contains
 2573        * @since      JDK1.1
 2574        */
 2575       public Component getComponentAt(Point p) {
 2576           return getComponentAt(p.x, p.y);
 2577       }
 2578   
 2579       /**
 2580        * Returns the position of the mouse pointer in this <code>Container</code>'s
 2581        * coordinate space if the <code>Container</code> is under the mouse pointer,
 2582        * otherwise returns <code>null</code>.
 2583        * This method is similar to {@link Component#getMousePosition()} with the exception
 2584        * that it can take the <code>Container</code>'s children into account.
 2585        * If <code>allowChildren</code> is <code>false</code>, this method will return
 2586        * a non-null value only if the mouse pointer is above the <code>Container</code>
 2587        * directly, not above the part obscured by children.
 2588        * If <code>allowChildren</code> is <code>true</code>, this method returns
 2589        * a non-null value if the mouse pointer is above <code>Container</code> or any
 2590        * of its descendants.
 2591        *
 2592        * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
 2593        * @param     allowChildren true if children should be taken into account
 2594        * @see       Component#getMousePosition
 2595        * @return    mouse coordinates relative to this <code>Component</code>, or null
 2596        * @since     1.5
 2597        */
 2598       public Point getMousePosition(boolean allowChildren) throws HeadlessException {
 2599           if (GraphicsEnvironment.isHeadless()) {
 2600               throw new HeadlessException();
 2601           }
 2602           PointerInfo pi = (PointerInfo)java.security.AccessController.doPrivileged(
 2603               new java.security.PrivilegedAction() {
 2604                   public Object run() {
 2605                       return MouseInfo.getPointerInfo();
 2606                   }
 2607               }
 2608           );
 2609           synchronized (getTreeLock()) {
 2610               Component inTheSameWindow = findUnderMouseInWindow(pi);
 2611               if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {
 2612                   return  pointRelativeToComponent(pi.getLocation());
 2613               }
 2614               return null;
 2615           }
 2616       }
 2617   
 2618       boolean isSameOrAncestorOf(Component comp, boolean allowChildren) {
 2619           return this == comp || (allowChildren && isParentOf(comp));
 2620       }
 2621   
 2622       /**
 2623        * Locates the visible child component that contains the specified
 2624        * position.  The top-most child component is returned in the case
 2625        * where there is overlap in the components.  If the containing child
 2626        * component is a Container, this method will continue searching for
 2627        * the deepest nested child component.  Components which are not
 2628        * visible are ignored during the search.<p>
 2629        *
 2630        * The findComponentAt method is different from getComponentAt in
 2631        * that getComponentAt only searches the Container's immediate
 2632        * children; if the containing component is a Container,
 2633        * findComponentAt will search that child to find a nested component.
 2634        *
 2635        * @param x the <i>x</i> coordinate
 2636        * @param y the <i>y</i> coordinate
 2637        * @return null if the component does not contain the position.
 2638        * If there is no child component at the requested point and the
 2639        * point is within the bounds of the container the container itself
 2640        * is returned.
 2641        * @see Component#contains
 2642        * @see #getComponentAt
 2643        * @since 1.2
 2644        */
 2645       public Component findComponentAt(int x, int y) {
 2646           return findComponentAt(x, y, true);
 2647       }
 2648   
 2649       /**
 2650        * Private version of findComponentAt which has a controllable
 2651        * behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled
 2652        * Components during the search. This behavior is used by the
 2653        * lightweight cursor support in sun.awt.GlobalCursorManager.
 2654        * The cursor code calls this function directly via native code.
 2655        *
 2656        * The addition of this feature is temporary, pending the
 2657        * adoption of new, public API which exports this feature.
 2658        */
 2659       final Component findComponentAt(int x, int y, boolean ignoreEnabled) {
 2660           synchronized (getTreeLock()) {
 2661               if (isRecursivelyVisible()){
 2662                   return findComponentAtImpl(x, y, ignoreEnabled);
 2663               }
 2664           }
 2665           return null;
 2666       }
 2667   
 2668       final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){
 2669           checkTreeLock();
 2670   
 2671           if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {
 2672               return null;
 2673           }
 2674   
 2675           // Two passes: see comment in sun.awt.SunGraphicsCallback
 2676           for (int i = 0; i < component.size(); i++) {
 2677               Component comp = component.get(i);
 2678               if (comp != null &&
 2679                   !(comp.peer instanceof LightweightPeer)) {
 2680                   if (comp instanceof Container) {
 2681                       comp = ((Container)comp).findComponentAtImpl(x - comp.x,
 2682                                                                    y - comp.y,
 2683                                                                    ignoreEnabled);
 2684                   } else {
 2685                       comp = comp.locate(x - comp.x, y - comp.y);
 2686                   }
 2687                   if (comp != null && comp.visible &&
 2688                       (ignoreEnabled || comp.enabled))
 2689                   {
 2690                       return comp;
 2691                   }
 2692               }
 2693           }
 2694           for (int i = 0; i < component.size(); i++) {
 2695               Component comp = component.get(i);
 2696               if (comp != null &&
 2697                   comp.peer instanceof LightweightPeer) {
 2698                   if (comp instanceof Container) {
 2699                       comp = ((Container)comp).findComponentAtImpl(x - comp.x,
 2700                                                                    y - comp.y,
 2701                                                                    ignoreEnabled);
 2702                   } else {
 2703                       comp = comp.locate(x - comp.x, y - comp.y);
 2704                   }
 2705                   if (comp != null && comp.visible &&
 2706                       (ignoreEnabled || comp.enabled))
 2707                   {
 2708                       return comp;
 2709                   }
 2710               }
 2711           }
 2712   
 2713           return this;
 2714       }
 2715   
 2716       /**
 2717        * Locates the visible child component that contains the specified
 2718        * point.  The top-most child component is returned in the case
 2719        * where there is overlap in the components.  If the containing child
 2720        * component is a Container, this method will continue searching for
 2721        * the deepest nested child component.  Components which are not
 2722        * visible are ignored during the search.<p>
 2723        *
 2724        * The findComponentAt method is different from getComponentAt in
 2725        * that getComponentAt only searches the Container's immediate
 2726        * children; if the containing component is a Container,
 2727        * findComponentAt will search that child to find a nested component.
 2728        *
 2729        * @param      p   the point.
 2730        * @return null if the component does not contain the position.
 2731        * If there is no child component at the requested point and the
 2732        * point is within the bounds of the container the container itself
 2733        * is returned.
 2734        * @throws NullPointerException if {@code p} is {@code null}
 2735        * @see Component#contains
 2736        * @see #getComponentAt
 2737        * @since 1.2
 2738        */
 2739       public Component findComponentAt(Point p) {
 2740           return findComponentAt(p.x, p.y);
 2741       }
 2742   
 2743       /**
 2744        * Makes this Container displayable by connecting it to
 2745        * a native screen resource.  Making a container displayable will
 2746        * cause all of its children to be made displayable.
 2747        * This method is called internally by the toolkit and should
 2748        * not be called directly by programs.
 2749        * @see Component#isDisplayable
 2750        * @see #removeNotify
 2751        */
 2752       public void addNotify() {
 2753           synchronized (getTreeLock()) {
 2754               // addNotify() on the children may cause proxy event enabling
 2755               // on this instance, so we first call super.addNotify() and
 2756               // possibly create an lightweight event dispatcher before calling
 2757               // addNotify() on the children which may be lightweight.
 2758               super.addNotify();
 2759               if (! (peer instanceof LightweightPeer)) {
 2760                   dispatcher = new LightweightDispatcher(this);
 2761               }
 2762   
 2763               // We shouldn't use iterator because of the Swing menu
 2764               // implementation specifics:
 2765               // the menu is being assigned as a child to JLayeredPane
 2766               // instead of particular component so always affect
 2767               // collection of component if menu is becoming shown or hidden.
 2768               for (int i = 0; i < component.size(); i++) {
 2769                   component.get(i).addNotify();
 2770               }
 2771           }
 2772       }
 2773   
 2774       /**
 2775        * Makes this Container undisplayable by removing its connection
 2776        * to its native screen resource.  Making a container undisplayable
 2777        * will cause all of its children to be made undisplayable.
 2778        * This method is called by the toolkit internally and should
 2779        * not be called directly by programs.
 2780        * @see Component#isDisplayable
 2781        * @see #addNotify
 2782        */
 2783       public void removeNotify() {
 2784           synchronized (getTreeLock()) {
 2785               // We shouldn't use iterator because of the Swing menu
 2786               // implementation specifics:
 2787               // the menu is being assigned as a child to JLayeredPane
 2788               // instead of particular component so always affect
 2789               // collection of component if menu is becoming shown or hidden.
 2790               for (int i = component.size()-1 ; i >= 0 ; i--) {
 2791                   Component comp = component.get(i);
 2792                   if (comp != null) {
 2793                       // Fix for 6607170.
 2794                       // We want to suppress focus change on disposal
 2795                       // of the focused component. But because of focus
 2796                       // is asynchronous, we should suppress focus change
 2797                       // on every component in case it receives native focus
 2798                       // in the process of disposal.
 2799                       comp.setAutoFocusTransferOnDisposal(false);
 2800                       comp.removeNotify();
 2801                       comp.setAutoFocusTransferOnDisposal(true);
 2802                    }
 2803                }
 2804               // If some of the children had focus before disposal then it still has.
 2805               // Auto-transfer focus to the next (or previous) component if auto-transfer
 2806               // is enabled.
 2807               if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {
 2808                   if (!transferFocus(false)) {
 2809                       transferFocusBackward(true);
 2810                   }
 2811               }
 2812               if ( dispatcher != null ) {
 2813                   dispatcher.dispose();
 2814                   dispatcher = null;
 2815               }
 2816               super.removeNotify();
 2817           }
 2818       }
 2819   
 2820       /**
 2821        * Checks if the component is contained in the component hierarchy of
 2822        * this container.
 2823        * @param c the component
 2824        * @return     <code>true</code> if it is an ancestor;
 2825        *             <code>false</code> otherwise.
 2826        * @since      JDK1.1
 2827        */
 2828       public boolean isAncestorOf(Component c) {
 2829           Container p;
 2830           if (c == null || ((p = c.getParent()) == null)) {
 2831               return false;
 2832           }
 2833           while (p != null) {
 2834               if (p == this) {
 2835                   return true;
 2836               }
 2837               p = p.getParent();
 2838           }
 2839           return false;
 2840       }
 2841   
 2842       /*
 2843        * The following code was added to support modal JInternalFrames
 2844        * Unfortunately this code has to be added here so that we can get access to
 2845        * some private AWT classes like SequencedEvent.
 2846        *
 2847        * The native container of the LW component has this field set
 2848        * to tell it that it should block Mouse events for all LW
 2849        * children except for the modal component.
 2850        *
 2851        * In the case of nested Modal components, we store the previous
 2852        * modal component in the new modal components value of modalComp;
 2853        */
 2854   
 2855       transient Component modalComp;
 2856       transient AppContext modalAppContext;
 2857   
 2858       private void startLWModal() {
 2859           // Store the app context on which this component is being shown.
 2860           // Event dispatch thread of this app context will be sleeping until
 2861           // we wake it by any event from hideAndDisposeHandler().
 2862           modalAppContext = AppContext.getAppContext();
 2863   
 2864           // keep the KeyEvents from being dispatched
 2865           // until the focus has been transfered
 2866           long time = Toolkit.getEventQueue().getMostRecentEventTime();
 2867           Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null;
 2868           if (predictedFocusOwner != null) {
 2869               KeyboardFocusManager.getCurrentKeyboardFocusManager().
 2870                   enqueueKeyEvents(time, predictedFocusOwner);
 2871           }
 2872           // We have two mechanisms for blocking: 1. If we're on the
 2873           // EventDispatchThread, start a new event pump. 2. If we're
 2874           // on any other thread, call wait() on the treelock.
 2875           final Container nativeContainer;
 2876           synchronized (getTreeLock()) {
 2877               nativeContainer = getHeavyweightContainer();
 2878               if (nativeContainer.modalComp != null) {
 2879                   this.modalComp =  nativeContainer.modalComp;
 2880                   nativeContainer.modalComp = this;
 2881                   return;
 2882               }
 2883               else {
 2884                   nativeContainer.modalComp = this;
 2885               }
 2886           }
 2887   
 2888           Runnable pumpEventsForHierarchy = new Runnable() {
 2889               public void run() {
 2890                   EventDispatchThread dispatchThread =
 2891                       (EventDispatchThread)Thread.currentThread();
 2892                   dispatchThread.pumpEventsForHierarchy(
 2893                           new Conditional() {
 2894                           public boolean evaluate() {
 2895                           return ((windowClosingException == null) && (nativeContainer.modalComp != null)) ;
 2896                           }
 2897                           }, Container.this);
 2898               }
 2899           };
 2900   
 2901           if (EventQueue.isDispatchThread()) {
 2902               SequencedEvent currentSequencedEvent =
 2903                   KeyboardFocusManager.getCurrentKeyboardFocusManager().
 2904                   getCurrentSequencedEvent();
 2905               if (currentSequencedEvent != null) {
 2906                   currentSequencedEvent.dispose();
 2907               }
 2908   
 2909               pumpEventsForHierarchy.run();
 2910           } else {
 2911               synchronized (getTreeLock()) {
 2912                   Toolkit.getEventQueue().
 2913                       postEvent(new PeerEvent(this,
 2914                                   pumpEventsForHierarchy,
 2915                                   PeerEvent.PRIORITY_EVENT));
 2916                   while ((windowClosingException == null) &&
 2917                          (nativeContainer.modalComp != null))
 2918                   {
 2919                       try {
 2920                           getTreeLock().wait();
 2921                       } catch (InterruptedException e) {
 2922                           break;
 2923                       }
 2924                   }
 2925               }
 2926           }
 2927           if (windowClosingException != null) {
 2928               windowClosingException.fillInStackTrace();
 2929               throw windowClosingException;
 2930           }
 2931           if (predictedFocusOwner != null) {
 2932               KeyboardFocusManager.getCurrentKeyboardFocusManager().
 2933                   dequeueKeyEvents(time, predictedFocusOwner);
 2934           }
 2935       }
 2936   
 2937       private void stopLWModal() {
 2938           synchronized (getTreeLock()) {
 2939               if (modalAppContext != null) {
 2940                   Container nativeContainer = getHeavyweightContainer();
 2941                   if(nativeContainer != null) {
 2942                       if (this.modalComp !=  null) {
 2943                           nativeContainer.modalComp = this.modalComp;
 2944                           this.modalComp = null;
 2945                           return;
 2946                       }
 2947                       else {
 2948                           nativeContainer.modalComp = null;
 2949                       }
 2950                   }
 2951                   // Wake up event dispatch thread on which the dialog was
 2952                   // initially shown
 2953                   SunToolkit.postEvent(modalAppContext,
 2954                           new PeerEvent(this,
 2955                                   new WakingRunnable(),
 2956                                   PeerEvent.PRIORITY_EVENT));
 2957               }
 2958               EventQueue.invokeLater(new WakingRunnable());
 2959               getTreeLock().notifyAll();
 2960           }
 2961       }
 2962   
 2963       final static class WakingRunnable implements Runnable {
 2964           public void run() {
 2965           }
 2966       }
 2967   
 2968       /* End of JOptionPane support code */
 2969   
 2970       /**
 2971        * Returns a string representing the state of this <code>Container</code>.
 2972        * This method is intended to be used only for debugging purposes, and the
 2973        * content and format of the returned string may vary between
 2974        * implementations. The returned string may be empty but may not be
 2975        * <code>null</code>.
 2976        *
 2977        * @return    the parameter string of this container
 2978        */
 2979       protected String paramString() {
 2980           String str = super.paramString();
 2981           LayoutManager layoutMgr = this.layoutMgr;
 2982           if (layoutMgr != null) {
 2983               str += ",layout=" + layoutMgr.getClass().getName();
 2984           }
 2985           return str;
 2986       }
 2987   
 2988       /**
 2989        * Prints a listing of this container to the specified output
 2990        * stream. The listing starts at the specified indentation.
 2991        * <p>
 2992        * The immediate children of the container are printed with
 2993        * an indentation of <code>indent+1</code>.  The children
 2994        * of those children are printed at <code>indent+2</code>
 2995        * and so on.
 2996        *
 2997        * @param    out      a print stream
 2998        * @param    indent   the number of spaces to indent
 2999        * @throws   NullPointerException if {@code out} is {@code null}
 3000        * @see      Component#list(java.io.PrintStream, int)
 3001        * @since    JDK1.0
 3002        */
 3003       public void list(PrintStream out, int indent) {
 3004           super.list(out, indent);
 3005           synchronized(getTreeLock()) {
 3006               for (int i = 0; i < component.size(); i++) {
 3007                   Component comp = component.get(i);
 3008                   if (comp != null) {
 3009                       comp.list(out, indent+1);
 3010                   }
 3011               }
 3012           }
 3013       }
 3014   
 3015       /**
 3016        * Prints out a list, starting at the specified indentation,
 3017        * to the specified print writer.
 3018        * <p>
 3019        * The immediate children of the container are printed with
 3020        * an indentation of <code>indent+1</code>.  The children
 3021        * of those children are printed at <code>indent+2</code>
 3022        * and so on.
 3023        *
 3024        * @param    out      a print writer
 3025        * @param    indent   the number of spaces to indent
 3026        * @throws   NullPointerException if {@code out} is {@code null}
 3027        * @see      Component#list(java.io.PrintWriter, int)
 3028        * @since    JDK1.1
 3029        */
 3030       public void list(PrintWriter out, int indent) {
 3031           super.list(out, indent);
 3032           synchronized(getTreeLock()) {
 3033               for (int i = 0; i < component.size(); i++) {
 3034                   Component comp = component.get(i);
 3035                   if (comp != null) {
 3036                       comp.list(out, indent+1);
 3037                   }
 3038               }
 3039           }
 3040       }
 3041   
 3042       /**
 3043        * Sets the focus traversal keys for a given traversal operation for this
 3044        * Container.
 3045        * <p>
 3046        * The default values for a Container's focus traversal keys are
 3047        * implementation-dependent. Sun recommends that all implementations for a
 3048        * particular native platform use the same default values. The
 3049        * recommendations for Windows and Unix are listed below. These
 3050        * recommendations are used in the Sun AWT implementations.
 3051        *
 3052        * <table border=1 summary="Recommended default values for a Container's focus traversal keys">
 3053        * <tr>
 3054        *    <th>Identifier</th>
 3055        *    <th>Meaning</th>
 3056        *    <th>Default</th>
 3057        * </tr>
 3058        * <tr>
 3059        *    <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
 3060        *    <td>Normal forward keyboard traversal</td>
 3061        *    <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td>
 3062        * </tr>
 3063        * <tr>
 3064        *    <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
 3065        *    <td>Normal reverse keyboard traversal</td>
 3066        *    <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td>
 3067        * </tr>
 3068        * <tr>
 3069        *    <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
 3070        *    <td>Go up one focus traversal cycle</td>
 3071        *    <td>none</td>
 3072        * </tr>
 3073        * <tr>
 3074        *    <td>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS<td>
 3075        *    <td>Go down one focus traversal cycle</td>
 3076        *    <td>none</td>
 3077        * </tr>
 3078        * </table>
 3079        *
 3080        * To disable a traversal key, use an empty Set; Collections.EMPTY_SET is
 3081        * recommended.
 3082        * <p>
 3083        * Using the AWTKeyStroke API, client code can specify on which of two
 3084        * specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal
 3085        * operation will occur. Regardless of which KeyEvent is specified,
 3086        * however, all KeyEvents related to the focus traversal key, including the
 3087        * associated KEY_TYPED event, will be consumed, and will not be dispatched
 3088        * to any Container. It is a runtime error to specify a KEY_TYPED event as
 3089        * mapping to a focus traversal operation, or to map the same event to
 3090        * multiple default focus traversal operations.
 3091        * <p>
 3092        * If a value of null is specified for the Set, this Container inherits the
 3093        * Set from its parent. If all ancestors of this Container have null
 3094        * specified for the Set, then the current KeyboardFocusManager's default
 3095        * Set is used.
 3096        *
 3097        * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3098        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3099        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3100        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 3101        * @param keystrokes the Set of AWTKeyStroke for the specified operation
 3102        * @see #getFocusTraversalKeys
 3103        * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
 3104        * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
 3105        * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
 3106        * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
 3107        * @throws IllegalArgumentException if id is not one of
 3108        *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3109        *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3110        *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3111        *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes
 3112        *         contains null, or if any Object in keystrokes is not an
 3113        *         AWTKeyStroke, or if any keystroke represents a KEY_TYPED event,
 3114        *         or if any keystroke already maps to another focus traversal
 3115        *         operation for this Container
 3116        * @since 1.4
 3117        * @beaninfo
 3118        *       bound: true
 3119        */
 3120       public void setFocusTraversalKeys(int id,
 3121                                         Set<? extends AWTKeyStroke> keystrokes)
 3122       {
 3123           if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
 3124               throw new IllegalArgumentException("invalid focus traversal key identifier");
 3125           }
 3126   
 3127           // Don't call super.setFocusTraversalKey. The Component parameter check
 3128           // does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.
 3129           setFocusTraversalKeys_NoIDCheck(id, keystrokes);
 3130       }
 3131   
 3132       /**
 3133        * Returns the Set of focus traversal keys for a given traversal operation
 3134        * for this Container. (See
 3135        * <code>setFocusTraversalKeys</code> for a full description of each key.)
 3136        * <p>
 3137        * If a Set of traversal keys has not been explicitly defined for this
 3138        * Container, then this Container's parent's Set is returned. If no Set
 3139        * has been explicitly defined for any of this Container's ancestors, then
 3140        * the current KeyboardFocusManager's default Set is returned.
 3141        *
 3142        * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3143        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3144        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3145        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 3146        * @return the Set of AWTKeyStrokes for the specified operation. The Set
 3147        *         will be unmodifiable, and may be empty. null will never be
 3148        *         returned.
 3149        * @see #setFocusTraversalKeys
 3150        * @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
 3151        * @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
 3152        * @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
 3153        * @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
 3154        * @throws IllegalArgumentException if id is not one of
 3155        *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3156        *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3157        *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3158        *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 3159        * @since 1.4
 3160        */
 3161       public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
 3162           if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
 3163               throw new IllegalArgumentException("invalid focus traversal key identifier");
 3164           }
 3165   
 3166           // Don't call super.getFocusTraversalKey. The Component parameter check
 3167           // does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.
 3168           return getFocusTraversalKeys_NoIDCheck(id);
 3169       }
 3170   
 3171       /**
 3172        * Returns whether the Set of focus traversal keys for the given focus
 3173        * traversal operation has been explicitly defined for this Container. If
 3174        * this method returns <code>false</code>, this Container is inheriting the
 3175        * Set from an ancestor, or from the current KeyboardFocusManager.
 3176        *
 3177        * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3178        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3179        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3180        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 3181        * @return <code>true</code> if the the Set of focus traversal keys for the
 3182        *         given focus traversal operation has been explicitly defined for
 3183        *         this Component; <code>false</code> otherwise.
 3184        * @throws IllegalArgumentException if id is not one of
 3185        *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 3186        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 3187        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 3188        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 3189        * @since 1.4
 3190        */
 3191       public boolean areFocusTraversalKeysSet(int id) {
 3192           if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
 3193               throw new IllegalArgumentException("invalid focus traversal key identifier");
 3194           }
 3195   
 3196           return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
 3197       }
 3198   
 3199       /**
 3200        * Returns whether the specified Container is the focus cycle root of this
 3201        * Container's focus traversal cycle. Each focus traversal cycle has only
 3202        * a single focus cycle root and each Container which is not a focus cycle
 3203        * root belongs to only a single focus traversal cycle. Containers which
 3204        * are focus cycle roots belong to two cycles: one rooted at the Container
 3205        * itself, and one rooted at the Container's nearest focus-cycle-root
 3206        * ancestor. This method will return <code>true</code> for both such
 3207        * Containers in this case.
 3208        *
 3209        * @param container the Container to be tested
 3210        * @return <code>true</code> if the specified Container is a focus-cycle-
 3211        *         root of this Container; <code>false</code> otherwise
 3212        * @see #isFocusCycleRoot()
 3213        * @since 1.4
 3214        */
 3215       public boolean isFocusCycleRoot(Container container) {
 3216           if (isFocusCycleRoot() && container == this) {
 3217               return true;
 3218           } else {
 3219               return super.isFocusCycleRoot(container);
 3220           }
 3221       }
 3222   
 3223       private Container findTraversalRoot() {
 3224           // I potentially have two roots, myself and my root parent
 3225           // If I am the current root, then use me
 3226           // If none of my parents are roots, then use me
 3227           // If my root parent is the current root, then use my root parent
 3228           // If neither I nor my root parent is the current root, then
 3229           // use my root parent (a guess)
 3230   
 3231           Container currentFocusCycleRoot = KeyboardFocusManager.
 3232               getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot();
 3233           Container root;
 3234   
 3235           if (currentFocusCycleRoot == this) {
 3236               root = this;
 3237           } else {
 3238               root = getFocusCycleRootAncestor();
 3239               if (root == null) {
 3240                   root = this;
 3241               }
 3242           }
 3243   
 3244           if (root != currentFocusCycleRoot) {
 3245               KeyboardFocusManager.getCurrentKeyboardFocusManager().
 3246                   setGlobalCurrentFocusCycleRoot(root);
 3247           }
 3248           return root;
 3249       }
 3250   
 3251       final boolean containsFocus() {
 3252           final Component focusOwner = KeyboardFocusManager.
 3253               getCurrentKeyboardFocusManager().getFocusOwner();
 3254           return isParentOf(focusOwner);
 3255       }
 3256   
 3257       /**
 3258        * Check if this component is the child of this container or its children.
 3259        * Note: this function acquires treeLock
 3260        * Note: this function traverses children tree only in one Window.
 3261        * @param comp a component in test, must not be null
 3262        */
 3263       private boolean isParentOf(Component comp) {
 3264           synchronized(getTreeLock()) {
 3265               while (comp != null && comp != this && !(comp instanceof Window)) {
 3266                   comp = comp.getParent();
 3267               }
 3268               return (comp == this);
 3269           }
 3270       }
 3271   
 3272       void clearMostRecentFocusOwnerOnHide() {
 3273           boolean reset = false;
 3274           Window window = null;
 3275   
 3276           synchronized (getTreeLock()) {
 3277               window = getContainingWindow();
 3278               if (window != null) {
 3279                   Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window);
 3280                   reset = ((comp == this) || isParentOf(comp));
 3281                   // This synchronized should always be the second in a pair
 3282                   // (tree lock, KeyboardFocusManager.class)
 3283                   synchronized(KeyboardFocusManager.class) {
 3284                       Component storedComp = window.getTemporaryLostComponent();
 3285                       if (isParentOf(storedComp) || storedComp == this) {
 3286                           window.setTemporaryLostComponent(null);
 3287                       }
 3288                   }
 3289               }
 3290           }
 3291   
 3292           if (reset) {
 3293               KeyboardFocusManager.setMostRecentFocusOwner(window, null);
 3294           }
 3295       }
 3296   
 3297       void clearCurrentFocusCycleRootOnHide() {
 3298           KeyboardFocusManager kfm =
 3299               KeyboardFocusManager.getCurrentKeyboardFocusManager();
 3300           Container cont = kfm.getCurrentFocusCycleRoot();
 3301   
 3302           if (cont == this || isParentOf(cont)) {
 3303               kfm.setGlobalCurrentFocusCycleRoot(null);
 3304           }
 3305       }
 3306   
 3307       final Container getTraversalRoot() {
 3308           if (isFocusCycleRoot()) {
 3309               return findTraversalRoot();
 3310           }
 3311   
 3312           return super.getTraversalRoot();
 3313       }
 3314   
 3315       /**
 3316        * Sets the focus traversal policy that will manage keyboard traversal of
 3317        * this Container's children, if this Container is a focus cycle root. If
 3318        * the argument is null, this Container inherits its policy from its focus-
 3319        * cycle-root ancestor. If the argument is non-null, this policy will be
 3320        * inherited by all focus-cycle-root children that have no keyboard-
 3321        * traversal policy of their own (as will, recursively, their focus-cycle-
 3322        * root children).
 3323        * <p>
 3324        * If this Container is not a focus cycle root, the policy will be
 3325        * remembered, but will not be used or inherited by this or any other
 3326        * Containers until this Container is made a focus cycle root.
 3327        *
 3328        * @param policy the new focus traversal policy for this Container
 3329        * @see #getFocusTraversalPolicy
 3330        * @see #setFocusCycleRoot
 3331        * @see #isFocusCycleRoot
 3332        * @since 1.4
 3333        * @beaninfo
 3334        *       bound: true
 3335        */
 3336       public void setFocusTraversalPolicy(FocusTraversalPolicy policy) {
 3337           FocusTraversalPolicy oldPolicy;
 3338           synchronized (this) {
 3339               oldPolicy = this.focusTraversalPolicy;
 3340               this.focusTraversalPolicy = policy;
 3341           }
 3342           firePropertyChange("focusTraversalPolicy", oldPolicy, policy);
 3343       }
 3344   
 3345       /**
 3346        * Returns the focus traversal policy that will manage keyboard traversal
 3347        * of this Container's children, or null if this Container is not a focus
 3348        * cycle root. If no traversal policy has been explicitly set for this
 3349        * Container, then this Container's focus-cycle-root ancestor's policy is
 3350        * returned.
 3351        *
 3352        * @return this Container's focus traversal policy, or null if this
 3353        *         Container is not a focus cycle root.
 3354        * @see #setFocusTraversalPolicy
 3355        * @see #setFocusCycleRoot
 3356        * @see #isFocusCycleRoot
 3357        * @since 1.4
 3358        */
 3359       public FocusTraversalPolicy getFocusTraversalPolicy() {
 3360           if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {
 3361               return null;
 3362           }
 3363   
 3364           FocusTraversalPolicy policy = this.focusTraversalPolicy;
 3365           if (policy != null) {
 3366               return policy;
 3367           }
 3368   
 3369           Container rootAncestor = getFocusCycleRootAncestor();
 3370           if (rootAncestor != null) {
 3371               return rootAncestor.getFocusTraversalPolicy();
 3372           } else {
 3373               return KeyboardFocusManager.getCurrentKeyboardFocusManager().
 3374                   getDefaultFocusTraversalPolicy();
 3375           }
 3376       }
 3377   
 3378       /**
 3379        * Returns whether the focus traversal policy has been explicitly set for
 3380        * this Container. If this method returns <code>false</code>, this
 3381        * Container will inherit its focus traversal policy from an ancestor.
 3382        *
 3383        * @return <code>true</code> if the focus traversal policy has been
 3384        *         explicitly set for this Container; <code>false</code> otherwise.
 3385        * @since 1.4
 3386        */
 3387       public boolean isFocusTraversalPolicySet() {
 3388           return (focusTraversalPolicy != null);
 3389       }
 3390   
 3391       /**
 3392        * Sets whether this Container is the root of a focus traversal cycle. Once
 3393        * focus enters a traversal cycle, typically it cannot leave it via focus
 3394        * traversal unless one of the up- or down-cycle keys is pressed. Normal
 3395        * traversal is limited to this Container, and all of this Container's
 3396        * descendants that are not descendants of inferior focus cycle roots. Note
 3397        * that a FocusTraversalPolicy may bend these restrictions, however. For
 3398        * example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
 3399        * traversal.
 3400        * <p>
 3401        * The alternative way to specify the traversal order of this Container's
 3402        * children is to make this Container a
 3403        * <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.
 3404        *
 3405        * @param focusCycleRoot indicates whether this Container is the root of a
 3406        *        focus traversal cycle
 3407        * @see #isFocusCycleRoot()
 3408        * @see #setFocusTraversalPolicy
 3409        * @see #getFocusTraversalPolicy
 3410        * @see ContainerOrderFocusTraversalPolicy
 3411        * @see #setFocusTraversalPolicyProvider
 3412        * @since 1.4
 3413        * @beaninfo
 3414        *       bound: true
 3415        */
 3416       public void setFocusCycleRoot(boolean focusCycleRoot) {
 3417           boolean oldFocusCycleRoot;
 3418           synchronized (this) {
 3419               oldFocusCycleRoot = this.focusCycleRoot;
 3420               this.focusCycleRoot = focusCycleRoot;
 3421           }
 3422           firePropertyChange("focusCycleRoot", oldFocusCycleRoot,
 3423                              focusCycleRoot);
 3424       }
 3425   
 3426       /**
 3427        * Returns whether this Container is the root of a focus traversal cycle.
 3428        * Once focus enters a traversal cycle, typically it cannot leave it via
 3429        * focus traversal unless one of the up- or down-cycle keys is pressed.
 3430        * Normal traversal is limited to this Container, and all of this
 3431        * Container's descendants that are not descendants of inferior focus
 3432        * cycle roots. Note that a FocusTraversalPolicy may bend these
 3433        * restrictions, however. For example, ContainerOrderFocusTraversalPolicy
 3434        * supports implicit down-cycle traversal.
 3435        *
 3436        * @return whether this Container is the root of a focus traversal cycle
 3437        * @see #setFocusCycleRoot
 3438        * @see #setFocusTraversalPolicy
 3439        * @see #getFocusTraversalPolicy
 3440        * @see ContainerOrderFocusTraversalPolicy
 3441        * @since 1.4
 3442        */
 3443       public boolean isFocusCycleRoot() {
 3444           return focusCycleRoot;
 3445       }
 3446   
 3447       /**
 3448        * Sets whether this container will be used to provide focus
 3449        * traversal policy. Container with this property as
 3450        * <code>true</code> will be used to acquire focus traversal policy
 3451        * instead of closest focus cycle root ancestor.
 3452        * @param provider indicates whether this container will be used to
 3453        *                provide focus traversal policy
 3454        * @see #setFocusTraversalPolicy
 3455        * @see #getFocusTraversalPolicy
 3456        * @see #isFocusTraversalPolicyProvider
 3457        * @since 1.5
 3458        * @beaninfo
 3459        *        bound: true
 3460        */
 3461       public final void setFocusTraversalPolicyProvider(boolean provider) {
 3462           boolean oldProvider;
 3463           synchronized(this) {
 3464               oldProvider = focusTraversalPolicyProvider;
 3465               focusTraversalPolicyProvider = provider;
 3466           }
 3467           firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);
 3468       }
 3469   
 3470       /**
 3471        * Returns whether this container provides focus traversal
 3472        * policy. If this property is set to <code>true</code> then when
 3473        * keyboard focus manager searches container hierarchy for focus
 3474        * traversal policy and encounters this container before any other
 3475        * container with this property as true or focus cycle roots then
 3476        * its focus traversal policy will be used instead of focus cycle
 3477        * root's policy.
 3478        * @see #setFocusTraversalPolicy
 3479        * @see #getFocusTraversalPolicy
 3480        * @see #setFocusCycleRoot
 3481        * @see #setFocusTraversalPolicyProvider
 3482        * @return <code>true</code> if this container provides focus traversal
 3483        *         policy, <code>false</code> otherwise
 3484        * @since 1.5
 3485        * @beaninfo
 3486        *        bound: true
 3487        */
 3488       public final boolean isFocusTraversalPolicyProvider() {
 3489           return focusTraversalPolicyProvider;
 3490       }
 3491   
 3492       /**
 3493        * Transfers the focus down one focus traversal cycle. If this Container is
 3494        * a focus cycle root, then the focus owner is set to this Container's
 3495        * default Component to focus, and the current focus cycle root is set to
 3496        * this Container. If this Container is not a focus cycle root, then no
 3497        * focus traversal operation occurs.
 3498        *
 3499        * @see       Component#requestFocus()
 3500        * @see       #isFocusCycleRoot
 3501        * @see       #setFocusCycleRoot
 3502        * @since     1.4
 3503        */
 3504       public void transferFocusDownCycle() {
 3505           if (isFocusCycleRoot()) {
 3506               KeyboardFocusManager.getCurrentKeyboardFocusManager().
 3507                   setGlobalCurrentFocusCycleRoot(this);
 3508               Component toFocus = getFocusTraversalPolicy().
 3509                   getDefaultComponent(this);
 3510               if (toFocus != null) {
 3511                   toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN);
 3512               }
 3513           }
 3514       }
 3515   
 3516       void preProcessKeyEvent(KeyEvent e) {
 3517           Container parent = this.parent;
 3518           if (parent != null) {
 3519               parent.preProcessKeyEvent(e);
 3520           }
 3521       }
 3522   
 3523       void postProcessKeyEvent(KeyEvent e) {
 3524           Container parent = this.parent;
 3525           if (parent != null) {
 3526               parent.postProcessKeyEvent(e);
 3527           }
 3528       }
 3529   
 3530       boolean postsOldMouseEvents() {
 3531           return true;
 3532       }
 3533   
 3534       /**
 3535        * Sets the <code>ComponentOrientation</code> property of this container
 3536        * and all components contained within it.
 3537        * <p>
 3538        * This method changes layout-related information, and therefore,
 3539        * invalidates the component hierarchy.
 3540        *
 3541        * @param o the new component orientation of this container and
 3542        *        the components contained within it.
 3543        * @exception NullPointerException if <code>orientation</code> is null.
 3544        * @see Component#setComponentOrientation
 3545        * @see Component#getComponentOrientation
 3546        * @see #invalidate
 3547        * @since 1.4
 3548        */
 3549       public void applyComponentOrientation(ComponentOrientation o) {
 3550           super.applyComponentOrientation(o);
 3551           synchronized (getTreeLock()) {
 3552               for (int i = 0; i < component.size(); i++) {
 3553                   Component comp = component.get(i);
 3554                   comp.applyComponentOrientation(o);
 3555               }
 3556           }
 3557       }
 3558   
 3559       /**
 3560        * Adds a PropertyChangeListener to the listener list. The listener is
 3561        * registered for all bound properties of this class, including the
 3562        * following:
 3563        * <ul>
 3564        *    <li>this Container's font ("font")</li>
 3565        *    <li>this Container's background color ("background")</li>
 3566        *    <li>this Container's foreground color ("foreground")</li>
 3567        *    <li>this Container's focusability ("focusable")</li>
 3568        *    <li>this Container's focus traversal keys enabled state
 3569        *        ("focusTraversalKeysEnabled")</li>
 3570        *    <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
 3571        *        ("forwardFocusTraversalKeys")</li>
 3572        *    <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
 3573        *        ("backwardFocusTraversalKeys")</li>
 3574        *    <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
 3575        *        ("upCycleFocusTraversalKeys")</li>
 3576        *    <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
 3577        *        ("downCycleFocusTraversalKeys")</li>
 3578        *    <li>this Container's focus traversal policy ("focusTraversalPolicy")
 3579        *        </li>
 3580        *    <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
 3581        * </ul>
 3582        * Note that if this Container is inheriting a bound property, then no
 3583        * event will be fired in response to a change in the inherited property.
 3584        * <p>
 3585        * If listener is null, no exception is thrown and no action is performed.
 3586        *
 3587        * @param    listener  the PropertyChangeListener to be added
 3588        *
 3589        * @see Component#removePropertyChangeListener
 3590        * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 3591        */
 3592       public void addPropertyChangeListener(PropertyChangeListener listener) {
 3593           super.addPropertyChangeListener(listener);
 3594       }
 3595   
 3596       /**
 3597        * Adds a PropertyChangeListener to the listener list for a specific
 3598        * property. The specified property may be user-defined, or one of the
 3599        * following defaults:
 3600        * <ul>
 3601        *    <li>this Container's font ("font")</li>
 3602        *    <li>this Container's background color ("background")</li>
 3603        *    <li>this Container's foreground color ("foreground")</li>
 3604        *    <li>this Container's focusability ("focusable")</li>
 3605        *    <li>this Container's focus traversal keys enabled state
 3606        *        ("focusTraversalKeysEnabled")</li>
 3607        *    <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
 3608        *        ("forwardFocusTraversalKeys")</li>
 3609        *    <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
 3610        *        ("backwardFocusTraversalKeys")</li>
 3611        *    <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
 3612        *        ("upCycleFocusTraversalKeys")</li>
 3613        *    <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
 3614        *        ("downCycleFocusTraversalKeys")</li>
 3615        *    <li>this Container's focus traversal policy ("focusTraversalPolicy")
 3616        *        </li>
 3617        *    <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
 3618        *    <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
 3619        *    <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
 3620        * </ul>
 3621        * Note that if this Container is inheriting a bound property, then no
 3622        * event will be fired in response to a change in the inherited property.
 3623        * <p>
 3624        * If listener is null, no exception is thrown and no action is performed.
 3625        *
 3626        * @param propertyName one of the property names listed above
 3627        * @param listener the PropertyChangeListener to be added
 3628        *
 3629        * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
 3630        * @see Component#removePropertyChangeListener
 3631        */
 3632       public void addPropertyChangeListener(String propertyName,
 3633                                             PropertyChangeListener listener) {
 3634           super.addPropertyChangeListener(propertyName, listener);
 3635       }
 3636   
 3637       // Serialization support. A Container is responsible for restoring the
 3638       // parent fields of its component children.
 3639   
 3640       /**
 3641        * Container Serial Data Version.
 3642        */
 3643       private int containerSerializedDataVersion = 1;
 3644   
 3645       /**
 3646        * Serializes this <code>Container</code> to the specified
 3647        * <code>ObjectOutputStream</code>.
 3648        * <ul>
 3649        *    <li>Writes default serializable fields to the stream.</li>
 3650        *    <li>Writes a list of serializable ContainerListener(s) as optional
 3651        *        data. The non-serializable ContainerListner(s) are detected and
 3652        *        no attempt is made to serialize them.</li>
 3653        *    <li>Write this Container's FocusTraversalPolicy if and only if it
 3654        *        is Serializable; otherwise, <code>null</code> is written.</li>
 3655        * </ul>
 3656        *
 3657        * @param s the <code>ObjectOutputStream</code> to write
 3658        * @serialData <code>null</code> terminated sequence of 0 or more pairs;
 3659        *   the pair consists of a <code>String</code> and <code>Object</code>;
 3660        *   the <code>String</code> indicates the type of object and
 3661        *   is one of the following:
 3662        *   <code>containerListenerK</code> indicating an
 3663        *     <code>ContainerListener</code> object;
 3664        *   the <code>Container</code>'s <code>FocusTraversalPolicy</code>,
 3665        *     or <code>null</code>
 3666        *
 3667        * @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
 3668        * @see Container#containerListenerK
 3669        * @see #readObject(ObjectInputStream)
 3670        */
 3671       private void writeObject(ObjectOutputStream s) throws IOException {
 3672           ObjectOutputStream.PutField f = s.putFields();
 3673           f.put("ncomponents", component.size());
 3674           f.put("component", getComponentsSync());
 3675           f.put("layoutMgr", layoutMgr);
 3676           f.put("dispatcher", dispatcher);
 3677           f.put("maxSize", maxSize);
 3678           f.put("focusCycleRoot", focusCycleRoot);
 3679           f.put("containerSerializedDataVersion", containerSerializedDataVersion);
 3680           f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);
 3681           s.writeFields();
 3682   
 3683           AWTEventMulticaster.save(s, containerListenerK, containerListener);
 3684           s.writeObject(null);
 3685   
 3686           if (focusTraversalPolicy instanceof java.io.Serializable) {
 3687               s.writeObject(focusTraversalPolicy);
 3688           } else {
 3689               s.writeObject(null);
 3690           }
 3691       }
 3692   
 3693       /**
 3694        * Deserializes this <code>Container</code> from the specified
 3695        * <code>ObjectInputStream</code>.
 3696        * <ul>
 3697        *    <li>Reads default serializable fields from the stream.</li>
 3698        *    <li>Reads a list of serializable ContainerListener(s) as optional
 3699        *        data. If the list is null, no Listeners are installed.</li>
 3700        *    <li>Reads this Container's FocusTraversalPolicy, which may be null,
 3701        *        as optional data.</li>
 3702        * </ul>
 3703        *
 3704        * @param s the <code>ObjectInputStream</code> to read
 3705        * @serial
 3706        * @see #addContainerListener
 3707        * @see #writeObject(ObjectOutputStream)
 3708        */
 3709       private void readObject(ObjectInputStream s)
 3710           throws ClassNotFoundException, IOException
 3711       {
 3712           ObjectInputStream.GetField f = s.readFields();
 3713           Component [] tmpComponent = (Component[])f.get("component", EMPTY_ARRAY);
 3714           int ncomponents = (Integer) f.get("ncomponents", 0);
 3715           component = new java.util.ArrayList<Component>(ncomponents);
 3716           for (int i = 0; i < ncomponents; ++i) {
 3717               component.add(tmpComponent[i]);
 3718           }
 3719           layoutMgr = (LayoutManager)f.get("layoutMgr", null);
 3720           dispatcher = (LightweightDispatcher)f.get("dispatcher", null);
 3721           // Old stream. Doesn't contain maxSize among Component's fields.
 3722           if (maxSize == null) {
 3723               maxSize = (Dimension)f.get("maxSize", null);
 3724           }
 3725           focusCycleRoot = f.get("focusCycleRoot", false);
 3726           containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1);
 3727           focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false);
 3728           java.util.List<Component> component = this.component;
 3729           for(Component comp : component) {
 3730               comp.parent = this;
 3731               adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
 3732                                       comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
 3733               adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
 3734                                       comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
 3735               adjustDescendants(comp.countHierarchyMembers());
 3736           }
 3737   
 3738           Object keyOrNull;
 3739           while(null != (keyOrNull = s.readObject())) {
 3740               String key = ((String)keyOrNull).intern();
 3741   
 3742               if (containerListenerK == key) {
 3743                   addContainerListener((ContainerListener)(s.readObject()));
 3744               } else {
 3745                   // skip value for unrecognized key
 3746                   s.readObject();
 3747               }
 3748           }
 3749   
 3750           try {
 3751               Object policy = s.readObject();
 3752               if (policy instanceof FocusTraversalPolicy) {
 3753                   focusTraversalPolicy = (FocusTraversalPolicy)policy;
 3754               }
 3755           } catch (java.io.OptionalDataException e) {
 3756               // JDK 1.1/1.2/1.3 instances will not have this optional data.
 3757               // e.eof will be true to indicate that there is no more data
 3758               // available for this object. If e.eof is not true, throw the
 3759               // exception as it might have been caused by reasons unrelated to
 3760               // focusTraversalPolicy.
 3761   
 3762               if (!e.eof) {
 3763                   throw e;
 3764               }
 3765           }
 3766       }
 3767   
 3768       /*
 3769        * --- Accessibility Support ---
 3770        */
 3771   
 3772       /**
 3773        * Inner class of Container used to provide default support for
 3774        * accessibility.  This class is not meant to be used directly by
 3775        * application developers, but is instead meant only to be
 3776        * subclassed by container developers.
 3777        * <p>
 3778        * The class used to obtain the accessible role for this object,
 3779        * as well as implementing many of the methods in the
 3780        * AccessibleContainer interface.
 3781        * @since 1.3
 3782        */
 3783       protected class AccessibleAWTContainer extends AccessibleAWTComponent {
 3784   
 3785           /**
 3786            * JDK1.3 serialVersionUID
 3787            */
 3788           private static final long serialVersionUID = 5081320404842566097L;
 3789   
 3790           /**
 3791            * Returns the number of accessible children in the object.  If all
 3792            * of the children of this object implement <code>Accessible</code>,
 3793            * then this method should return the number of children of this object.
 3794            *
 3795            * @return the number of accessible children in the object
 3796            */
 3797           public int getAccessibleChildrenCount() {
 3798               return Container.this.getAccessibleChildrenCount();
 3799           }
 3800   
 3801           /**
 3802            * Returns the nth <code>Accessible</code> child of the object.
 3803            *
 3804            * @param i zero-based index of child
 3805            * @return the nth <code>Accessible</code> child of the object
 3806            */
 3807           public Accessible getAccessibleChild(int i) {
 3808               return Container.this.getAccessibleChild(i);
 3809           }
 3810   
 3811           /**
 3812            * Returns the <code>Accessible</code> child, if one exists,
 3813            * contained at the local coordinate <code>Point</code>.
 3814            *
 3815            * @param p the point defining the top-left corner of the
 3816            *    <code>Accessible</code>, given in the coordinate space
 3817            *    of the object's parent
 3818            * @return the <code>Accessible</code>, if it exists,
 3819            *    at the specified location; else <code>null</code>
 3820            */
 3821           public Accessible getAccessibleAt(Point p) {
 3822               return Container.this.getAccessibleAt(p);
 3823           }
 3824   
 3825           protected ContainerListener accessibleContainerHandler = null;
 3826   
 3827           /**
 3828            * Fire <code>PropertyChange</code> listener, if one is registered,
 3829            * when children are added or removed.
 3830            * @since 1.3
 3831            */
 3832           protected class AccessibleContainerHandler
 3833               implements ContainerListener {
 3834               public void componentAdded(ContainerEvent e) {
 3835                   Component c = e.getChild();
 3836                   if (c != null && c instanceof Accessible) {
 3837                       AccessibleAWTContainer.this.firePropertyChange(
 3838                           AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
 3839                           null, ((Accessible) c).getAccessibleContext());
 3840                   }
 3841               }
 3842               public void componentRemoved(ContainerEvent e) {
 3843                   Component c = e.getChild();
 3844                   if (c != null && c instanceof Accessible) {
 3845                       AccessibleAWTContainer.this.firePropertyChange(
 3846                           AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
 3847                           ((Accessible) c).getAccessibleContext(), null);
 3848                   }
 3849               }
 3850           }
 3851   
 3852           /**
 3853            * Adds a PropertyChangeListener to the listener list.
 3854            *
 3855            * @param listener  the PropertyChangeListener to be added
 3856            */
 3857           public void addPropertyChangeListener(PropertyChangeListener listener) {
 3858               if (accessibleContainerHandler == null) {
 3859                   accessibleContainerHandler = new AccessibleContainerHandler();
 3860                   Container.this.addContainerListener(accessibleContainerHandler);
 3861               }
 3862               super.addPropertyChangeListener(listener);
 3863           }
 3864   
 3865       } // inner class AccessibleAWTContainer
 3866   
 3867       /**
 3868        * Returns the <code>Accessible</code> child contained at the local
 3869        * coordinate <code>Point</code>, if one exists.  Otherwise
 3870        * returns <code>null</code>.
 3871        *
 3872        * @param p the point defining the top-left corner of the
 3873        *    <code>Accessible</code>, given in the coordinate space
 3874        *    of the object's parent
 3875        * @return the <code>Accessible</code> at the specified location,
 3876        *    if it exists; otherwise <code>null</code>
 3877        */
 3878       Accessible getAccessibleAt(Point p) {
 3879           synchronized (getTreeLock()) {
 3880               if (this instanceof Accessible) {
 3881                   Accessible a = (Accessible)this;
 3882                   AccessibleContext ac = a.getAccessibleContext();
 3883                   if (ac != null) {
 3884                       AccessibleComponent acmp;
 3885                       Point location;
 3886                       int nchildren = ac.getAccessibleChildrenCount();
 3887                       for (int i=0; i < nchildren; i++) {
 3888                           a = ac.getAccessibleChild(i);
 3889                           if ((a != null)) {
 3890                               ac = a.getAccessibleContext();
 3891                               if (ac != null) {
 3892                                   acmp = ac.getAccessibleComponent();
 3893                                   if ((acmp != null) && (acmp.isShowing())) {
 3894                                       location = acmp.getLocation();
 3895                                       Point np = new Point(p.x-location.x,
 3896                                                            p.y-location.y);
 3897                                       if (acmp.contains(np)){
 3898                                           return a;
 3899                                       }
 3900                                   }
 3901                               }
 3902                           }
 3903                       }
 3904                   }
 3905                   return (Accessible)this;
 3906               } else {
 3907                   Component ret = this;
 3908                   if (!this.contains(p.x,p.y)) {
 3909                       ret = null;
 3910                   } else {
 3911                       int ncomponents = this.getComponentCount();
 3912                       for (int i=0; i < ncomponents; i++) {
 3913                           Component comp = this.getComponent(i);
 3914                           if ((comp != null) && comp.isShowing()) {
 3915                               Point location = comp.getLocation();
 3916                               if (comp.contains(p.x-location.x,p.y-location.y)) {
 3917                                   ret = comp;
 3918                               }
 3919                           }
 3920                       }
 3921                   }
 3922                   if (ret instanceof Accessible) {
 3923                       return (Accessible) ret;
 3924                   }
 3925               }
 3926               return null;
 3927           }
 3928       }
 3929   
 3930       /**
 3931        * Returns the number of accessible children in the object.  If all
 3932        * of the children of this object implement <code>Accessible</code>,
 3933        * then this method should return the number of children of this object.
 3934        *
 3935        * @return the number of accessible children in the object
 3936        */
 3937       int getAccessibleChildrenCount() {
 3938           synchronized (getTreeLock()) {
 3939               int count = 0;
 3940               Component[] children = this.getComponents();
 3941               for (int i = 0; i < children.length; i++) {
 3942                   if (children[i] instanceof Accessible) {
 3943                       count++;
 3944                   }
 3945               }
 3946               return count;
 3947           }
 3948       }
 3949   
 3950       /**
 3951        * Returns the nth <code>Accessible</code> child of the object.
 3952        *
 3953        * @param i zero-based index of child
 3954        * @return the nth <code>Accessible</code> child of the object
 3955        */
 3956       Accessible getAccessibleChild(int i) {
 3957           synchronized (getTreeLock()) {
 3958               Component[] children = this.getComponents();
 3959               int count = 0;
 3960               for (int j = 0; j < children.length; j++) {
 3961                   if (children[j] instanceof Accessible) {
 3962                       if (count == i) {
 3963                           return (Accessible) children[j];
 3964                       } else {
 3965                           count++;
 3966                       }
 3967                   }
 3968               }
 3969               return null;
 3970           }
 3971       }
 3972   
 3973       // ************************** MIXING CODE *******************************
 3974   
 3975       final void increaseComponentCount(Component c) {
 3976           synchronized (getTreeLock()) {
 3977               if (!c.isDisplayable()) {
 3978                   throw new IllegalStateException(
 3979                       "Peer does not exist while invoking the increaseComponentCount() method"
 3980                   );
 3981               }
 3982   
 3983               int addHW = 0;
 3984               int addLW = 0;
 3985   
 3986               if (c instanceof Container) {
 3987                   addLW = ((Container)c).numOfLWComponents;
 3988                   addHW = ((Container)c).numOfHWComponents;
 3989               }
 3990               if (c.isLightweight()) {
 3991                   addLW++;
 3992               } else {
 3993                   addHW++;
 3994               }
 3995   
 3996               for (Container cont = this; cont != null; cont = cont.getContainer()) {
 3997                   cont.numOfLWComponents += addLW;
 3998                   cont.numOfHWComponents += addHW;
 3999               }
 4000           }
 4001       }
 4002   
 4003       final void decreaseComponentCount(Component c) {
 4004           synchronized (getTreeLock()) {
 4005               if (!c.isDisplayable()) {
 4006                   throw new IllegalStateException(
 4007                       "Peer does not exist while invoking the decreaseComponentCount() method"
 4008                   );
 4009               }
 4010   
 4011               int subHW = 0;
 4012               int subLW = 0;
 4013   
 4014               if (c instanceof Container) {
 4015                   subLW = ((Container)c).numOfLWComponents;
 4016                   subHW = ((Container)c).numOfHWComponents;
 4017               }
 4018               if (c.isLightweight()) {
 4019                   subLW++;
 4020               } else {
 4021                   subHW++;
 4022               }
 4023   
 4024               for (Container cont = this; cont != null; cont = cont.getContainer()) {
 4025                   cont.numOfLWComponents -= subLW;
 4026                   cont.numOfHWComponents -= subHW;
 4027               }
 4028           }
 4029       }
 4030   
 4031       private int getTopmostComponentIndex() {
 4032           checkTreeLock();
 4033           if (getComponentCount() > 0) {
 4034               return 0;
 4035           }
 4036           return -1;
 4037       }
 4038   
 4039       private int getBottommostComponentIndex() {
 4040           checkTreeLock();
 4041           if (getComponentCount() > 0) {
 4042               return getComponentCount() - 1;
 4043           }
 4044           return -1;
 4045       }
 4046   
 4047       /*
 4048        * This method is overriden to handle opaque children in non-opaque
 4049        * containers.
 4050        */
 4051       @Override
 4052       final Region getOpaqueShape() {
 4053           checkTreeLock();
 4054           if (isLightweight() && isNonOpaqueForMixing()
 4055                   && hasLightweightDescendants())
 4056           {
 4057               Region s = Region.EMPTY_REGION;
 4058               for (int index = 0; index < getComponentCount(); index++) {
 4059                   Component c = getComponent(index);
 4060                   if (c.isLightweight() && c.isShowing()) {
 4061                       s = s.getUnion(c.getOpaqueShape());
 4062                   }
 4063               }
 4064               return s.getIntersection(getNormalShape());
 4065           }
 4066           return super.getOpaqueShape();
 4067       }
 4068   
 4069       final void recursiveSubtractAndApplyShape(Region shape) {
 4070           recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex());
 4071       }
 4072   
 4073       final void recursiveSubtractAndApplyShape(Region shape, int fromZorder) {
 4074           recursiveSubtractAndApplyShape(shape, fromZorder, getBottommostComponentIndex());
 4075       }
 4076   
 4077       final void recursiveSubtractAndApplyShape(Region shape, int fromZorder, int toZorder) {
 4078           checkTreeLock();
 4079           if (mixingLog.isLoggable(PlatformLogger.FINE)) {
 4080               mixingLog.fine("this = " + this +
 4081                   "; shape=" + shape + "; fromZ=" + fromZorder + "; toZ=" + toZorder);
 4082           }
 4083           if (fromZorder == -1) {
 4084               return;
 4085           }
 4086           if (shape.isEmpty()) {
 4087               return;
 4088           }
 4089           // An invalid container with not-null layout should be ignored
 4090           // by the mixing code, the container will be validated later
 4091           // and the mixing code will be executed later.
 4092           if (getLayout() != null && !isValid()) {
 4093               return;
 4094           }
 4095           for (int index = fromZorder; index <= toZorder; index++) {
 4096               Component comp = getComponent(index);
 4097               if (!comp.isLightweight()) {
 4098                   comp.subtractAndApplyShape(shape);
 4099               } else if (comp instanceof Container &&
 4100                       ((Container)comp).hasHeavyweightDescendants() && comp.isShowing()) {
 4101                   ((Container)comp).recursiveSubtractAndApplyShape(shape);
 4102               }
 4103           }
 4104       }
 4105   
 4106       final void recursiveApplyCurrentShape() {
 4107           recursiveApplyCurrentShape(getTopmostComponentIndex(), getBottommostComponentIndex());
 4108       }
 4109   
 4110       final void recursiveApplyCurrentShape(int fromZorder) {
 4111           recursiveApplyCurrentShape(fromZorder, getBottommostComponentIndex());
 4112       }
 4113   
 4114       final void recursiveApplyCurrentShape(int fromZorder, int toZorder) {
 4115           checkTreeLock();
 4116           if (mixingLog.isLoggable(PlatformLogger.FINE)) {
 4117               mixingLog.fine("this = " + this +
 4118                   "; fromZ=" + fromZorder + "; toZ=" + toZorder);
 4119           }
 4120           if (fromZorder == -1) {
 4121               return;
 4122           }
 4123           // An invalid container with not-null layout should be ignored
 4124           // by the mixing code, the container will be validated later
 4125           // and the mixing code will be executed later.
 4126           if (getLayout() != null && !isValid()) {
 4127               return;
 4128           }
 4129           for (int index = fromZorder; index <= toZorder; index++) {
 4130               Component comp = getComponent(index);
 4131               if (!comp.isLightweight()) {
 4132                   comp.applyCurrentShape();
 4133               }
 4134               if (comp instanceof Container &&
 4135                       ((Container)comp).hasHeavyweightDescendants()) {
 4136                   ((Container)comp).recursiveApplyCurrentShape();
 4137               }
 4138           }
 4139       }
 4140   
 4141       private void recursiveShowHeavyweightChildren() {
 4142           if (!hasHeavyweightDescendants() || !isVisible()) {
 4143               return;
 4144           }
 4145           for (int index = 0; index < getComponentCount(); index++) {
 4146               Component comp = getComponent(index);
 4147               if (comp.isLightweight()) {
 4148                   if  (comp instanceof Container) {
 4149                       ((Container)comp).recursiveShowHeavyweightChildren();
 4150                   }
 4151               } else {
 4152                   if (comp.isVisible()) {
 4153                       ComponentPeer peer = comp.getPeer();
 4154                       if (peer != null) {
 4155                           peer.setVisible(true);
 4156                       }
 4157                   }
 4158               }
 4159           }
 4160       }
 4161   
 4162       private void recursiveHideHeavyweightChildren() {
 4163           if (!hasHeavyweightDescendants()) {
 4164               return;
 4165           }
 4166           for (int index = 0; index < getComponentCount(); index++) {
 4167               Component comp = getComponent(index);
 4168               if (comp.isLightweight()) {
 4169                   if  (comp instanceof Container) {
 4170                       ((Container)comp).recursiveHideHeavyweightChildren();
 4171                   }
 4172               } else {
 4173                   if (comp.isVisible()) {
 4174                       ComponentPeer peer = comp.getPeer();
 4175                       if (peer != null) {
 4176                           peer.setVisible(false);
 4177                       }
 4178                   }
 4179               }
 4180           }
 4181       }
 4182   
 4183       private void recursiveRelocateHeavyweightChildren(Point origin) {
 4184           for (int index = 0; index < getComponentCount(); index++) {
 4185               Component comp = getComponent(index);
 4186               if (comp.isLightweight()) {
 4187                   if  (comp instanceof Container &&
 4188                           ((Container)comp).hasHeavyweightDescendants())
 4189                   {
 4190                       final Point newOrigin = new Point(origin);
 4191                       newOrigin.translate(comp.getX(), comp.getY());
 4192                       ((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);
 4193                   }
 4194               } else {
 4195                   ComponentPeer peer = comp.getPeer();
 4196                   if (peer != null) {
 4197                       peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),
 4198                               comp.getWidth(), comp.getHeight(),
 4199                               ComponentPeer.SET_LOCATION);
 4200                   }
 4201               }
 4202           }
 4203       }
 4204   
 4205       /**
 4206        * Checks if the container and its direct lightweight containers are
 4207        * visible.
 4208        *
 4209        * Consider the heavyweight container hides or shows the HW descendants
 4210        * automatically. Therefore we care of LW containers' visibility only.
 4211        *
 4212        * This method MUST be invoked under the TreeLock.
 4213        */
 4214       final boolean isRecursivelyVisibleUpToHeavyweightContainer() {
 4215           if (!isLightweight()) {
 4216               return true;
 4217           }
 4218   
 4219           for (Container cont = this;
 4220                   cont != null && cont.isLightweight();
 4221                   cont = cont.getContainer())
 4222           {
 4223               if (!cont.isVisible()) {
 4224                   return false;
 4225               }
 4226           }
 4227           return true;
 4228       }
 4229   
 4230       @Override
 4231       void mixOnShowing() {
 4232           synchronized (getTreeLock()) {
 4233               if (mixingLog.isLoggable(PlatformLogger.FINE)) {
 4234                   mixingLog.fine("this = " + this);
 4235               }
 4236   
 4237               boolean isLightweight = isLightweight();
 4238   
 4239               if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {
 4240                   recursiveShowHeavyweightChildren();
 4241               }
 4242   
 4243               if (!isMixingNeeded()) {
 4244                   return;
 4245               }
 4246   
 4247               if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {
 4248                   recursiveApplyCurrentShape();
 4249               }
 4250   
 4251               super.mixOnShowing();
 4252           }
 4253       }
 4254   
 4255       @Override
 4256       void mixOnHiding(boolean isLightweight) {
 4257           synchronized (getTreeLock()) {
 4258               if (mixingLog.isLoggable(PlatformLogger.FINE)) {
 4259                   mixingLog.fine("this = " + this +
 4260                           "; isLightweight=" + isLightweight);
 4261               }
 4262               if (isLightweight) {
 4263                   recursiveHideHeavyweightChildren();
 4264               }
 4265               super.mixOnHiding(isLightweight);
 4266           }
 4267       }
 4268   
 4269       @Override
 4270       void mixOnReshaping() {
 4271           synchronized (getTreeLock()) {
 4272               if (mixingLog.isLoggable(PlatformLogger.FINE)) {
 4273                   mixingLog.fine("this = " + this);
 4274               }
 4275   
 4276               boolean isMixingNeeded = isMixingNeeded();
 4277   
 4278               if (isLightweight() && hasHeavyweightDescendants()) {
 4279                   final Point origin = new Point(getX(), getY());
 4280                   for (Container cont = getContainer();
 4281                           cont != null && cont.isLightweight();
 4282                           cont = cont.getContainer())
 4283                   {
 4284                       origin.translate(cont.getX(), cont.getY());
 4285                   }
 4286   
 4287                   recursiveRelocateHeavyweightChildren(origin);
 4288   
 4289                   if (!isMixingNeeded) {
 4290                       return;
 4291                   }
 4292   
 4293                   recursiveApplyCurrentShape();
 4294               }
 4295   
 4296               if (!isMixingNeeded) {
 4297                   return;
 4298               }
 4299   
 4300               super.mixOnReshaping();
 4301           }
 4302       }
 4303   
 4304       @Override
 4305       void mixOnZOrderChanging(int oldZorder, int newZorder) {
 4306           synchronized (getTreeLock()) {
 4307               if (mixingLog.isLoggable(PlatformLogger.FINE)) {
 4308                   mixingLog.fine("this = " + this +
 4309                       "; oldZ=" + oldZorder + "; newZ=" + newZorder);
 4310               }
 4311   
 4312               if (!isMixingNeeded()) {
 4313                   return;
 4314               }
 4315   
 4316               boolean becameHigher = newZorder < oldZorder;
 4317   
 4318               if (becameHigher && isLightweight() && hasHeavyweightDescendants()) {
 4319                   recursiveApplyCurrentShape();
 4320               }
 4321               super.mixOnZOrderChanging(oldZorder, newZorder);
 4322           }
 4323       }
 4324   
 4325       @Override
 4326       void mixOnValidating() {
 4327           synchronized (getTreeLock()) {
 4328               if (mixingLog.isLoggable(PlatformLogger.FINE)) {
 4329                   mixingLog.fine("this = " + this);
 4330               }
 4331   
 4332               if (!isMixingNeeded()) {
 4333                   return;
 4334               }
 4335   
 4336               if (hasHeavyweightDescendants()) {
 4337                   recursiveApplyCurrentShape();
 4338               }
 4339   
 4340               if (isLightweight() && isNonOpaqueForMixing()) {
 4341                   subtractAndApplyShapeBelowMe();
 4342               }
 4343   
 4344               super.mixOnValidating();
 4345           }
 4346       }
 4347   
 4348       // ****************** END OF MIXING CODE ********************************
 4349   }
 4350   
 4351   
 4352   /**
 4353    * Class to manage the dispatching of MouseEvents to the lightweight descendants
 4354    * and SunDropTargetEvents to both lightweight and heavyweight descendants
 4355    * contained by a native container.
 4356    *
 4357    * NOTE: the class name is not appropriate anymore, but we cannot change it
 4358    * because we must keep serialization compatibility.
 4359    *
 4360    * @author Timothy Prinzing
 4361    */
 4362   class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
 4363   
 4364       /*
 4365        * JDK 1.1 serialVersionUID
 4366        */
 4367       private static final long serialVersionUID = 5184291520170872969L;
 4368       /*
 4369        * Our own mouse event for when we're dragged over from another hw
 4370        * container
 4371        */
 4372       private static final int  LWD_MOUSE_DRAGGED_OVER = 1500;
 4373   
 4374       private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher");
 4375   
 4376       LightweightDispatcher(Container nativeContainer) {
 4377           this.nativeContainer = nativeContainer;
 4378           mouseEventTarget = null;
 4379           eventMask = 0;
 4380       }
 4381   
 4382       /*
 4383        * Clean up any resources allocated when dispatcher was created;
 4384        * should be called from Container.removeNotify
 4385        */
 4386       void dispose() {
 4387           //System.out.println("Disposing lw dispatcher");
 4388           stopListeningForOtherDrags();
 4389           mouseEventTarget = null;
 4390       }
 4391   
 4392       /**
 4393        * Enables events to subcomponents.
 4394        */
 4395       void enableEvents(long events) {
 4396           eventMask |= events;
 4397       }
 4398   
 4399       /**
 4400        * Dispatches an event to a sub-component if necessary, and
 4401        * returns whether or not the event was forwarded to a
 4402        * sub-component.
 4403        *
 4404        * @param e the event
 4405        */
 4406       boolean dispatchEvent(AWTEvent e) {
 4407           boolean ret = false;
 4408   
 4409           /*
 4410            * Fix for BugTraq Id 4389284.
 4411            * Dispatch SunDropTargetEvents regardless of eventMask value.
 4412            * Do not update cursor on dispatching SunDropTargetEvents.
 4413            */
 4414           if (e instanceof SunDropTargetEvent) {
 4415   
 4416               SunDropTargetEvent sdde = (SunDropTargetEvent) e;
 4417               ret = processDropTargetEvent(sdde);
 4418   
 4419           } else {
 4420               if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) {
 4421                   MouseEvent me = (MouseEvent) e;
 4422                   ret = processMouseEvent(me);
 4423               }
 4424   
 4425               if (e.getID() == MouseEvent.MOUSE_MOVED) {
 4426                   nativeContainer.updateCursorImmediately();
 4427               }
 4428           }
 4429   
 4430           return ret;
 4431       }
 4432   
 4433       /* This method effectively returns whether or not a mouse button was down
 4434        * just BEFORE the event happened.  A better method name might be
 4435        * wasAMouseButtonDownBeforeThisEvent().
 4436        */
 4437       private boolean isMouseGrab(MouseEvent e) {
 4438           int modifiers = e.getModifiersEx();
 4439   
 4440           if(e.getID() == MouseEvent.MOUSE_PRESSED
 4441               || e.getID() == MouseEvent.MOUSE_RELEASED)
 4442           {
 4443               switch (e.getButton()) {
 4444               case MouseEvent.BUTTON1:
 4445                   modifiers ^= InputEvent.BUTTON1_DOWN_MASK;
 4446                   break;
 4447               case MouseEvent.BUTTON2:
 4448                   modifiers ^= InputEvent.BUTTON2_DOWN_MASK;
 4449                   break;
 4450               case MouseEvent.BUTTON3:
 4451                   modifiers ^= InputEvent.BUTTON3_DOWN_MASK;
 4452                   break;
 4453               }
 4454           }
 4455           /* modifiers now as just before event */
 4456           return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK
 4457                                 | InputEvent.BUTTON2_DOWN_MASK
 4458                                 | InputEvent.BUTTON3_DOWN_MASK)) != 0);
 4459       }
 4460   
 4461       /**
 4462        * This method attempts to distribute a mouse event to a lightweight
 4463        * component.  It tries to avoid doing any unnecessary probes down
 4464        * into the component tree to minimize the overhead of determining
 4465        * where to route the event, since mouse movement events tend to
 4466        * come in large and frequent amounts.
 4467        */
 4468       private boolean processMouseEvent(MouseEvent e) {
 4469           int id = e.getID();
 4470           Component mouseOver =   // sensitive to mouse events
 4471               nativeContainer.getMouseEventTarget(e.getX(), e.getY(),
 4472                                                   Container.INCLUDE_SELF);
 4473   
 4474           trackMouseEnterExit(mouseOver, e);
 4475   
 4476       // 4508327 : MOUSE_CLICKED should only go to the recipient of
 4477       // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
 4478       // MOUSE_CLICKED.
 4479       if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
 4480               mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null;
 4481           }
 4482   
 4483           if (mouseEventTarget != null) {
 4484               switch (id) {
 4485               case MouseEvent.MOUSE_ENTERED:
 4486               case MouseEvent.MOUSE_EXITED:
 4487                   break;
 4488               case MouseEvent.MOUSE_PRESSED:
 4489                   retargetMouseEvent(mouseEventTarget, id, e);
 4490                   break;
 4491           case MouseEvent.MOUSE_RELEASED:
 4492               retargetMouseEvent(mouseEventTarget, id, e);
 4493           break;
 4494           case MouseEvent.MOUSE_CLICKED:
 4495           // 4508327: MOUSE_CLICKED should never be dispatched to a Component
 4496           // other than that which received the MOUSE_PRESSED event.  If the
 4497           // mouse is now over a different Component, don't dispatch the event.
 4498           // The previous fix for a similar problem was associated with bug
 4499           // 4155217.
 4500           if (mouseOver == mouseEventTarget) {
 4501               retargetMouseEvent(mouseOver, id, e);
 4502           }
 4503           break;
 4504               case MouseEvent.MOUSE_MOVED:
 4505                   retargetMouseEvent(mouseEventTarget, id, e);
 4506                   break;
 4507           case MouseEvent.MOUSE_DRAGGED:
 4508               if (isMouseGrab(e)) {
 4509                   retargetMouseEvent(mouseEventTarget, id, e);
 4510               }
 4511                   break;
 4512           case MouseEvent.MOUSE_WHEEL:
 4513               // This may send it somewhere that doesn't have MouseWheelEvents
 4514               // enabled.  In this case, Component.dispatchEventImpl() will
 4515               // retarget the event to a parent that DOES have the events enabled.
 4516               if (eventLog.isLoggable(PlatformLogger.FINEST) && (mouseOver != null)) {
 4517                   eventLog.finest("retargeting mouse wheel to " +
 4518                                   mouseOver.getName() + ", " +
 4519                                   mouseOver.getClass());
 4520               }
 4521               retargetMouseEvent(mouseOver, id, e);
 4522           break;
 4523               }
 4524               //Consuming of wheel events is implemented in "retargetMouseEvent".
 4525               if (id != MouseEvent.MOUSE_WHEEL) {
 4526                   e.consume();
 4527               }
 4528       }
 4529       return e.isConsumed();
 4530       }
 4531   
 4532       private boolean processDropTargetEvent(SunDropTargetEvent e) {
 4533           int id = e.getID();
 4534           int x = e.getX();
 4535           int y = e.getY();
 4536   
 4537           /*
 4538            * Fix for BugTraq ID 4395290.
 4539            * It is possible that SunDropTargetEvent's Point is outside of the
 4540            * native container bounds. In this case we truncate coordinates.
 4541            */
 4542           if (!nativeContainer.contains(x, y)) {
 4543               final Dimension d = nativeContainer.getSize();
 4544               if (d.width <= x) {
 4545                   x = d.width - 1;
 4546               } else if (x < 0) {
 4547                   x = 0;
 4548               }
 4549               if (d.height <= y) {
 4550                   y = d.height - 1;
 4551               } else if (y < 0) {
 4552                   y = 0;
 4553               }
 4554           }
 4555           Component mouseOver =   // not necessarily sensitive to mouse events
 4556               nativeContainer.getDropTargetEventTarget(x, y,
 4557                                                        Container.INCLUDE_SELF);
 4558           trackMouseEnterExit(mouseOver, e);
 4559   
 4560           if (mouseOver != nativeContainer && mouseOver != null) {
 4561               switch (id) {
 4562               case SunDropTargetEvent.MOUSE_ENTERED:
 4563               case SunDropTargetEvent.MOUSE_EXITED:
 4564                   break;
 4565               default:
 4566                   retargetMouseEvent(mouseOver, id, e);
 4567                   e.consume();
 4568                   break;
 4569               }
 4570           }
 4571           return e.isConsumed();
 4572       }
 4573   
 4574       /*
 4575        * Generates enter/exit events as mouse moves over lw components
 4576        * @param targetOver        Target mouse is over (including native container)
 4577        * @param e                 Mouse event in native container
 4578        */
 4579       private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
 4580           Component       targetEnter = null;
 4581           int             id = e.getID();
 4582   
 4583           if (e instanceof SunDropTargetEvent &&
 4584               id == MouseEvent.MOUSE_ENTERED &&
 4585               isMouseInNativeContainer == true) {
 4586               // This can happen if a lightweight component which initiated the
 4587               // drag has an associated drop target. MOUSE_ENTERED comes when the
 4588               // mouse is in the native container already. To propagate this event
 4589               // properly we should null out targetLastEntered.
 4590               targetLastEntered = null;
 4591           } else if ( id != MouseEvent.MOUSE_EXITED &&
 4592                id != MouseEvent.MOUSE_DRAGGED &&
 4593                id != LWD_MOUSE_DRAGGED_OVER &&
 4594                isMouseInNativeContainer == false ) {
 4595               // any event but an exit or drag means we're in the native container
 4596               isMouseInNativeContainer = true;
 4597               startListeningForOtherDrags();
 4598           } else if ( id == MouseEvent.MOUSE_EXITED ) {
 4599               isMouseInNativeContainer = false;
 4600               stopListeningForOtherDrags();
 4601           }
 4602   
 4603           if (isMouseInNativeContainer) {
 4604               targetEnter = targetOver;
 4605           }
 4606   
 4607           if (targetLastEntered == targetEnter) {
 4608                   return;
 4609           }
 4610   
 4611           if (targetLastEntered != null) {
 4612               retargetMouseEvent(targetLastEntered, MouseEvent.MOUSE_EXITED, e);
 4613           }
 4614           if (id == MouseEvent.MOUSE_EXITED) {
 4615               // consume native exit event if we generate one
 4616               e.consume();
 4617           }
 4618   
 4619           if (targetEnter != null) {
 4620               retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
 4621           }
 4622           if (id == MouseEvent.MOUSE_ENTERED) {
 4623               // consume native enter event if we generate one
 4624               e.consume();
 4625           }
 4626   
 4627           targetLastEntered = targetEnter;
 4628       }
 4629   
 4630       /*
 4631        * Listens to global mouse drag events so even drags originating
 4632        * from other heavyweight containers will generate enter/exit
 4633        * events in this container
 4634        */
 4635       private void startListeningForOtherDrags() {
 4636           //System.out.println("Adding AWTEventListener");
 4637           java.security.AccessController.doPrivileged(
 4638               new java.security.PrivilegedAction() {
 4639                   public Object run() {
 4640                       nativeContainer.getToolkit().addAWTEventListener(
 4641                           LightweightDispatcher.this,
 4642                           AWTEvent.MOUSE_EVENT_MASK |
 4643                           AWTEvent.MOUSE_MOTION_EVENT_MASK);
 4644                       return null;
 4645                   }
 4646               }
 4647           );
 4648       }
 4649   
 4650       private void stopListeningForOtherDrags() {
 4651           //System.out.println("Removing AWTEventListener");
 4652           java.security.AccessController.doPrivileged(
 4653               new java.security.PrivilegedAction() {
 4654                   public Object run() {
 4655                       nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);
 4656                       return null;
 4657                   }
 4658               }
 4659           );
 4660       }
 4661   
 4662       /*
 4663        * (Implementation of AWTEventListener)
 4664        * Listen for drag events posted in other hw components so we can
 4665        * track enter/exit regardless of where a drag originated
 4666        */
 4667       public void eventDispatched(AWTEvent e) {
 4668           boolean isForeignDrag = (e instanceof MouseEvent) &&
 4669                                   !(e instanceof SunDropTargetEvent) &&
 4670                                   (e.id == MouseEvent.MOUSE_DRAGGED) &&
 4671                                   (e.getSource() != nativeContainer);
 4672   
 4673           if (!isForeignDrag) {
 4674               // only interested in drags from other hw components
 4675               return;
 4676           }
 4677   
 4678           MouseEvent      srcEvent = (MouseEvent)e;
 4679           MouseEvent      me;
 4680   
 4681           synchronized (nativeContainer.getTreeLock()) {
 4682               Component srcComponent = srcEvent.getComponent();
 4683   
 4684               // component may have disappeared since drag event posted
 4685               // (i.e. Swing hierarchical menus)
 4686               if ( !srcComponent.isShowing() ) {
 4687                   return;
 4688               }
 4689   
 4690               // see 5083555
 4691               // check if srcComponent is in any modal blocked window
 4692               Component c = nativeContainer;
 4693               while ((c != null) && !(c instanceof Window)) {
 4694                   c = c.getParent_NoClientCode();
 4695               }
 4696               if ((c == null) || ((Window)c).isModalBlocked()) {
 4697                   return;
 4698               }
 4699   
 4700               //
 4701               // create an internal 'dragged-over' event indicating
 4702               // we are being dragged over from another hw component
 4703               //
 4704               me = new MouseEvent(nativeContainer,
 4705                                  LWD_MOUSE_DRAGGED_OVER,
 4706                                  srcEvent.getWhen(),
 4707                                  srcEvent.getModifiersEx() | srcEvent.getModifiers(),
 4708                                  srcEvent.getX(),
 4709                                  srcEvent.getY(),
 4710                                  srcEvent.getXOnScreen(),
 4711                                  srcEvent.getYOnScreen(),
 4712                                  srcEvent.getClickCount(),
 4713                                  srcEvent.isPopupTrigger(),
 4714                                  srcEvent.getButton());
 4715               ((AWTEvent)srcEvent).copyPrivateDataInto(me);
 4716               // translate coordinates to this native container
 4717               final Point ptSrcOrigin = srcComponent.getLocationOnScreen();
 4718   
 4719               if (AppContext.getAppContext() != nativeContainer.appContext) {
 4720                   final MouseEvent mouseEvent = me;
 4721                   Runnable r = new Runnable() {
 4722                           public void run() {
 4723                               if (!nativeContainer.isShowing() ) {
 4724                                   return;
 4725                               }
 4726   
 4727                               Point       ptDstOrigin = nativeContainer.getLocationOnScreen();
 4728                               mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x,
 4729                                                 ptSrcOrigin.y - ptDstOrigin.y );
 4730                               Component targetOver =
 4731                                   nativeContainer.getMouseEventTarget(mouseEvent.getX(),
 4732                                                                       mouseEvent.getY(),
 4733                                                                       Container.INCLUDE_SELF);
 4734                               trackMouseEnterExit(targetOver, mouseEvent);
 4735                           }
 4736                       };
 4737                   SunToolkit.executeOnEventHandlerThread(nativeContainer, r);
 4738                   return;
 4739               } else {
 4740                   if (!nativeContainer.isShowing() ) {
 4741                       return;
 4742                   }
 4743   
 4744                   Point   ptDstOrigin = nativeContainer.getLocationOnScreen();
 4745                   me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );
 4746               }
 4747           }
 4748           //System.out.println("Track event: " + me);
 4749           // feed the 'dragged-over' event directly to the enter/exit
 4750           // code (not a real event so don't pass it to dispatchEvent)
 4751           Component targetOver =
 4752               nativeContainer.getMouseEventTarget(me.getX(), me.getY(),
 4753                                                   Container.INCLUDE_SELF);
 4754           trackMouseEnterExit(targetOver, me);
 4755       }
 4756   
 4757       /**
 4758        * Sends a mouse event to the current mouse event recipient using
 4759        * the given event (sent to the windowed host) as a srcEvent.  If
 4760        * the mouse event target is still in the component tree, the
 4761        * coordinates of the event are translated to those of the target.
 4762        * If the target has been removed, we don't bother to send the
 4763        * message.
 4764        */
 4765       void retargetMouseEvent(Component target, int id, MouseEvent e) {
 4766           if (target == null) {
 4767               return; // mouse is over another hw component or target is disabled
 4768           }
 4769   
 4770           int x = e.getX(), y = e.getY();
 4771           Component component;
 4772   
 4773           for(component = target;
 4774               component != null && component != nativeContainer;
 4775               component = component.getParent()) {
 4776               x -= component.x;
 4777               y -= component.y;
 4778           }
 4779           MouseEvent retargeted;
 4780           if (component != null) {
 4781               if (e instanceof SunDropTargetEvent) {
 4782                   retargeted = new SunDropTargetEvent(target,
 4783                                                       id,
 4784                                                       x,
 4785                                                       y,
 4786                                                       ((SunDropTargetEvent)e).getDispatcher());
 4787               } else if (id == MouseEvent.MOUSE_WHEEL) {
 4788                   retargeted = new MouseWheelEvent(target,
 4789                                         id,
 4790                                          e.getWhen(),
 4791                                          e.getModifiersEx() | e.getModifiers(),
 4792                                          x,
 4793                                          y,
 4794                                          e.getXOnScreen(),
 4795                                          e.getYOnScreen(),
 4796                                          e.getClickCount(),
 4797                                          e.isPopupTrigger(),
 4798                                          ((MouseWheelEvent)e).getScrollType(),
 4799                                          ((MouseWheelEvent)e).getScrollAmount(),
 4800                                          ((MouseWheelEvent)e).getWheelRotation(),
 4801                                          ((MouseWheelEvent)e).getPreciseWheelRotation());
 4802               }
 4803               else {
 4804                   retargeted = new MouseEvent(target,
 4805                                               id,
 4806                                               e.getWhen(),
 4807                                               e.getModifiersEx() | e.getModifiers(),
 4808                                               x,
 4809                                               y,
 4810                                               e.getXOnScreen(),
 4811                                               e.getYOnScreen(),
 4812                                               e.getClickCount(),
 4813                                               e.isPopupTrigger(),
 4814                                               e.getButton());
 4815               }
 4816   
 4817               ((AWTEvent)e).copyPrivateDataInto(retargeted);
 4818   
 4819               if (target == nativeContainer) {
 4820                   // avoid recursively calling LightweightDispatcher...
 4821                   ((Container)target).dispatchEventToSelf(retargeted);
 4822               } else {
 4823                   assert AppContext.getAppContext() == target.appContext;
 4824   
 4825                   if (nativeContainer.modalComp != null) {
 4826                       if (((Container)nativeContainer.modalComp).isAncestorOf(target)) {
 4827                           target.dispatchEvent(retargeted);
 4828                       } else {
 4829                           e.consume();
 4830                       }
 4831                   } else {
 4832                       target.dispatchEvent(retargeted);
 4833                   }
 4834               }
 4835               if (id == MouseEvent.MOUSE_WHEEL && retargeted.isConsumed()) {
 4836                   //An exception for wheel bubbling to the native system.
 4837                   //In "processMouseEvent" total event consuming for wheel events is skipped.
 4838                   //Protection from bubbling of Java-accepted wheel events.
 4839                   e.consume();
 4840               }
 4841           }
 4842       }
 4843   
 4844       // --- member variables -------------------------------
 4845   
 4846       /**
 4847        * The windowed container that might be hosting events for
 4848        * subcomponents.
 4849        */
 4850       private Container nativeContainer;
 4851   
 4852       /**
 4853        * This variable is not used, but kept for serialization compatibility
 4854        */
 4855       private Component focus;
 4856   
 4857       /**
 4858        * The current subcomponent being hosted by this windowed
 4859        * component that has events being forwarded to it.  If this
 4860        * is null, there are currently no events being forwarded to
 4861        * a subcomponent.
 4862        */
 4863       private transient Component mouseEventTarget;
 4864   
 4865       /**
 4866        * The last component entered
 4867        */
 4868       private transient Component targetLastEntered;
 4869   
 4870       /**
 4871        * Is the mouse over the native container
 4872        */
 4873       private transient boolean isMouseInNativeContainer = false;
 4874   
 4875       /**
 4876        * This variable is not used, but kept for serialization compatibility
 4877        */
 4878       private Cursor nativeCursor;
 4879   
 4880       /**
 4881        * The event mask for contained lightweight components.  Lightweight
 4882        * components need a windowed container to host window-related
 4883        * events.  This separate mask indicates events that have been
 4884        * requested by contained lightweight components without effecting
 4885        * the mask of the windowed component itself.
 4886        */
 4887       private long eventMask;
 4888   
 4889       /**
 4890        * The kind of events routed to lightweight components from windowed
 4891        * hosts.
 4892        */
 4893       private static final long PROXY_EVENT_MASK =
 4894           AWTEvent.FOCUS_EVENT_MASK |
 4895           AWTEvent.KEY_EVENT_MASK |
 4896           AWTEvent.MOUSE_EVENT_MASK |
 4897           AWTEvent.MOUSE_MOTION_EVENT_MASK |
 4898           AWTEvent.MOUSE_WHEEL_EVENT_MASK;
 4899   
 4900       private static final long MOUSE_MASK =
 4901           AWTEvent.MOUSE_EVENT_MASK |
 4902           AWTEvent.MOUSE_MOTION_EVENT_MASK |
 4903           AWTEvent.MOUSE_WHEEL_EVENT_MASK;
 4904   }

Save This Page
Home » openjdk-7 » java » awt » [javadoc | source]