This fixes a couple of issues that I had with Espial Espresso (a
Swing-alike lightweight toolkit implementation). This does:
- validate() in paintAll()
- don't enable events in the various addXXXListener() methods. There are
two methods for catching events, adding a listener OR calling
enableEvents() in a subclass and overriding processXXXEvent(). It's not
meant to call enableEvent() from the addXXXListener() methods.
- Fix some painting issues.
2006-09-18 Roman Kennke <[EMAIL PROTECTED]>
* java/awt/Component.java
(show): Test for the peer beeing lightweight directly.
(paintAll): Validate before painting. Don't paint when not
showing. Call peer.paint() when the component is heavyweight.
(repaint): Delegate to the parent when lightweight, rather
than skipping to the nearest heavyweight.
(createImage): Added null check to prevent NPE.
(dispatchEvent): Moved old event dispatching and toolkit
event dispatching to dispatchEventImpl.
(addComponentListener): Don't enable event. Only add listener
when not null. Switch to new event dispatching only.
(addFocusListener): Likewise.
(addHierarchyListener): Likewise.
(addHierarchyBoundsListener): Likewise.
(addKeyListener): Likewise.
(addMouseListener): Likewise.
(addMouseMotionListener): Likewise.
(addMouseWheelListener): Likewise.
(addInputMethodListener): Likewise.
(coalesceEvents): For mouse events coalesce them only when
their modifiers are equal. For paint events coalesce the events
when one contains the other, without going through complicated
heuristics.
(dispatchEventImpl): Moved old event dispatching and toolkit
event dispatching to dispatchEventImpl.
(coalescePaintEvents): Removed.
(HeavyweightInLightweightListener.componentHidden):
Fixed condition.
* java/awt/Container.java
(addImpl): Don't enable events on lightweights.
(remove): Reordered operations. Don't remove any listeners.
Throw ArrayIndexOutOfBoundsException when index >= ncomponents.
Only removeNotify() when peer is != null. Only invalidate if
not already invalid. Only fire ContainerEvent if there is
an interested listener or the event is enabled. Dispatch this
event directly without the event queue.
(removeAll): Likewise.
(paintComponents): Only paint when showing. Also paint heavyweights.
Don't paint the container itself.
(removeNotify): Create local variables for improved thread safety.
(addNotifyContainerChildren): Don't enable events for lightweights.
/Roman
Index: java/awt/Component.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Component.java,v
retrieving revision 1.146
diff -u -1 -5 -r1.146 Component.java
--- java/awt/Component.java 16 Aug 2006 20:26:03 -0000 1.146
+++ java/awt/Component.java 18 Sep 2006 13:22:16 -0000
@@ -959,50 +959,50 @@
show(visible);
}
/**
* Makes this component visible on the screen.
*
* @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())
+ if(! visible)
{
// Need to lock the tree here to avoid races and inconsistencies.
synchronized (getTreeLock())
{
visible = true;
// Avoid NullPointerExceptions by creating a local reference.
- ComponentPeer currentPeer=peer;
+ 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())
+ if (peer instanceof LightweightPeer)
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
@@ -1025,31 +1025,31 @@
public void show(boolean visible)
{
if (visible)
show();
else
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())
+ if (visible)
{
// Need to lock the tree here to avoid races and inconsistencies.
synchronized (getTreeLock())
{
visible = false;
// Avoid NullPointerExceptions by creating a local reference.
ComponentPeer currentPeer = peer;
if (currentPeer != null)
{
currentPeer.hide();
// Fire hierarchy event.
fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
this, parent,
@@ -2217,33 +2217,38 @@
// Note 2 (for peer implementors): The JDK doesn't seem call update() for
// toplevel components, even when an UPDATE event is sent (as a result
// of repaint).
paint(g);
}
/**
* Paints this entire component, including any sub-components.
*
* @param g the graphics context for this paint job
*
* @see #paint(Graphics)
*/
public void paintAll(Graphics g)
{
- if (! visible)
- return;
- paint(g);
+ if (isShowing())
+ {
+ validate();
+ if (peer instanceof LightweightPeer)
+ paint(g);
+ else
+ peer.paint(g);
+ }
}
/**
* Repaint this entire component. The <code>update()</code> method
* on this component will be called as soon as possible.
*
* @see #update(Graphics)
* @see #repaint(long, int, int, int, int)
*/
public void repaint()
{
repaint(0, 0, 0, width, height);
}
/**
@@ -2290,60 +2295,56 @@
* @param height the height of the region to repaint
* @see #update(Graphics)
*/
public void repaint(long tm, int x, int y, int width, int height)
{
// The repaint() call has previously been delegated to
// [EMAIL PROTECTED] ComponentPeer.repaint()}. Testing on the JDK using some
// dummy peers show that this methods is never called. I think it makes
// sense to actually perform the tasks below here, since it's pretty
// much peer independent anyway, and makes sure only heavyweights are
// bothered by this.
ComponentPeer p = peer;
// Let the nearest heavyweight parent handle repainting for lightweight
// components.
- // This goes up the hierarchy until we hit
- // a heavyweight component that handles this and translates the
- // rectangle while doing so.
-
- // We perform some boundary checking to restrict the paint
- // region to this component.
- int px = (x < 0 ? 0 : x);
- int py = (y < 0 ? 0 : y);
- int pw = width;
- int ph = height;
- Component par = this;
- while (par != null && p instanceof LightweightPeer)
+ // We need to recursivly call repaint() on the parent here, since
+ // a (lightweight) parent component might have overridden repaint()
+ // to perform additional custom tasks.
+
+ if (p instanceof LightweightPeer)
{
- px += par.x;
- py += par.y;
// We perform some boundary checking to restrict the paint
// region to this component.
- pw = Math.min(pw, par.width);
- ph = Math.min(ph, par.height);
- par = par.parent;
- p = par == null ? null : par.peer;
+ if (parent != null)
+ {
+ int px = this.x + Math.max(0, x);
+ int py = this.y + Math.max(0, y);
+ int pw = Math.min(this.width, width);
+ int ph = Math.min(this.height, height);
+ parent.repaint(tm, px, py, pw, ph);
+ }
}
-
- // Now send an UPDATE event to the heavyweight component that we've found.
- if (par != null && par.isVisible() && p != null && pw > 0 && ph > 0)
+ else
{
- assert ! (p instanceof LightweightPeer);
- PaintEvent pe = new PaintEvent(par, PaintEvent.UPDATE,
- new Rectangle(px, py, pw, ph));
- getToolkit().getSystemEventQueue().postEvent(pe);
+ // Now send an UPDATE event to the heavyweight component that we've found.
+ if (isVisible() && p != null && width > 0 && height > 0)
+ {
+ PaintEvent pe = new PaintEvent(this, PaintEvent.UPDATE,
+ new Rectangle(x, y, width, height));
+ getToolkit().getSystemEventQueue().postEvent(pe);
+ }
}
}
/**
* Prints this component. This method is provided so that printing can be
* done in a different manner from painting. However, the implementation
* in this class simply calls the <code>paint()</code> method.
*
* @param g the graphics context of the print device
*
* @see #paint(Graphics)
*/
public void print(Graphics g)
{
paint(g);
@@ -2447,31 +2448,32 @@
*/
public Image createImage (int width, int height)
{
Image returnValue = null;
if (!GraphicsEnvironment.isHeadless ())
{
// Only heavyweight peers can handle this.
ComponentPeer p = peer;
Component comp = this;
while (p instanceof LightweightPeer)
{
comp = comp.parent;
p = comp == null ? null : comp.peer;
}
- returnValue = p.createImage(width, height);
+ if (p != null)
+ returnValue = p.createImage(width, height);
}
return returnValue;
}
/**
* Creates an image with the specified width and height for use in
* double buffering. Headless environments do not support images.
*
* @param width the width of the image
* @param height the height of the image
* @return the requested image, or null if it is not supported
* @since 1.4
*/
public VolatileImage createVolatileImage(int width, int height)
{
@@ -2744,38 +2746,30 @@
{
postEvent (e);
}
/**
* Forwards AWT events to processEvent() if:<ul>
* <li>Events have been enabled for this type of event via
* <code>enableEvents()</code></li>,
* <li>There is at least one registered listener for this type of event</li>
* </ul>
*
* @param e the event to dispatch
*/
public final void dispatchEvent(AWTEvent e)
{
- Event oldEvent = translateEvent(e);
- if (oldEvent != null)
- postEvent (oldEvent);
-
- // Give toolkit a chance to dispatch the event
- // to globally registered listeners.
- Toolkit.getDefaultToolkit().globalDispatchEvent(e);
-
// Some subclasses in the AWT package need to override this behavior,
// hence the use of dispatchEventImpl().
dispatchEventImpl(e);
}
/**
* By default, no old mouse events should be ignored.
* This can be overridden by subclasses.
*
* @return false, no mouse events are ignored.
*/
static boolean ignoreOldMouseEvents()
{
return false;
}
@@ -2802,33 +2796,36 @@
}
/**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
*
* @param listener the new listener to add
* @see ComponentEvent
* @see #removeComponentListener(ComponentListener)
* @see #getComponentListeners()
* @since 1.1
*/
public synchronized void addComponentListener(ComponentListener listener)
{
- componentListener = AWTEventMulticaster.add(componentListener, listener);
- if (componentListener != null)
- enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
+ if (listener != null)
+ {
+ componentListener = AWTEventMulticaster.add(componentListener,
+ listener);
+ newEventsOnly = true;
+ }
}
/**
* Removes the specified listener from the component. This is harmless if
* the listener was not previously registered.
*
* @param listener the listener to remove
* @see ComponentEvent
* @see #addComponentListener(ComponentListener)
* @see #getComponentListeners()
* @since 1.1
*/
public synchronized void removeComponentListener(ComponentListener listener)
{
componentListener = AWTEventMulticaster.remove(componentListener, listener);
@@ -2850,33 +2847,35 @@
}
/**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
*
* @param listener the new listener to add
* @see FocusEvent
* @see #removeFocusListener(FocusListener)
* @see #getFocusListeners()
* @since 1.1
*/
public synchronized void addFocusListener(FocusListener listener)
{
- focusListener = AWTEventMulticaster.add(focusListener, listener);
- if (focusListener != null)
- enableEvents(AWTEvent.FOCUS_EVENT_MASK);
+ if (listener != null)
+ {
+ focusListener = AWTEventMulticaster.add(focusListener, listener);
+ newEventsOnly = true;
+ }
}
/**
* Removes the specified listener from the component. This is harmless if
* the listener was not previously registered.
*
* @param listener the listener to remove
* @see FocusEvent
* @see #addFocusListener(FocusListener)
* @see #getFocusListeners()
* @since 1.1
*/
public synchronized void removeFocusListener(FocusListener listener)
{
focusListener = AWTEventMulticaster.remove(focusListener, listener);
@@ -2897,40 +2896,43 @@
}
/**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
*
* @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);
-
- // Need to lock the tree, otherwise we might end up inconsistent.
- synchronized (getTreeLock())
+ if (listener != null)
{
- numHierarchyListeners++;
- if (parent != null)
- parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 1);
+ hierarchyListener = AWTEventMulticaster.add(hierarchyListener,
+ listener);
+ newEventsOnly = true;
+ // 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)
{
@@ -2963,43 +2965,44 @@
/**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
*
* @param listener the new listener to add
* @see HierarchyEvent
* @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);
-
- // Need to lock the tree, otherwise we might end up inconsistent.
- synchronized (getTreeLock())
+ if (listener != null)
{
- numHierarchyBoundsListeners++;
- if (parent != null)
- parent.updateHierarchyListenerCount
- (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
- 1);
+ hierarchyBoundsListener =
+ AWTEventMulticaster.add(hierarchyBoundsListener, listener);
+ newEventsOnly = true;
+
+ // 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)
@@ -3068,33 +3071,35 @@
}
/**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
*
* @param listener the new listener to add
* @see KeyEvent
* @see #removeKeyListener(KeyListener)
* @see #getKeyListeners()
* @since 1.1
*/
public synchronized void addKeyListener(KeyListener listener)
{
- keyListener = AWTEventMulticaster.add(keyListener, listener);
- if (keyListener != null)
- enableEvents(AWTEvent.KEY_EVENT_MASK);
+ if (listener != null)
+ {
+ keyListener = AWTEventMulticaster.add(keyListener, listener);
+ newEventsOnly = true;
+ }
}
/**
* Removes the specified listener from the component. This is harmless if
* the listener was not previously registered.
*
* @param listener the listener to remove
* @see KeyEvent
* @see #addKeyListener(KeyListener)
* @see #getKeyListeners()
* @since 1.1
*/
public synchronized void removeKeyListener(KeyListener listener)
{
keyListener = AWTEventMulticaster.remove(keyListener, listener);
@@ -3115,33 +3120,35 @@
}
/**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
*
* @param listener the new listener to add
* @see MouseEvent
* @see #removeMouseListener(MouseListener)
* @see #getMouseListeners()
* @since 1.1
*/
public synchronized void addMouseListener(MouseListener listener)
{
- mouseListener = AWTEventMulticaster.add(mouseListener, listener);
- if (mouseListener != null)
- enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+ if (listener != null)
+ {
+ mouseListener = AWTEventMulticaster.add(mouseListener, listener);
+ newEventsOnly = true;
+ }
}
/**
* Removes the specified listener from the component. This is harmless if
* the listener was not previously registered.
*
* @param listener the listener to remove
* @see MouseEvent
* @see #addMouseListener(MouseListener)
* @see #getMouseListeners()
* @since 1.1
*/
public synchronized void removeMouseListener(MouseListener listener)
{
mouseListener = AWTEventMulticaster.remove(mouseListener, listener);
@@ -3162,33 +3169,36 @@
}
/**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
*
* @param listener the new listener to add
* @see MouseEvent
* @see #removeMouseMotionListener(MouseMotionListener)
* @see #getMouseMotionListeners()
* @since 1.1
*/
public synchronized void addMouseMotionListener(MouseMotionListener listener)
{
- mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, listener);
- if (mouseMotionListener != null)
- enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ if (listener != null)
+ {
+ mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener,
+ listener);
+ newEventsOnly = true;
+ }
}
/**
* Removes the specified listener from the component. This is harmless if
* the listener was not previously registered.
*
* @param listener the listener to remove
* @see MouseEvent
* @see #addMouseMotionListener(MouseMotionListener)
* @see #getMouseMotionListeners()
* @since 1.1
*/
public synchronized void removeMouseMotionListener(MouseMotionListener listener)
{
mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener);
@@ -3211,33 +3221,36 @@
/**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
*
* @param listener the new listener to add
* @see MouseEvent
* @see MouseWheelEvent
* @see #removeMouseWheelListener(MouseWheelListener)
* @see #getMouseWheelListeners()
* @since 1.4
*/
public synchronized void addMouseWheelListener(MouseWheelListener listener)
{
- mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener, listener);
- if (mouseWheelListener != null)
- enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
+ if (listener != null)
+ {
+ mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener,
+ listener);
+ newEventsOnly = true;
+ }
}
/**
* Removes the specified listener from the component. This is harmless if
* the listener was not previously registered.
*
* @param listener the listener to remove
* @see MouseEvent
* @see MouseWheelEvent
* @see #addMouseWheelListener(MouseWheelListener)
* @see #getMouseWheelListeners()
* @since 1.4
*/
public synchronized void removeMouseWheelListener(MouseWheelListener listener)
{
@@ -3261,33 +3274,36 @@
/**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
*
* @param listener the new listener to add
* @see InputMethodEvent
* @see #removeInputMethodListener(InputMethodListener)
* @see #getInputMethodListeners()
* @see #getInputMethodRequests()
* @since 1.2
*/
public synchronized void addInputMethodListener(InputMethodListener listener)
{
- inputMethodListener = AWTEventMulticaster.add(inputMethodListener, listener);
- if (inputMethodListener != null)
- enableEvents(AWTEvent.INPUT_METHOD_EVENT_MASK);
+ if (listener != null)
+ {
+ inputMethodListener = AWTEventMulticaster.add(inputMethodListener,
+ listener);
+ newEventsOnly = true;
+ }
}
/**
* Removes the specified listener from the component. This is harmless if
* the listener was not previously registered.
*
* @param listener the listener to remove
* @see InputMethodEvent
* @see #addInputMethodListener(InputMethodListener)
* @see #getInputMethodRequests()
* @since 1.2
*/
public synchronized void removeInputMethodListener(InputMethodListener listener)
{
inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener);
@@ -3500,43 +3516,60 @@
}
/**
* This is called by the EventQueue if two events with the same event id
* and owner component are queued. Returns a new combined event, or null if
* no combining is done. The coelesced events are currently mouse moves
* (intermediate ones are discarded) and paint events (a merged paint is
* created in place of the two events).
*
* @param existingEvent the event on the queue
* @param newEvent the new event that might be entered on the queue
* @return null if both events are kept, or the replacement coelesced event
*/
protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
{
+ AWTEvent coalesced = null;
switch (existingEvent.id)
{
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
// Just drop the old (intermediate) event and return the new one.
- return newEvent;
+ MouseEvent me1 = (MouseEvent) existingEvent;
+ MouseEvent me2 = (MouseEvent) newEvent;
+ if (me1.getModifiers() == me2.getModifiers())
+ coalesced = newEvent;
+ break;
case PaintEvent.PAINT:
case PaintEvent.UPDATE:
- return coalescePaintEvents((PaintEvent) existingEvent,
- (PaintEvent) newEvent);
+ // For heavyweights the EventQueue should ask the peer.
+ if (peer == null || peer instanceof LightweightPeer)
+ {
+ PaintEvent pe1 = (PaintEvent) existingEvent;
+ PaintEvent pe2 = (PaintEvent) newEvent;
+ Rectangle r1 = pe1.getUpdateRect();
+ Rectangle r2 = pe2.getUpdateRect();
+ if (r1.contains(r2))
+ coalesced = existingEvent;
+ else if (r2.contains(r1))
+ coalesced = newEvent;
+ }
+ break;
default:
- return null;
+ coalesced = null;
}
+ return coalesced;
}
/**
* Processes the specified event. In this class, this method simply
* calls one of the more specific event handlers.
*
* @param e the event to process
* @throws NullPointerException if e is null
* @see #processComponentEvent(ComponentEvent)
* @see #processFocusEvent(FocusEvent)
* @see #processKeyEvent(KeyEvent)
* @see #processMouseEvent(MouseEvent)
* @see #processMouseMotionEvent(MouseEvent)
* @see #processInputMethodEvent(InputMethodEvent)
* @see #processHierarchyEvent(HierarchyEvent)
@@ -5587,35 +5620,45 @@
void dispatchEventImpl(AWTEvent e)
{
// Retarget focus events before dispatching it to the KeyboardFocusManager
// in order to handle lightweight components properly.
boolean dispatched = false;
if (! e.isFocusManagerEvent)
{
e = KeyboardFocusManager.retargetFocusEvent(e);
dispatched = KeyboardFocusManager.getCurrentKeyboardFocusManager()
.dispatchEvent(e);
}
if (! dispatched)
{
- if (eventTypeEnabled (e.id))
+ // Give toolkit a chance to dispatch the event
+ // to globally registered listeners.
+ Toolkit.getDefaultToolkit().globalDispatchEvent(e);
+
+ if (newEventsOnly)
{
- if (e.id != PaintEvent.PAINT && e.id != PaintEvent.UPDATE)
+ if (eventTypeEnabled(e.id))
processEvent(e);
}
+ else
+ {
+ Event oldEvent = translateEvent(e);
+ if (oldEvent != null)
+ postEvent (oldEvent);
+ }
if (peer != null)
peer.handleEvent(e);
}
}
/**
* Tells whether or not an event type is enabled.
*/
boolean eventTypeEnabled (int type)
{
if (type > AWTEvent.RESERVED_ID_MAX)
return true;
switch (type)
{
@@ -5684,69 +5727,30 @@
*/
boolean isHierarchyVisible()
{
boolean visible = isVisible();
Component comp = parent;
while (comp != null && visible)
{
comp = comp.parent;
if (comp != null)
visible = visible && comp.isVisible();
}
return visible;
}
/**
- * Coalesce paint events. Current heuristic is: Merge if the union of
- * areas is less than twice that of the sum of the areas. The X server
- * tend to create a lot of paint events that are adjacent but not
- * overlapping.
- *
- * <pre>
- * +------+
- * | +-----+ ...will be merged
- * | | |
- * | | |
- * +------+ |
- * +-----+
- *
- * +---------------+--+
- * | | | ...will not be merged
- * +---------------+ |
- * | |
- * | |
- * | |
- * | |
- * | |
- * +--+
- * </pre>
- *
- * @param queuedEvent the first paint event
- * @param newEvent the second paint event
- * @return the combined paint event, or null
- */
- private PaintEvent coalescePaintEvents(PaintEvent queuedEvent,
- PaintEvent newEvent)
- {
- Rectangle r1 = queuedEvent.getUpdateRect();
- Rectangle r2 = newEvent.getUpdateRect();
- Rectangle union = r1.union(r2);
- newEvent.setUpdateRect(union);
- return newEvent;
- }
-
- /**
* This method is used to implement transferFocus(). CHILD is the child
* making the request. This is overridden by Container; when called for an
* ordinary component there is no child and so we always return null.
*
* FIXME: is this still needed, in light of focus traversal policies?
*
* @param child the component making the request
* @return the next component to focus on
*/
Component findNextFocusComponent(Component child)
{
return null;
}
/**
@@ -5862,31 +5866,31 @@
* @param event the <code>ComponentEvent</code> indicating the visibility
*/
public void componentShown(ComponentEvent event)
{
if (isShowing())
peer.show();
}
/**
* This method is called when the component is hidden.
*
* @param event the <code>ComponentEvent</code> indicating the visibility
*/
public void componentHidden(ComponentEvent event)
{
- if (!isShowing())
+ if (isShowing())
peer.hide();
}
}
/**
* This class provides accessibility support for subclasses of container.
*
* @author Eric Blake ([EMAIL PROTECTED])
* @since 1.3
* @status updated to 1.4
*/
protected abstract class AccessibleAWTComponent extends AccessibleContext
implements Serializable, AccessibleComponent
{
/**
Index: java/awt/Container.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Container.java,v
retrieving revision 1.104
diff -u -1 -5 -r1.104 Container.java
--- java/awt/Container.java 23 Aug 2006 14:23:27 -0000 1.104
+++ java/awt/Container.java 18 Sep 2006 13:22:16 -0000
@@ -318,37 +318,30 @@
|| comp instanceof Window
|| (comp instanceof Container
&& ((Container) comp).isAncestorOf(this)))
throw new IllegalArgumentException();
// Reparent component, and make sure component is instantiated if
// we are.
if (comp.parent != null)
comp.parent.remove(comp);
comp.parent = this;
if (peer != null)
{
// Notify the component that it has a new parent.
comp.addNotify();
-
- if (comp.isLightweight ())
- {
- enableEvents (comp.eventMask);
- if (!isLightweight ())
- enableEvents (AWTEvent.PAINT_EVENT_MASK);
- }
}
// Invalidate the layout of the added component and its ancestors.
comp.invalidate();
if (component == null)
component = new Component[4]; // FIXME, better initial size?
// This isn't the most efficient implementation. We could do less
// copying when growing the array. It probably doesn't matter.
if (ncomponents >= component.length)
{
int nl = component.length * 2;
Component[] c = new Component[nl];
System.arraycopy(component, 0, c, 0, ncomponents);
@@ -405,66 +398,67 @@
// Notify hierarchy listeners.
comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp,
this, HierarchyEvent.PARENT_CHANGED);
}
}
/**
* Removes the component at the specified index from this container.
*
* @param index The index of the component to remove.
*/
public void remove(int index)
{
synchronized (getTreeLock ())
{
- Component r = component[index];
+ if (index < 0 || index >= ncomponents)
+ throw new ArrayIndexOutOfBoundsException();
- ComponentListener[] list = r.getComponentListeners();
- for (int j = 0; j < list.length; j++)
- r.removeComponentListener(list[j]);
-
- r.removeNotify();
+ Component r = component[index];
+ if (peer != null)
+ r.removeNotify();
- System.arraycopy(component, index + 1, component, index,
- ncomponents - index - 1);
- component[--ncomponents] = null;
+ if (layoutMgr != null)
+ layoutMgr.removeLayoutComponent(r);
// Update the counter for Hierarchy(Bounds)Listeners.
int childHierarchyListeners = r.numHierarchyListeners;
if (childHierarchyListeners > 0)
updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
-childHierarchyListeners);
int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
if (childHierarchyBoundsListeners > 0)
updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
-childHierarchyListeners);
- invalidate();
+ r.parent = null;
- if (layoutMgr != null)
- layoutMgr.removeLayoutComponent(r);
+ System.arraycopy(component, index + 1, component, index,
+ ncomponents - index - 1);
+ component[--ncomponents] = null;
- r.parent = null;
+ if (valid)
+ invalidate();
- if (isShowing ())
+ if (containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
{
// Post event to notify of removing the component.
ContainerEvent ce = new ContainerEvent(this,
- ContainerEvent.COMPONENT_REMOVED,
- r);
- getToolkit().getSystemEventQueue().postEvent(ce);
+ ContainerEvent.COMPONENT_REMOVED,
+ r);
+ dispatchEvent(ce);
}
// Notify hierarchy listeners.
r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r,
this, HierarchyEvent.PARENT_CHANGED);
}
}
/**
* Removes the specified component from this container.
*
* @param comp The component to remove from this container.
*/
public void remove(Component comp)
{
@@ -484,77 +478,75 @@
/**
* Removes all components from this container.
*/
public void removeAll()
{
synchronized (getTreeLock ())
{
// In order to allow the same bad tricks to be used as in RI
// this code has to stay exactly that way: In a real-life app
// a Container subclass implemented its own vector for
// subcomponents, supplied additional addXYZ() methods
// and overrode remove(int) and removeAll (the latter calling
// super.removeAll() ).
// By doing it this way, user code cannot prevent the correct
// removal of components.
- for ( int index = 0; index < ncomponents; index++)
+ while (ncomponents > 0)
{
- Component r = component[index];
+ ncomponents--;
+ Component r = component[ncomponents];
+ component[ncomponents] = null;
- ComponentListener[] list = r.getComponentListeners();
- for (int j = 0; j < list.length; j++)
- r.removeComponentListener(list[j]);
-
- r.removeNotify();
-
- // Update the counter for Hierarchy(Bounds)Listeners.
- int childHierarchyListeners = r.numHierarchyListeners;
- if (childHierarchyListeners > 0)
- updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
- -childHierarchyListeners);
- int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
- if (childHierarchyBoundsListeners > 0)
- updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
- -childHierarchyListeners);
+ if (peer != null)
+ r.removeNotify();
if (layoutMgr != null)
layoutMgr.removeLayoutComponent(r);
r.parent = null;
// Send ContainerEvent if necessary.
if (containerListener != null
|| (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
{
// Post event to notify of removing the component.
ContainerEvent ce
= new ContainerEvent(this,
ContainerEvent.COMPONENT_REMOVED,
r);
dispatchEvent(ce);
}
+ // Update the counter for Hierarchy(Bounds)Listeners.
+ int childHierarchyListeners = r.numHierarchyListeners;
+ if (childHierarchyListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ -childHierarchyListeners);
+ int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
+ if (childHierarchyBoundsListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ -childHierarchyListeners);
+
+
// Send HierarchyEvent if necessary.
fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this,
HierarchyEvent.PARENT_CHANGED);
}
if (valid)
invalidate();
-
- ncomponents = 0;
}
}
/**
* Returns the current layout manager for this container.
*
* @return The layout manager for this container.
*/
public LayoutManager getLayout()
{
return layoutMgr;
}
/**
* Sets the layout manager for this container to the specified layout
@@ -783,32 +775,33 @@
*
* @return The maximum size of this container.
*/
public Dimension getMaximumSize()
{
Dimension size = maxSize;
// Try to return cached value if possible.
if (size == null || !(maxSizeSet || valid))
{
// Need to lock here.
synchronized (getTreeLock())
{
LayoutManager l = layoutMgr;
if (l instanceof LayoutManager2)
maxSize = ((LayoutManager2) l).maximumLayoutSize(this);
- else
+ else {
maxSize = super.maximumSizeImpl();
+ }
size = maxSize;
}
}
if (size != null)
return new Dimension(size);
else
return size;
}
/**
* 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.
@@ -919,32 +912,32 @@
* @param g The graphics context for this print job.
*/
public void print(Graphics g)
{
super.print(g);
visitChildren(g, GfxPrintVisitor.INSTANCE, true);
}
/**
* Paints all of the components in this container.
*
* @param g The graphics context for this paint job.
*/
public void paintComponents(Graphics g)
{
- paint(g);
- visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
+ if (isShowing())
+ visitChildren(g, GfxPaintAllVisitor.INSTANCE, false);
}
/**
* Prints all of the components in this container.
*
* @param g The graphics context for this print job.
*/
public void printComponents(Graphics g)
{
super.paint(g);
visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
}
/**
* Adds the specified container listener to this object's list of
@@ -1246,32 +1239,38 @@
{
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)
- component[i].removeNotify();
+ int ncomps = ncomponents;
+ Component[] comps = component;
+ for (int i = ncomps - 1; i >= 0; --i)
+ {
+ Component comp = comps[i];
+ if (comp != null)
+ comp.removeNotify();
+ }
super.removeNotify();
}
}
/**
* Tests whether or not the specified component is contained within
* this components subtree.
*
* @param comp The component to test.
*
* @return <code>true</code> if this container is an ancestor of the
* specified component, <code>false</code> otherwise.
*/
public boolean isAncestorOf(Component comp)
{
@@ -2047,36 +2046,30 @@
Component child = getComponent(i);
child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
this, parent, 0);
}
}
}
}
private void addNotifyContainerChildren()
{
synchronized (getTreeLock ())
{
for (int i = ncomponents; --i >= 0; )
{
component[i].addNotify();
- if (component[i].isLightweight ())
- {
- enableEvents(component[i].eventMask);
- if (peer != null && !isLightweight ())
- enableEvents (AWTEvent.PAINT_EVENT_MASK);
- }
}
}
}
/**
* Deserialize this Container:
* <ol>
* <li>Read from the stream the default serializable fields.</li>
* <li>Read a list of serializable ContainerListeners as optional
* data. If the list is null, no listeners will be registered.</li>
* <li>Read this Container's FocusTraversalPolicy as optional data.
* If this is null, then this Container will use a
* DefaultFocusTraversalPolicy.</li>
* </ol>
*