/*
* Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.awt;
import java.awt.dnd.DropTarget;
import java.awt.event.*;
import java.awt.peer.ContainerPeer;
import java.awt.peer.ComponentPeer;
import java.awt.peer.LightweightPeer;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.security.AccessController;
import java.util.Arrays;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Set;
import javax.accessibility.*;
import sun.util.logging.PlatformLogger;
import sun.awt.AppContext;
import sun.awt.AWTAccessor;
import sun.awt.CausedFocusEvent;
import sun.awt.PeerEvent;
import sun.awt.SunToolkit;
import sun.awt.dnd.SunDropTargetEvent;
import sun.java2d.pipe.Region;
import sun.security.action.GetBooleanAction;
A generic Abstract Window Toolkit(AWT) container object is a component
that can contain other AWT components.
Components added to a container are tracked in a list. The order
of the list will define the components' front-to-back stacking order
within the container. If no index is specified when adding a
component to a container, it will be added to the end of the list
(and hence to the bottom of the stacking order).
Note: For details on the focus subsystem, see
How to Use the Focus Subsystem,
a section in The Java Tutorial, and the
Focus Specification
for more information.
Author: Arthur van Hoff, Sami Shaio See Also: Since: JDK1.0
/**
* A generic Abstract Window Toolkit(AWT) container object is a component
* that can contain other AWT components.
* <p>
* Components added to a container are tracked in a list. The order
* of the list will define the components' front-to-back stacking order
* within the container. If no index is specified when adding a
* component to a container, it will be added to the end of the list
* (and hence to the bottom of the stacking order).
* <p>
* <b>Note</b>: For details on the focus subsystem, see
* <a href="https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html">
* How to Use the Focus Subsystem</a>,
* a section in <em>The Java Tutorial</em>, and the
* <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
* for more information.
*
* @author Arthur van Hoff
* @author Sami Shaio
* @see #add(java.awt.Component, int)
* @see #getComponent(int)
* @see LayoutManager
* @since JDK1.0
*/
public class Container extends Component {
private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.Container");
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.Container");
private static final Component[] EMPTY_ARRAY = new Component[0];
The components in this container.
See Also:
/**
* The components in this container.
* @see #add
* @see #getComponents
*/
private java.util.List<Component> component = new java.util.ArrayList<Component>();
Layout manager for this container.
See Also:
/**
* Layout manager for this container.
* @see #doLayout
* @see #setLayout
* @see #getLayout
*/
LayoutManager layoutMgr;
Event router for lightweight components. If this container
is native, this dispatcher takes care of forwarding and
retargeting the events to lightweight components contained
(if any).
/**
* Event router for lightweight components. If this container
* is native, this dispatcher takes care of forwarding and
* retargeting the events to lightweight components contained
* (if any).
*/
private LightweightDispatcher dispatcher;
The focus traversal policy that will manage keyboard traversal of this
Container's children, if this Container is a focus cycle root. If the
value is null, this Container inherits its policy from its focus-cycle-
root ancestor. If all such ancestors of this Container have null
policies, then the current KeyboardFocusManager's default policy is
used. If the value is non-null, this policy will be inherited by all
focus-cycle-root children that have no keyboard-traversal policy of
their own (as will, recursively, their focus-cycle-root children).
If this Container is not a focus cycle root, the value will be
remembered, but will not be used or inherited by this or any other
Containers until this Container is made a focus cycle root.
See Also: - setFocusTraversalPolicy
- getFocusTraversalPolicy
Since: 1.4
/**
* The focus traversal policy that will manage keyboard traversal of this
* Container's children, if this Container is a focus cycle root. If the
* value is null, this Container inherits its policy from its focus-cycle-
* root ancestor. If all such ancestors of this Container have null
* policies, then the current KeyboardFocusManager's default policy is
* used. If the value is non-null, this policy will be inherited by all
* focus-cycle-root children that have no keyboard-traversal policy of
* their own (as will, recursively, their focus-cycle-root children).
* <p>
* If this Container is not a focus cycle root, the value will be
* remembered, but will not be used or inherited by this or any other
* Containers until this Container is made a focus cycle root.
*
* @see #setFocusTraversalPolicy
* @see #getFocusTraversalPolicy
* @since 1.4
*/
private transient FocusTraversalPolicy focusTraversalPolicy;
Indicates whether this Component is the root of a focus traversal cycle.
Once focus enters a traversal cycle, typically it cannot leave it via
focus traversal unless one of the up- or down-cycle keys is pressed.
Normal traversal is limited to this Container, and all of this
Container's descendants that are not descendants of inferior focus cycle
roots.
See Also: - setFocusCycleRoot
- isFocusCycleRoot
Since: 1.4
/**
* Indicates whether this Component is the root of a focus traversal cycle.
* Once focus enters a traversal cycle, typically it cannot leave it via
* focus traversal unless one of the up- or down-cycle keys is pressed.
* Normal traversal is limited to this Container, and all of this
* Container's descendants that are not descendants of inferior focus cycle
* roots.
*
* @see #setFocusCycleRoot
* @see #isFocusCycleRoot
* @since 1.4
*/
private boolean focusCycleRoot = false;
Stores the value of focusTraversalPolicyProvider property.
See Also: Since: 1.5
/**
* Stores the value of focusTraversalPolicyProvider property.
* @since 1.5
* @see #setFocusTraversalPolicyProvider
*/
private boolean focusTraversalPolicyProvider;
// keeps track of the threads that are printing this component
private transient Set printingThreads;
// True if there is at least one thread that's printing this component
private transient boolean printing = false;
transient ContainerListener containerListener;
/* HierarchyListener and HierarchyBoundsListener support */
transient int listeningChildren;
transient int listeningBoundsChildren;
transient int descendantsCount;
/* Non-opaque window support -- see Window.setLayersOpaque */
transient Color preserveBackgroundColor = null;
JDK 1.1 serialVersionUID
/**
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 4613797578919906343L;
A constant which toggles one of the controllable behaviors
of getMouseEventTarget
. It is used to specify whether
the method can return the Container on which it is originally called
in case if none of its children are the current mouse event targets.
See Also: - getMouseEventTarget(int, int, boolean, boolean, boolean)
/**
* A constant which toggles one of the controllable behaviors
* of <code>getMouseEventTarget</code>. It is used to specify whether
* the method can return the Container on which it is originally called
* in case if none of its children are the current mouse event targets.
*
* @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
*/
static final boolean INCLUDE_SELF = true;
A constant which toggles one of the controllable behaviors
of getMouseEventTarget
. It is used to specify whether
the method should search only lightweight components.
See Also: - getMouseEventTarget(int, int, boolean, boolean, boolean)
/**
* A constant which toggles one of the controllable behaviors
* of <code>getMouseEventTarget</code>. It is used to specify whether
* the method should search only lightweight components.
*
* @see #getMouseEventTarget(int, int, boolean, boolean, boolean)
*/
static final boolean SEARCH_HEAVYWEIGHTS = true;
/*
* Number of HW or LW components in this container (including
* all descendant containers).
*/
private transient int numOfHWComponents = 0;
private transient int numOfLWComponents = 0;
private static final PlatformLogger mixingLog = PlatformLogger.getLogger("java.awt.mixing.Container");
@serialField ncomponents int
The number of components in this container.
This value can be null. @serialField component Component[]
The components in this container. @serialField layoutMgr LayoutManager
Layout manager for this container. @serialField dispatcher LightweightDispatcher
Event router for lightweight components. If this container
is native, this dispatcher takes care of forwarding and
retargeting the events to lightweight components contained
(if any). @serialField maxSize Dimension
Maximum size of this Container. @serialField focusCycleRoot boolean
Indicates whether this Component is the root of a focus traversal cycle.
Once focus enters a traversal cycle, typically it cannot leave it via
focus traversal unless one of the up- or down-cycle keys is pressed.
Normal traversal is limited to this Container, and all of this
Container's descendants that are not descendants of inferior focus cycle
roots. @serialField containerSerializedDataVersion int
Container Serial Data Version. @serialField focusTraversalPolicyProvider boolean
Stores the value of focusTraversalPolicyProvider property.
/**
* @serialField ncomponents int
* The number of components in this container.
* This value can be null.
* @serialField component Component[]
* The components in this container.
* @serialField layoutMgr LayoutManager
* Layout manager for this container.
* @serialField dispatcher LightweightDispatcher
* Event router for lightweight components. If this container
* is native, this dispatcher takes care of forwarding and
* retargeting the events to lightweight components contained
* (if any).
* @serialField maxSize Dimension
* Maximum size of this Container.
* @serialField focusCycleRoot boolean
* Indicates whether this Component is the root of a focus traversal cycle.
* Once focus enters a traversal cycle, typically it cannot leave it via
* focus traversal unless one of the up- or down-cycle keys is pressed.
* Normal traversal is limited to this Container, and all of this
* Container's descendants that are not descendants of inferior focus cycle
* roots.
* @serialField containerSerializedDataVersion int
* Container Serial Data Version.
* @serialField focusTraversalPolicyProvider boolean
* Stores the value of focusTraversalPolicyProvider property.
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("ncomponents", Integer.TYPE),
new ObjectStreamField("component", Component[].class),
new ObjectStreamField("layoutMgr", LayoutManager.class),
new ObjectStreamField("dispatcher", LightweightDispatcher.class),
new ObjectStreamField("maxSize", Dimension.class),
new ObjectStreamField("focusCycleRoot", Boolean.TYPE),
new ObjectStreamField("containerSerializedDataVersion", Integer.TYPE),
new ObjectStreamField("focusTraversalPolicyProvider", Boolean.TYPE),
};
static {
/* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
AWTAccessor.setContainerAccessor(new AWTAccessor.ContainerAccessor() {
@Override
public void validateUnconditionally(Container cont) {
cont.validateUnconditionally();
}
});
}
Initialize JNI field and method IDs for fields that may be
called from C.
/**
* Initialize JNI field and method IDs for fields that may be
called from C.
*/
private static native void initIDs();
Constructs a new Container. Containers can be extended directly,
but are lightweight in this case and must be contained by a parent
somewhere higher up in the component tree that is native.
(such as Frame for example).
/**
* Constructs a new Container. Containers can be extended directly,
* but are lightweight in this case and must be contained by a parent
* somewhere higher up in the component tree that is native.
* (such as Frame for example).
*/
public Container() {
}
void initializeFocusTraversalKeys() {
focusTraversalKeys = new Set[4];
}
Gets the number of components in this panel.
Note: This method should be called under AWT tree lock.
See Also: Returns: the number of components in this panel. Since: JDK1.1
/**
* Gets the number of components in this panel.
* <p>
* Note: This method should be called under AWT tree lock.
*
* @return the number of components in this panel.
* @see #getComponent
* @since JDK1.1
* @see Component#getTreeLock()
*/
public int getComponentCount() {
return countComponents();
}
Deprecated: As of JDK version 1.1,
replaced by getComponentCount().
/**
* @deprecated As of JDK version 1.1,
* replaced by getComponentCount().
*/
@Deprecated
public int countComponents() {
// This method is not synchronized under AWT tree lock.
// Instead, the calling code is responsible for the
// synchronization. See 6784816 for details.
return component.size();
}
Gets the nth component in this container.
Note: This method should be called under AWT tree lock.
Params: - n – the index of the component to get.
Throws: - ArrayIndexOutOfBoundsException –
if the nth value does not exist.
See Also: Returns: the nth component in this container.
/**
* Gets the nth component in this container.
* <p>
* Note: This method should be called under AWT tree lock.
*
* @param n the index of the component to get.
* @return the n<sup>th</sup> component in this container.
* @exception ArrayIndexOutOfBoundsException
* if the n<sup>th</sup> value does not exist.
* @see Component#getTreeLock()
*/
public Component getComponent(int n) {
// This method is not synchronized under AWT tree lock.
// Instead, the calling code is responsible for the
// synchronization. See 6784816 for details.
try {
return component.get(n);
} catch (IndexOutOfBoundsException z) {
throw new ArrayIndexOutOfBoundsException("No such child: " + n);
}
}
Gets all the components in this container.
Note: This method should be called under AWT tree lock.
See Also: Returns: an array of all the components in this container.
/**
* Gets all the components in this container.
* <p>
* Note: This method should be called under AWT tree lock.
*
* @return an array of all the components in this container.
* @see Component#getTreeLock()
*/
public Component[] getComponents() {
// This method is not synchronized under AWT tree lock.
// Instead, the calling code is responsible for the
// synchronization. See 6784816 for details.
return getComponents_NoClientCode();
}
// NOTE: This method may be called by privileged threads.
// This functionality is implemented in a package-private method
// to insure that it cannot be overridden by client subclasses.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
final Component[] getComponents_NoClientCode() {
return component.toArray(EMPTY_ARRAY);
}
/*
* Wrapper for getComponents() method with a proper synchronization.
*/
Component[] getComponentsSync() {
synchronized (getTreeLock()) {
return getComponents();
}
}
Determines the insets of this container, which indicate the size
of the container's border.
A Frame
object, for example, has a top inset that
corresponds to the height of the frame's title bar.
See Also: Returns: the insets of this container. Since: JDK1.1
/**
* Determines the insets of this container, which indicate the size
* of the container's border.
* <p>
* A <code>Frame</code> object, for example, has a top inset that
* corresponds to the height of the frame's title bar.
* @return the insets of this container.
* @see Insets
* @see LayoutManager
* @since JDK1.1
*/
public Insets getInsets() {
return insets();
}
Deprecated: As of JDK version 1.1,
replaced by getInsets()
.
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>getInsets()</code>.
*/
@Deprecated
public Insets insets() {
ComponentPeer peer = this.peer;
if (peer instanceof ContainerPeer) {
ContainerPeer cpeer = (ContainerPeer)peer;
return (Insets)cpeer.getInsets().clone();
}
return new Insets(0, 0, 0, 0);
}
Appends the specified component to the end of this container. This is a convenience method for addImpl
.
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
display the added component.
Params: - comp – the component to be added
Throws: - NullPointerException – if
comp
is null
See Also: Returns: the component argument
/**
* Appends the specified component to the end of this container.
* This is a convenience method for {@link #addImpl}.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy. If the container has already been
* displayed, the hierarchy must be validated thereafter in order to
* display the added component.
*
* @param comp the component to be added
* @exception NullPointerException if {@code comp} is {@code null}
* @see #addImpl
* @see #invalidate
* @see #validate
* @see javax.swing.JComponent#revalidate()
* @return the component argument
*/
public Component add(Component comp) {
addImpl(comp, null, -1);
return comp;
}
Adds the specified component to this container. This is a convenience method for addImpl
.
This method is obsolete as of 1.1. Please use the
method add(Component, Object)
instead.
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
display the added component.
Throws: - NullPointerException – if
comp
is null
See Also:
/**
* Adds the specified component to this container.
* This is a convenience method for {@link #addImpl}.
* <p>
* This method is obsolete as of 1.1. Please use the
* method <code>add(Component, Object)</code> instead.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy. If the container has already been
* displayed, the hierarchy must be validated thereafter in order to
* display the added component.
*
* @exception NullPointerException if {@code comp} is {@code null}
* @see #add(Component, Object)
* @see #invalidate
*/
public Component add(String name, Component comp) {
addImpl(comp, name, -1);
return comp;
}
Adds the specified component to this container at the given position. This is a convenience method for addImpl
.
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
display the added component.
Params: - comp – the component to be added
- index – the position at which to insert the component,
or
-1
to append the component to the end
Throws: - NullPointerException – if
comp
is null
- IllegalArgumentException – if
index
is invalid (see addImpl
for details)
See Also: Returns: the component comp
/**
* Adds the specified component to this container at the given
* position.
* This is a convenience method for {@link #addImpl}.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy. If the container has already been
* displayed, the hierarchy must be validated thereafter in order to
* display the added component.
*
*
* @param comp the component to be added
* @param index the position at which to insert the component,
* or <code>-1</code> to append the component to the end
* @exception NullPointerException if {@code comp} is {@code null}
* @exception IllegalArgumentException if {@code index} is invalid (see
* {@link #addImpl} for details)
* @return the component <code>comp</code>
* @see #addImpl
* @see #remove
* @see #invalidate
* @see #validate
* @see javax.swing.JComponent#revalidate()
*/
public Component add(Component comp, int index) {
addImpl(comp, null, index);
return comp;
}
Checks that the component
isn't supposed to be added into itself.
/**
* Checks that the component
* isn't supposed to be added into itself.
*/
private void checkAddToSelf(Component comp){
if (comp instanceof Container) {
for (Container cn = this; cn != null; cn=cn.parent) {
if (cn == comp) {
throw new IllegalArgumentException("adding container's parent to itself");
}
}
}
}
Checks that the component is not a Window instance.
/**
* Checks that the component is not a Window instance.
*/
private void checkNotAWindow(Component comp){
if (comp instanceof Window) {
throw new IllegalArgumentException("adding a window to a container");
}
}
Checks that the component comp can be added to this container
Checks : index in bounds of container's size,
comp is not one of this container's parents,
and comp is not a window.
Comp and container must be on the same GraphicsDevice.
if comp is container, all sub-components must be on
same GraphicsDevice.
Since: 1.5
/**
* Checks that the component comp can be added to this container
* Checks : index in bounds of container's size,
* comp is not one of this container's parents,
* and comp is not a window.
* Comp and container must be on the same GraphicsDevice.
* if comp is container, all sub-components must be on
* same GraphicsDevice.
*
* @since 1.5
*/
private void checkAdding(Component comp, int index) {
checkTreeLock();
GraphicsConfiguration thisGC = getGraphicsConfiguration();
if (index > component.size() || index < 0) {
throw new IllegalArgumentException("illegal component position");
}
if (comp.parent == this) {
if (index == component.size()) {
throw new IllegalArgumentException("illegal component position " +
index + " should be less then " + component.size());
}
}
checkAddToSelf(comp);
checkNotAWindow(comp);
Window thisTopLevel = getContainingWindow();
Window compTopLevel = comp.getContainingWindow();
if (thisTopLevel != compTopLevel) {
throw new IllegalArgumentException("component and container should be in the same top-level window");
}
if (thisGC != null) {
comp.checkGD(thisGC.getDevice().getIDstring());
}
}
Removes component comp from this container without making unneccessary changes
and generating unneccessary events. This function intended to perform optimized
remove, for example, if newParent and current parent are the same it just changes
index without calling removeNotify.
Note: Should be called while holding treeLock
Returns whether removeNotify was invoked
Since: : 1.5
/**
* Removes component comp from this container without making unneccessary changes
* and generating unneccessary events. This function intended to perform optimized
* remove, for example, if newParent and current parent are the same it just changes
* index without calling removeNotify.
* Note: Should be called while holding treeLock
* Returns whether removeNotify was invoked
* @since: 1.5
*/
private boolean removeDelicately(Component comp, Container newParent, int newIndex) {
checkTreeLock();
int index = getComponentZOrder(comp);
boolean needRemoveNotify = isRemoveNotifyNeeded(comp, this, newParent);
if (needRemoveNotify) {
comp.removeNotify();
}
if (newParent != this) {
if (layoutMgr != null) {
layoutMgr.removeLayoutComponent(comp);
}
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
-comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
-comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
adjustDescendants(-(comp.countHierarchyMembers()));
comp.parent = null;
if (needRemoveNotify) {
comp.setGraphicsConfiguration(null);
}
component.remove(index);
invalidateIfValid();
} else {
// We should remove component and then
// add it by the newIndex without newIndex decrement if even we shift components to the left
// after remove. Consult the rules below:
// 2->4: 012345 -> 013425, 2->5: 012345 -> 013452
// 4->2: 012345 -> 014235
component.remove(index);
component.add(newIndex, comp);
}
if (comp.parent == null) { // was actually removed
if (containerListener != null ||
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
ContainerEvent e = new ContainerEvent(this,
ContainerEvent.COMPONENT_REMOVED,
comp);
dispatchEvent(e);
}
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
this, HierarchyEvent.PARENT_CHANGED,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
if (peer != null && layoutMgr == null && isVisible()) {
updateCursorImmediately();
}
}
return needRemoveNotify;
}
Checks whether this container can contain component which is focus owner.
Verifies that container is enable and showing, and if it is focus cycle root
its FTP allows component to be focus owner
Since: 1.5
/**
* Checks whether this container can contain component which is focus owner.
* Verifies that container is enable and showing, and if it is focus cycle root
* its FTP allows component to be focus owner
* @since 1.5
*/
boolean canContainFocusOwner(Component focusOwnerCandidate) {
if (!(isEnabled() && isDisplayable()
&& isVisible() && isFocusable()))
{
return false;
}
if (isFocusCycleRoot()) {
FocusTraversalPolicy policy = getFocusTraversalPolicy();
if (policy instanceof DefaultFocusTraversalPolicy) {
if (!((DefaultFocusTraversalPolicy)policy).accept(focusOwnerCandidate)) {
return false;
}
}
}
synchronized(getTreeLock()) {
if (parent != null) {
return parent.canContainFocusOwner(focusOwnerCandidate);
}
}
return true;
}
Checks whether or not this container has heavyweight children.
Note: Should be called while holding tree lock
Returns: true if there is at least one heavyweight children in a container, false otherwise Since: 1.5
/**
* Checks whether or not this container has heavyweight children.
* Note: Should be called while holding tree lock
* @return true if there is at least one heavyweight children in a container, false otherwise
* @since 1.5
*/
final boolean hasHeavyweightDescendants() {
checkTreeLock();
return numOfHWComponents > 0;
}
Checks whether or not this container has lightweight children.
Note: Should be called while holding tree lock
Returns: true if there is at least one lightweight children in a container, false otherwise Since: 1.7
/**
* Checks whether or not this container has lightweight children.
* Note: Should be called while holding tree lock
* @return true if there is at least one lightweight children in a container, false otherwise
* @since 1.7
*/
final boolean hasLightweightDescendants() {
checkTreeLock();
return numOfLWComponents > 0;
}
Returns closest heavyweight component to this container. If this container is heavyweight
returns this.
Since: 1.5
/**
* Returns closest heavyweight component to this container. If this container is heavyweight
* returns this.
* @since 1.5
*/
Container getHeavyweightContainer() {
checkTreeLock();
if (peer != null && !(peer instanceof LightweightPeer)) {
return this;
} else {
return getNativeContainer();
}
}
Detects whether or not remove from current parent and adding to new parent requires call of
removeNotify on the component. Since removeNotify destroys native window this might (not)
be required. For example, if new container and old containers are the same we don't need to
destroy native window.
Since: : 1.5
/**
* Detects whether or not remove from current parent and adding to new parent requires call of
* removeNotify on the component. Since removeNotify destroys native window this might (not)
* be required. For example, if new container and old containers are the same we don't need to
* destroy native window.
* @since: 1.5
*/
private static boolean isRemoveNotifyNeeded(Component comp, Container oldContainer, Container newContainer) {
if (oldContainer == null) { // Component didn't have parent - no removeNotify
return false;
}
if (comp.peer == null) { // Component didn't have peer - no removeNotify
return false;
}
if (newContainer.peer == null) {
// Component has peer but new Container doesn't - call removeNotify
return true;
}
// If component is lightweight non-Container or lightweight Container with all but heavyweight
// children there is no need to call remove notify
if (comp.isLightweight()) {
boolean isContainer = comp instanceof Container;
if (!isContainer || (isContainer && !((Container)comp).hasHeavyweightDescendants())) {
return false;
}
}
// If this point is reached, then the comp is either a HW or a LW container with HW descendants.
// All three components have peers, check for peer change
Container newNativeContainer = oldContainer.getHeavyweightContainer();
Container oldNativeContainer = newContainer.getHeavyweightContainer();
if (newNativeContainer != oldNativeContainer) {
// Native containers change - check whether or not current platform supports
// changing of widget hierarchy on native level without recreation.
// The current implementation forbids reparenting of LW containers with HW descendants
// into another native container w/o destroying the peers. Actually such an operation
// is quite rare. If we ever need to save the peers, we'll have to slightly change the
// addDelicately() method in order to handle such LW containers recursively, reparenting
// each HW descendant independently.
return !comp.peer.isReparentSupported();
} else {
return false;
}
}
Moves the specified component to the specified z-order index in
the container. The z-order determines the order that components
are painted; the component with the highest z-order paints first
and the component with the lowest z-order paints last.
Where components overlap, the component with the lower
z-order paints over the component with the higher z-order.
If the component is a child of some other container, it is
removed from that container before being added to this container.
The important difference between this method and
java.awt.Container.add(Component, int)
is that this method
doesn't call removeNotify
on the component while
removing it from its previous container unless necessary and when
allowed by the underlying native windowing system. This way, if the
component has the keyboard focus, it maintains the focus when
moved to the new position.
This property is guaranteed to apply only to lightweight
non-Container
components.
This method changes layout-related information, and therefore,
invalidates the component hierarchy.
Note: Not all platforms support changing the z-order of
heavyweight components from one container into another without
the call to removeNotify
. There is no way to detect
whether a platform supports this, so developers shouldn't make
any assumptions.
Params: - comp – the component to be moved
- index – the position in the container's list to
insert the component, where
getComponentCount()
appends to the end
Throws: - NullPointerException – if
comp
is
null
- IllegalArgumentException – if
comp
is one of the
container's parents - IllegalArgumentException – if
index
is not in
the range [0, getComponentCount()]
for moving
between containers, or not in the range
[0, getComponentCount()-1]
for moving inside
a container - IllegalArgumentException – if adding a container to itself
- IllegalArgumentException – if adding a
Window
to a container
See Also: Since: 1.5
/**
* Moves the specified component to the specified z-order index in
* the container. The z-order determines the order that components
* are painted; the component with the highest z-order paints first
* and the component with the lowest z-order paints last.
* Where components overlap, the component with the lower
* z-order paints over the component with the higher z-order.
* <p>
* If the component is a child of some other container, it is
* removed from that container before being added to this container.
* The important difference between this method and
* <code>java.awt.Container.add(Component, int)</code> is that this method
* doesn't call <code>removeNotify</code> on the component while
* removing it from its previous container unless necessary and when
* allowed by the underlying native windowing system. This way, if the
* component has the keyboard focus, it maintains the focus when
* moved to the new position.
* <p>
* This property is guaranteed to apply only to lightweight
* non-<code>Container</code> components.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy.
* <p>
* <b>Note</b>: Not all platforms support changing the z-order of
* heavyweight components from one container into another without
* the call to <code>removeNotify</code>. There is no way to detect
* whether a platform supports this, so developers shouldn't make
* any assumptions.
*
* @param comp the component to be moved
* @param index the position in the container's list to
* insert the component, where <code>getComponentCount()</code>
* appends to the end
* @exception NullPointerException if <code>comp</code> is
* <code>null</code>
* @exception IllegalArgumentException if <code>comp</code> is one of the
* container's parents
* @exception IllegalArgumentException if <code>index</code> is not in
* the range <code>[0, getComponentCount()]</code> for moving
* between containers, or not in the range
* <code>[0, getComponentCount()-1]</code> for moving inside
* a container
* @exception IllegalArgumentException if adding a container to itself
* @exception IllegalArgumentException if adding a <code>Window</code>
* to a container
* @see #getComponentZOrder(java.awt.Component)
* @see #invalidate
* @since 1.5
*/
public void setComponentZOrder(Component comp, int index) {
synchronized (getTreeLock()) {
// Store parent because remove will clear it
Container curParent = comp.parent;
int oldZindex = getComponentZOrder(comp);
if (curParent == this && index == oldZindex) {
return;
}
checkAdding(comp, index);
boolean peerRecreated = (curParent != null) ?
curParent.removeDelicately(comp, this, index) : false;
addDelicately(comp, curParent, index);
// If the oldZindex == -1, the component gets inserted,
// rather than it changes its z-order.
if (!peerRecreated && oldZindex != -1) {
// The new 'index' cannot be == -1.
// It gets checked at the checkAdding() method.
// Therefore both oldZIndex and index denote
// some existing positions at this point and
// this is actually a Z-order changing.
comp.mixOnZOrderChanging(oldZindex, index);
}
}
}
Traverses the tree of components and reparents children heavyweight component
to new heavyweight parent.
Since: 1.5
/**
* Traverses the tree of components and reparents children heavyweight component
* to new heavyweight parent.
* @since 1.5
*/
private void reparentTraverse(ContainerPeer parentPeer, Container child) {
checkTreeLock();
for (int i = 0; i < child.getComponentCount(); i++) {
Component comp = child.getComponent(i);
if (comp.isLightweight()) {
// If components is lightweight check if it is container
// If it is container it might contain heavyweight children we need to reparent
if (comp instanceof Container) {
reparentTraverse(parentPeer, (Container)comp);
}
} else {
// Q: Need to update NativeInLightFixer?
comp.getPeer().reparent(parentPeer);
}
}
}
Reparents child component peer to this container peer.
Container must be heavyweight.
Since: 1.5
/**
* Reparents child component peer to this container peer.
* Container must be heavyweight.
* @since 1.5
*/
private void reparentChild(Component comp) {
checkTreeLock();
if (comp == null) {
return;
}
if (comp.isLightweight()) {
// If component is lightweight container we need to reparent all its explicit heavyweight children
if (comp instanceof Container) {
// Traverse component's tree till depth-first until encountering heavyweight component
reparentTraverse((ContainerPeer)getPeer(), (Container)comp);
}
} else {
comp.getPeer().reparent((ContainerPeer)getPeer());
}
}
Adds component to this container. Tries to minimize side effects of this adding -
doesn't call remove notify if it is not required.
Since: 1.5
/**
* Adds component to this container. Tries to minimize side effects of this adding -
* doesn't call remove notify if it is not required.
* @since 1.5
*/
private void addDelicately(Component comp, Container curParent, int index) {
checkTreeLock();
// Check if moving between containers
if (curParent != this) {
//index == -1 means add to the end.
if (index == -1) {
component.add(comp);
} else {
component.add(index, comp);
}
comp.parent = this;
comp.setGraphicsConfiguration(getGraphicsConfiguration());
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
adjustDescendants(comp.countHierarchyMembers());
} else {
if (index < component.size()) {
component.set(index, comp);
}
}
invalidateIfValid();
if (peer != null) {
if (comp.peer == null) { // Remove notify was called or it didn't have peer - create new one
comp.addNotify();
} else { // Both container and child have peers, it means child peer should be reparented.
// In both cases we need to reparent native widgets.
Container newNativeContainer = getHeavyweightContainer();
Container oldNativeContainer = curParent.getHeavyweightContainer();
if (oldNativeContainer != newNativeContainer) {
// Native container changed - need to reparent native widgets
newNativeContainer.reparentChild(comp);
}
comp.updateZOrder();
if (!comp.isLightweight() && isLightweight()) {
// If component is heavyweight and one of the containers is lightweight
// the location of the component should be fixed.
comp.relocateComponent();
}
}
}
if (curParent != this) {
/* Notify the layout manager of the added component. */
if (layoutMgr != null) {
if (layoutMgr instanceof LayoutManager2) {
((LayoutManager2)layoutMgr).addLayoutComponent(comp, null);
} else {
layoutMgr.addLayoutComponent(null, comp);
}
}
if (containerListener != null ||
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
ContainerEvent e = new ContainerEvent(this,
ContainerEvent.COMPONENT_ADDED,
comp);
dispatchEvent(e);
}
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
this, HierarchyEvent.PARENT_CHANGED,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
// If component is focus owner or parent container of focus owner check that after reparenting
// focus owner moved out if new container prohibit this kind of focus owner.
if (comp.isFocusOwner() && !comp.canBeFocusOwnerRecursively()) {
comp.transferFocus();
} else if (comp instanceof Container) {
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (focusOwner != null && isParentOf(focusOwner) && !focusOwner.canBeFocusOwnerRecursively()) {
focusOwner.transferFocus();
}
}
} else {
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
this, HierarchyEvent.HIERARCHY_CHANGED,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
}
if (peer != null && layoutMgr == null && isVisible()) {
updateCursorImmediately();
}
}
Returns the z-order index of the component inside the container.
The higher a component is in the z-order hierarchy, the lower
its index. The component with the lowest z-order index is
painted last, above all other child components.
Params: - comp – the component being queried
See Also: Returns: the z-order index of the component; otherwise
returns -1 if the component is null
or doesn't belong to the container Since: 1.5
/**
* Returns the z-order index of the component inside the container.
* The higher a component is in the z-order hierarchy, the lower
* its index. The component with the lowest z-order index is
* painted last, above all other child components.
*
* @param comp the component being queried
* @return the z-order index of the component; otherwise
* returns -1 if the component is <code>null</code>
* or doesn't belong to the container
* @see #setComponentZOrder(java.awt.Component, int)
* @since 1.5
*/
public int getComponentZOrder(Component comp) {
if (comp == null) {
return -1;
}
synchronized(getTreeLock()) {
// Quick check - container should be immediate parent of the component
if (comp.parent != this) {
return -1;
}
return component.indexOf(comp);
}
}
Adds the specified component to the end of this container. Also notifies the layout manager to add the component to this container's layout using the specified constraints object. This is a convenience method for addImpl
.
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
display the added component.
Params: - comp – the component to be added
- constraints – an object expressing
layout constraints for this component
Throws: - NullPointerException – if
comp
is null
See Also: Since: JDK1.1
/**
* Adds the specified component to the end of this container.
* Also notifies the layout manager to add the component to
* this container's layout using the specified constraints object.
* This is a convenience method for {@link #addImpl}.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy. If the container has already been
* displayed, the hierarchy must be validated thereafter in order to
* display the added component.
*
*
* @param comp the component to be added
* @param constraints an object expressing
* layout constraints for this component
* @exception NullPointerException if {@code comp} is {@code null}
* @see #addImpl
* @see #invalidate
* @see #validate
* @see javax.swing.JComponent#revalidate()
* @see LayoutManager
* @since JDK1.1
*/
public void add(Component comp, Object constraints) {
addImpl(comp, constraints, -1);
}
Adds the specified component to this container with the specified constraints at the specified index. Also notifies the layout manager to add the component to the this container's layout using the specified constraints object. This is a convenience method for addImpl
.
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
display the added component.
Params: - comp – the component to be added
- constraints – an object expressing layout constraints for this
- index – the position in the container's list at which to insert
the component;
-1
means insert at the end
component
Throws: - NullPointerException – if
comp
is null
- IllegalArgumentException – if
index
is invalid (see addImpl
for details)
See Also:
/**
* Adds the specified component to this container with the specified
* constraints at the specified index. Also notifies the layout
* manager to add the component to the this container's layout using
* the specified constraints object.
* This is a convenience method for {@link #addImpl}.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy. If the container has already been
* displayed, the hierarchy must be validated thereafter in order to
* display the added component.
*
*
* @param comp the component to be added
* @param constraints an object expressing layout constraints for this
* @param index the position in the container's list at which to insert
* the component; <code>-1</code> means insert at the end
* component
* @exception NullPointerException if {@code comp} is {@code null}
* @exception IllegalArgumentException if {@code index} is invalid (see
* {@link #addImpl} for details)
* @see #addImpl
* @see #invalidate
* @see #validate
* @see javax.swing.JComponent#revalidate()
* @see #remove
* @see LayoutManager
*/
public void add(Component comp, Object constraints, int index) {
addImpl(comp, constraints, index);
}
Adds the specified component to this container at the specified
index. This method also notifies the layout manager to add
the component to this container's layout using the specified
constraints object via the addLayoutComponent
method.
The constraints are
defined by the particular layout manager being used. For
example, the BorderLayout
class defines five
constraints: BorderLayout.NORTH
,
BorderLayout.SOUTH
, BorderLayout.EAST
,
BorderLayout.WEST
, and BorderLayout.CENTER
.
The GridBagLayout
class requires a
GridBagConstraints
object. Failure to pass
the correct type of constraints object results in an
IllegalArgumentException
.
If the current layout manager implements LayoutManager2
, then LayoutManager2.addLayoutComponent(Component, Object)
is invoked on it. If the current layout manager does not implement LayoutManager2
, and constraints is a String
, then LayoutManager.addLayoutComponent(String, Component)
is invoked on it.
If the component is not an ancestor of this container and has a non-null
parent, it is removed from its current parent before it is added to this
container.
This is the method to override if a program needs to track
every add request to a container as all other add methods defer
to this one. An overriding method should
usually include a call to the superclass's version of the method:
super.addImpl(comp, constraints, index)
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
display the added component.
Params: - comp – the component to be added
- constraints – an object expressing layout constraints
for this component
- index – the position in the container's list at which to
insert the component, where
-1
means append to the end
Throws: - IllegalArgumentException – if
index
is invalid; if comp
is a child of this container, the valid range is [-1, getComponentCount()-1]
; if component is not a child of this container, the valid range is [-1, getComponentCount()]
- IllegalArgumentException – if
comp
is an ancestor of this container - IllegalArgumentException – if adding a window to a container
- NullPointerException – if
comp
is null
See Also: Since: JDK1.1
/**
* Adds the specified component to this container at the specified
* index. This method also notifies the layout manager to add
* the component to this container's layout using the specified
* constraints object via the <code>addLayoutComponent</code>
* method.
* <p>
* The constraints are
* defined by the particular layout manager being used. For
* example, the <code>BorderLayout</code> class defines five
* constraints: <code>BorderLayout.NORTH</code>,
* <code>BorderLayout.SOUTH</code>, <code>BorderLayout.EAST</code>,
* <code>BorderLayout.WEST</code>, and <code>BorderLayout.CENTER</code>.
* <p>
* The <code>GridBagLayout</code> class requires a
* <code>GridBagConstraints</code> object. Failure to pass
* the correct type of constraints object results in an
* <code>IllegalArgumentException</code>.
* <p>
* If the current layout manager implements {@code LayoutManager2}, then
* {@link LayoutManager2#addLayoutComponent(Component,Object)} is invoked on
* it. If the current layout manager does not implement
* {@code LayoutManager2}, and constraints is a {@code String}, then
* {@link LayoutManager#addLayoutComponent(String,Component)} is invoked on it.
* <p>
* If the component is not an ancestor of this container and has a non-null
* parent, it is removed from its current parent before it is added to this
* container.
* <p>
* This is the method to override if a program needs to track
* every add request to a container as all other add methods defer
* to this one. An overriding method should
* usually include a call to the superclass's version of the method:
* <p>
* <blockquote>
* <code>super.addImpl(comp, constraints, index)</code>
* </blockquote>
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy. If the container has already been
* displayed, the hierarchy must be validated thereafter in order to
* display the added component.
*
* @param comp the component to be added
* @param constraints an object expressing layout constraints
* for this component
* @param index the position in the container's list at which to
* insert the component, where <code>-1</code>
* means append to the end
* @exception IllegalArgumentException if {@code index} is invalid;
* if {@code comp} is a child of this container, the valid
* range is {@code [-1, getComponentCount()-1]}; if component is
* not a child of this container, the valid range is
* {@code [-1, getComponentCount()]}
*
* @exception IllegalArgumentException if {@code comp} is an ancestor of
* this container
* @exception IllegalArgumentException if adding a window to a container
* @exception NullPointerException if {@code comp} is {@code null}
* @see #add(Component)
* @see #add(Component, int)
* @see #add(Component, java.lang.Object)
* @see #invalidate
* @see LayoutManager
* @see LayoutManager2
* @since JDK1.1
*/
protected void addImpl(Component comp, Object constraints, int index) {
synchronized (getTreeLock()) {
/* Check for correct arguments: index in bounds,
* comp cannot be one of this container's parents,
* and comp cannot be a window.
* comp and container must be on the same GraphicsDevice.
* if comp is container, all sub-components must be on
* same GraphicsDevice.
*/
GraphicsConfiguration thisGC = this.getGraphicsConfiguration();
if (index > component.size() || (index < 0 && index != -1)) {
throw new IllegalArgumentException(
"illegal component position");
}
checkAddToSelf(comp);
checkNotAWindow(comp);
if (thisGC != null) {
comp.checkGD(thisGC.getDevice().getIDstring());
}
/* Reparent the component and tidy up the tree's state. */
if (comp.parent != null) {
comp.parent.remove(comp);
if (index > component.size()) {
throw new IllegalArgumentException("illegal component position");
}
}
//index == -1 means add to the end.
if (index == -1) {
component.add(comp);
} else {
component.add(index, comp);
}
comp.parent = this;
comp.setGraphicsConfiguration(thisGC);
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
adjustDescendants(comp.countHierarchyMembers());
invalidateIfValid();
if (peer != null) {
comp.addNotify();
}
/* Notify the layout manager of the added component. */
if (layoutMgr != null) {
if (layoutMgr instanceof LayoutManager2) {
((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
} else if (constraints instanceof String) {
layoutMgr.addLayoutComponent((String)constraints, comp);
}
}
if (containerListener != null ||
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
ContainerEvent e = new ContainerEvent(this,
ContainerEvent.COMPONENT_ADDED,
comp);
dispatchEvent(e);
}
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
this, HierarchyEvent.PARENT_CHANGED,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
if (peer != null && layoutMgr == null && isVisible()) {
updateCursorImmediately();
}
}
}
@Override
boolean updateGraphicsData(GraphicsConfiguration gc) {
checkTreeLock();
boolean ret = super.updateGraphicsData(gc);
for (Component comp : component) {
if (comp != null) {
ret |= comp.updateGraphicsData(gc);
}
}
return ret;
}
Checks that all Components that this Container contains are on
the same GraphicsDevice as this Container. If not, throws an
IllegalArgumentException.
/**
* Checks that all Components that this Container contains are on
* the same GraphicsDevice as this Container. If not, throws an
* IllegalArgumentException.
*/
void checkGD(String stringID) {
for (Component comp : component) {
if (comp != null) {
comp.checkGD(stringID);
}
}
}
Removes the component, specified by index
,
from this container.
This method also notifies the layout manager to remove the
component from this container's layout via the
removeLayoutComponent
method.
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
reflect the changes.
Params: - index – the index of the component to be removed
Throws: - ArrayIndexOutOfBoundsException – if
index
is not in range [0, getComponentCount()-1]
See Also: Since: JDK1.1
/**
* Removes the component, specified by <code>index</code>,
* from this container.
* This method also notifies the layout manager to remove the
* component from this container's layout via the
* <code>removeLayoutComponent</code> method.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy. If the container has already been
* displayed, the hierarchy must be validated thereafter in order to
* reflect the changes.
*
*
* @param index the index of the component to be removed
* @throws ArrayIndexOutOfBoundsException if {@code index} is not in
* range {@code [0, getComponentCount()-1]}
* @see #add
* @see #invalidate
* @see #validate
* @see #getComponentCount
* @since JDK1.1
*/
public void remove(int index) {
synchronized (getTreeLock()) {
if (index < 0 || index >= component.size()) {
throw new ArrayIndexOutOfBoundsException(index);
}
Component comp = component.get(index);
if (peer != null) {
comp.removeNotify();
}
if (layoutMgr != null) {
layoutMgr.removeLayoutComponent(comp);
}
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
-comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
-comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
adjustDescendants(-(comp.countHierarchyMembers()));
comp.parent = null;
component.remove(index);
comp.setGraphicsConfiguration(null);
invalidateIfValid();
if (containerListener != null ||
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
ContainerEvent e = new ContainerEvent(this,
ContainerEvent.COMPONENT_REMOVED,
comp);
dispatchEvent(e);
}
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
this, HierarchyEvent.PARENT_CHANGED,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
if (peer != null && layoutMgr == null && isVisible()) {
updateCursorImmediately();
}
}
}
Removes the specified component from this container.
This method also notifies the layout manager to remove the
component from this container's layout via the
removeLayoutComponent
method.
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
reflect the changes.
Params: - comp – the component to be removed
Throws: - NullPointerException – if
comp
is null
See Also:
/**
* Removes the specified component from this container.
* This method also notifies the layout manager to remove the
* component from this container's layout via the
* <code>removeLayoutComponent</code> method.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy. If the container has already been
* displayed, the hierarchy must be validated thereafter in order to
* reflect the changes.
*
* @param comp the component to be removed
* @throws NullPointerException if {@code comp} is {@code null}
* @see #add
* @see #invalidate
* @see #validate
* @see #remove(int)
*/
public void remove(Component comp) {
synchronized (getTreeLock()) {
if (comp.parent == this) {
int index = component.indexOf(comp);
if (index >= 0) {
remove(index);
}
}
}
}
Removes all the components from this container.
This method also notifies the layout manager to remove the
components from this container's layout via the
removeLayoutComponent
method.
This method changes layout-related information, and therefore,
invalidates the component hierarchy. If the container has already been
displayed, the hierarchy must be validated thereafter in order to
reflect the changes.
See Also:
/**
* Removes all the components from this container.
* This method also notifies the layout manager to remove the
* components from this container's layout via the
* <code>removeLayoutComponent</code> method.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy. If the container has already been
* displayed, the hierarchy must be validated thereafter in order to
* reflect the changes.
*
* @see #add
* @see #remove
* @see #invalidate
*/
public void removeAll() {
synchronized (getTreeLock()) {
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
-listeningChildren);
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
-listeningBoundsChildren);
adjustDescendants(-descendantsCount);
while (!component.isEmpty()) {
Component comp = component.remove(component.size()-1);
if (peer != null) {
comp.removeNotify();
}
if (layoutMgr != null) {
layoutMgr.removeLayoutComponent(comp);
}
comp.parent = null;
comp.setGraphicsConfiguration(null);
if (containerListener != null ||
(eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
ContainerEvent e = new ContainerEvent(this,
ContainerEvent.COMPONENT_REMOVED,
comp);
dispatchEvent(e);
}
comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
comp, this,
HierarchyEvent.PARENT_CHANGED,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
}
if (peer != null && layoutMgr == null && isVisible()) {
updateCursorImmediately();
}
invalidateIfValid();
}
}
// Should only be called while holding tree lock
int numListening(long mask) {
int superListening = super.numListening(mask);
if (mask == AWTEvent.HIERARCHY_EVENT_MASK) {
if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
// Verify listeningChildren is correct
int sum = 0;
for (Component comp : component) {
sum += comp.numListening(mask);
}
if (listeningChildren != sum) {
eventLog.fine("Assertion (listeningChildren == sum) failed");
}
}
return listeningChildren + superListening;
} else if (mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) {
if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
// Verify listeningBoundsChildren is correct
int sum = 0;
for (Component comp : component) {
sum += comp.numListening(mask);
}
if (listeningBoundsChildren != sum) {
eventLog.fine("Assertion (listeningBoundsChildren == sum) failed");
}
}
return listeningBoundsChildren + superListening;
} else {
// assert false;
if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
eventLog.fine("This code must never be reached");
}
return superListening;
}
}
// Should only be called while holding tree lock
void adjustListeningChildren(long mask, int num) {
if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
boolean toAssert = (mask == AWTEvent.HIERARCHY_EVENT_MASK ||
mask == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK ||
mask == (AWTEvent.HIERARCHY_EVENT_MASK |
AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
if (!toAssert) {
eventLog.fine("Assertion failed");
}
}
if (num == 0)
return;
if ((mask & AWTEvent.HIERARCHY_EVENT_MASK) != 0) {
listeningChildren += num;
}
if ((mask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0) {
listeningBoundsChildren += num;
}
adjustListeningChildrenOnParent(mask, num);
}
// Should only be called while holding tree lock
void adjustDescendants(int num) {
if (num == 0)
return;
descendantsCount += num;
adjustDecendantsOnParent(num);
}
// Should only be called while holding tree lock
void adjustDecendantsOnParent(int num) {
if (parent != null) {
parent.adjustDescendants(num);
}
}
// Should only be called while holding tree lock
int countHierarchyMembers() {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
// Verify descendantsCount is correct
int sum = 0;
for (Component comp : component) {
sum += comp.countHierarchyMembers();
}
if (descendantsCount != sum) {
log.fine("Assertion (descendantsCount == sum) failed");
}
}
return descendantsCount + 1;
}
private int getListenersCount(int id, boolean enabledOnToolkit) {
checkTreeLock();
if (enabledOnToolkit) {
return descendantsCount;
}
switch (id) {
case HierarchyEvent.HIERARCHY_CHANGED:
return listeningChildren;
case HierarchyEvent.ANCESTOR_MOVED:
case HierarchyEvent.ANCESTOR_RESIZED:
return listeningBoundsChildren;
default:
return 0;
}
}
final int createHierarchyEvents(int id, Component changed,
Container changedParent, long changeFlags, boolean enabledOnToolkit)
{
checkTreeLock();
int listeners = getListenersCount(id, enabledOnToolkit);
for (int count = listeners, i = 0; count > 0; i++) {
count -= component.get(i).createHierarchyEvents(id, changed,
changedParent, changeFlags, enabledOnToolkit);
}
return listeners +
super.createHierarchyEvents(id, changed, changedParent,
changeFlags, enabledOnToolkit);
}
final void createChildHierarchyEvents(int id, long changeFlags,
boolean enabledOnToolkit)
{
checkTreeLock();
if (component.isEmpty()) {
return;
}
int listeners = getListenersCount(id, enabledOnToolkit);
for (int count = listeners, i = 0; count > 0; i++) {
count -= component.get(i).createHierarchyEvents(id, this, parent,
changeFlags, enabledOnToolkit);
}
}
Gets the layout manager for this container.
See Also: - doLayout
- setLayout
/**
* Gets the layout manager for this container.
* @see #doLayout
* @see #setLayout
*/
public LayoutManager getLayout() {
return layoutMgr;
}
Sets the layout manager for this container.
This method changes layout-related information, and therefore,
invalidates the component hierarchy.
Params: - mgr – the specified layout manager
See Also:
/**
* Sets the layout manager for this container.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy.
*
* @param mgr the specified layout manager
* @see #doLayout
* @see #getLayout
* @see #invalidate
*/
public void setLayout(LayoutManager mgr) {
layoutMgr = mgr;
invalidateIfValid();
}
Causes this container to lay out its components. Most programs
should not call this method directly, but should invoke
the validate
method instead.
See Also: Since: JDK1.1
/**
* Causes this container to lay out its components. Most programs
* should not call this method directly, but should invoke
* the <code>validate</code> method instead.
* @see LayoutManager#layoutContainer
* @see #setLayout
* @see #validate
* @since JDK1.1
*/
public void doLayout() {
layout();
}
Deprecated: As of JDK version 1.1,
replaced by doLayout()
.
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>doLayout()</code>.
*/
@Deprecated
public void layout() {
LayoutManager layoutMgr = this.layoutMgr;
if (layoutMgr != null) {
layoutMgr.layoutContainer(this);
}
}
Indicates if this container is a validate root.
Layout-related changes, such as bounds of the validate root descendants, do not affect the layout of the validate root parent. This peculiarity enables the invalidate()
method to stop invalidating the component hierarchy when the method encounters a validate root. However, to preserve backward compatibility this new optimized behavior is enabled only when the java.awt.smartInvalidate
system property value is set to true
.
If a component hierarchy contains validate roots and the new optimized invalidate()
behavior is enabled, the validate()
method must be invoked on the validate root of a previously invalidated component to restore the validity of the hierarchy later. Otherwise, calling the validate()
method on the top-level container (such as a Frame
object) should be used to restore the validity of the component hierarchy.
The Window
class and the Applet
class are the validate roots in AWT. Swing introduces more validate roots.
See Also: Returns: whether this container is a validate root Since: 1.7
/**
* Indicates if this container is a <i>validate root</i>.
* <p>
* Layout-related changes, such as bounds of the validate root descendants,
* do not affect the layout of the validate root parent. This peculiarity
* enables the {@code invalidate()} method to stop invalidating the
* component hierarchy when the method encounters a validate root. However,
* to preserve backward compatibility this new optimized behavior is
* enabled only when the {@code java.awt.smartInvalidate} system property
* value is set to {@code true}.
* <p>
* If a component hierarchy contains validate roots and the new optimized
* {@code invalidate()} behavior is enabled, the {@code validate()} method
* must be invoked on the validate root of a previously invalidated
* component to restore the validity of the hierarchy later. Otherwise,
* calling the {@code validate()} method on the top-level container (such
* as a {@code Frame} object) should be used to restore the validity of the
* component hierarchy.
* <p>
* The {@code Window} class and the {@code Applet} class are the validate
* roots in AWT. Swing introduces more validate roots.
*
* @return whether this container is a validate root
* @see #invalidate
* @see java.awt.Component#invalidate
* @see javax.swing.JComponent#isValidateRoot
* @see javax.swing.JComponent#revalidate
* @since 1.7
*/
public boolean isValidateRoot() {
return false;
}
private static final boolean isJavaAwtSmartInvalidate;
static {
// Don't lazy-read because every app uses invalidate()
isJavaAwtSmartInvalidate = AccessController.doPrivileged(
new GetBooleanAction("java.awt.smartInvalidate"));
}
Invalidates the parent of the container unless the container
is a validate root.
/**
* Invalidates the parent of the container unless the container
* is a validate root.
*/
@Override
void invalidateParent() {
if (!isJavaAwtSmartInvalidate || !isValidateRoot()) {
super.invalidateParent();
}
}
Invalidates the container.
If the LayoutManager
installed on this container is an instance of the LayoutManager2
interface, then the LayoutManager2.invalidateLayout(Container)
method is invoked on it supplying this Container
as the argument.
Afterwards this method marks this container invalid, and invalidates its ancestors. See the Component.invalidate
method for more details.
See Also:
/**
* Invalidates the container.
* <p>
* If the {@code LayoutManager} installed on this container is an instance
* of the {@code LayoutManager2} interface, then
* the {@link LayoutManager2#invalidateLayout(Container)} method is invoked
* on it supplying this {@code Container} as the argument.
* <p>
* Afterwards this method marks this container invalid, and invalidates its
* ancestors. See the {@link Component#invalidate} method for more details.
*
* @see #validate
* @see #layout
* @see LayoutManager2
*/
@Override
public void invalidate() {
LayoutManager layoutMgr = this.layoutMgr;
if (layoutMgr instanceof LayoutManager2) {
LayoutManager2 lm = (LayoutManager2) layoutMgr;
lm.invalidateLayout(this);
}
super.invalidate();
}
Validates this container and all of its subcomponents.
Validating a container means laying out its subcomponents. Layout-related changes, such as setting the bounds of a component, or adding a component to the container, invalidate the container automatically. Note that the ancestors of the container may be invalidated also (see Component.invalidate
for details.) Therefore, to restore the validity of the hierarchy, the
validate()
method should be invoked on the top-most invalid container of the hierarchy.
Validating the container may be a quite time-consuming operation. For
performance reasons a developer may postpone the validation of the
hierarchy till a set of layout-related operations completes, e.g. after
adding all the children to the container.
If this Container
is not valid, this method invokes the validateTree
method and marks this Container
as valid. Otherwise, no action is performed.
See Also:
/**
* Validates this container and all of its subcomponents.
* <p>
* Validating a container means laying out its subcomponents.
* Layout-related changes, such as setting the bounds of a component, or
* adding a component to the container, invalidate the container
* automatically. Note that the ancestors of the container may be
* invalidated also (see {@link Component#invalidate} for details.)
* Therefore, to restore the validity of the hierarchy, the {@code
* validate()} method should be invoked on the top-most invalid
* container of the hierarchy.
* <p>
* Validating the container may be a quite time-consuming operation. For
* performance reasons a developer may postpone the validation of the
* hierarchy till a set of layout-related operations completes, e.g. after
* adding all the children to the container.
* <p>
* If this {@code Container} is not valid, this method invokes
* the {@code validateTree} method and marks this {@code Container}
* as valid. Otherwise, no action is performed.
*
* @see #add(java.awt.Component)
* @see #invalidate
* @see Container#isValidateRoot
* @see javax.swing.JComponent#revalidate()
* @see #validateTree
*/
public void validate() {
boolean updateCur = false;
synchronized (getTreeLock()) {
if ((!isValid() || descendUnconditionallyWhenValidating)
&& peer != null)
{
ContainerPeer p = null;
if (peer instanceof ContainerPeer) {
p = (ContainerPeer) peer;
}
if (p != null) {
p.beginValidate();
}
validateTree();
if (p != null) {
p.endValidate();
// Avoid updating cursor if this is an internal call.
// See validateUnconditionally() for details.
if (!descendUnconditionallyWhenValidating) {
updateCur = isVisible();
}
}
}
}
if (updateCur) {
updateCursorImmediately();
}
}
Indicates whether valid containers should also traverse their
children and call the validateTree() method on them.
Synchronization: TreeLock.
The field is allowed to be static as long as the TreeLock itself is
static.
See Also: - validateUnconditionally()
/**
* Indicates whether valid containers should also traverse their
* children and call the validateTree() method on them.
*
* Synchronization: TreeLock.
*
* The field is allowed to be static as long as the TreeLock itself is
* static.
*
* @see #validateUnconditionally()
*/
private static boolean descendUnconditionallyWhenValidating = false;
Unconditionally validate the component hierarchy.
/**
* Unconditionally validate the component hierarchy.
*/
final void validateUnconditionally() {
boolean updateCur = false;
synchronized (getTreeLock()) {
descendUnconditionallyWhenValidating = true;
validate();
if (peer instanceof ContainerPeer) {
updateCur = isVisible();
}
descendUnconditionallyWhenValidating = false;
}
if (updateCur) {
updateCursorImmediately();
}
}
Recursively descends the container tree and recomputes the
layout for any subtrees marked as needing it (those marked as
invalid). Synchronization should be provided by the method
that calls this one: validate
.
See Also: - doLayout
- validate
/**
* Recursively descends the container tree and recomputes the
* layout for any subtrees marked as needing it (those marked as
* invalid). Synchronization should be provided by the method
* that calls this one: <code>validate</code>.
*
* @see #doLayout
* @see #validate
*/
protected void validateTree() {
checkTreeLock();
if (!isValid() || descendUnconditionallyWhenValidating) {
if (peer instanceof ContainerPeer) {
((ContainerPeer)peer).beginLayout();
}
if (!isValid()) {
doLayout();
}
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if ( (comp instanceof Container)
&& !(comp instanceof Window)
&& (!comp.isValid() ||
descendUnconditionallyWhenValidating))
{
((Container)comp).validateTree();
} else {
comp.validate();
}
}
if (peer instanceof ContainerPeer) {
((ContainerPeer)peer).endLayout();
}
}
super.validate();
}
Recursively descends the container tree and invalidates all
contained components.
/**
* Recursively descends the container tree and invalidates all
* contained components.
*/
void invalidateTree() {
synchronized (getTreeLock()) {
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if (comp instanceof Container) {
((Container)comp).invalidateTree();
}
else {
comp.invalidateIfValid();
}
}
invalidateIfValid();
}
}
Sets the font of this container.
This method changes layout-related information, and therefore,
invalidates the component hierarchy.
Params: - f – The font to become this container's font.
See Also: Since: JDK1.0
/**
* Sets the font of this container.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy.
*
* @param f The font to become this container's font.
* @see Component#getFont
* @see #invalidate
* @since JDK1.0
*/
public void setFont(Font f) {
boolean shouldinvalidate = false;
Font oldfont = getFont();
super.setFont(f);
Font newfont = getFont();
if (newfont != oldfont && (oldfont == null ||
!oldfont.equals(newfont))) {
invalidateTree();
}
}
Returns the preferred size of this container. If the preferred size has not been set explicitly by Component.setPreferredSize(Dimension)
and this Container
has a non-null
LayoutManager
, then LayoutManager.preferredLayoutSize(Container)
is used to calculate the preferred size. Note: some implementations may cache the value returned from the LayoutManager
. Implementations that cache need not invoke preferredLayoutSize
on the LayoutManager
every time this method is invoked, rather the LayoutManager
will only be queried after the Container
becomes invalid.
See Also: Returns: an instance of Dimension
that represents
the preferred size of this container.
/**
* Returns the preferred size of this container. If the preferred size has
* not been set explicitly by {@link Component#setPreferredSize(Dimension)}
* and this {@code Container} has a {@code non-null} {@link LayoutManager},
* then {@link LayoutManager#preferredLayoutSize(Container)}
* is used to calculate the preferred size.
*
* <p>Note: some implementations may cache the value returned from the
* {@code LayoutManager}. Implementations that cache need not invoke
* {@code preferredLayoutSize} on the {@code LayoutManager} every time
* this method is invoked, rather the {@code LayoutManager} will only
* be queried after the {@code Container} becomes invalid.
*
* @return an instance of <code>Dimension</code> that represents
* the preferred size of this container.
* @see #getMinimumSize
* @see #getMaximumSize
* @see #getLayout
* @see LayoutManager#preferredLayoutSize(Container)
* @see Component#getPreferredSize
*/
public Dimension getPreferredSize() {
return preferredSize();
}
Deprecated: As of JDK version 1.1,
replaced by getPreferredSize()
.
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>getPreferredSize()</code>.
*/
@Deprecated
public Dimension preferredSize() {
/* Avoid grabbing the lock if a reasonable cached size value
* is available.
*/
Dimension dim = prefSize;
if (dim == null || !(isPreferredSizeSet() || isValid())) {
synchronized (getTreeLock()) {
prefSize = (layoutMgr != null) ?
layoutMgr.preferredLayoutSize(this) :
super.preferredSize();
dim = prefSize;
}
}
if (dim != null){
return new Dimension(dim);
}
else{
return dim;
}
}
Returns the minimum size of this container. If the minimum size has not been set explicitly by Component.setMinimumSize(Dimension)
and this Container
has a non-null
LayoutManager
, then LayoutManager.minimumLayoutSize(Container)
is used to calculate the minimum size. Note: some implementations may cache the value returned from the LayoutManager
. Implementations that cache need not invoke minimumLayoutSize
on the LayoutManager
every time this method is invoked, rather the LayoutManager
will only be queried after the Container
becomes invalid.
See Also: Returns: an instance of Dimension
that represents
the minimum size of this container. Since: JDK1.1
/**
* Returns the minimum size of this container. If the minimum size has
* not been set explicitly by {@link Component#setMinimumSize(Dimension)}
* and this {@code Container} has a {@code non-null} {@link LayoutManager},
* then {@link LayoutManager#minimumLayoutSize(Container)}
* is used to calculate the minimum size.
*
* <p>Note: some implementations may cache the value returned from the
* {@code LayoutManager}. Implementations that cache need not invoke
* {@code minimumLayoutSize} on the {@code LayoutManager} every time
* this method is invoked, rather the {@code LayoutManager} will only
* be queried after the {@code Container} becomes invalid.
*
* @return an instance of <code>Dimension</code> that represents
* the minimum size of this container.
* @see #getPreferredSize
* @see #getMaximumSize
* @see #getLayout
* @see LayoutManager#minimumLayoutSize(Container)
* @see Component#getMinimumSize
* @since JDK1.1
*/
public Dimension getMinimumSize() {
return minimumSize();
}
Deprecated: As of JDK version 1.1,
replaced by getMinimumSize()
.
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>getMinimumSize()</code>.
*/
@Deprecated
public Dimension minimumSize() {
/* Avoid grabbing the lock if a reasonable cached size value
* is available.
*/
Dimension dim = minSize;
if (dim == null || !(isMinimumSizeSet() || isValid())) {
synchronized (getTreeLock()) {
minSize = (layoutMgr != null) ?
layoutMgr.minimumLayoutSize(this) :
super.minimumSize();
dim = minSize;
}
}
if (dim != null){
return new Dimension(dim);
}
else{
return dim;
}
}
Returns the maximum size of this container. If the maximum size has not been set explicitly by Component.setMaximumSize(Dimension)
and the LayoutManager
installed on this Container
is an instance of LayoutManager2
, then LayoutManager2.maximumLayoutSize(Container)
is used to calculate the maximum size. Note: some implementations may cache the value returned from the LayoutManager2
. Implementations that cache need not invoke maximumLayoutSize
on the LayoutManager2
every time this method is invoked, rather the LayoutManager2
will only be queried after the Container
becomes invalid.
See Also: Returns: an instance of Dimension
that represents
the maximum size of this container.
/**
* Returns the maximum size of this container. If the maximum size has
* not been set explicitly by {@link Component#setMaximumSize(Dimension)}
* and the {@link LayoutManager} installed on this {@code Container}
* is an instance of {@link LayoutManager2}, then
* {@link LayoutManager2#maximumLayoutSize(Container)}
* is used to calculate the maximum size.
*
* <p>Note: some implementations may cache the value returned from the
* {@code LayoutManager2}. Implementations that cache need not invoke
* {@code maximumLayoutSize} on the {@code LayoutManager2} every time
* this method is invoked, rather the {@code LayoutManager2} will only
* be queried after the {@code Container} becomes invalid.
*
* @return an instance of <code>Dimension</code> that represents
* the maximum size of this container.
* @see #getPreferredSize
* @see #getMinimumSize
* @see #getLayout
* @see LayoutManager2#maximumLayoutSize(Container)
* @see Component#getMaximumSize
*/
public Dimension getMaximumSize() {
/* Avoid grabbing the lock if a reasonable cached size value
* is available.
*/
Dimension dim = maxSize;
if (dim == null || !(isMaximumSizeSet() || isValid())) {
synchronized (getTreeLock()) {
if (layoutMgr instanceof LayoutManager2) {
LayoutManager2 lm = (LayoutManager2) layoutMgr;
maxSize = lm.maximumLayoutSize(this);
} else {
maxSize = super.getMaximumSize();
}
dim = maxSize;
}
}
if (dim != null){
return new Dimension(dim);
}
else{
return dim;
}
}
Returns the alignment along the x axis. This specifies how
the component would like to be aligned relative to other
components. The value should be a number between 0 and 1
where 0 represents alignment along the origin, 1 is aligned
the furthest away from the origin, 0.5 is centered, etc.
/**
* Returns the alignment along the x axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getAlignmentX() {
float xAlign;
if (layoutMgr instanceof LayoutManager2) {
synchronized (getTreeLock()) {
LayoutManager2 lm = (LayoutManager2) layoutMgr;
xAlign = lm.getLayoutAlignmentX(this);
}
} else {
xAlign = super.getAlignmentX();
}
return xAlign;
}
Returns the alignment along the y axis. This specifies how
the component would like to be aligned relative to other
components. The value should be a number between 0 and 1
where 0 represents alignment along the origin, 1 is aligned
the furthest away from the origin, 0.5 is centered, etc.
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getAlignmentY() {
float yAlign;
if (layoutMgr instanceof LayoutManager2) {
synchronized (getTreeLock()) {
LayoutManager2 lm = (LayoutManager2) layoutMgr;
yAlign = lm.getLayoutAlignmentY(this);
}
} else {
yAlign = super.getAlignmentY();
}
return yAlign;
}
Paints the container. This forwards the paint to any lightweight
components that are children of this container. If this method is
reimplemented, super.paint(g) should be called so that lightweight
components are properly rendered. If a child component is entirely
clipped by the current clipping setting in g, paint() will not be
forwarded to that child.
Params: - g – the specified Graphics window
See Also:
/**
* Paints the container. This forwards the paint to any lightweight
* components that are children of this container. If this method is
* reimplemented, super.paint(g) should be called so that lightweight
* components are properly rendered. If a child component is entirely
* clipped by the current clipping setting in g, paint() will not be
* forwarded to that child.
*
* @param g the specified Graphics window
* @see Component#update(Graphics)
*/
public void paint(Graphics g) {
if (isShowing()) {
synchronized (getObjectLock()) {
if (printing) {
if (printingThreads.contains(Thread.currentThread())) {
return;
}
}
}
// The container is showing on screen and
// this paint() is not called from print().
// Paint self and forward the paint to lightweight subcomponents.
// super.paint(); -- Don't bother, since it's a NOP.
GraphicsCallback.PaintCallback.getInstance().
runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
}
}
Updates the container. This forwards the update to any lightweight
components that are children of this container. If this method is
reimplemented, super.update(g) should be called so that lightweight
components are properly rendered. If a child component is entirely
clipped by the current clipping setting in g, update() will not be
forwarded to that child.
Params: - g – the specified Graphics window
See Also:
/**
* Updates the container. This forwards the update to any lightweight
* components that are children of this container. If this method is
* reimplemented, super.update(g) should be called so that lightweight
* components are properly rendered. If a child component is entirely
* clipped by the current clipping setting in g, update() will not be
* forwarded to that child.
*
* @param g the specified Graphics window
* @see Component#update(Graphics)
*/
public void update(Graphics g) {
if (isShowing()) {
if (! (peer instanceof LightweightPeer)) {
g.clearRect(0, 0, width, height);
}
paint(g);
}
}
Prints the container. This forwards the print to any lightweight
components that are children of this container. If this method is
reimplemented, super.print(g) should be called so that lightweight
components are properly rendered. If a child component is entirely
clipped by the current clipping setting in g, print() will not be
forwarded to that child.
Params: - g – the specified Graphics window
See Also:
/**
* Prints the container. This forwards the print to any lightweight
* components that are children of this container. If this method is
* reimplemented, super.print(g) should be called so that lightweight
* components are properly rendered. If a child component is entirely
* clipped by the current clipping setting in g, print() will not be
* forwarded to that child.
*
* @param g the specified Graphics window
* @see Component#update(Graphics)
*/
public void print(Graphics g) {
if (isShowing()) {
Thread t = Thread.currentThread();
try {
synchronized (getObjectLock()) {
if (printingThreads == null) {
printingThreads = new HashSet();
}
printingThreads.add(t);
printing = true;
}
super.print(g); // By default, Component.print() calls paint()
} finally {
synchronized (getObjectLock()) {
printingThreads.remove(t);
printing = !printingThreads.isEmpty();
}
}
GraphicsCallback.PrintCallback.getInstance().
runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
}
}
Paints each of the components in this container.
Params: - g – the graphics context.
See Also:
/**
* Paints each of the components in this container.
* @param g the graphics context.
* @see Component#paint
* @see Component#paintAll
*/
public void paintComponents(Graphics g) {
if (isShowing()) {
GraphicsCallback.PaintAllCallback.getInstance().
runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
}
}
Simulates the peer callbacks into java.awt for printing of
lightweight Containers.
Params: - g – the graphics context to use for printing.
See Also:
/**
* Simulates the peer callbacks into java.awt for printing of
* lightweight Containers.
* @param g the graphics context to use for printing.
* @see Component#printAll
* @see #printComponents
*/
void lightweightPaint(Graphics g) {
super.lightweightPaint(g);
paintHeavyweightComponents(g);
}
Prints all the heavyweight subcomponents.
/**
* Prints all the heavyweight subcomponents.
*/
void paintHeavyweightComponents(Graphics g) {
if (isShowing()) {
GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
runComponents(getComponentsSync(), g,
GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
}
}
Prints each of the components in this container.
Params: - g – the graphics context.
See Also:
/**
* Prints each of the components in this container.
* @param g the graphics context.
* @see Component#print
* @see Component#printAll
*/
public void printComponents(Graphics g) {
if (isShowing()) {
GraphicsCallback.PrintAllCallback.getInstance().
runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
}
}
Simulates the peer callbacks into java.awt for printing of
lightweight Containers.
Params: - g – the graphics context to use for printing.
See Also:
/**
* Simulates the peer callbacks into java.awt for printing of
* lightweight Containers.
* @param g the graphics context to use for printing.
* @see Component#printAll
* @see #printComponents
*/
void lightweightPrint(Graphics g) {
super.lightweightPrint(g);
printHeavyweightComponents(g);
}
Prints all the heavyweight subcomponents.
/**
* Prints all the heavyweight subcomponents.
*/
void printHeavyweightComponents(Graphics g) {
if (isShowing()) {
GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
runComponents(getComponentsSync(), g,
GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
}
}
Adds the specified container listener to receive container events
from this container.
If l is null, no exception is thrown and no action is performed.
Refer to AWT Threading Issues for details on AWT's threading model.
Params: - l – the container listener
See Also:
/**
* Adds the specified container listener to receive container events
* from this container.
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the container listener
*
* @see #removeContainerListener
* @see #getContainerListeners
*/
public synchronized void addContainerListener(ContainerListener l) {
if (l == null) {
return;
}
containerListener = AWTEventMulticaster.add(containerListener, l);
newEventsOnly = true;
}
Removes the specified container listener so it no longer receives
container events from this container.
If l is null, no exception is thrown and no action is performed.
Refer to AWT Threading Issues for details on AWT's threading model.
Params: - l – the container listener
See Also:
/**
* Removes the specified container listener so it no longer receives
* container events from this container.
* If l is null, no exception is thrown and no action is performed.
* <p>Refer to <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for details on AWT's threading model.
*
* @param l the container listener
*
* @see #addContainerListener
* @see #getContainerListeners
*/
public synchronized void removeContainerListener(ContainerListener l) {
if (l == null) {
return;
}
containerListener = AWTEventMulticaster.remove(containerListener, l);
}
Returns an array of all the container listeners
registered on this container.
See Also: Returns: all of this container's ContainerListener
s
or an empty array if no container
listeners are currently registered Since: 1.4
/**
* Returns an array of all the container listeners
* registered on this container.
*
* @return all of this container's <code>ContainerListener</code>s
* or an empty array if no container
* listeners are currently registered
*
* @see #addContainerListener
* @see #removeContainerListener
* @since 1.4
*/
public synchronized ContainerListener[] getContainerListeners() {
return (ContainerListener[]) (getListeners(ContainerListener.class));
}
Returns an array of all the objects currently registered
as FooListener
s
upon this Container
.
FooListener
s are registered using the
addFooListener
method.
You can specify the listenerType
argument
with a class literal, such as
FooListener.class
.
For example, you can query a
Container
c
for its container listeners with the following code:
ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));
If no such listeners exist, this method returns an empty array.
Params: - listenerType – the type of listeners requested; this parameter
should specify an interface that descends from
java.util.EventListener
Throws: - ClassCastException – if
listenerType
doesn't specify a class or interface that implements
java.util.EventListener
- NullPointerException – if
listenerType
is null
See Also: Returns: an array of all objects registered as
FooListener
s on this container,
or an empty array if no such listeners have been added Since: 1.3
/**
* Returns an array of all the objects currently registered
* as <code><em>Foo</em>Listener</code>s
* upon this <code>Container</code>.
* <code><em>Foo</em>Listener</code>s are registered using the
* <code>add<em>Foo</em>Listener</code> method.
*
* <p>
* You can specify the <code>listenerType</code> argument
* with a class literal, such as
* <code><em>Foo</em>Listener.class</code>.
* For example, you can query a
* <code>Container</code> <code>c</code>
* for its container listeners with the following code:
*
* <pre>ContainerListener[] cls = (ContainerListener[])(c.getListeners(ContainerListener.class));</pre>
*
* If no such listeners exist, this method returns an empty array.
*
* @param listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
* <code>java.util.EventListener</code>
* @return an array of all objects registered as
* <code><em>Foo</em>Listener</code>s on this container,
* or an empty array if no such listeners have been added
* @exception ClassCastException if <code>listenerType</code>
* doesn't specify a class or interface that implements
* <code>java.util.EventListener</code>
* @exception NullPointerException if {@code listenerType} is {@code null}
*
* @see #getContainerListeners
*
* @since 1.3
*/
public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
EventListener l = null;
if (listenerType == ContainerListener.class) {
l = containerListener;
} else {
return super.getListeners(listenerType);
}
return AWTEventMulticaster.getListeners(l, listenerType);
}
// REMIND: remove when filtering is done at lower level
boolean eventEnabled(AWTEvent e) {
int id = e.getID();
if (id == ContainerEvent.COMPONENT_ADDED ||
id == ContainerEvent.COMPONENT_REMOVED) {
if ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
containerListener != null) {
return true;
}
return false;
}
return super.eventEnabled(e);
}
Processes events on this container. If the event is a
ContainerEvent
, it invokes the
processContainerEvent
method, else it invokes
its superclass's processEvent
.
Note that if the event parameter is null
the behavior is unspecified and may result in an
exception.
Params: - e – the event
/**
* Processes events on this container. If the event is a
* <code>ContainerEvent</code>, it invokes the
* <code>processContainerEvent</code> method, else it invokes
* its superclass's <code>processEvent</code>.
* <p>Note that if the event parameter is <code>null</code>
* the behavior is unspecified and may result in an
* exception.
*
* @param e the event
*/
protected void processEvent(AWTEvent e) {
if (e instanceof ContainerEvent) {
processContainerEvent((ContainerEvent)e);
return;
}
super.processEvent(e);
}
Processes container events occurring on this container by
dispatching them to any registered ContainerListener objects.
NOTE: This method will not be called unless container events
are enabled for this component; this happens when one of the
following occurs:
- A ContainerListener object is registered via
addContainerListener
- Container events are enabled via
enableEvents
Note that if the event parameter is null
the behavior is unspecified and may result in an
exception.
Params: - e – the container event
See Also:
/**
* Processes container events occurring on this container by
* dispatching them to any registered ContainerListener objects.
* NOTE: This method will not be called unless container events
* are enabled for this component; this happens when one of the
* following occurs:
* <ul>
* <li>A ContainerListener object is registered via
* <code>addContainerListener</code>
* <li>Container events are enabled via <code>enableEvents</code>
* </ul>
* <p>Note that if the event parameter is <code>null</code>
* the behavior is unspecified and may result in an
* exception.
*
* @param e the container event
* @see Component#enableEvents
*/
protected void processContainerEvent(ContainerEvent e) {
ContainerListener listener = containerListener;
if (listener != null) {
switch(e.getID()) {
case ContainerEvent.COMPONENT_ADDED:
listener.componentAdded(e);
break;
case ContainerEvent.COMPONENT_REMOVED:
listener.componentRemoved(e);
break;
}
}
}
/*
* Dispatches an event to this component or one of its sub components.
* Create ANCESTOR_RESIZED and ANCESTOR_MOVED events in response to
* COMPONENT_RESIZED and COMPONENT_MOVED events. We have to do this
* here instead of in processComponentEvent because ComponentEvents
* may not be enabled for this Container.
* @param e the event
*/
void dispatchEventImpl(AWTEvent e) {
if ((dispatcher != null) && dispatcher.dispatchEvent(e)) {
// event was sent to a lightweight component. The
// native-produced event sent to the native container
// must be properly disposed of by the peer, so it
// gets forwarded. If the native host has been removed
// as a result of the sending the lightweight event,
// the peer reference will be null.
e.consume();
if (peer != null) {
peer.handleEvent(e);
}
return;
}
super.dispatchEventImpl(e);
synchronized (getTreeLock()) {
switch (e.getID()) {
case ComponentEvent.COMPONENT_RESIZED:
createChildHierarchyEvents(HierarchyEvent.ANCESTOR_RESIZED, 0,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
break;
case ComponentEvent.COMPONENT_MOVED:
createChildHierarchyEvents(HierarchyEvent.ANCESTOR_MOVED, 0,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
break;
default:
break;
}
}
}
/*
* Dispatches an event to this component, without trying to forward
* it to any subcomponents
* @param e the event
*/
void dispatchEventToSelf(AWTEvent e) {
super.dispatchEventImpl(e);
}
Fetchs the top-most (deepest) lightweight component that is interested
in receiving mouse events.
/**
* Fetchs the top-most (deepest) lightweight component that is interested
* in receiving mouse events.
*/
Component getMouseEventTarget(int x, int y, boolean includeSelf) {
return getMouseEventTarget(x, y, includeSelf,
MouseEventTargetFilter.FILTER,
!SEARCH_HEAVYWEIGHTS);
}
Fetches the top-most (deepest) component to receive SunDropTargetEvents.
/**
* Fetches the top-most (deepest) component to receive SunDropTargetEvents.
*/
Component getDropTargetEventTarget(int x, int y, boolean includeSelf) {
return getMouseEventTarget(x, y, includeSelf,
DropTargetEventTargetFilter.FILTER,
SEARCH_HEAVYWEIGHTS);
}
A private version of getMouseEventTarget which has two additional
controllable behaviors. This method searches for the top-most
descendant of this container that contains the given coordinates
and is accepted by the given filter. The search will be constrained to
lightweight descendants if the last argument is false
.
Params: - filter – EventTargetFilter instance to determine whether the
given component is a valid target for this event.
- searchHeavyweights – if
false
, the method
will bypass heavyweight components during the search.
/**
* A private version of getMouseEventTarget which has two additional
* controllable behaviors. This method searches for the top-most
* descendant of this container that contains the given coordinates
* and is accepted by the given filter. The search will be constrained to
* lightweight descendants if the last argument is <code>false</code>.
*
* @param filter EventTargetFilter instance to determine whether the
* given component is a valid target for this event.
* @param searchHeavyweights if <code>false</code>, the method
* will bypass heavyweight components during the search.
*/
private Component getMouseEventTarget(int x, int y, boolean includeSelf,
EventTargetFilter filter,
boolean searchHeavyweights) {
Component comp = null;
if (searchHeavyweights) {
comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
SEARCH_HEAVYWEIGHTS,
searchHeavyweights);
}
if (comp == null || comp == this) {
comp = getMouseEventTargetImpl(x, y, includeSelf, filter,
!SEARCH_HEAVYWEIGHTS,
searchHeavyweights);
}
return comp;
}
A private version of getMouseEventTarget which has three additional
controllable behaviors. This method searches for the top-most
descendant of this container that contains the given coordinates
and is accepted by the given filter. The search will be constrained to
descendants of only lightweight children or only heavyweight children
of this container depending on searchHeavyweightChildren. The search will
be constrained to only lightweight descendants of the searched children
of this container if searchHeavyweightDescendants is false
.
Params: - filter – EventTargetFilter instance to determine whether the
selected component is a valid target for this event.
- searchHeavyweightChildren – if
true
, the method
will bypass immediate lightweight children during the search.
If false
, the methods will bypass immediate
heavyweight children during the search. - searchHeavyweightDescendants – if
false
, the method
will bypass heavyweight descendants which are not immediate
children during the search. If true
, the method
will traverse both lightweight and heavyweight descendants during
the search.
/**
* A private version of getMouseEventTarget which has three additional
* controllable behaviors. This method searches for the top-most
* descendant of this container that contains the given coordinates
* and is accepted by the given filter. The search will be constrained to
* descendants of only lightweight children or only heavyweight children
* of this container depending on searchHeavyweightChildren. The search will
* be constrained to only lightweight descendants of the searched children
* of this container if searchHeavyweightDescendants is <code>false</code>.
*
* @param filter EventTargetFilter instance to determine whether the
* selected component is a valid target for this event.
* @param searchHeavyweightChildren if <code>true</code>, the method
* will bypass immediate lightweight children during the search.
* If <code>false</code>, the methods will bypass immediate
* heavyweight children during the search.
* @param searchHeavyweightDescendants if <code>false</code>, the method
* will bypass heavyweight descendants which are not immediate
* children during the search. If <code>true</code>, the method
* will traverse both lightweight and heavyweight descendants during
* the search.
*/
private Component getMouseEventTargetImpl(int x, int y, boolean includeSelf,
EventTargetFilter filter,
boolean searchHeavyweightChildren,
boolean searchHeavyweightDescendants) {
synchronized (getTreeLock()) {
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if (comp != null && comp.visible &&
((!searchHeavyweightChildren &&
comp.peer instanceof LightweightPeer) ||
(searchHeavyweightChildren &&
!(comp.peer instanceof LightweightPeer))) &&
comp.contains(x - comp.x, y - comp.y)) {
// found a component that intersects the point, see if there
// is a deeper possibility.
if (comp instanceof Container) {
Container child = (Container) comp;
Component deeper = child.getMouseEventTarget(
x - child.x,
y - child.y,
includeSelf,
filter,
searchHeavyweightDescendants);
if (deeper != null) {
return deeper;
}
} else {
if (filter.accept(comp)) {
// there isn't a deeper target, but this component
// is a target
return comp;
}
}
}
}
boolean isPeerOK;
boolean isMouseOverMe;
isPeerOK = (peer instanceof LightweightPeer) || includeSelf;
isMouseOverMe = contains(x,y);
// didn't find a child target, return this component if it's
// a possible target
if (isMouseOverMe && isPeerOK && filter.accept(this)) {
return this;
}
// no possible target
return null;
}
}
static interface EventTargetFilter {
boolean accept(final Component comp);
}
static class MouseEventTargetFilter implements EventTargetFilter {
static final EventTargetFilter FILTER = new MouseEventTargetFilter();
private MouseEventTargetFilter() {}
public boolean accept(final Component comp) {
return (comp.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
|| (comp.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
|| (comp.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0
|| comp.mouseListener != null
|| comp.mouseMotionListener != null
|| comp.mouseWheelListener != null;
}
}
static class DropTargetEventTargetFilter implements EventTargetFilter {
static final EventTargetFilter FILTER = new DropTargetEventTargetFilter();
private DropTargetEventTargetFilter() {}
public boolean accept(final Component comp) {
DropTarget dt = comp.getDropTarget();
return dt != null && dt.isActive();
}
}
This is called by lightweight components that want the containing
windowed parent to enable some kind of events on their behalf.
This is needed for events that are normally only dispatched to
windows to be accepted so that they can be forwarded downward to
the lightweight component that has enabled them.
/**
* This is called by lightweight components that want the containing
* windowed parent to enable some kind of events on their behalf.
* This is needed for events that are normally only dispatched to
* windows to be accepted so that they can be forwarded downward to
* the lightweight component that has enabled them.
*/
void proxyEnableEvents(long events) {
if (peer instanceof LightweightPeer) {
// this container is lightweight.... continue sending it
// upward.
if (parent != null) {
parent.proxyEnableEvents(events);
}
} else {
// This is a native container, so it needs to host
// one of it's children. If this function is called before
// a peer has been created we don't yet have a dispatcher
// because it has not yet been determined if this instance
// is lightweight.
if (dispatcher != null) {
dispatcher.enableEvents(events);
}
}
}
Deprecated: As of JDK version 1.1,
replaced by dispatchEvent(AWTEvent e)
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>dispatchEvent(AWTEvent e)</code>
*/
@Deprecated
public void deliverEvent(Event e) {
Component comp = getComponentAt(e.x, e.y);
if ((comp != null) && (comp != this)) {
e.translate(-comp.x, -comp.y);
comp.deliverEvent(e);
} else {
postEvent(e);
}
}
Locates the component that contains the x,y position. The
top-most child component is returned in the case where there
is overlap in the components. This is determined by finding
the component closest to the index 0 that claims to contain
the given point via Component.contains(), except that Components
which have native peers take precedence over those which do not
(i.e., lightweight Components).
Params: - x – the x coordinate
- y – the y coordinate
See Also: Returns: null if the component does not contain the position.
If there is no child component at the requested point and the
point is within the bounds of the container the container itself
is returned; otherwise the top-most child is returned. Since: JDK1.1
/**
* Locates the component that contains the x,y position. The
* top-most child component is returned in the case where there
* is overlap in the components. This is determined by finding
* the component closest to the index 0 that claims to contain
* the given point via Component.contains(), except that Components
* which have native peers take precedence over those which do not
* (i.e., lightweight Components).
*
* @param x the <i>x</i> coordinate
* @param y the <i>y</i> coordinate
* @return null if the component does not contain the position.
* If there is no child component at the requested point and the
* point is within the bounds of the container the container itself
* is returned; otherwise the top-most child is returned.
* @see Component#contains
* @since JDK1.1
*/
public Component getComponentAt(int x, int y) {
return locate(x, y);
}
Deprecated: As of JDK version 1.1,
replaced by getComponentAt(int, int)
.
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>getComponentAt(int, int)</code>.
*/
@Deprecated
public Component locate(int x, int y) {
if (!contains(x, y)) {
return null;
}
synchronized (getTreeLock()) {
// Two passes: see comment in sun.awt.SunGraphicsCallback
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if (comp != null &&
!(comp.peer instanceof LightweightPeer)) {
if (comp.contains(x - comp.x, y - comp.y)) {
return comp;
}
}
}
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if (comp != null &&
comp.peer instanceof LightweightPeer) {
if (comp.contains(x - comp.x, y - comp.y)) {
return comp;
}
}
}
}
return this;
}
Gets the component that contains the specified point.
Params: - p – the point.
See Also: Returns: returns the component that contains the point,
or null
if the component does
not contain the point. Since: JDK1.1
/**
* Gets the component that contains the specified point.
* @param p the point.
* @return returns the component that contains the point,
* or <code>null</code> if the component does
* not contain the point.
* @see Component#contains
* @since JDK1.1
*/
public Component getComponentAt(Point p) {
return getComponentAt(p.x, p.y);
}
Returns the position of the mouse pointer in this Container
's
coordinate space if the Container
is under the mouse pointer,
otherwise returns null
. This method is similar to Component.getMousePosition()
with the exception that it can take the Container
's children into account.
If allowChildren
is false
, this method will return
a non-null value only if the mouse pointer is above the Container
directly, not above the part obscured by children.
If allowChildren
is true
, this method returns
a non-null value if the mouse pointer is above Container
or any
of its descendants.
Params: - allowChildren – true if children should be taken into account
Throws: - HeadlessException – if GraphicsEnvironment.isHeadless() returns true
See Also: Returns: mouse coordinates relative to this Component
, or null Since: 1.5
/**
* Returns the position of the mouse pointer in this <code>Container</code>'s
* coordinate space if the <code>Container</code> is under the mouse pointer,
* otherwise returns <code>null</code>.
* This method is similar to {@link Component#getMousePosition()} with the exception
* that it can take the <code>Container</code>'s children into account.
* If <code>allowChildren</code> is <code>false</code>, this method will return
* a non-null value only if the mouse pointer is above the <code>Container</code>
* directly, not above the part obscured by children.
* If <code>allowChildren</code> is <code>true</code>, this method returns
* a non-null value if the mouse pointer is above <code>Container</code> or any
* of its descendants.
*
* @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true
* @param allowChildren true if children should be taken into account
* @see Component#getMousePosition
* @return mouse coordinates relative to this <code>Component</code>, or null
* @since 1.5
*/
public Point getMousePosition(boolean allowChildren) throws HeadlessException {
if (GraphicsEnvironment.isHeadless()) {
throw new HeadlessException();
}
PointerInfo pi = (PointerInfo)java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
return MouseInfo.getPointerInfo();
}
}
);
synchronized (getTreeLock()) {
Component inTheSameWindow = findUnderMouseInWindow(pi);
if (isSameOrAncestorOf(inTheSameWindow, allowChildren)) {
return pointRelativeToComponent(pi.getLocation());
}
return null;
}
}
boolean isSameOrAncestorOf(Component comp, boolean allowChildren) {
return this == comp || (allowChildren && isParentOf(comp));
}
Locates the visible child component that contains the specified
position. The top-most child component is returned in the case
where there is overlap in the components. If the containing child
component is a Container, this method will continue searching for
the deepest nested child component. Components which are not
visible are ignored during the search.
The findComponentAt method is different from getComponentAt in
that getComponentAt only searches the Container's immediate
children; if the containing component is a Container,
findComponentAt will search that child to find a nested component.
Params: - x – the x coordinate
- y – the y coordinate
See Also: Returns: null if the component does not contain the position.
If there is no child component at the requested point and the
point is within the bounds of the container the container itself
is returned. Since: 1.2
/**
* Locates the visible child component that contains the specified
* position. The top-most child component is returned in the case
* where there is overlap in the components. If the containing child
* component is a Container, this method will continue searching for
* the deepest nested child component. Components which are not
* visible are ignored during the search.<p>
*
* The findComponentAt method is different from getComponentAt in
* that getComponentAt only searches the Container's immediate
* children; if the containing component is a Container,
* findComponentAt will search that child to find a nested component.
*
* @param x the <i>x</i> coordinate
* @param y the <i>y</i> coordinate
* @return null if the component does not contain the position.
* If there is no child component at the requested point and the
* point is within the bounds of the container the container itself
* is returned.
* @see Component#contains
* @see #getComponentAt
* @since 1.2
*/
public Component findComponentAt(int x, int y) {
return findComponentAt(x, y, true);
}
Private version of findComponentAt which has a controllable
behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled
Components during the search. This behavior is used by the
lightweight cursor support in sun.awt.GlobalCursorManager.
The cursor code calls this function directly via native code.
The addition of this feature is temporary, pending the
adoption of new, public API which exports this feature.
/**
* Private version of findComponentAt which has a controllable
* behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled
* Components during the search. This behavior is used by the
* lightweight cursor support in sun.awt.GlobalCursorManager.
* The cursor code calls this function directly via native code.
*
* The addition of this feature is temporary, pending the
* adoption of new, public API which exports this feature.
*/
final Component findComponentAt(int x, int y, boolean ignoreEnabled) {
synchronized (getTreeLock()) {
if (isRecursivelyVisible()){
return findComponentAtImpl(x, y, ignoreEnabled);
}
}
return null;
}
final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){
checkTreeLock();
if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {
return null;
}
// Two passes: see comment in sun.awt.SunGraphicsCallback
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if (comp != null &&
!(comp.peer instanceof LightweightPeer)) {
if (comp instanceof Container) {
comp = ((Container)comp).findComponentAtImpl(x - comp.x,
y - comp.y,
ignoreEnabled);
} else {
comp = comp.locate(x - comp.x, y - comp.y);
}
if (comp != null && comp.visible &&
(ignoreEnabled || comp.enabled))
{
return comp;
}
}
}
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if (comp != null &&
comp.peer instanceof LightweightPeer) {
if (comp instanceof Container) {
comp = ((Container)comp).findComponentAtImpl(x - comp.x,
y - comp.y,
ignoreEnabled);
} else {
comp = comp.locate(x - comp.x, y - comp.y);
}
if (comp != null && comp.visible &&
(ignoreEnabled || comp.enabled))
{
return comp;
}
}
}
return this;
}
Locates the visible child component that contains the specified
point. The top-most child component is returned in the case
where there is overlap in the components. If the containing child
component is a Container, this method will continue searching for
the deepest nested child component. Components which are not
visible are ignored during the search.
The findComponentAt method is different from getComponentAt in
that getComponentAt only searches the Container's immediate
children; if the containing component is a Container,
findComponentAt will search that child to find a nested component.
Params: - p – the point.
Throws: - NullPointerException – if
p
is null
See Also: Returns: null if the component does not contain the position.
If there is no child component at the requested point and the
point is within the bounds of the container the container itself
is returned. Since: 1.2
/**
* Locates the visible child component that contains the specified
* point. The top-most child component is returned in the case
* where there is overlap in the components. If the containing child
* component is a Container, this method will continue searching for
* the deepest nested child component. Components which are not
* visible are ignored during the search.<p>
*
* The findComponentAt method is different from getComponentAt in
* that getComponentAt only searches the Container's immediate
* children; if the containing component is a Container,
* findComponentAt will search that child to find a nested component.
*
* @param p the point.
* @return null if the component does not contain the position.
* If there is no child component at the requested point and the
* point is within the bounds of the container the container itself
* is returned.
* @throws NullPointerException if {@code p} is {@code null}
* @see Component#contains
* @see #getComponentAt
* @since 1.2
*/
public Component findComponentAt(Point p) {
return findComponentAt(p.x, p.y);
}
Makes this Container displayable by connecting it to
a native screen resource. Making a container displayable will
cause all of its children to be made displayable.
This method is called internally by the toolkit and should
not be called directly by programs.
See Also: - isDisplayable.isDisplayable
- removeNotify
/**
* Makes this Container displayable by connecting it to
* a native screen resource. Making a container displayable will
* cause all of its children to be made displayable.
* This method is called internally by the toolkit and should
* not be called directly by programs.
* @see Component#isDisplayable
* @see #removeNotify
*/
public void addNotify() {
synchronized (getTreeLock()) {
// addNotify() on the children may cause proxy event enabling
// on this instance, so we first call super.addNotify() and
// possibly create an lightweight event dispatcher before calling
// addNotify() on the children which may be lightweight.
super.addNotify();
if (! (peer instanceof LightweightPeer)) {
dispatcher = new LightweightDispatcher(this);
}
// We shouldn't use iterator because of the Swing menu
// implementation specifics:
// the menu is being assigned as a child to JLayeredPane
// instead of particular component so always affect
// collection of component if menu is becoming shown or hidden.
for (int i = 0; i < component.size(); i++) {
component.get(i).addNotify();
}
}
}
Makes this Container undisplayable by removing its connection
to its native screen resource. Making a container undisplayable
will cause all of its children to be made undisplayable.
This method is called by the toolkit internally and should
not be called directly by programs.
See Also: - isDisplayable.isDisplayable
- addNotify
/**
* Makes this Container undisplayable by removing its connection
* to its native screen resource. Making a container undisplayable
* will cause all of its children to be made undisplayable.
* This method is called by the toolkit internally and should
* not be called directly by programs.
* @see Component#isDisplayable
* @see #addNotify
*/
public void removeNotify() {
synchronized (getTreeLock()) {
// We shouldn't use iterator because of the Swing menu
// implementation specifics:
// the menu is being assigned as a child to JLayeredPane
// instead of particular component so always affect
// collection of component if menu is becoming shown or hidden.
for (int i = component.size()-1 ; i >= 0 ; i--) {
Component comp = component.get(i);
if (comp != null) {
// Fix for 6607170.
// We want to suppress focus change on disposal
// of the focused component. But because of focus
// is asynchronous, we should suppress focus change
// on every component in case it receives native focus
// in the process of disposal.
comp.setAutoFocusTransferOnDisposal(false);
comp.removeNotify();
comp.setAutoFocusTransferOnDisposal(true);
}
}
// If some of the children had focus before disposal then it still has.
// Auto-transfer focus to the next (or previous) component if auto-transfer
// is enabled.
if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {
if (!transferFocus(false)) {
transferFocusBackward(true);
}
}
if ( dispatcher != null ) {
dispatcher.dispose();
dispatcher = null;
}
super.removeNotify();
}
}
Checks if the component is contained in the component hierarchy of
this container.
Params: - c – the component
Returns: true
if it is an ancestor;
false
otherwise. Since: JDK1.1
/**
* Checks if the component is contained in the component hierarchy of
* this container.
* @param c the component
* @return <code>true</code> if it is an ancestor;
* <code>false</code> otherwise.
* @since JDK1.1
*/
public boolean isAncestorOf(Component c) {
Container p;
if (c == null || ((p = c.getParent()) == null)) {
return false;
}
while (p != null) {
if (p == this) {
return true;
}
p = p.getParent();
}
return false;
}
/*
* The following code was added to support modal JInternalFrames
* Unfortunately this code has to be added here so that we can get access to
* some private AWT classes like SequencedEvent.
*
* The native container of the LW component has this field set
* to tell it that it should block Mouse events for all LW
* children except for the modal component.
*
* In the case of nested Modal components, we store the previous
* modal component in the new modal components value of modalComp;
*/
transient Component modalComp;
transient AppContext modalAppContext;
private void startLWModal() {
// Store the app context on which this component is being shown.
// Event dispatch thread of this app context will be sleeping until
// we wake it by any event from hideAndDisposeHandler().
modalAppContext = AppContext.getAppContext();
// keep the KeyEvents from being dispatched
// until the focus has been transfered
long time = Toolkit.getEventQueue().getMostRecentEventTime();
Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null;
if (predictedFocusOwner != null) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().
enqueueKeyEvents(time, predictedFocusOwner);
}
// We have two mechanisms for blocking: 1. If we're on the
// EventDispatchThread, start a new event pump. 2. If we're
// on any other thread, call wait() on the treelock.
final Container nativeContainer;
synchronized (getTreeLock()) {
nativeContainer = getHeavyweightContainer();
if (nativeContainer.modalComp != null) {
this.modalComp = nativeContainer.modalComp;
nativeContainer.modalComp = this;
return;
}
else {
nativeContainer.modalComp = this;
}
}
Runnable pumpEventsForHierarchy = new Runnable() {
public void run() {
EventDispatchThread dispatchThread =
(EventDispatchThread)Thread.currentThread();
dispatchThread.pumpEventsForHierarchy(
new Conditional() {
public boolean evaluate() {
return ((windowClosingException == null) && (nativeContainer.modalComp != null)) ;
}
}, Container.this);
}
};
if (EventQueue.isDispatchThread()) {
SequencedEvent currentSequencedEvent =
KeyboardFocusManager.getCurrentKeyboardFocusManager().
getCurrentSequencedEvent();
if (currentSequencedEvent != null) {
currentSequencedEvent.dispose();
}
pumpEventsForHierarchy.run();
} else {
synchronized (getTreeLock()) {
Toolkit.getEventQueue().
postEvent(new PeerEvent(this,
pumpEventsForHierarchy,
PeerEvent.PRIORITY_EVENT));
while ((windowClosingException == null) &&
(nativeContainer.modalComp != null))
{
try {
getTreeLock().wait();
} catch (InterruptedException e) {
break;
}
}
}
}
if (windowClosingException != null) {
windowClosingException.fillInStackTrace();
throw windowClosingException;
}
if (predictedFocusOwner != null) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().
dequeueKeyEvents(time, predictedFocusOwner);
}
}
private void stopLWModal() {
synchronized (getTreeLock()) {
if (modalAppContext != null) {
Container nativeContainer = getHeavyweightContainer();
if(nativeContainer != null) {
if (this.modalComp != null) {
nativeContainer.modalComp = this.modalComp;
this.modalComp = null;
return;
}
else {
nativeContainer.modalComp = null;
}
}
// Wake up event dispatch thread on which the dialog was
// initially shown
SunToolkit.postEvent(modalAppContext,
new PeerEvent(this,
new WakingRunnable(),
PeerEvent.PRIORITY_EVENT));
}
EventQueue.invokeLater(new WakingRunnable());
getTreeLock().notifyAll();
}
}
final static class WakingRunnable implements Runnable {
public void run() {
}
}
/* End of JOptionPane support code */
Returns a string representing the state of this Container
.
This method is intended to be used only for debugging purposes, and the
content and format of the returned string may vary between
implementations. The returned string may be empty but may not be
null
.
Returns: the parameter string of this container
/**
* Returns a string representing the state of this <code>Container</code>.
* This method is intended to be used only for debugging purposes, and the
* content and format of the returned string may vary between
* implementations. The returned string may be empty but may not be
* <code>null</code>.
*
* @return the parameter string of this container
*/
protected String paramString() {
String str = super.paramString();
LayoutManager layoutMgr = this.layoutMgr;
if (layoutMgr != null) {
str += ",layout=" + layoutMgr.getClass().getName();
}
return str;
}
Prints a listing of this container to the specified output
stream. The listing starts at the specified indentation.
The immediate children of the container are printed with
an indentation of indent+1
. The children
of those children are printed at indent+2
and so on.
Params: - out – a print stream
- indent – the number of spaces to indent
Throws: - NullPointerException – if
out
is null
See Also: Since: JDK1.0
/**
* Prints a listing of this container to the specified output
* stream. The listing starts at the specified indentation.
* <p>
* The immediate children of the container are printed with
* an indentation of <code>indent+1</code>. The children
* of those children are printed at <code>indent+2</code>
* and so on.
*
* @param out a print stream
* @param indent the number of spaces to indent
* @throws NullPointerException if {@code out} is {@code null}
* @see Component#list(java.io.PrintStream, int)
* @since JDK1.0
*/
public void list(PrintStream out, int indent) {
super.list(out, indent);
synchronized(getTreeLock()) {
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if (comp != null) {
comp.list(out, indent+1);
}
}
}
}
Prints out a list, starting at the specified indentation,
to the specified print writer.
The immediate children of the container are printed with
an indentation of indent+1
. The children
of those children are printed at indent+2
and so on.
Params: - out – a print writer
- indent – the number of spaces to indent
Throws: - NullPointerException – if
out
is null
See Also: Since: JDK1.1
/**
* Prints out a list, starting at the specified indentation,
* to the specified print writer.
* <p>
* The immediate children of the container are printed with
* an indentation of <code>indent+1</code>. The children
* of those children are printed at <code>indent+2</code>
* and so on.
*
* @param out a print writer
* @param indent the number of spaces to indent
* @throws NullPointerException if {@code out} is {@code null}
* @see Component#list(java.io.PrintWriter, int)
* @since JDK1.1
*/
public void list(PrintWriter out, int indent) {
super.list(out, indent);
synchronized(getTreeLock()) {
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if (comp != null) {
comp.list(out, indent+1);
}
}
}
}
Sets the focus traversal keys for a given traversal operation for this
Container.
The default values for a Container's focus traversal keys are
implementation-dependent. Sun recommends that all implementations for a
particular native platform use the same default values. The
recommendations for Windows and Unix are listed below. These
recommendations are used in the Sun AWT implementations.
Identifier
Meaning
Default
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS
Normal forward keyboard traversal
TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS
Normal reverse keyboard traversal
SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED
KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS
Go up one focus traversal cycle
none
KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
Go down one focus traversal cycle
none
To disable a traversal key, use an empty Set; Collections.EMPTY_SET is
recommended.
Using the AWTKeyStroke API, client code can specify on which of two
specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal
operation will occur. Regardless of which KeyEvent is specified,
however, all KeyEvents related to the focus traversal key, including the
associated KEY_TYPED event, will be consumed, and will not be dispatched
to any Container. It is a runtime error to specify a KEY_TYPED event as
mapping to a focus traversal operation, or to map the same event to
multiple default focus traversal operations.
If a value of null is specified for the Set, this Container inherits the
Set from its parent. If all ancestors of this Container have null
specified for the Set, then the current KeyboardFocusManager's default
Set is used.
Params: - id – one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
- keystrokes – the Set of AWTKeyStroke for the specified operation
Throws: - IllegalArgumentException – if id is not one of
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes
contains null, or if any Object in keystrokes is not an
AWTKeyStroke, or if any keystroke represents a KEY_TYPED event,
or if any keystroke already maps to another focus traversal
operation for this Container
See Also: Since: 1.4 @beaninfo
bound: true
/**
* Sets the focus traversal keys for a given traversal operation for this
* Container.
* <p>
* The default values for a Container's focus traversal keys are
* implementation-dependent. Sun recommends that all implementations for a
* particular native platform use the same default values. The
* recommendations for Windows and Unix are listed below. These
* recommendations are used in the Sun AWT implementations.
*
* <table border=1 summary="Recommended default values for a Container's focus traversal keys">
* <tr>
* <th>Identifier</th>
* <th>Meaning</th>
* <th>Default</th>
* </tr>
* <tr>
* <td>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</td>
* <td>Normal forward keyboard traversal</td>
* <td>TAB on KEY_PRESSED, CTRL-TAB on KEY_PRESSED</td>
* </tr>
* <tr>
* <td>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</td>
* <td>Normal reverse keyboard traversal</td>
* <td>SHIFT-TAB on KEY_PRESSED, CTRL-SHIFT-TAB on KEY_PRESSED</td>
* </tr>
* <tr>
* <td>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</td>
* <td>Go up one focus traversal cycle</td>
* <td>none</td>
* </tr>
* <tr>
* <td>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS<td>
* <td>Go down one focus traversal cycle</td>
* <td>none</td>
* </tr>
* </table>
*
* To disable a traversal key, use an empty Set; Collections.EMPTY_SET is
* recommended.
* <p>
* Using the AWTKeyStroke API, client code can specify on which of two
* specific KeyEvents, KEY_PRESSED or KEY_RELEASED, the focus traversal
* operation will occur. Regardless of which KeyEvent is specified,
* however, all KeyEvents related to the focus traversal key, including the
* associated KEY_TYPED event, will be consumed, and will not be dispatched
* to any Container. It is a runtime error to specify a KEY_TYPED event as
* mapping to a focus traversal operation, or to map the same event to
* multiple default focus traversal operations.
* <p>
* If a value of null is specified for the Set, this Container inherits the
* Set from its parent. If all ancestors of this Container have null
* specified for the Set, then the current KeyboardFocusManager's default
* Set is used.
*
* @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
* @param keystrokes the Set of AWTKeyStroke for the specified operation
* @see #getFocusTraversalKeys
* @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
* @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
* @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
* @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
* @throws IllegalArgumentException if id is not one of
* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS, or if keystrokes
* contains null, or if any Object in keystrokes is not an
* AWTKeyStroke, or if any keystroke represents a KEY_TYPED event,
* or if any keystroke already maps to another focus traversal
* operation for this Container
* @since 1.4
* @beaninfo
* bound: true
*/
public void setFocusTraversalKeys(int id,
Set<? extends AWTKeyStroke> keystrokes)
{
if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
throw new IllegalArgumentException("invalid focus traversal key identifier");
}
// Don't call super.setFocusTraversalKey. The Component parameter check
// does not allow DOWN_CYCLE_TRAVERSAL_KEYS, but we do.
setFocusTraversalKeys_NoIDCheck(id, keystrokes);
}
Returns the Set of focus traversal keys for a given traversal operation
for this Container. (See
setFocusTraversalKeys
for a full description of each key.)
If a Set of traversal keys has not been explicitly defined for this
Container, then this Container's parent's Set is returned. If no Set
has been explicitly defined for any of this Container's ancestors, then
the current KeyboardFocusManager's default Set is returned.
Params: - id – one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
Throws: - IllegalArgumentException – if id is not one of
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
See Also: Returns: the Set of AWTKeyStrokes for the specified operation. The Set
will be unmodifiable, and may be empty. null will never be
returned. Since: 1.4
/**
* Returns the Set of focus traversal keys for a given traversal operation
* for this Container. (See
* <code>setFocusTraversalKeys</code> for a full description of each key.)
* <p>
* If a Set of traversal keys has not been explicitly defined for this
* Container, then this Container's parent's Set is returned. If no Set
* has been explicitly defined for any of this Container's ancestors, then
* the current KeyboardFocusManager's default Set is returned.
*
* @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
* @return the Set of AWTKeyStrokes for the specified operation. The Set
* will be unmodifiable, and may be empty. null will never be
* returned.
* @see #setFocusTraversalKeys
* @see KeyboardFocusManager#FORWARD_TRAVERSAL_KEYS
* @see KeyboardFocusManager#BACKWARD_TRAVERSAL_KEYS
* @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
* @see KeyboardFocusManager#DOWN_CYCLE_TRAVERSAL_KEYS
* @throws IllegalArgumentException if id is not one of
* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
* @since 1.4
*/
public Set<AWTKeyStroke> getFocusTraversalKeys(int id) {
if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
throw new IllegalArgumentException("invalid focus traversal key identifier");
}
// Don't call super.getFocusTraversalKey. The Component parameter check
// does not allow DOWN_CYCLE_TRAVERSAL_KEY, but we do.
return getFocusTraversalKeys_NoIDCheck(id);
}
Returns whether the Set of focus traversal keys for the given focus
traversal operation has been explicitly defined for this Container. If
this method returns false
, this Container is inheriting the
Set from an ancestor, or from the current KeyboardFocusManager.
Params: - id – one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
Throws: - IllegalArgumentException – if id is not one of
KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
Returns: true
if the the Set of focus traversal keys for the
given focus traversal operation has been explicitly defined for
this Component; false
otherwise.Since: 1.4
/**
* Returns whether the Set of focus traversal keys for the given focus
* traversal operation has been explicitly defined for this Container. If
* this method returns <code>false</code>, this Container is inheriting the
* Set from an ancestor, or from the current KeyboardFocusManager.
*
* @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
* @return <code>true</code> if the the Set of focus traversal keys for the
* given focus traversal operation has been explicitly defined for
* this Component; <code>false</code> otherwise.
* @throws IllegalArgumentException if id is not one of
* KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
* KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
* KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
* @since 1.4
*/
public boolean areFocusTraversalKeysSet(int id) {
if (id < 0 || id >= KeyboardFocusManager.TRAVERSAL_KEY_LENGTH) {
throw new IllegalArgumentException("invalid focus traversal key identifier");
}
return (focusTraversalKeys != null && focusTraversalKeys[id] != null);
}
Returns whether the specified Container is the focus cycle root of this
Container's focus traversal cycle. Each focus traversal cycle has only
a single focus cycle root and each Container which is not a focus cycle
root belongs to only a single focus traversal cycle. Containers which
are focus cycle roots belong to two cycles: one rooted at the Container
itself, and one rooted at the Container's nearest focus-cycle-root
ancestor. This method will return true
for both such
Containers in this case.
Params: - container – the Container to be tested
See Also: Returns: true
if the specified Container is a focus-cycle-
root of this Container; false
otherwiseSince: 1.4
/**
* Returns whether the specified Container is the focus cycle root of this
* Container's focus traversal cycle. Each focus traversal cycle has only
* a single focus cycle root and each Container which is not a focus cycle
* root belongs to only a single focus traversal cycle. Containers which
* are focus cycle roots belong to two cycles: one rooted at the Container
* itself, and one rooted at the Container's nearest focus-cycle-root
* ancestor. This method will return <code>true</code> for both such
* Containers in this case.
*
* @param container the Container to be tested
* @return <code>true</code> if the specified Container is a focus-cycle-
* root of this Container; <code>false</code> otherwise
* @see #isFocusCycleRoot()
* @since 1.4
*/
public boolean isFocusCycleRoot(Container container) {
if (isFocusCycleRoot() && container == this) {
return true;
} else {
return super.isFocusCycleRoot(container);
}
}
private Container findTraversalRoot() {
// I potentially have two roots, myself and my root parent
// If I am the current root, then use me
// If none of my parents are roots, then use me
// If my root parent is the current root, then use my root parent
// If neither I nor my root parent is the current root, then
// use my root parent (a guess)
Container currentFocusCycleRoot = KeyboardFocusManager.
getCurrentKeyboardFocusManager().getCurrentFocusCycleRoot();
Container root;
if (currentFocusCycleRoot == this) {
root = this;
} else {
root = getFocusCycleRootAncestor();
if (root == null) {
root = this;
}
}
if (root != currentFocusCycleRoot) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().
setGlobalCurrentFocusCycleRoot(root);
}
return root;
}
final boolean containsFocus() {
final Component focusOwner = KeyboardFocusManager.
getCurrentKeyboardFocusManager().getFocusOwner();
return isParentOf(focusOwner);
}
Check if this component is the child of this container or its children.
Note: this function acquires treeLock
Note: this function traverses children tree only in one Window.
Params: - comp – a component in test, must not be null
/**
* Check if this component is the child of this container or its children.
* Note: this function acquires treeLock
* Note: this function traverses children tree only in one Window.
* @param comp a component in test, must not be null
*/
private boolean isParentOf(Component comp) {
synchronized(getTreeLock()) {
while (comp != null && comp != this && !(comp instanceof Window)) {
comp = comp.getParent();
}
return (comp == this);
}
}
void clearMostRecentFocusOwnerOnHide() {
boolean reset = false;
Window window = null;
synchronized (getTreeLock()) {
window = getContainingWindow();
if (window != null) {
Component comp = KeyboardFocusManager.getMostRecentFocusOwner(window);
reset = ((comp == this) || isParentOf(comp));
// This synchronized should always be the second in a pair
// (tree lock, KeyboardFocusManager.class)
synchronized(KeyboardFocusManager.class) {
Component storedComp = window.getTemporaryLostComponent();
if (isParentOf(storedComp) || storedComp == this) {
window.setTemporaryLostComponent(null);
}
}
}
}
if (reset) {
KeyboardFocusManager.setMostRecentFocusOwner(window, null);
}
}
void clearCurrentFocusCycleRootOnHide() {
KeyboardFocusManager kfm =
KeyboardFocusManager.getCurrentKeyboardFocusManager();
Container cont = kfm.getCurrentFocusCycleRoot();
if (cont == this || isParentOf(cont)) {
kfm.setGlobalCurrentFocusCycleRoot(null);
}
}
final Container getTraversalRoot() {
if (isFocusCycleRoot()) {
return findTraversalRoot();
}
return super.getTraversalRoot();
}
Sets the focus traversal policy that will manage keyboard traversal of
this Container's children, if this Container is a focus cycle root. If
the argument is null, this Container inherits its policy from its focus-
cycle-root ancestor. If the argument is non-null, this policy will be
inherited by all focus-cycle-root children that have no keyboard-
traversal policy of their own (as will, recursively, their focus-cycle-
root children).
If this Container is not a focus cycle root, the policy will be
remembered, but will not be used or inherited by this or any other
Containers until this Container is made a focus cycle root.
Params: - policy – the new focus traversal policy for this Container
See Also: Since: 1.4 @beaninfo
bound: true
/**
* Sets the focus traversal policy that will manage keyboard traversal of
* this Container's children, if this Container is a focus cycle root. If
* the argument is null, this Container inherits its policy from its focus-
* cycle-root ancestor. If the argument is non-null, this policy will be
* inherited by all focus-cycle-root children that have no keyboard-
* traversal policy of their own (as will, recursively, their focus-cycle-
* root children).
* <p>
* If this Container is not a focus cycle root, the policy will be
* remembered, but will not be used or inherited by this or any other
* Containers until this Container is made a focus cycle root.
*
* @param policy the new focus traversal policy for this Container
* @see #getFocusTraversalPolicy
* @see #setFocusCycleRoot
* @see #isFocusCycleRoot
* @since 1.4
* @beaninfo
* bound: true
*/
public void setFocusTraversalPolicy(FocusTraversalPolicy policy) {
FocusTraversalPolicy oldPolicy;
synchronized (this) {
oldPolicy = this.focusTraversalPolicy;
this.focusTraversalPolicy = policy;
}
firePropertyChange("focusTraversalPolicy", oldPolicy, policy);
}
Returns the focus traversal policy that will manage keyboard traversal
of this Container's children, or null if this Container is not a focus
cycle root. If no traversal policy has been explicitly set for this
Container, then this Container's focus-cycle-root ancestor's policy is
returned.
See Also: Returns: this Container's focus traversal policy, or null if this
Container is not a focus cycle root. Since: 1.4
/**
* Returns the focus traversal policy that will manage keyboard traversal
* of this Container's children, or null if this Container is not a focus
* cycle root. If no traversal policy has been explicitly set for this
* Container, then this Container's focus-cycle-root ancestor's policy is
* returned.
*
* @return this Container's focus traversal policy, or null if this
* Container is not a focus cycle root.
* @see #setFocusTraversalPolicy
* @see #setFocusCycleRoot
* @see #isFocusCycleRoot
* @since 1.4
*/
public FocusTraversalPolicy getFocusTraversalPolicy() {
if (!isFocusTraversalPolicyProvider() && !isFocusCycleRoot()) {
return null;
}
FocusTraversalPolicy policy = this.focusTraversalPolicy;
if (policy != null) {
return policy;
}
Container rootAncestor = getFocusCycleRootAncestor();
if (rootAncestor != null) {
return rootAncestor.getFocusTraversalPolicy();
} else {
return KeyboardFocusManager.getCurrentKeyboardFocusManager().
getDefaultFocusTraversalPolicy();
}
}
Returns whether the focus traversal policy has been explicitly set for
this Container. If this method returns false
, this
Container will inherit its focus traversal policy from an ancestor.
Returns: true
if the focus traversal policy has been
explicitly set for this Container; false
otherwise.Since: 1.4
/**
* Returns whether the focus traversal policy has been explicitly set for
* this Container. If this method returns <code>false</code>, this
* Container will inherit its focus traversal policy from an ancestor.
*
* @return <code>true</code> if the focus traversal policy has been
* explicitly set for this Container; <code>false</code> otherwise.
* @since 1.4
*/
public boolean isFocusTraversalPolicySet() {
return (focusTraversalPolicy != null);
}
Sets whether this Container is the root of a focus traversal cycle. Once
focus enters a traversal cycle, typically it cannot leave it via focus
traversal unless one of the up- or down-cycle keys is pressed. Normal
traversal is limited to this Container, and all of this Container's
descendants that are not descendants of inferior focus cycle roots. Note
that a FocusTraversalPolicy may bend these restrictions, however. For
example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
traversal.
The alternative way to specify the traversal order of this Container's
children is to make this Container a
focus traversal policy provider.
Params: - focusCycleRoot – indicates whether this Container is the root of a
focus traversal cycle
See Also: Since: 1.4 @beaninfo
bound: true
/**
* Sets whether this Container is the root of a focus traversal cycle. Once
* focus enters a traversal cycle, typically it cannot leave it via focus
* traversal unless one of the up- or down-cycle keys is pressed. Normal
* traversal is limited to this Container, and all of this Container's
* descendants that are not descendants of inferior focus cycle roots. Note
* that a FocusTraversalPolicy may bend these restrictions, however. For
* example, ContainerOrderFocusTraversalPolicy supports implicit down-cycle
* traversal.
* <p>
* The alternative way to specify the traversal order of this Container's
* children is to make this Container a
* <a href="doc-files/FocusSpec.html#FocusTraversalPolicyProviders">focus traversal policy provider</a>.
*
* @param focusCycleRoot indicates whether this Container is the root of a
* focus traversal cycle
* @see #isFocusCycleRoot()
* @see #setFocusTraversalPolicy
* @see #getFocusTraversalPolicy
* @see ContainerOrderFocusTraversalPolicy
* @see #setFocusTraversalPolicyProvider
* @since 1.4
* @beaninfo
* bound: true
*/
public void setFocusCycleRoot(boolean focusCycleRoot) {
boolean oldFocusCycleRoot;
synchronized (this) {
oldFocusCycleRoot = this.focusCycleRoot;
this.focusCycleRoot = focusCycleRoot;
}
firePropertyChange("focusCycleRoot", oldFocusCycleRoot,
focusCycleRoot);
}
Returns whether this Container is the root of a focus traversal cycle.
Once focus enters a traversal cycle, typically it cannot leave it via
focus traversal unless one of the up- or down-cycle keys is pressed.
Normal traversal is limited to this Container, and all of this
Container's descendants that are not descendants of inferior focus
cycle roots. Note that a FocusTraversalPolicy may bend these
restrictions, however. For example, ContainerOrderFocusTraversalPolicy
supports implicit down-cycle traversal.
See Also: Returns: whether this Container is the root of a focus traversal cycle Since: 1.4
/**
* Returns whether this Container is the root of a focus traversal cycle.
* Once focus enters a traversal cycle, typically it cannot leave it via
* focus traversal unless one of the up- or down-cycle keys is pressed.
* Normal traversal is limited to this Container, and all of this
* Container's descendants that are not descendants of inferior focus
* cycle roots. Note that a FocusTraversalPolicy may bend these
* restrictions, however. For example, ContainerOrderFocusTraversalPolicy
* supports implicit down-cycle traversal.
*
* @return whether this Container is the root of a focus traversal cycle
* @see #setFocusCycleRoot
* @see #setFocusTraversalPolicy
* @see #getFocusTraversalPolicy
* @see ContainerOrderFocusTraversalPolicy
* @since 1.4
*/
public boolean isFocusCycleRoot() {
return focusCycleRoot;
}
Sets whether this container will be used to provide focus
traversal policy. Container with this property as
true
will be used to acquire focus traversal policy
instead of closest focus cycle root ancestor.
Params: - provider – indicates whether this container will be used to
provide focus traversal policy
See Also: Since: 1.5 @beaninfo
bound: true
/**
* Sets whether this container will be used to provide focus
* traversal policy. Container with this property as
* <code>true</code> will be used to acquire focus traversal policy
* instead of closest focus cycle root ancestor.
* @param provider indicates whether this container will be used to
* provide focus traversal policy
* @see #setFocusTraversalPolicy
* @see #getFocusTraversalPolicy
* @see #isFocusTraversalPolicyProvider
* @since 1.5
* @beaninfo
* bound: true
*/
public final void setFocusTraversalPolicyProvider(boolean provider) {
boolean oldProvider;
synchronized(this) {
oldProvider = focusTraversalPolicyProvider;
focusTraversalPolicyProvider = provider;
}
firePropertyChange("focusTraversalPolicyProvider", oldProvider, provider);
}
Returns whether this container provides focus traversal
policy. If this property is set to true
then when
keyboard focus manager searches container hierarchy for focus
traversal policy and encounters this container before any other
container with this property as true or focus cycle roots then
its focus traversal policy will be used instead of focus cycle
root's policy.
See Also: - setFocusTraversalPolicy
- getFocusTraversalPolicy
- setFocusCycleRoot
- setFocusTraversalPolicyProvider
Returns: true
if this container provides focus traversal
policy, false
otherwiseSince: 1.5 @beaninfo
bound: true
/**
* Returns whether this container provides focus traversal
* policy. If this property is set to <code>true</code> then when
* keyboard focus manager searches container hierarchy for focus
* traversal policy and encounters this container before any other
* container with this property as true or focus cycle roots then
* its focus traversal policy will be used instead of focus cycle
* root's policy.
* @see #setFocusTraversalPolicy
* @see #getFocusTraversalPolicy
* @see #setFocusCycleRoot
* @see #setFocusTraversalPolicyProvider
* @return <code>true</code> if this container provides focus traversal
* policy, <code>false</code> otherwise
* @since 1.5
* @beaninfo
* bound: true
*/
public final boolean isFocusTraversalPolicyProvider() {
return focusTraversalPolicyProvider;
}
Transfers the focus down one focus traversal cycle. If this Container is
a focus cycle root, then the focus owner is set to this Container's
default Component to focus, and the current focus cycle root is set to
this Container. If this Container is not a focus cycle root, then no
focus traversal operation occurs.
See Also: - requestFocus.requestFocus()
- isFocusCycleRoot
- setFocusCycleRoot
Since: 1.4
/**
* Transfers the focus down one focus traversal cycle. If this Container is
* a focus cycle root, then the focus owner is set to this Container's
* default Component to focus, and the current focus cycle root is set to
* this Container. If this Container is not a focus cycle root, then no
* focus traversal operation occurs.
*
* @see Component#requestFocus()
* @see #isFocusCycleRoot
* @see #setFocusCycleRoot
* @since 1.4
*/
public void transferFocusDownCycle() {
if (isFocusCycleRoot()) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().
setGlobalCurrentFocusCycleRoot(this);
Component toFocus = getFocusTraversalPolicy().
getDefaultComponent(this);
if (toFocus != null) {
toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN);
}
}
}
void preProcessKeyEvent(KeyEvent e) {
Container parent = this.parent;
if (parent != null) {
parent.preProcessKeyEvent(e);
}
}
void postProcessKeyEvent(KeyEvent e) {
Container parent = this.parent;
if (parent != null) {
parent.postProcessKeyEvent(e);
}
}
boolean postsOldMouseEvents() {
return true;
}
Sets the ComponentOrientation
property of this container
and all components contained within it.
This method changes layout-related information, and therefore,
invalidates the component hierarchy.
Params: - o – the new component orientation of this container and
the components contained within it.
Throws: - NullPointerException – if
orientation
is null.
See Also: Since: 1.4
/**
* Sets the <code>ComponentOrientation</code> property of this container
* and all components contained within it.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy.
*
* @param o the new component orientation of this container and
* the components contained within it.
* @exception NullPointerException if <code>orientation</code> is null.
* @see Component#setComponentOrientation
* @see Component#getComponentOrientation
* @see #invalidate
* @since 1.4
*/
public void applyComponentOrientation(ComponentOrientation o) {
super.applyComponentOrientation(o);
synchronized (getTreeLock()) {
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
comp.applyComponentOrientation(o);
}
}
}
Adds a PropertyChangeListener to the listener list. The listener is
registered for all bound properties of this class, including the
following:
- this Container's font ("font")
- this Container's background color ("background")
- this Container's foreground color ("foreground")
- this Container's focusability ("focusable")
- this Container's focus traversal keys enabled state
("focusTraversalKeysEnabled")
- this Container's Set of FORWARD_TRAVERSAL_KEYS
("forwardFocusTraversalKeys")
- this Container's Set of BACKWARD_TRAVERSAL_KEYS
("backwardFocusTraversalKeys")
- this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
("upCycleFocusTraversalKeys")
- this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
("downCycleFocusTraversalKeys")
- this Container's focus traversal policy ("focusTraversalPolicy")
- this Container's focus-cycle-root state ("focusCycleRoot")
Note that if this Container is inheriting a bound property, then no
event will be fired in response to a change in the inherited property.
If listener is null, no exception is thrown and no action is performed.
Params: - listener – the PropertyChangeListener to be added
See Also:
/**
* Adds a PropertyChangeListener to the listener list. The listener is
* registered for all bound properties of this class, including the
* following:
* <ul>
* <li>this Container's font ("font")</li>
* <li>this Container's background color ("background")</li>
* <li>this Container's foreground color ("foreground")</li>
* <li>this Container's focusability ("focusable")</li>
* <li>this Container's focus traversal keys enabled state
* ("focusTraversalKeysEnabled")</li>
* <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
* ("forwardFocusTraversalKeys")</li>
* <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
* ("backwardFocusTraversalKeys")</li>
* <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
* ("upCycleFocusTraversalKeys")</li>
* <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
* ("downCycleFocusTraversalKeys")</li>
* <li>this Container's focus traversal policy ("focusTraversalPolicy")
* </li>
* <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
* </ul>
* Note that if this Container is inheriting a bound property, then no
* event will be fired in response to a change in the inherited property.
* <p>
* If listener is null, no exception is thrown and no action is performed.
*
* @param listener the PropertyChangeListener to be added
*
* @see Component#removePropertyChangeListener
* @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
super.addPropertyChangeListener(listener);
}
Adds a PropertyChangeListener to the listener list for a specific
property. The specified property may be user-defined, or one of the
following defaults:
- this Container's font ("font")
- this Container's background color ("background")
- this Container's foreground color ("foreground")
- this Container's focusability ("focusable")
- this Container's focus traversal keys enabled state
("focusTraversalKeysEnabled")
- this Container's Set of FORWARD_TRAVERSAL_KEYS
("forwardFocusTraversalKeys")
- this Container's Set of BACKWARD_TRAVERSAL_KEYS
("backwardFocusTraversalKeys")
- this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
("upCycleFocusTraversalKeys")
- this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
("downCycleFocusTraversalKeys")
- this Container's focus traversal policy ("focusTraversalPolicy")
- this Container's focus-cycle-root state ("focusCycleRoot")
- this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")
- this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")
Note that if this Container is inheriting a bound property, then no
event will be fired in response to a change in the inherited property.
If listener is null, no exception is thrown and no action is performed.
Params: - propertyName – one of the property names listed above
- listener – the PropertyChangeListener to be added
See Also:
/**
* Adds a PropertyChangeListener to the listener list for a specific
* property. The specified property may be user-defined, or one of the
* following defaults:
* <ul>
* <li>this Container's font ("font")</li>
* <li>this Container's background color ("background")</li>
* <li>this Container's foreground color ("foreground")</li>
* <li>this Container's focusability ("focusable")</li>
* <li>this Container's focus traversal keys enabled state
* ("focusTraversalKeysEnabled")</li>
* <li>this Container's Set of FORWARD_TRAVERSAL_KEYS
* ("forwardFocusTraversalKeys")</li>
* <li>this Container's Set of BACKWARD_TRAVERSAL_KEYS
* ("backwardFocusTraversalKeys")</li>
* <li>this Container's Set of UP_CYCLE_TRAVERSAL_KEYS
* ("upCycleFocusTraversalKeys")</li>
* <li>this Container's Set of DOWN_CYCLE_TRAVERSAL_KEYS
* ("downCycleFocusTraversalKeys")</li>
* <li>this Container's focus traversal policy ("focusTraversalPolicy")
* </li>
* <li>this Container's focus-cycle-root state ("focusCycleRoot")</li>
* <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
* <li>this Container's focus-traversal-policy-provider state("focusTraversalPolicyProvider")</li>
* </ul>
* Note that if this Container is inheriting a bound property, then no
* event will be fired in response to a change in the inherited property.
* <p>
* If listener is null, no exception is thrown and no action is performed.
*
* @param propertyName one of the property names listed above
* @param listener the PropertyChangeListener to be added
*
* @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
* @see Component#removePropertyChangeListener
*/
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
super.addPropertyChangeListener(propertyName, listener);
}
// Serialization support. A Container is responsible for restoring the
// parent fields of its component children.
Container Serial Data Version.
/**
* Container Serial Data Version.
*/
private int containerSerializedDataVersion = 1;
Serializes this Container
to the specified
ObjectOutputStream
.
- Writes default serializable fields to the stream.
- Writes a list of serializable ContainerListener(s) as optional
data. The non-serializable ContainerListner(s) are detected and
no attempt is made to serialize them.
- Write this Container's FocusTraversalPolicy if and only if it
is Serializable; otherwise,
null
is written.
Params: - s – the
ObjectOutputStream
to write
See Also: @serialData null
terminated sequence of 0 or more pairs;
the pair consists of a String
and Object
;
the String
indicates the type of object and
is one of the following:
containerListenerK
indicating an
ContainerListener
object;
the Container
's FocusTraversalPolicy
,
or null
/**
* Serializes this <code>Container</code> to the specified
* <code>ObjectOutputStream</code>.
* <ul>
* <li>Writes default serializable fields to the stream.</li>
* <li>Writes a list of serializable ContainerListener(s) as optional
* data. The non-serializable ContainerListner(s) are detected and
* no attempt is made to serialize them.</li>
* <li>Write this Container's FocusTraversalPolicy if and only if it
* is Serializable; otherwise, <code>null</code> is written.</li>
* </ul>
*
* @param s the <code>ObjectOutputStream</code> to write
* @serialData <code>null</code> terminated sequence of 0 or more pairs;
* the pair consists of a <code>String</code> and <code>Object</code>;
* the <code>String</code> indicates the type of object and
* is one of the following:
* <code>containerListenerK</code> indicating an
* <code>ContainerListener</code> object;
* the <code>Container</code>'s <code>FocusTraversalPolicy</code>,
* or <code>null</code>
*
* @see AWTEventMulticaster#save(java.io.ObjectOutputStream, java.lang.String, java.util.EventListener)
* @see Container#containerListenerK
* @see #readObject(ObjectInputStream)
*/
private void writeObject(ObjectOutputStream s) throws IOException {
ObjectOutputStream.PutField f = s.putFields();
f.put("ncomponents", component.size());
f.put("component", getComponentsSync());
f.put("layoutMgr", layoutMgr);
f.put("dispatcher", dispatcher);
f.put("maxSize", maxSize);
f.put("focusCycleRoot", focusCycleRoot);
f.put("containerSerializedDataVersion", containerSerializedDataVersion);
f.put("focusTraversalPolicyProvider", focusTraversalPolicyProvider);
s.writeFields();
AWTEventMulticaster.save(s, containerListenerK, containerListener);
s.writeObject(null);
if (focusTraversalPolicy instanceof java.io.Serializable) {
s.writeObject(focusTraversalPolicy);
} else {
s.writeObject(null);
}
}
Deserializes this Container
from the specified
ObjectInputStream
.
- Reads default serializable fields from the stream.
- Reads a list of serializable ContainerListener(s) as optional
data. If the list is null, no Listeners are installed.
- Reads this Container's FocusTraversalPolicy, which may be null,
as optional data.
Params: - s – the
ObjectInputStream
to read
See Also: @serial
/**
* Deserializes this <code>Container</code> from the specified
* <code>ObjectInputStream</code>.
* <ul>
* <li>Reads default serializable fields from the stream.</li>
* <li>Reads a list of serializable ContainerListener(s) as optional
* data. If the list is null, no Listeners are installed.</li>
* <li>Reads this Container's FocusTraversalPolicy, which may be null,
* as optional data.</li>
* </ul>
*
* @param s the <code>ObjectInputStream</code> to read
* @serial
* @see #addContainerListener
* @see #writeObject(ObjectOutputStream)
*/
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
ObjectInputStream.GetField f = s.readFields();
// array of components may not be present in the stream or may be null
Component [] tmpComponent = (Component[])f.get("component", null);
if (tmpComponent == null) {
tmpComponent = EMPTY_ARRAY;
}
int ncomponents = (Integer) f.get("ncomponents", 0);
if (ncomponents < 0 || ncomponents > tmpComponent.length) {
throw new InvalidObjectException("Incorrect number of components");
}
component = new java.util.ArrayList<Component>(ncomponents);
for (int i = 0; i < ncomponents; ++i) {
component.add(tmpComponent[i]);
}
layoutMgr = (LayoutManager)f.get("layoutMgr", null);
dispatcher = (LightweightDispatcher)f.get("dispatcher", null);
// Old stream. Doesn't contain maxSize among Component's fields.
if (maxSize == null) {
maxSize = (Dimension)f.get("maxSize", null);
}
focusCycleRoot = f.get("focusCycleRoot", false);
containerSerializedDataVersion = f.get("containerSerializedDataVersion", 1);
focusTraversalPolicyProvider = f.get("focusTraversalPolicyProvider", false);
java.util.List<Component> component = this.component;
for(Component comp : component) {
comp.parent = this;
adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK,
comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
adjustDescendants(comp.countHierarchyMembers());
}
Object keyOrNull;
while(null != (keyOrNull = s.readObject())) {
String key = ((String)keyOrNull).intern();
if (containerListenerK == key) {
addContainerListener((ContainerListener)(s.readObject()));
} else {
// skip value for unrecognized key
s.readObject();
}
}
try {
Object policy = s.readObject();
if (policy instanceof FocusTraversalPolicy) {
focusTraversalPolicy = (FocusTraversalPolicy)policy;
}
} catch (java.io.OptionalDataException e) {
// JDK 1.1/1.2/1.3 instances will not have this optional data.
// e.eof will be true to indicate that there is no more data
// available for this object. If e.eof is not true, throw the
// exception as it might have been caused by reasons unrelated to
// focusTraversalPolicy.
if (!e.eof) {
throw e;
}
}
}
/*
* --- Accessibility Support ---
*/
Inner class of Container used to provide default support for
accessibility. This class is not meant to be used directly by
application developers, but is instead meant only to be
subclassed by container developers.
The class used to obtain the accessible role for this object,
as well as implementing many of the methods in the
AccessibleContainer interface.
Since: 1.3
/**
* Inner class of Container used to provide default support for
* accessibility. This class is not meant to be used directly by
* application developers, but is instead meant only to be
* subclassed by container developers.
* <p>
* The class used to obtain the accessible role for this object,
* as well as implementing many of the methods in the
* AccessibleContainer interface.
* @since 1.3
*/
protected class AccessibleAWTContainer extends AccessibleAWTComponent {
JDK1.3 serialVersionUID
/**
* JDK1.3 serialVersionUID
*/
private static final long serialVersionUID = 5081320404842566097L;
Returns the number of accessible children in the object. If all
of the children of this object implement Accessible
,
then this method should return the number of children of this object.
Returns: the number of accessible children in the object
/**
* Returns the number of accessible children in the object. If all
* of the children of this object implement <code>Accessible</code>,
* then this method should return the number of children of this object.
*
* @return the number of accessible children in the object
*/
public int getAccessibleChildrenCount() {
return Container.this.getAccessibleChildrenCount();
}
Returns the nth Accessible
child of the object.
Params: - i – zero-based index of child
Returns: the nth Accessible
child of the object
/**
* Returns the nth <code>Accessible</code> child of the object.
*
* @param i zero-based index of child
* @return the nth <code>Accessible</code> child of the object
*/
public Accessible getAccessibleChild(int i) {
return Container.this.getAccessibleChild(i);
}
Returns the Accessible
child, if one exists,
contained at the local coordinate Point
.
Params: - p – the point defining the top-left corner of the
Accessible
, given in the coordinate space
of the object's parent
Returns: the Accessible
, if it exists,
at the specified location; else null
/**
* Returns the <code>Accessible</code> child, if one exists,
* contained at the local coordinate <code>Point</code>.
*
* @param p the point defining the top-left corner of the
* <code>Accessible</code>, given in the coordinate space
* of the object's parent
* @return the <code>Accessible</code>, if it exists,
* at the specified location; else <code>null</code>
*/
public Accessible getAccessibleAt(Point p) {
return Container.this.getAccessibleAt(p);
}
protected ContainerListener accessibleContainerHandler = null;
Fire PropertyChange
listener, if one is registered,
when children are added or removed.
Since: 1.3
/**
* Fire <code>PropertyChange</code> listener, if one is registered,
* when children are added or removed.
* @since 1.3
*/
protected class AccessibleContainerHandler
implements ContainerListener {
public void componentAdded(ContainerEvent e) {
Component c = e.getChild();
if (c != null && c instanceof Accessible) {
AccessibleAWTContainer.this.firePropertyChange(
AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
null, ((Accessible) c).getAccessibleContext());
}
}
public void componentRemoved(ContainerEvent e) {
Component c = e.getChild();
if (c != null && c instanceof Accessible) {
AccessibleAWTContainer.this.firePropertyChange(
AccessibleContext.ACCESSIBLE_CHILD_PROPERTY,
((Accessible) c).getAccessibleContext(), null);
}
}
}
Adds a PropertyChangeListener to the listener list.
Params: - listener – the PropertyChangeListener to be added
/**
* Adds a PropertyChangeListener to the listener list.
*
* @param listener the PropertyChangeListener to be added
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
if (accessibleContainerHandler == null) {
accessibleContainerHandler = new AccessibleContainerHandler();
Container.this.addContainerListener(accessibleContainerHandler);
}
super.addPropertyChangeListener(listener);
}
} // inner class AccessibleAWTContainer
Returns the Accessible
child contained at the local
coordinate Point
, if one exists. Otherwise
returns null
.
Params: - p – the point defining the top-left corner of the
Accessible
, given in the coordinate space
of the object's parent
Returns: the Accessible
at the specified location,
if it exists; otherwise null
/**
* Returns the <code>Accessible</code> child contained at the local
* coordinate <code>Point</code>, if one exists. Otherwise
* returns <code>null</code>.
*
* @param p the point defining the top-left corner of the
* <code>Accessible</code>, given in the coordinate space
* of the object's parent
* @return the <code>Accessible</code> at the specified location,
* if it exists; otherwise <code>null</code>
*/
Accessible getAccessibleAt(Point p) {
synchronized (getTreeLock()) {
if (this instanceof Accessible) {
Accessible a = (Accessible)this;
AccessibleContext ac = a.getAccessibleContext();
if (ac != null) {
AccessibleComponent acmp;
Point location;
int nchildren = ac.getAccessibleChildrenCount();
for (int i=0; i < nchildren; i++) {
a = ac.getAccessibleChild(i);
if ((a != null)) {
ac = a.getAccessibleContext();
if (ac != null) {
acmp = ac.getAccessibleComponent();
if ((acmp != null) && (acmp.isShowing())) {
location = acmp.getLocation();
Point np = new Point(p.x-location.x,
p.y-location.y);
if (acmp.contains(np)){
return a;
}
}
}
}
}
}
return (Accessible)this;
} else {
Component ret = this;
if (!this.contains(p.x,p.y)) {
ret = null;
} else {
int ncomponents = this.getComponentCount();
for (int i=0; i < ncomponents; i++) {
Component comp = this.getComponent(i);
if ((comp != null) && comp.isShowing()) {
Point location = comp.getLocation();
if (comp.contains(p.x-location.x,p.y-location.y)) {
ret = comp;
}
}
}
}
if (ret instanceof Accessible) {
return (Accessible) ret;
}
}
return null;
}
}
Returns the number of accessible children in the object. If all
of the children of this object implement Accessible
,
then this method should return the number of children of this object.
Returns: the number of accessible children in the object
/**
* Returns the number of accessible children in the object. If all
* of the children of this object implement <code>Accessible</code>,
* then this method should return the number of children of this object.
*
* @return the number of accessible children in the object
*/
int getAccessibleChildrenCount() {
synchronized (getTreeLock()) {
int count = 0;
Component[] children = this.getComponents();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Accessible) {
count++;
}
}
return count;
}
}
Returns the nth Accessible
child of the object.
Params: - i – zero-based index of child
Returns: the nth Accessible
child of the object
/**
* Returns the nth <code>Accessible</code> child of the object.
*
* @param i zero-based index of child
* @return the nth <code>Accessible</code> child of the object
*/
Accessible getAccessibleChild(int i) {
synchronized (getTreeLock()) {
Component[] children = this.getComponents();
int count = 0;
for (int j = 0; j < children.length; j++) {
if (children[j] instanceof Accessible) {
if (count == i) {
return (Accessible) children[j];
} else {
count++;
}
}
}
return null;
}
}
// ************************** MIXING CODE *******************************
final void increaseComponentCount(Component c) {
synchronized (getTreeLock()) {
if (!c.isDisplayable()) {
throw new IllegalStateException(
"Peer does not exist while invoking the increaseComponentCount() method"
);
}
int addHW = 0;
int addLW = 0;
if (c instanceof Container) {
addLW = ((Container)c).numOfLWComponents;
addHW = ((Container)c).numOfHWComponents;
}
if (c.isLightweight()) {
addLW++;
} else {
addHW++;
}
for (Container cont = this; cont != null; cont = cont.getContainer()) {
cont.numOfLWComponents += addLW;
cont.numOfHWComponents += addHW;
}
}
}
final void decreaseComponentCount(Component c) {
synchronized (getTreeLock()) {
if (!c.isDisplayable()) {
throw new IllegalStateException(
"Peer does not exist while invoking the decreaseComponentCount() method"
);
}
int subHW = 0;
int subLW = 0;
if (c instanceof Container) {
subLW = ((Container)c).numOfLWComponents;
subHW = ((Container)c).numOfHWComponents;
}
if (c.isLightweight()) {
subLW++;
} else {
subHW++;
}
for (Container cont = this; cont != null; cont = cont.getContainer()) {
cont.numOfLWComponents -= subLW;
cont.numOfHWComponents -= subHW;
}
}
}
private int getTopmostComponentIndex() {
checkTreeLock();
if (getComponentCount() > 0) {
return 0;
}
return -1;
}
private int getBottommostComponentIndex() {
checkTreeLock();
if (getComponentCount() > 0) {
return getComponentCount() - 1;
}
return -1;
}
/*
* This method is overriden to handle opaque children in non-opaque
* containers.
*/
@Override
final Region getOpaqueShape() {
checkTreeLock();
if (isLightweight() && isNonOpaqueForMixing()
&& hasLightweightDescendants())
{
Region s = Region.EMPTY_REGION;
for (int index = 0; index < getComponentCount(); index++) {
Component c = getComponent(index);
if (c.isLightweight() && c.isShowing()) {
s = s.getUnion(c.getOpaqueShape());
}
}
return s.getIntersection(getNormalShape());
}
return super.getOpaqueShape();
}
final void recursiveSubtractAndApplyShape(Region shape) {
recursiveSubtractAndApplyShape(shape, getTopmostComponentIndex(), getBottommostComponentIndex());
}
final void recursiveSubtractAndApplyShape(Region shape, int fromZorder) {
recursiveSubtractAndApplyShape(shape, fromZorder, getBottommostComponentIndex());
}
final void recursiveSubtractAndApplyShape(Region shape, int fromZorder, int toZorder) {
checkTreeLock();
if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
mixingLog.fine("this = " + this +
"; shape=" + shape + "; fromZ=" + fromZorder + "; toZ=" + toZorder);
}
if (fromZorder == -1) {
return;
}
if (shape.isEmpty()) {
return;
}
// An invalid container with not-null layout should be ignored
// by the mixing code, the container will be validated later
// and the mixing code will be executed later.
if (getLayout() != null && !isValid()) {
return;
}
for (int index = fromZorder; index <= toZorder; index++) {
Component comp = getComponent(index);
if (!comp.isLightweight()) {
comp.subtractAndApplyShape(shape);
} else if (comp instanceof Container &&
((Container)comp).hasHeavyweightDescendants() && comp.isShowing()) {
((Container)comp).recursiveSubtractAndApplyShape(shape);
}
}
}
final void recursiveApplyCurrentShape() {
recursiveApplyCurrentShape(getTopmostComponentIndex(), getBottommostComponentIndex());
}
final void recursiveApplyCurrentShape(int fromZorder) {
recursiveApplyCurrentShape(fromZorder, getBottommostComponentIndex());
}
final void recursiveApplyCurrentShape(int fromZorder, int toZorder) {
checkTreeLock();
if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
mixingLog.fine("this = " + this +
"; fromZ=" + fromZorder + "; toZ=" + toZorder);
}
if (fromZorder == -1) {
return;
}
// An invalid container with not-null layout should be ignored
// by the mixing code, the container will be validated later
// and the mixing code will be executed later.
if (getLayout() != null && !isValid()) {
return;
}
for (int index = fromZorder; index <= toZorder; index++) {
Component comp = getComponent(index);
if (!comp.isLightweight()) {
comp.applyCurrentShape();
}
if (comp instanceof Container &&
((Container)comp).hasHeavyweightDescendants()) {
((Container)comp).recursiveApplyCurrentShape();
}
}
}
private void recursiveShowHeavyweightChildren() {
if (!hasHeavyweightDescendants() || !isVisible()) {
return;
}
for (int index = 0; index < getComponentCount(); index++) {
Component comp = getComponent(index);
if (comp.isLightweight()) {
if (comp instanceof Container) {
((Container)comp).recursiveShowHeavyweightChildren();
}
} else {
if (comp.isVisible()) {
ComponentPeer peer = comp.getPeer();
if (peer != null) {
peer.setVisible(true);
}
}
}
}
}
private void recursiveHideHeavyweightChildren() {
if (!hasHeavyweightDescendants()) {
return;
}
for (int index = 0; index < getComponentCount(); index++) {
Component comp = getComponent(index);
if (comp.isLightweight()) {
if (comp instanceof Container) {
((Container)comp).recursiveHideHeavyweightChildren();
}
} else {
if (comp.isVisible()) {
ComponentPeer peer = comp.getPeer();
if (peer != null) {
peer.setVisible(false);
}
}
}
}
}
private void recursiveRelocateHeavyweightChildren(Point origin) {
for (int index = 0; index < getComponentCount(); index++) {
Component comp = getComponent(index);
if (comp.isLightweight()) {
if (comp instanceof Container &&
((Container)comp).hasHeavyweightDescendants())
{
final Point newOrigin = new Point(origin);
newOrigin.translate(comp.getX(), comp.getY());
((Container)comp).recursiveRelocateHeavyweightChildren(newOrigin);
}
} else {
ComponentPeer peer = comp.getPeer();
if (peer != null) {
peer.setBounds(origin.x + comp.getX(), origin.y + comp.getY(),
comp.getWidth(), comp.getHeight(),
ComponentPeer.SET_LOCATION);
}
}
}
}
Checks if the container and its direct lightweight containers are
visible.
Consider the heavyweight container hides or shows the HW descendants
automatically. Therefore we care of LW containers' visibility only.
This method MUST be invoked under the TreeLock.
/**
* Checks if the container and its direct lightweight containers are
* visible.
*
* Consider the heavyweight container hides or shows the HW descendants
* automatically. Therefore we care of LW containers' visibility only.
*
* This method MUST be invoked under the TreeLock.
*/
final boolean isRecursivelyVisibleUpToHeavyweightContainer() {
if (!isLightweight()) {
return true;
}
for (Container cont = this;
cont != null && cont.isLightweight();
cont = cont.getContainer())
{
if (!cont.isVisible()) {
return false;
}
}
return true;
}
@Override
void mixOnShowing() {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
mixingLog.fine("this = " + this);
}
boolean isLightweight = isLightweight();
if (isLightweight && isRecursivelyVisibleUpToHeavyweightContainer()) {
recursiveShowHeavyweightChildren();
}
if (!isMixingNeeded()) {
return;
}
if (!isLightweight || (isLightweight && hasHeavyweightDescendants())) {
recursiveApplyCurrentShape();
}
super.mixOnShowing();
}
}
@Override
void mixOnHiding(boolean isLightweight) {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
mixingLog.fine("this = " + this +
"; isLightweight=" + isLightweight);
}
if (isLightweight) {
recursiveHideHeavyweightChildren();
}
super.mixOnHiding(isLightweight);
}
}
@Override
void mixOnReshaping() {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
mixingLog.fine("this = " + this);
}
boolean isMixingNeeded = isMixingNeeded();
if (isLightweight() && hasHeavyweightDescendants()) {
final Point origin = new Point(getX(), getY());
for (Container cont = getContainer();
cont != null && cont.isLightweight();
cont = cont.getContainer())
{
origin.translate(cont.getX(), cont.getY());
}
recursiveRelocateHeavyweightChildren(origin);
if (!isMixingNeeded) {
return;
}
recursiveApplyCurrentShape();
}
if (!isMixingNeeded) {
return;
}
super.mixOnReshaping();
}
}
@Override
void mixOnZOrderChanging(int oldZorder, int newZorder) {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
mixingLog.fine("this = " + this +
"; oldZ=" + oldZorder + "; newZ=" + newZorder);
}
if (!isMixingNeeded()) {
return;
}
boolean becameHigher = newZorder < oldZorder;
if (becameHigher && isLightweight() && hasHeavyweightDescendants()) {
recursiveApplyCurrentShape();
}
super.mixOnZOrderChanging(oldZorder, newZorder);
}
}
@Override
void mixOnValidating() {
synchronized (getTreeLock()) {
if (mixingLog.isLoggable(PlatformLogger.Level.FINE)) {
mixingLog.fine("this = " + this);
}
if (!isMixingNeeded()) {
return;
}
if (hasHeavyweightDescendants()) {
recursiveApplyCurrentShape();
}
if (isLightweight() && isNonOpaqueForMixing()) {
subtractAndApplyShapeBelowMe();
}
super.mixOnValidating();
}
}
// ****************** END OF MIXING CODE ********************************
}
Class to manage the dispatching of MouseEvents to the lightweight descendants
and SunDropTargetEvents to both lightweight and heavyweight descendants
contained by a native container.
NOTE: the class name is not appropriate anymore, but we cannot change it
because we must keep serialization compatibility.
Author: Timothy Prinzing
/**
* Class to manage the dispatching of MouseEvents to the lightweight descendants
* and SunDropTargetEvents to both lightweight and heavyweight descendants
* contained by a native container.
*
* NOTE: the class name is not appropriate anymore, but we cannot change it
* because we must keep serialization compatibility.
*
* @author Timothy Prinzing
*/
class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
/*
* JDK 1.1 serialVersionUID
*/
private static final long serialVersionUID = 5184291520170872969L;
/*
* Our own mouse event for when we're dragged over from another hw
* container
*/
private static final int LWD_MOUSE_DRAGGED_OVER = 1500;
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher");
LightweightDispatcher(Container nativeContainer) {
this.nativeContainer = nativeContainer;
mouseEventTarget = null;
eventMask = 0;
}
/*
* Clean up any resources allocated when dispatcher was created;
* should be called from Container.removeNotify
*/
void dispose() {
//System.out.println("Disposing lw dispatcher");
stopListeningForOtherDrags();
mouseEventTarget = null;
}
Enables events to subcomponents.
/**
* Enables events to subcomponents.
*/
void enableEvents(long events) {
eventMask |= events;
}
Dispatches an event to a sub-component if necessary, and
returns whether or not the event was forwarded to a
sub-component.
Params: - e – the event
/**
* Dispatches an event to a sub-component if necessary, and
* returns whether or not the event was forwarded to a
* sub-component.
*
* @param e the event
*/
boolean dispatchEvent(AWTEvent e) {
boolean ret = false;
/*
* Fix for BugTraq Id 4389284.
* Dispatch SunDropTargetEvents regardless of eventMask value.
* Do not update cursor on dispatching SunDropTargetEvents.
*/
if (e instanceof SunDropTargetEvent) {
SunDropTargetEvent sdde = (SunDropTargetEvent) e;
ret = processDropTargetEvent(sdde);
} else {
if (e instanceof MouseEvent && (eventMask & MOUSE_MASK) != 0) {
MouseEvent me = (MouseEvent) e;
ret = processMouseEvent(me);
}
if (e.getID() == MouseEvent.MOUSE_MOVED) {
nativeContainer.updateCursorImmediately();
}
}
return ret;
}
/* This method effectively returns whether or not a mouse button was down
* just BEFORE the event happened. A better method name might be
* wasAMouseButtonDownBeforeThisEvent().
*/
private boolean isMouseGrab(MouseEvent e) {
int modifiers = e.getModifiersEx();
if(e.getID() == MouseEvent.MOUSE_PRESSED
|| e.getID() == MouseEvent.MOUSE_RELEASED)
{
switch (e.getButton()) {
case MouseEvent.BUTTON1:
modifiers ^= InputEvent.BUTTON1_DOWN_MASK;
break;
case MouseEvent.BUTTON2:
modifiers ^= InputEvent.BUTTON2_DOWN_MASK;
break;
case MouseEvent.BUTTON3:
modifiers ^= InputEvent.BUTTON3_DOWN_MASK;
break;
}
}
/* modifiers now as just before event */
return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK
| InputEvent.BUTTON2_DOWN_MASK
| InputEvent.BUTTON3_DOWN_MASK)) != 0);
}
This method attempts to distribute a mouse event to a lightweight
component. It tries to avoid doing any unnecessary probes down
into the component tree to minimize the overhead of determining
where to route the event, since mouse movement events tend to
come in large and frequent amounts.
/**
* This method attempts to distribute a mouse event to a lightweight
* component. It tries to avoid doing any unnecessary probes down
* into the component tree to minimize the overhead of determining
* where to route the event, since mouse movement events tend to
* come in large and frequent amounts.
*/
private boolean processMouseEvent(MouseEvent e) {
int id = e.getID();
Component mouseOver = // sensitive to mouse events
nativeContainer.getMouseEventTarget(e.getX(), e.getY(),
Container.INCLUDE_SELF);
trackMouseEnterExit(mouseOver, e);
// 4508327 : MOUSE_CLICKED should only go to the recipient of
// the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
// MOUSE_CLICKED.
if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null;
}
if (mouseEventTarget != null) {
switch (id) {
case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_EXITED:
break;
case MouseEvent.MOUSE_PRESSED:
retargetMouseEvent(mouseEventTarget, id, e);
break;
case MouseEvent.MOUSE_RELEASED:
retargetMouseEvent(mouseEventTarget, id, e);
break;
case MouseEvent.MOUSE_CLICKED:
// 4508327: MOUSE_CLICKED should never be dispatched to a Component
// other than that which received the MOUSE_PRESSED event. If the
// mouse is now over a different Component, don't dispatch the event.
// The previous fix for a similar problem was associated with bug
// 4155217.
if (mouseOver == mouseEventTarget) {
retargetMouseEvent(mouseOver, id, e);
}
break;
case MouseEvent.MOUSE_MOVED:
retargetMouseEvent(mouseEventTarget, id, e);
break;
case MouseEvent.MOUSE_DRAGGED:
if (isMouseGrab(e)) {
retargetMouseEvent(mouseEventTarget, id, e);
}
break;
case MouseEvent.MOUSE_WHEEL:
// This may send it somewhere that doesn't have MouseWheelEvents
// enabled. In this case, Component.dispatchEventImpl() will
// retarget the event to a parent that DOES have the events enabled.
if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {
eventLog.finest("retargeting mouse wheel to " +
mouseOver.getName() + ", " +
mouseOver.getClass());
}
retargetMouseEvent(mouseOver, id, e);
break;
}
//Consuming of wheel events is implemented in "retargetMouseEvent".
if (id != MouseEvent.MOUSE_WHEEL) {
e.consume();
}
}
return e.isConsumed();
}
private boolean processDropTargetEvent(SunDropTargetEvent e) {
int id = e.getID();
int x = e.getX();
int y = e.getY();
/*
* Fix for BugTraq ID 4395290.
* It is possible that SunDropTargetEvent's Point is outside of the
* native container bounds. In this case we truncate coordinates.
*/
if (!nativeContainer.contains(x, y)) {
final Dimension d = nativeContainer.getSize();
if (d.width <= x) {
x = d.width - 1;
} else if (x < 0) {
x = 0;
}
if (d.height <= y) {
y = d.height - 1;
} else if (y < 0) {
y = 0;
}
}
Component mouseOver = // not necessarily sensitive to mouse events
nativeContainer.getDropTargetEventTarget(x, y,
Container.INCLUDE_SELF);
trackMouseEnterExit(mouseOver, e);
if (mouseOver != nativeContainer && mouseOver != null) {
switch (id) {
case SunDropTargetEvent.MOUSE_ENTERED:
case SunDropTargetEvent.MOUSE_EXITED:
break;
default:
retargetMouseEvent(mouseOver, id, e);
e.consume();
break;
}
}
return e.isConsumed();
}
/*
* Generates enter/exit events as mouse moves over lw components
* @param targetOver Target mouse is over (including native container)
* @param e Mouse event in native container
*/
private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
Component targetEnter = null;
int id = e.getID();
if (e instanceof SunDropTargetEvent &&
id == MouseEvent.MOUSE_ENTERED &&
isMouseInNativeContainer == true) {
// This can happen if a lightweight component which initiated the
// drag has an associated drop target. MOUSE_ENTERED comes when the
// mouse is in the native container already. To propagate this event
// properly we should null out targetLastEntered.
targetLastEntered = null;
} else if ( id != MouseEvent.MOUSE_EXITED &&
id != MouseEvent.MOUSE_DRAGGED &&
id != LWD_MOUSE_DRAGGED_OVER &&
isMouseInNativeContainer == false ) {
// any event but an exit or drag means we're in the native container
isMouseInNativeContainer = true;
startListeningForOtherDrags();
} else if ( id == MouseEvent.MOUSE_EXITED ) {
isMouseInNativeContainer = false;
stopListeningForOtherDrags();
}
if (isMouseInNativeContainer) {
targetEnter = targetOver;
}
if (targetLastEntered == targetEnter) {
return;
}
if (targetLastEntered != null) {
retargetMouseEvent(targetLastEntered, MouseEvent.MOUSE_EXITED, e);
}
if (id == MouseEvent.MOUSE_EXITED) {
// consume native exit event if we generate one
e.consume();
}
if (targetEnter != null) {
retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
}
if (id == MouseEvent.MOUSE_ENTERED) {
// consume native enter event if we generate one
e.consume();
}
targetLastEntered = targetEnter;
}
/*
* Listens to global mouse drag events so even drags originating
* from other heavyweight containers will generate enter/exit
* events in this container
*/
private void startListeningForOtherDrags() {
//System.out.println("Adding AWTEventListener");
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
nativeContainer.getToolkit().addAWTEventListener(
LightweightDispatcher.this,
AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK);
return null;
}
}
);
}
private void stopListeningForOtherDrags() {
//System.out.println("Removing AWTEventListener");
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
nativeContainer.getToolkit().removeAWTEventListener(LightweightDispatcher.this);
return null;
}
}
);
}
/*
* (Implementation of AWTEventListener)
* Listen for drag events posted in other hw components so we can
* track enter/exit regardless of where a drag originated
*/
public void eventDispatched(AWTEvent e) {
boolean isForeignDrag = (e instanceof MouseEvent) &&
!(e instanceof SunDropTargetEvent) &&
(e.id == MouseEvent.MOUSE_DRAGGED) &&
(e.getSource() != nativeContainer);
if (!isForeignDrag) {
// only interested in drags from other hw components
return;
}
MouseEvent srcEvent = (MouseEvent)e;
MouseEvent me;
synchronized (nativeContainer.getTreeLock()) {
Component srcComponent = srcEvent.getComponent();
// component may have disappeared since drag event posted
// (i.e. Swing hierarchical menus)
if ( !srcComponent.isShowing() ) {
return;
}
// see 5083555
// check if srcComponent is in any modal blocked window
Component c = nativeContainer;
while ((c != null) && !(c instanceof Window)) {
c = c.getParent_NoClientCode();
}
if ((c == null) || ((Window)c).isModalBlocked()) {
return;
}
//
// create an internal 'dragged-over' event indicating
// we are being dragged over from another hw component
//
me = new MouseEvent(nativeContainer,
LWD_MOUSE_DRAGGED_OVER,
srcEvent.getWhen(),
srcEvent.getModifiersEx() | srcEvent.getModifiers(),
srcEvent.getX(),
srcEvent.getY(),
srcEvent.getXOnScreen(),
srcEvent.getYOnScreen(),
srcEvent.getClickCount(),
srcEvent.isPopupTrigger(),
srcEvent.getButton());
((AWTEvent)srcEvent).copyPrivateDataInto(me);
// translate coordinates to this native container
final Point ptSrcOrigin = srcComponent.getLocationOnScreen();
if (AppContext.getAppContext() != nativeContainer.appContext) {
final MouseEvent mouseEvent = me;
Runnable r = new Runnable() {
public void run() {
if (!nativeContainer.isShowing() ) {
return;
}
Point ptDstOrigin = nativeContainer.getLocationOnScreen();
mouseEvent.translatePoint(ptSrcOrigin.x - ptDstOrigin.x,
ptSrcOrigin.y - ptDstOrigin.y );
Component targetOver =
nativeContainer.getMouseEventTarget(mouseEvent.getX(),
mouseEvent.getY(),
Container.INCLUDE_SELF);
trackMouseEnterExit(targetOver, mouseEvent);
}
};
SunToolkit.executeOnEventHandlerThread(nativeContainer, r);
return;
} else {
if (!nativeContainer.isShowing() ) {
return;
}
Point ptDstOrigin = nativeContainer.getLocationOnScreen();
me.translatePoint( ptSrcOrigin.x - ptDstOrigin.x, ptSrcOrigin.y - ptDstOrigin.y );
}
}
//System.out.println("Track event: " + me);
// feed the 'dragged-over' event directly to the enter/exit
// code (not a real event so don't pass it to dispatchEvent)
Component targetOver =
nativeContainer.getMouseEventTarget(me.getX(), me.getY(),
Container.INCLUDE_SELF);
trackMouseEnterExit(targetOver, me);
}
Sends a mouse event to the current mouse event recipient using
the given event (sent to the windowed host) as a srcEvent. If
the mouse event target is still in the component tree, the
coordinates of the event are translated to those of the target.
If the target has been removed, we don't bother to send the
message.
/**
* Sends a mouse event to the current mouse event recipient using
* the given event (sent to the windowed host) as a srcEvent. If
* the mouse event target is still in the component tree, the
* coordinates of the event are translated to those of the target.
* If the target has been removed, we don't bother to send the
* message.
*/
void retargetMouseEvent(Component target, int id, MouseEvent e) {
if (target == null) {
return; // mouse is over another hw component or target is disabled
}
int x = e.getX(), y = e.getY();
Component component;
for(component = target;
component != null && component != nativeContainer;
component = component.getParent()) {
x -= component.x;
y -= component.y;
}
MouseEvent retargeted;
if (component != null) {
if (e instanceof SunDropTargetEvent) {
retargeted = new SunDropTargetEvent(target,
id,
x,
y,
((SunDropTargetEvent)e).getDispatcher());
} else if (id == MouseEvent.MOUSE_WHEEL) {
retargeted = new MouseWheelEvent(target,
id,
e.getWhen(),
e.getModifiersEx() | e.getModifiers(),
x,
y,
e.getXOnScreen(),
e.getYOnScreen(),
e.getClickCount(),
e.isPopupTrigger(),
((MouseWheelEvent)e).getScrollType(),
((MouseWheelEvent)e).getScrollAmount(),
((MouseWheelEvent)e).getWheelRotation(),
((MouseWheelEvent)e).getPreciseWheelRotation());
}
else {
retargeted = new MouseEvent(target,
id,
e.getWhen(),
e.getModifiersEx() | e.getModifiers(),
x,
y,
e.getXOnScreen(),
e.getYOnScreen(),
e.getClickCount(),
e.isPopupTrigger(),
e.getButton());
}
((AWTEvent)e).copyPrivateDataInto(retargeted);
if (target == nativeContainer) {
// avoid recursively calling LightweightDispatcher...
((Container)target).dispatchEventToSelf(retargeted);
} else {
assert AppContext.getAppContext() == target.appContext;
if (nativeContainer.modalComp != null) {
if (((Container)nativeContainer.modalComp).isAncestorOf(target)) {
target.dispatchEvent(retargeted);
} else {
e.consume();
}
} else {
target.dispatchEvent(retargeted);
}
}
if (id == MouseEvent.MOUSE_WHEEL && retargeted.isConsumed()) {
//An exception for wheel bubbling to the native system.
//In "processMouseEvent" total event consuming for wheel events is skipped.
//Protection from bubbling of Java-accepted wheel events.
e.consume();
}
}
}
// --- member variables -------------------------------
The windowed container that might be hosting events for
subcomponents.
/**
* The windowed container that might be hosting events for
* subcomponents.
*/
private Container nativeContainer;
This variable is not used, but kept for serialization compatibility
/**
* This variable is not used, but kept for serialization compatibility
*/
private Component focus;
The current subcomponent being hosted by this windowed
component that has events being forwarded to it. If this
is null, there are currently no events being forwarded to
a subcomponent.
/**
* The current subcomponent being hosted by this windowed
* component that has events being forwarded to it. If this
* is null, there are currently no events being forwarded to
* a subcomponent.
*/
private transient Component mouseEventTarget;
The last component entered
/**
* The last component entered
*/
private transient Component targetLastEntered;
Is the mouse over the native container
/**
* Is the mouse over the native container
*/
private transient boolean isMouseInNativeContainer = false;
This variable is not used, but kept for serialization compatibility
/**
* This variable is not used, but kept for serialization compatibility
*/
private Cursor nativeCursor;
The event mask for contained lightweight components. Lightweight
components need a windowed container to host window-related
events. This separate mask indicates events that have been
requested by contained lightweight components without effecting
the mask of the windowed component itself.
/**
* The event mask for contained lightweight components. Lightweight
* components need a windowed container to host window-related
* events. This separate mask indicates events that have been
* requested by contained lightweight components without effecting
* the mask of the windowed component itself.
*/
private long eventMask;
The kind of events routed to lightweight components from windowed
hosts.
/**
* The kind of events routed to lightweight components from windowed
* hosts.
*/
private static final long PROXY_EVENT_MASK =
AWTEvent.FOCUS_EVENT_MASK |
AWTEvent.KEY_EVENT_MASK |
AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK |
AWTEvent.MOUSE_WHEEL_EVENT_MASK;
private static final long MOUSE_MASK =
AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK |
AWTEvent.MOUSE_WHEEL_EVENT_MASK;
}