diff options
Diffstat (limited to 'libjava/classpath/java/awt/Container.java')
-rw-r--r-- | libjava/classpath/java/awt/Container.java | 435 |
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(); - } -} |