History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/Container.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/awt/Container.java+4904−0
@@ -0,0 +1,4904 @@
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+}