summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/awt/Container.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/awt/Container.java')
-rw-r--r--libjava/classpath/java/awt/Container.java435
1 files changed, 131 insertions, 304 deletions
diff --git a/libjava/classpath/java/awt/Container.java b/libjava/classpath/java/awt/Container.java
index 67f0ed184d4..41892caeafa 100644
--- a/libjava/classpath/java/awt/Container.java
+++ b/libjava/classpath/java/awt/Container.java
@@ -1,5 +1,6 @@
/* Container.java -- parent container class in AWT
- Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation
This file is part of GNU Classpath.
@@ -42,12 +43,10 @@ import java.awt.event.ComponentListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.peer.LightweightPeer;
import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@@ -62,8 +61,6 @@ import java.util.Set;
import javax.accessibility.Accessible;
-import gnu.java.awt.AWTUtilities;
-
/**
* A generic window toolkit object that acts as a container for other objects.
* Components are tracked in a list, and new elements are at the end of the
@@ -88,11 +85,14 @@ public class Container extends Component
Component[] component;
LayoutManager layoutMgr;
- LightweightDispatcher dispatcher;
-
Dimension maxSize;
/**
+ * Keeps track if the Container was cleared during a paint/update.
+ */
+ private boolean backCleared;
+
+ /**
* @since 1.4
*/
boolean focusCycleRoot;
@@ -101,7 +101,6 @@ public class Container extends Component
/* Anything else is non-serializable, and should be declared "transient". */
transient ContainerListener containerListener;
- transient PropertyChangeSupport changeSupport;
/** The focus traversal policy that determines how focus is
transferred between this Container and its children. */
@@ -187,25 +186,6 @@ public class Container extends Component
}
/**
- * Swaps the components at position i and j, in the container.
- */
-
- protected void swapComponents (int i, int j)
- {
- synchronized (getTreeLock ())
- {
- if (i < 0
- || i >= component.length
- || j < 0
- || j >= component.length)
- throw new ArrayIndexOutOfBoundsException ();
- Component tmp = component[i];
- component[i] = component[j];
- component[j] = tmp;
- }
- }
-
- /**
* Returns the insets for this container, which is the space used for
* borders, the margin, etc.
*
@@ -385,6 +365,8 @@ public class Container extends Component
// Notify the layout manager.
if (layoutMgr != null)
{
+ // If we have a LayoutManager2 the constraints are "real",
+ // otherwise they are the "name" of the Component to add.
if (layoutMgr instanceof LayoutManager2)
{
LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
@@ -393,7 +375,7 @@ public class Container extends Component
else if (constraints instanceof String)
layoutMgr.addLayoutComponent((String) constraints, comp);
else
- layoutMgr.addLayoutComponent(null, comp);
+ layoutMgr.addLayoutComponent("", comp);
}
// We previously only sent an event when this container is showing.
@@ -428,8 +410,7 @@ public class Container extends Component
for (int j = 0; j < list.length; j++)
r.removeComponentListener(list[j]);
- if (r.isShowing())
- r.removeNotify();
+ r.removeNotify();
System.arraycopy(component, index + 1, component, index,
ncomponents - index - 1);
@@ -777,16 +758,17 @@ public class Container extends Component
* a superclass method so that lightweight components are properly
* drawn.
*
- * @param g The graphics context for this paint job.
+ * @param g - The graphics context for this paint job.
*/
public void paint(Graphics g)
{
if (!isShowing())
return;
- // Visit heavyweights as well, in case they were
- // erased when we cleared the background for this container.
- visitChildren(g, GfxPaintVisitor.INSTANCE, false);
+ // Visit heavyweights if the background was cleared
+ // for this container.
+ visitChildren(g, GfxPaintVisitor.INSTANCE, !backCleared);
+ backCleared = false;
}
/**
@@ -817,8 +799,11 @@ public class Container extends Component
// also not cleared. So we do a check on !(peer instanceof LightweightPeer)
// instead.
ComponentPeer p = peer;
- if (p != null && !(p instanceof LightweightPeer))
- g.clearRect(0, 0, getWidth(), getHeight());
+ if (p != null && ! (p instanceof LightweightPeer))
+ {
+ g.clearRect(0, 0, getWidth(), getHeight());
+ backCleared = true;
+ }
paint(g);
}
@@ -1557,28 +1542,105 @@ public class Container extends Component
if (orientation == null)
throw new NullPointerException ();
}
-
+
public void addPropertyChangeListener (PropertyChangeListener listener)
{
- if (listener == null)
- return;
-
- if (changeSupport == null)
- changeSupport = new PropertyChangeSupport (this);
-
- changeSupport.addPropertyChangeListener (listener);
+ // TODO: Why is this overridden?
+ super.addPropertyChangeListener(listener);
}
-
- public void addPropertyChangeListener (String name,
+
+ public void addPropertyChangeListener (String propertyName,
PropertyChangeListener listener)
{
- if (listener == null)
- return;
-
- if (changeSupport == null)
- changeSupport = new PropertyChangeSupport (this);
+ // TODO: Why is this overridden?
+ super.addPropertyChangeListener(propertyName, listener);
+ }
+
+
+ /**
+ * Sets the Z ordering for the component <code>comp</code> to
+ * <code>index</code>. Components with lower Z order paint above components
+ * with higher Z order.
+ *
+ * @param comp the component for which to change the Z ordering
+ * @param index the index to set
+ *
+ * @throws NullPointerException if <code>comp == null</code>
+ * @throws IllegalArgumentException if comp is an ancestor of this container
+ * @throws IllegalArgumentException if <code>index</code> is not in
+ * <code>[0, getComponentCount()]</code> for moving between
+ * containers or <code>[0, getComponentCount() - 1]</code> for moving
+ * inside this container
+ * @throws IllegalArgumentException if <code>comp == this</code>
+ * @throws IllegalArgumentException if <code>comp</code> is a
+ * <code>Window</code>
+ *
+ * @see #getComponentZOrder(Component)
+ *
+ * @since 1.5
+ */
+ public final void setComponentZOrder(Component comp, int index)
+ {
+ 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
+ {
+ // 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;
+ }
+ }
- changeSupport.addPropertyChangeListener (name, listener);
+ /**
+ * 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)
+ {
+ for (int i = 0; i < component.length; i++)
+ {
+ if (component[i] == comp)
+ {
+ index = i;
+ break;
+ }
+ }
+ }
+ return index;
}
// Hidden helper methods.
@@ -1600,17 +1662,17 @@ public class Container extends Component
private void visitChildren(Graphics gfx, GfxVisitor visitor,
boolean lightweightOnly)
{
- synchronized (getTreeLock ())
+ synchronized (getTreeLock())
{
for (int i = ncomponents - 1; i >= 0; --i)
{
Component comp = component[i];
boolean applicable = comp.isVisible()
- && (comp.isLightweight() || !lightweightOnly);
-
+ && (comp.isLightweight() || ! lightweightOnly);
+
if (applicable)
visitChild(gfx, visitor, comp);
- }
+ }
}
}
@@ -1631,10 +1693,9 @@ public class Container extends Component
Component comp)
{
Rectangle bounds = comp.getBounds();
-
+
if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height))
return;
-
Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width,
bounds.height);
try
@@ -1649,17 +1710,18 @@ public class Container extends Component
void dispatchEventImpl(AWTEvent e)
{
- // Give lightweight dispatcher a chance to handle it.
- if (dispatcher != null && dispatcher.handleEvent (e))
- return;
-
- if ((e.id <= ContainerEvent.CONTAINER_LAST
- && e.id >= ContainerEvent.CONTAINER_FIRST)
- && (containerListener != null
- || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
- processEvent(e);
- else
- super.dispatchEventImpl(e);
+ boolean dispatched =
+ LightweightDispatcher.getInstance().dispatchEvent(e);
+ if (! dispatched)
+ {
+ if ((e.id <= ContainerEvent.CONTAINER_LAST
+ && e.id >= ContainerEvent.CONTAINER_FIRST)
+ && (containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+ }
}
/**
@@ -1743,15 +1805,6 @@ public class Container extends Component
component[i].addNotify();
if (component[i].isLightweight ())
{
-
- // If we're not lightweight, and we just got a lightweight
- // child, we need a lightweight dispatcher to feed it events.
- if (!this.isLightweight() && dispatcher == null)
- dispatcher = new LightweightDispatcher (this);
-
- if (dispatcher != null)
- dispatcher.enableEvents(component[i].eventMask);
-
enableEvents(component[i].eventMask);
if (peer != null && !isLightweight ())
enableEvents (AWTEvent.PAINT_EVENT_MASK);
@@ -1998,229 +2051,3 @@ public class Container extends Component
} // class AccessibleContainerHandler
} // class AccessibleAWTContainer
} // class Container
-
-/**
- * There is a helper class implied from stack traces called
- * LightweightDispatcher, but since it is not part of the public API,
- * rather than mimic it exactly we write something which does "roughly
- * the same thing".
- */
-class LightweightDispatcher implements Serializable
-{
- private static final long serialVersionUID = 5184291520170872969L;
- private Container nativeContainer;
- private Cursor nativeCursor;
- private long eventMask;
-
- private transient Component pressedComponent;
- private transient Component lastComponentEntered;
- private transient int pressCount;
-
- LightweightDispatcher(Container c)
- {
- nativeContainer = c;
- }
-
- void enableEvents(long l)
- {
- eventMask |= l;
- }
-
- /**
- * Returns the deepest visible descendent of parent that contains the
- * specified location and that is not transparent and MouseListener-less.
- * @param parent the root component to begin the search
- * @param x the x coordinate
- * @param y the y coordinate
- * @return null if <code>parent</code> doesn't contain the location,
- * parent if parent is not a container or has no child that contains the
- * location, otherwise the appropriate component from the conditions
- * above.
- */
- Component getDeepestComponentForMouseEventAt(Component parent, int x, int y)
- {
- if (parent == null || (! parent.contains(x, y)))
- return null;
-
- if (! (parent instanceof Container))
- return parent;
-
- Container c = (Container) parent;
- return c.findComponentForMouseEventAt(x, y);
- }
-
- Component acquireComponentForMouseEvent(MouseEvent me)
- {
- int x = me.getX ();
- int y = me.getY ();
-
- Component mouseEventTarget = null;
- // Find the candidate which should receive this event.
- Component parent = nativeContainer;
- Component candidate = null;
- Point p = me.getPoint();
- while (candidate == null && parent != null)
- {
- candidate = getDeepestComponentForMouseEventAt(parent, p.x, p.y);
- if (candidate == null || (candidate.eventMask & me.getID()) == 0)
- {
- candidate = null;
- p = AWTUtilities.convertPoint(parent, p.x, p.y, parent.parent);
- parent = parent.parent;
- }
- }
-
- // If the only candidate we found was the native container itself,
- // don't dispatch any event at all. We only care about the lightweight
- // children here.
- if (candidate == nativeContainer)
- candidate = null;
-
- // If our candidate is new, inform the old target we're leaving.
- if (lastComponentEntered != null
- && lastComponentEntered.isShowing()
- && lastComponentEntered != candidate)
- {
- // Old candidate could have been removed from
- // the nativeContainer so we check first.
- if (AWTUtilities.isDescendingFrom(lastComponentEntered,
- nativeContainer))
- {
- Point tp = AWTUtilities.convertPoint(nativeContainer,
- x, y, lastComponentEntered);
- MouseEvent exited = new MouseEvent (lastComponentEntered,
- MouseEvent.MOUSE_EXITED,
- me.getWhen (),
- me.getModifiersEx (),
- tp.x, tp.y,
- me.getClickCount (),
- me.isPopupTrigger (),
- me.getButton ());
- lastComponentEntered.dispatchEvent (exited);
- }
- lastComponentEntered = null;
- }
-
- // If we have a candidate, maybe enter it.
- if (candidate != null)
- {
- mouseEventTarget = candidate;
- if (candidate.isLightweight()
- && candidate.isShowing()
- && candidate != nativeContainer
- && candidate != lastComponentEntered)
- {
- lastComponentEntered = mouseEventTarget;
- Point cp = AWTUtilities.convertPoint(nativeContainer,
- x, y, lastComponentEntered);
- MouseEvent entered = new MouseEvent (lastComponentEntered,
- MouseEvent.MOUSE_ENTERED,
- me.getWhen (),
- me.getModifiersEx (),
- cp.x, cp.y,
- me.getClickCount (),
- me.isPopupTrigger (),
- me.getButton ());
- lastComponentEntered.dispatchEvent (entered);
- }
- }
-
- // Check which buttons where pressed except the last button that
- // changed state.
- int modifiers = me.getModifiersEx() & (MouseEvent.BUTTON1_DOWN_MASK
- | MouseEvent.BUTTON2_DOWN_MASK
- | MouseEvent.BUTTON3_DOWN_MASK);
- switch(me.getButton())
- {
- case MouseEvent.BUTTON1:
- modifiers &= ~MouseEvent.BUTTON1_DOWN_MASK;
- break;
- case MouseEvent.BUTTON2:
- modifiers &= ~MouseEvent.BUTTON2_DOWN_MASK;
- break;
- case MouseEvent.BUTTON3:
- modifiers &= ~MouseEvent.BUTTON3_DOWN_MASK;
- break;
- }
-
- if (me.getID() == MouseEvent.MOUSE_RELEASED
- || me.getID() == MouseEvent.MOUSE_PRESSED && modifiers > 0
- || me.getID() == MouseEvent.MOUSE_DRAGGED)
- {
- // If any of the following events occur while a button is held down,
- // they should be dispatched to the same component to which the
- // original MOUSE_PRESSED event was dispatched:
- // - MOUSE_RELEASED: This is important for correct dragging
- // behaviour, otherwise the release goes to an arbitrary component
- // outside of the dragged component. OTOH, if there is no mouse
- // drag while the mouse is pressed, the component under the mouse
- // is the same as the previously pressed component anyway.
- // - MOUSE_PRESSED: another button pressed while the first is held
- // down
- // - MOUSE_DRAGGED
- if (AWTUtilities.isDescendingFrom(pressedComponent, nativeContainer))
- mouseEventTarget = pressedComponent;
- }
- else if (me.getID() == MouseEvent.MOUSE_CLICKED)
- {
- // Don't dispatch CLICKED events whose target is not the same as the
- // target for the original PRESSED event.
- if (candidate != pressedComponent)
- {
- mouseEventTarget = null;
- pressCount = 0;
- }
- else if (pressCount == 0)
- pressedComponent = null;
- }
- return mouseEventTarget;
- }
-
- boolean handleEvent(AWTEvent e)
- {
- if (e instanceof MouseEvent)
- {
- MouseEvent me = (MouseEvent) e;
-
- // Make the LightWeightDispatcher reentrant. This is necessary when
- // a lightweight component does its own modal event queue.
- Component mouseEventTarget = acquireComponentForMouseEvent(me);
-
- // Avoid dispatching ENTERED and EXITED events twice.
- if (mouseEventTarget != null
- && mouseEventTarget.isShowing()
- && e.getID() != MouseEvent.MOUSE_ENTERED
- && e.getID() != MouseEvent.MOUSE_EXITED)
- {
- switch (e.getID())
- {
- case MouseEvent.MOUSE_PRESSED:
- if (pressCount++ == 0)
- pressedComponent = mouseEventTarget;
- break;
- case MouseEvent.MOUSE_RELEASED:
- // Clear our memory of the original PRESSED event, only if
- // we're not expecting a CLICKED event after this. If
- // there is a CLICKED event after this, it will do clean up.
- if (--pressCount == 0
- && mouseEventTarget != pressedComponent)
- {
- pressedComponent = null;
- pressCount = 0;
- }
- break;
- }
-
- MouseEvent newEvt =
- AWTUtilities.convertMouseEvent(nativeContainer, me,
- mouseEventTarget);
- mouseEventTarget.dispatchEvent(newEvt);
-
- if (newEvt.isConsumed())
- e.consume();
- }
- }
-
- return e.isConsumed();
- }
-}