While working on an app that makes use of threading (the app is based on
the commercial Espresso toolkit, a Swing-alike toolkit based on AWT), I
noticed that we don't tree-lock some methods in Component/Container that
must be tree-locked. Generally we must synchronize on:
- coode that changes the state of the peer
- code that changes the structure of the component tree
- code that affects the layout of the component tree
- code that somehow accesses the above 3 points (like
getLocationOnScreen depends on the structure and layout, and thus must
be locked)
I added locking to a couple of places that seem critical. That's
basically all I could make up from reading my AWT books, the specs and
pure thinking (yay!).
2006-07-14 Roman Kennke <[EMAIL PROTECTED]>
* java/awt/Component.java
(enable): Added tree locking.
(disable): Added tree locking.
(show): Added tree locking.
(hide): Added tree locking.
(getLocationOnScreen): Added tree locking.
(reshape): Added tree locking.
(addHierarchyListener): Added tree locking.
(removeHierarchyListener): Added tree locking.
(addHierarchyBoundsListener): Added tree locking.
(removeHierarchyBoundsListener): Added tree locking.
(addNotify): Added tree locking.
(removeNotify): Added tree locking.
* java/awt/Container.java
(invalidateTree): Added tree locking.
(getAlignmentX): Added tree locking.
(getAlignmentY): Added tree locking.
(addNotify): Added tree locking.
(setComponentZOrder): Added tree locking.
(getComponentZOrder): Added tree locking.
/Roman
Index: java/awt/Component.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Component.java,v
retrieving revision 1.134
diff -u -1 -2 -r1.134 Component.java
--- java/awt/Component.java 14 Jul 2006 10:27:17 -0000 1.134
+++ java/awt/Component.java 14 Jul 2006 11:49:08 -0000
@@ -842,54 +842,70 @@
public void setEnabled(boolean enabled)
{
enable(enabled);
}
/**
* Enables this component.
*
* @deprecated use [EMAIL PROTECTED] #setEnabled(boolean)} instead
*/
public void enable()
{
- this.enabled = true;
- if (peer != null)
- peer.setEnabled (true);
+ if (! enabled)
+ {
+ // Need to lock the tree here, because the peers are involved.
+ synchronized (getTreeLock())
+ {
+ enabled = true;
+ ComponentPeer p = peer;
+ if (p != null)
+ p.enable();
+ }
+ }
}
/**
* Enables or disables this component.
*
* @param enabled true to enable this component
*
* @deprecated use [EMAIL PROTECTED] #setEnabled(boolean)} instead
*/
public void enable(boolean enabled)
{
if (enabled)
enable();
else
disable();
}
/**
* Disables this component.
*
* @deprecated use [EMAIL PROTECTED] #setEnabled(boolean)} instead
*/
public void disable()
{
- this.enabled = false;
- if (peer != null)
- peer.setEnabled (false);
+ if (enabled)
+ {
+ // Need to lock the tree here, because the peers are involved.
+ synchronized (getTreeLock())
+ {
+ enabled = false;
+ ComponentPeer p = peer;
+ if (p != null)
+ p.disable();
+ }
+ }
}
/**
* Checks if this image is painted to an offscreen image buffer that is
* later copied to screen (double buffering reduces flicker). This version
* returns false, so subclasses must override it if they provide double
* buffering.
*
* @return true if this is double buffered; defaults to false
*/
public boolean isDoubleBuffered()
{
@@ -936,57 +952,63 @@
*
* @deprecated use [EMAIL PROTECTED] #setVisible(boolean)} instead
*/
public void show()
{
// We must set visible before showing the peer. Otherwise the
// peer could post paint events before visible is true, in which
// case lightweight components are not initially painted --
// Container.paint first calls isShowing () before painting itself
// and its children.
if(!isVisible())
{
- this.visible = true;
- // Avoid NullPointerExceptions by creating a local reference.
- ComponentPeer currentPeer=peer;
- if (currentPeer != null)
+ // Need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
{
- currentPeer.show();
+ visible = true;
+ // Avoid NullPointerExceptions by creating a local reference.
+ ComponentPeer currentPeer=peer;
+ if (currentPeer != null)
+ {
+ currentPeer.show();
+
+ // Fire HierarchyEvent.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
+ this, parent,
+ HierarchyEvent.SHOWING_CHANGED);
+
+ // The JDK repaints the component before invalidating the parent.
+ // So do we.
+ if (isLightweight())
+ repaint();
+ }
- // Fire HierarchyEvent.
- fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
- this, parent,
- HierarchyEvent.SHOWING_CHANGED);
-
- // The JDK repaints the component before invalidating the parent.
- // So do we.
- if (isLightweight())
- repaint();
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
}
+
// Invalidate the parent if we have one. The component itself must
// not be invalidated. We also avoid NullPointerException with
// a local reference here.
Container currentParent = parent;
if (currentParent != null)
currentParent.invalidate();
- // Only post an event if this component actually has a listener
- // or has this event explicitly enabled.
- if (componentListener != null
- || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
- {
- ComponentEvent ce =
- new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
- getToolkit().getSystemEventQueue().postEvent(ce);
- }
}
}
/**
* Makes this component visible or invisible.
*
* @param visible true to make this component visible
*
* @deprecated use [EMAIL PROTECTED] #setVisible(boolean)} instead
*/
public void show(boolean visible)
{
@@ -996,59 +1018,63 @@
hide();
}
/**
* Hides this component so that it is no longer shown on the screen.
*
* @deprecated use [EMAIL PROTECTED] #setVisible(boolean)} instead
*/
public void hide()
{
if (isVisible())
{
- // Avoid NullPointerExceptions by creating a local reference.
- ComponentPeer currentPeer=peer;
- if (currentPeer != null)
+ // Need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
{
- currentPeer.hide();
+ visible = false;
- // Fire hierarchy event.
- fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
- this, parent,
- HierarchyEvent.SHOWING_CHANGED);
- }
+ // Avoid NullPointerExceptions by creating a local reference.
+ ComponentPeer currentPeer=peer;
+ if (currentPeer != null)
+ {
+ currentPeer.hide();
- boolean wasShowing = isShowing();
- this.visible = false;
+ // Fire hierarchy event.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
+ this, parent,
+ HierarchyEvent.SHOWING_CHANGED);
+ // The JDK repaints the component before invalidating the
+ // parent. So do we. This only applies for lightweights.
+ if (peer instanceof LightweightPeer)
+ repaint();
+ }
- // The JDK repaints the component before invalidating the parent.
- // So do we.
- if (wasShowing)
- repaint();
- // Invalidate the parent if we have one. The component itself must
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
+ // Invalidate the parent if we have one. The component itself need
// not be invalidated. We also avoid NullPointerException with
// a local reference here.
Container currentParent = parent;
if (currentParent != null)
currentParent.invalidate();
- // Only post an event if this component actually has a listener
- // or has this event explicitly enabled.
- if (componentListener != null
- || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
- {
- ComponentEvent ce =
- new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
- getToolkit().getSystemEventQueue().postEvent(ce);
- }
}
}
/**
* Returns this component's foreground color. If not set, this is inherited
* from the parent.
*
* @return this component's foreground color, or null
* @see #setForeground(Color)
*/
public Color getForeground()
{
@@ -1251,26 +1277,33 @@
* Returns the location of this component's top left corner in screen
* coordinates.
*
* @return the location of this component in screen coordinates
* @throws IllegalComponentStateException if the component is not showing
*/
public Point getLocationOnScreen()
{
if (! isShowing())
throw new IllegalComponentStateException("component "
+ getClass().getName()
+ " not showing");
- // We know peer != null here.
- return peer.getLocationOnScreen();
+
+ // Need to lock the tree here. We get crazy races and explosions when
+ // the tree changes while we are trying to find the location of this
+ // component.
+ synchronized (getTreeLock())
+ {
+ // We know peer != null here.
+ return peer.getLocationOnScreen();
+ }
}
/**
* Returns the location of this component's top left corner relative to
* its parent component.
*
* @return the location of this component
* @deprecated use [EMAIL PROTECTED] #getLocation()} instead
*/
public Point location()
{
return new Point (x, y);
@@ -1446,101 +1479,106 @@
/**
* Sets the bounding rectangle for this component to the specified values.
* Note that these coordinates are relative to the parent, not to the screen.
*
* @param x the X coordinate of the upper left corner of the rectangle
* @param y the Y coordinate of the upper left corner of the rectangle
* @param width the width of the rectangle
* @param height the height of the rectangle
* @deprecated use [EMAIL PROTECTED] #setBounds(int, int, int, int)} instead
*/
public void reshape(int x, int y, int width, int height)
{
- int oldx = this.x;
- int oldy = this.y;
- int oldwidth = this.width;
- int oldheight = this.height;
+ // We need to lock the tree here, otherwise we risk races and
+ // inconsistencies.
+ synchronized (getTreeLock())
+ {
+ int oldx = this.x;
+ int oldy = this.y;
+ int oldwidth = this.width;
+ int oldheight = this.height;
- if (this.x == x && this.y == y && this.width == width
- && this.height == height)
- return;
+ if (this.x == x && this.y == y && this.width == width
+ && this.height == height)
+ return;
- invalidate();
+ invalidate();
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- if (peer != null)
- peer.setBounds (x, y, width, height);
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ if (peer != null)
+ peer.setBounds (x, y, width, height);
- // Erase old bounds and repaint new bounds for lightweights.
- if (isLightweight() && isShowing())
- {
- if (parent != null)
+ // Erase old bounds and repaint new bounds for lightweights.
+ if (isLightweight() && isShowing())
{
- Rectangle oldBounds = new Rectangle(oldx, oldy, oldwidth,
- oldheight);
- Rectangle newBounds = new Rectangle(x, y, width, height);
- Rectangle destroyed = oldBounds.union(newBounds);
- if (!destroyed.isEmpty())
- parent.repaint(0, destroyed.x, destroyed.y, destroyed.width,
- destroyed.height);
+ if (parent != null)
+ {
+ Rectangle oldBounds = new Rectangle(oldx, oldy, oldwidth,
+ oldheight);
+ Rectangle newBounds = new Rectangle(x, y, width, height);
+ Rectangle destroyed = oldBounds.union(newBounds);
+ if (!destroyed.isEmpty())
+ parent.repaint(0, destroyed.x, destroyed.y, destroyed.width,
+ destroyed.height);
+ }
}
- }
- boolean resized = oldwidth != width || oldheight != height;
- boolean moved = oldx != x || oldy != y;
- // Only post an event if this component actually has a listener
- // or has this event explicitly enabled.
- if (componentListener != null
- || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
- {
- // Fire component event on this component.
- if (moved)
- {
- ComponentEvent ce = new ComponentEvent(this,
- ComponentEvent.COMPONENT_MOVED);
- getToolkit().getSystemEventQueue().postEvent(ce);
- }
- if (resized)
+ boolean resized = oldwidth != width || oldheight != height;
+ boolean moved = oldx != x || oldy != y;
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
{
- ComponentEvent ce = new ComponentEvent(this,
+ // Fire component event on this component.
+ if (moved)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
+ ComponentEvent.COMPONENT_MOVED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ if (resized)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
ComponentEvent.COMPONENT_RESIZED);
- getToolkit().getSystemEventQueue().postEvent(ce);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
}
- }
- else
- {
- // Otherwise we might need to notify child components when this is
- // a Container.
- if (this instanceof Container)
+ else
{
- Container cont = (Container) this;
- if (resized)
+ // Otherwise we might need to notify child components when this is
+ // a Container.
+ if (this instanceof Container)
{
- for (int i = 0; i < cont.getComponentCount(); i++)
+ Container cont = (Container) this;
+ if (resized)
{
- Component child = cont.getComponent(i);
- child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
- this, parent, 0);
+ for (int i = 0; i < cont.getComponentCount(); i++)
+ {
+ Component child = cont.getComponent(i);
+ child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
+ this, parent, 0);
+ }
}
- }
- if (moved)
- {
- for (int i = 0; i < cont.getComponentCount(); i++)
+ if (moved)
{
- Component child = cont.getComponent(i);
- child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
- this, parent, 0);
+ for (int i = 0; i < cont.getComponentCount(); i++)
+ {
+ Component child = cont.getComponent(i);
+ child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
+ this, parent, 0);
+ }
}
}
}
}
}
/**
* Sets the bounding rectangle for this component to the specified
* rectangle. Note that these coordinates are relative to the parent, not
* to the screen.
*
* @param r the new bounding rectangle
@@ -2738,46 +2776,55 @@
* @param listener the new listener to add
* @see HierarchyEvent
* @see #removeHierarchyListener(HierarchyListener)
* @see #getHierarchyListeners()
* @since 1.3
*/
public synchronized void addHierarchyListener(HierarchyListener listener)
{
hierarchyListener = AWTEventMulticaster.add(hierarchyListener, listener);
if (hierarchyListener != null)
enableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
- numHierarchyListeners++;
- if (parent != null)
- parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 1);
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 1);
+ }
}
/**
* Removes the specified listener from the component. This is harmless if
* the listener was not previously registered.
*
* @param listener the listener to remove
* @see HierarchyEvent
* @see #addHierarchyListener(HierarchyListener)
* @see #getHierarchyListeners()
* @since 1.3
*/
public synchronized void removeHierarchyListener(HierarchyListener listener)
{
hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener);
- numHierarchyListeners--;
- if (parent != null)
- parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, -1);
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ -1);
+ }
}
/**
* Returns an array of all specified listeners registered on this component.
*
* @return an array of listeners
* @see #addHierarchyListener(HierarchyListener)
* @see #removeHierarchyListener(HierarchyListener)
* @since 1.4
*/
public synchronized HierarchyListener[] getHierarchyListeners()
{
@@ -2796,50 +2843,60 @@
* @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
* @see #getHierarchyBoundsListeners()
* @since 1.3
*/
public synchronized void
addHierarchyBoundsListener(HierarchyBoundsListener listener)
{
hierarchyBoundsListener =
AWTEventMulticaster.add(hierarchyBoundsListener, listener);
if (hierarchyBoundsListener != null)
enableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
- numHierarchyBoundsListeners++;
- if (parent != null)
- parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
- 1);
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ 1);
+ }
}
/**
* Removes the specified listener from the component. This is harmless if
* the listener was not previously registered.
*
* @param listener the listener to remove
* @see HierarchyEvent
* @see #addHierarchyBoundsListener(HierarchyBoundsListener)
* @see #getHierarchyBoundsListeners()
* @since 1.3
*/
public synchronized void
removeHierarchyBoundsListener(HierarchyBoundsListener listener)
{
hierarchyBoundsListener =
AWTEventMulticaster.remove(hierarchyBoundsListener, listener);
- numHierarchyBoundsListeners--;
- if (parent != null)
- parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
-1);
+ }
}
/**
* Returns an array of all specified listeners registered on this component.
*
* @return an array of listeners
* @see #addHierarchyBoundsListener(HierarchyBoundsListener)
* @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
* @since 1.4
*/
public synchronized HierarchyBoundsListener[] getHierarchyBoundsListeners()
{
@@ -3775,60 +3832,68 @@
/**
* Called when the parent of this Component is made visible or when
* the Component is added to an already visible Container and needs
* to be shown. A native peer - if any - is created at this
* time. This method is called automatically by the AWT system and
* should not be called by user level code.
*
* @see #isDisplayable()
* @see #removeNotify()
*/
public void addNotify()
{
- if (peer == null)
- peer = getToolkit().createComponent(this);
- else if (parent != null && parent.isLightweight())
- new HeavyweightInLightweightListener(parent);
- /* Now that all the children has gotten their peers, we should
+ // We need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ if (peer == null)
+ peer = getToolkit().createComponent(this);
+ else if (parent != null && parent.isLightweight())
+ new HeavyweightInLightweightListener(parent);
+ /* Now that all the children has gotten their peers, we should
have the event mask needed for this component and its
lightweight subcomponents. */
- peer.setEventMask(eventMask);
- /* We do not invalidate here, but rather leave that job up to
+ peer.setEventMask(eventMask);
+ /* We do not invalidate here, but rather leave that job up to
the peer. For efficiency, the peer can choose not to
invalidate if it is happy with the current dimensions,
etc. */
+ }
}
/**
* Called to inform this component is has been removed from its
* container. Its native peer - if any - is destroyed at this time.
* This method is called automatically by the AWT system and should
* not be called by user level code.
*
* @see #isDisplayable()
* @see #addNotify()
*/
public void removeNotify()
{
- // We null our peer field before disposing of it, such that if we're
- // not the event dispatch thread and the dispatch thread is awoken by
- // the dispose call, there will be no race checking the peer's null
- // status.
-
- ComponentPeer tmp = peer;
- peer = null;
- if (tmp != null)
+ // We need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
{
- tmp.hide();
- tmp.dispose();
+ // We null our peer field before disposing of it, such that if we're
+ // not the event dispatch thread and the dispatch thread is awoken by
+ // the dispose call, there will be no race checking the peer's null
+ // status.
+
+ ComponentPeer tmp = peer;
+ peer = null;
+ if (tmp != null)
+ {
+ tmp.hide();
+ tmp.dispose();
+ }
}
}
/**
* AWT 1.0 GOT_FOCUS event handler. This method is meant to be
* overridden by components providing their own GOT_FOCUS handler.
* The default implementation simply returns false.
*
* @param evt the event to handle
* @param what the Object focused, ignored
* @return false
* @deprecated use [EMAIL PROTECTED] #processFocusEvent(FocusEvent)} instead
Index: java/awt/Container.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Container.java,v
retrieving revision 1.99
diff -u -1 -2 -r1.99 Container.java
--- java/awt/Container.java 14 Jul 2006 10:27:17 -0000 1.99
+++ java/awt/Container.java 14 Jul 2006 11:49:08 -0000
@@ -593,37 +593,40 @@
if (! isValid() && peer != null)
{
validateTree();
}
}
}
/**
* Recursively invalidates the container tree.
*/
void invalidateTree()
{
- super.invalidate(); // Clean cached layout state.
- for (int i = 0; i < ncomponents; i++)
+ synchronized (getTreeLock())
{
- Component comp = component[i];
- comp.invalidate();
- if (comp instanceof Container)
- ((Container) comp).invalidateTree();
- }
+ super.invalidate(); // Clean cached layout state.
+ for (int i = 0; i < ncomponents; i++)
+ {
+ Component comp = component[i];
+ comp.invalidate();
+ if (comp instanceof Container)
+ ((Container) comp).invalidateTree();
+ }
- if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
- {
- LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
- lm2.invalidateLayout(this);
+ if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
+ lm2.invalidateLayout(this);
+ }
}
}
/**
* Recursively validates the container tree, recomputing any invalid
* layouts.
*/
protected void validateTree()
{
if (valid)
return;
@@ -794,47 +797,53 @@
* Returns the preferred alignment along the X axis. This is a value
* between 0 and 1 where 0 represents alignment flush left and
* 1 means alignment flush right, and 0.5 means centered.
*
* @return The preferred alignment along the X axis.
*/
public float getAlignmentX()
{
LayoutManager layout = getLayout();
float alignmentX = 0.0F;
if (layout != null && layout instanceof LayoutManager2)
{
- LayoutManager2 lm2 = (LayoutManager2) layout;
- alignmentX = lm2.getLayoutAlignmentX(this);
+ synchronized (getTreeLock())
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layout;
+ alignmentX = lm2.getLayoutAlignmentX(this);
+ }
}
else
alignmentX = super.getAlignmentX();
return alignmentX;
}
/**
* Returns the preferred alignment along the Y axis. This is a value
* between 0 and 1 where 0 represents alignment flush top and
* 1 means alignment flush bottom, and 0.5 means centered.
*
* @return The preferred alignment along the Y axis.
*/
public float getAlignmentY()
{
LayoutManager layout = getLayout();
float alignmentY = 0.0F;
if (layout != null && layout instanceof LayoutManager2)
{
- LayoutManager2 lm2 = (LayoutManager2) layout;
- alignmentY = lm2.getLayoutAlignmentY(this);
+ synchronized (getTreeLock())
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layout;
+ alignmentY = lm2.getLayoutAlignmentY(this);
+ }
}
else
alignmentY = super.getAlignmentY();
return alignmentY;
}
/**
* Paints this container. The implementation of this method in this
* class forwards to any lightweight components in this container. If
* this method is subclassed, this method should still be invoked as
* a superclass method so that lightweight components are properly
* drawn.
@@ -1213,26 +1222,29 @@
public Component findComponentAt(Point p)
{
return findComponentAt(p.x, p.y);
}
/**
* Called when this container is added to another container to inform it
* to create its peer. Peers for any child components will also be
* created.
*/
public void addNotify()
{
- super.addNotify();
- addNotifyContainerChildren();
+ synchronized (getTreeLock())
+ {
+ super.addNotify();
+ addNotifyContainerChildren();
+ }
}
/**
* Called when this container is removed from its parent container to
* inform it to destroy its peer. This causes the peers of all child
* component to be destroyed as well.
*/
public void removeNotify()
{
synchronized (getTreeLock ())
{
for (int i = 0; i < ncomponents; ++i)
@@ -1695,73 +1707,79 @@
{
if (comp == null)
throw new NullPointerException("comp must not be null");
if (comp instanceof Container && ((Container) comp).isAncestorOf(this))
throw new IllegalArgumentException("comp must not be an ancestor of "
+ "this");
if (comp instanceof Window)
throw new IllegalArgumentException("comp must not be a Window");
if (comp == this)
throw new IllegalArgumentException("cannot add component to itself");
- // FIXME: Implement reparenting.
- if ( comp.getParent() != this)
- throw new AssertionError("Reparenting is not implemented yet");
- else
+ synchronized (getTreeLock())
{
- // Find current component index.
- int currentIndex = getComponentZOrder(comp);
- if (currentIndex < index)
- {
- System.arraycopy(component, currentIndex + 1, component,
- currentIndex, index - currentIndex);
- }
+ // FIXME: Implement reparenting.
+ if ( comp.getParent() != this)
+ throw new AssertionError("Reparenting is not implemented yet");
else
{
- System.arraycopy(component, index, component, index + 1,
- currentIndex - index);
+ // Find current component index.
+ int currentIndex = getComponentZOrder(comp);
+ if (currentIndex < index)
+ {
+ System.arraycopy(component, currentIndex + 1, component,
+ currentIndex, index - currentIndex);
+ }
+ else
+ {
+ System.arraycopy(component, index, component, index + 1,
+ currentIndex - index);
+ }
+ component[index] = comp;
}
- component[index] = comp;
}
}
/**
* Returns the Z ordering index of <code>comp</code>. If <code>comp</code>
* is not a child component of this Container, this returns <code>-1</code>.
*
* @param comp the component for which to query the Z ordering
*
* @return the Z ordering index of <code>comp</code> or <code>-1</code> if
* <code>comp</code> is not a child of this Container
*
* @see #setComponentZOrder(Component, int)
*
* @since 1.5
*/
public final int getComponentZOrder(Component comp)
{
- int index = -1;
- if (component != null)
+ synchronized (getTreeLock())
{
- for (int i = 0; i < ncomponents; i++)
+ int index = -1;
+ if (component != null)
{
- if (component[i] == comp)
+ for (int i = 0; i < ncomponents; i++)
{
- index = i;
- break;
+ if (component[i] == comp)
+ {
+ index = i;
+ break;
+ }
}
}
+ return index;
}
- return index;
}
// Hidden helper methods.
/**
* Perform a graphics operation on the children of this container.
* For each applicable child, the visitChild() method will be called
* to perform the graphics operation.
*
* @param gfx The graphics object that will be used to derive new
* graphics objects for the children.
*