Author: jlaba...@google.com
Date: Thu Jan 15 07:01:51 2009
New Revision: 4464

Modified:
    releases/1.6/user/src/com/google/gwt/user/client/DOM.java
    releases/1.6/user/src/com/google/gwt/user/client/Event.java
    releases/1.6/user/src/com/google/gwt/user/client/ListenerWrapper.java
    releases/1.6/user/src/com/google/gwt/user/client/impl/DOMImpl.java
    releases/1.6/user/src/com/google/gwt/user/client/ui/PopupPanel.java
    releases/1.6/user/test/com/google/gwt/user/client/EventTest.java

Log:
Merged the legecy EventPreview stack into the new NativePreviewHandler  
stack so legacy EventPreviews will only fire if they are at the top of the  
combined stack.  A previous change took PopupPanels off the legacy stack,  
which promoted other EventPreview to the top and broke legacy code.

Patch by: jlabanca
Review by: ecc (desk)
Issue: 3285



Modified: releases/1.6/user/src/com/google/gwt/user/client/DOM.java
==============================================================================
--- releases/1.6/user/src/com/google/gwt/user/client/DOM.java   (original)
+++ releases/1.6/user/src/com/google/gwt/user/client/DOM.java   Thu Jan 15  
07:01:51 2009
@@ -23,8 +23,6 @@
  import com.google.gwt.dom.client.SelectElement;
  import com.google.gwt.user.client.impl.DOMImpl;

-import java.util.ArrayList;
-
  /**
   * This class provides a set of static methods that allow you to  
manipulate the
   * browser's Document Object Model (DOM). It contains methods for  
manipulating
@@ -32,16 +30,11 @@
   * {...@link com.google.gwt.user.client.Event events}.
   */
  public class DOM {
-
    // The current event being fired
    private static Event currentEvent = null;
    private static final DOMImpl impl = GWT.create(DOMImpl.class);
    private static Element sCaptureElem;

-  // <BrowserEventPreview>
-  @SuppressWarnings("deprecation")
-  private static ArrayList<EventPreview> sEventPreviewStack;
-
    /**
     * Adds an event preview to the preview stack. As long as this preview  
remains
     * on the top of the stack, it will receive all events before they are  
fired
@@ -55,14 +48,7 @@
     */
    @Deprecated
    public static void addEventPreview(EventPreview preview) {
-    impl.maybeInitializeEventSystem();
-
-    // Add the event preview to the stack. It will automatically
-    // begin receiving events.
-    if (sEventPreviewStack == null) {
-      sEventPreviewStack = new ArrayList<EventPreview>();
-    }
-    sEventPreviewStack.add(preview);
+    ListenerWrapper.NativePreview.add(preview);
    }

    /**
@@ -532,7 +518,7 @@
    }

    /**
-   * Gets the key-repeat state of this event.  Only IE supports this  
attribute.
+   * Gets the key-repeat state of this event. Only IE supports this  
attribute.
     *
     * @param evt the event to be tested
     * @return <code>true</code> if this key event was an auto-repeat
@@ -909,8 +895,8 @@
     *
     * @param parent the parent element
     * @param child the child element to add to <code>parent</code>
-   * @param before an existing child element of <code>parent</code> before
-   *          which <code>child</code> will be inserted
+   * @param before an existing child element of <code>parent</code> before  
which
+   *          <code>child</code> will be inserted
     */
    public static void insertBefore(Element parent, Element child, Element  
before) {
      parent.insertBefore(child, before);
@@ -930,10 +916,10 @@
    }

    /**
-   * Creates an <code>&lt;option&gt;</code> element and inserts it as a  
child
-   * of the specified <code>&lt;select&gt;</code> element. If the index is
-   * less than zero, or greater than or equal to the length of the list,  
then
-   * the option element will be appended to the end of the list.
+   * Creates an <code>&lt;option&gt;</code> element and inserts it as a  
child of
+   * the specified <code>&lt;select&gt;</code> element. If the index is  
less
+   * than zero, or greater than or equal to the length of the list, then  
the
+   * option element will be appended to the end of the list.
     *
     * @param selectElem the <code>&lt;select&gt;</code> element
     * @param item the text of the new item; cannot be <code>null</code>
@@ -1012,12 +998,7 @@
     */
    @Deprecated
    public static void removeEventPreview(EventPreview preview) {
-    // Remove the event preview from the stack. If it was on top,
-    // any preview underneath it will automatically begin to
-    // receive events.
-    if (sEventPreviewStack != null) {
-      sEventPreviewStack.remove(preview);
-    }
+    ListenerWrapper.NativePreview.remove(preview);
    }

    /**
@@ -1270,6 +1251,13 @@
    }

    /**
+   * Initialize the event system if it has not already been initialized.
+   */
+  static void maybeInitializeEventSystem() {
+    impl.maybeInitializeEventSystem();
+  }
+
+  /**
     * This method is called directly by native code when event preview is  
being
     * used.
     *
@@ -1280,12 +1268,6 @@
    static boolean previewEvent(Event evt) {
      // Fire a NativePreviewEvent to NativePreviewHandlers
      boolean ret = Event.fireNativePreviewEvent(evt);
-
-    // If event previews are present, redirect events to the topmost of  
them.
-    if (sEventPreviewStack != null && sEventPreviewStack.size() > 0) {
-      EventPreview preview =  
sEventPreviewStack.get(sEventPreviewStack.size() - 1);
-      ret = preview.onEventPreview(evt) && ret;
-    }

      // If the preview cancels the event, stop it from bubbling and  
performing
      // its default action. Check for a null evt to allow unit tests to run.

Modified: releases/1.6/user/src/com/google/gwt/user/client/Event.java
==============================================================================
--- releases/1.6/user/src/com/google/gwt/user/client/Event.java (original)
+++ releases/1.6/user/src/com/google/gwt/user/client/Event.java Thu Jan 15  
07:01:51 2009
@@ -30,9 +30,9 @@
   * An opaque handle to a native DOM Event. An <code>Event</code> cannot be
   * created directly. Instead, use the <code>Event</code> type when  
returning a
   * native DOM event from JSNI methods. An <code>Event</code> passed back  
into
- * JSNI becomes the original DOM event the <code>Event</code> was created
- * from, and can be accessed in JavaScript code as expected. This is  
typically
- * done by calling methods in the {...@link com.google.gwt.user.client.DOM}  
class.
+ * JSNI becomes the original DOM event the <code>Event</code> was created  
from,
+ * and can be accessed in JavaScript code as expected. This is typically  
done by
+ * calling methods in the {...@link com.google.gwt.user.client.DOM} class.
   * </p>
   */
  public class Event extends JavaScriptObject {
@@ -85,6 +85,7 @@
          int numHandlers = handlers.size();
          for (int i = numHandlers - 1; i >= 0; i--) {
            handlers.get(i).onPreviewNativeEvent(singleton);
+          singleton.isFirstHandler = false;
          }

          // Kill the event and return
@@ -106,6 +107,12 @@
      private boolean isConsumed = false;

      /**
+     * A boolean indicating that the current handler is at the top of the  
event
+     * preview stack.
+     */
+    private boolean isFirstHandler = false;
+
+    /**
       * The event being previewed.
       */
      private Event nativeEvent;
@@ -162,6 +169,15 @@
        return isConsumed;
      }

+    /**
+     * Is the current handler the first to preview this event?
+     *
+     * @return true if the current handler is the first to preview the  
event
+     */
+    public boolean isFirstHandler() {
+      return isFirstHandler;
+    }
+
      @Override
      protected void dispatch(NativePreviewHandler handler) {
        handler.onPreviewNativeEvent(this);
@@ -172,6 +188,7 @@
        super.revive();
        isCanceled = false;
        isConsumed = false;
+      isFirstHandler = true;
        nativeEvent = null;
      }

@@ -304,7 +321,8 @@
    public static final int ONSCROLL = 0x04000;

    /**
-   * Fired when the user requests an element's context menu (usually by  
right-clicking).
+   * Fired when the user requests an element's context menu (usually by
+   * right-clicking).
     *
     * Note that not all browsers will fire this event (notably Opera, as of  
9.5).
     */
@@ -328,7 +346,7 @@
        | ONMOUSEOVER | ONMOUSEOUT;

    /**
-   * Value returned by accessors when the actual integer value is  
undefined.  In
+   * Value returned by accessors when the actual integer value is  
undefined. In
     * hosted mode, most accessors assert that the requested attribute is  
reliable
     * across all supported browsers.
     *
@@ -338,12 +356,11 @@
    public static final int UNDEFINED = 0;

    /**
-   * The list of {...@link NativePreviewHandler}.  We use a list instead of a
+   * The list of {...@link NativePreviewHandler}. We use a list instead of a
     * handler manager for efficiency and because we want to fire the  
handlers in
-   * reverse order.  When the last handler is removed, handlers is reset to
-   * null.
+   * reverse order. When the last handler is removed, handlers is reset to  
null.
     */
-  private static ArrayList<NativePreviewHandler> handlers;
+  static ArrayList<NativePreviewHandler> handlers;

    /**
     * Adds an event preview to the preview stack. As long as this preview  
remains
@@ -381,12 +398,14 @@
    public static HandlerRegistration addNativePreviewHandler(
        final NativePreviewHandler handler) {
      assert handler != null : "Cannot add a null handler";
+    DOM.maybeInitializeEventSystem();
+
      // Initialize the type
      NativePreviewEvent.getType();
      if (handlers == null) {
        handlers = new ArrayList<NativePreviewHandler>();
      }
-    handlers.add(handler);
+    handlers.add(handler);
      return new HandlerRegistration() {
        public void removeHandler() {
          if (handlers != null) {
@@ -430,7 +449,7 @@
     * @see #setCapture(Element)
     */
    public static void releaseCapture(Element elem) {
-    DOM.releaseCapture(elem.<com.google.gwt.user.client.Element>cast());
+    DOM.releaseCapture(elem.<com.google.gwt.user.client.Element> cast());
    }

    /**
@@ -453,7 +472,7 @@
     * @param elem the element on which to set mouse capture
     */
    public static void setCapture(Element elem) {
-    DOM.setCapture(elem.<com.google.gwt.user.client.Element>cast());
+    DOM.setCapture(elem.<com.google.gwt.user.client.Element> cast());
    }

    /**

Modified:  
releases/1.6/user/src/com/google/gwt/user/client/ListenerWrapper.java
==============================================================================
--- releases/1.6/user/src/com/google/gwt/user/client/ListenerWrapper.java       
 
(original)
+++ releases/1.6/user/src/com/google/gwt/user/client/ListenerWrapper.java       
 
Thu Jan 15 07:01:51 2009
@@ -25,21 +25,21 @@
  import com.google.gwt.event.shared.EventHandler;
  import com.google.gwt.event.shared.HandlerManager;
  import com.google.gwt.event.shared.GwtEvent.Type;
+import com.google.gwt.user.client.Event.NativePreviewEvent;

  import java.util.EventListener;

  /**
- * Legacy listener support hierarchy for  
<code>com.google.gwt.user.client</code>.
- * Gathers the bulk of the legacy glue code in one place, for easy  
deletion when
- * Listener methods are deleted.
+ * Legacy listener support for <code>com.google.gwt.user.client</code>.  
Gathers
+ * the bulk of the legacy glue code in one place, for easy deletion when
+ * Listener methods are deleted.
   *
- * @see com.google.gwt.user.ListenerWrapper
   * @param <T> listener type
   */
  @Deprecated
  abstract class ListenerWrapper<T> implements EventHandler {
-  public static class HistoryChange extends  
ListenerWrapper<HistoryListener> implements
-      ValueChangeHandler<String> {
+  public static class HistoryChange extends  
ListenerWrapper<HistoryListener>
+      implements ValueChangeHandler<String> {
      @Deprecated
      public static void add(HistoryListener listener) {
        History.addValueChangeHandler(new HistoryChange(listener));
@@ -58,8 +58,46 @@
      }
    }

-  public static class WindowClose extends  
ListenerWrapper<WindowCloseListener> implements
-      Window.ClosingHandler, CloseHandler<Window> {
+  public static class NativePreview extends ListenerWrapper<EventPreview>
+      implements Event.NativePreviewHandler {
+    @Deprecated
+    public static void add(EventPreview listener) {
+      Event.addNativePreviewHandler(new NativePreview(listener));
+    }
+
+    public static void remove(EventPreview listener) {
+      if (Event.handlers == null) {
+        return;
+      }
+      int handlerCount = Event.handlers.size();
+      // We only want to remove the first instance, as the legacy listener  
does
+      for (int i = 0; i < handlerCount; i++) {
+        Event.NativePreviewHandler handler = Event.handlers.get(i);
+        if (handler instanceof NativePreview
+            && ((NativePreview) handler).listener.equals(listener)) {
+          Event.handlers.remove(handler);
+          return;
+        }
+      }
+    }
+
+    private NativePreview(EventPreview listener) {
+      super(listener);
+    }
+
+    public void onPreviewNativeEvent(NativePreviewEvent event) {
+      // The legacy EventHandler should only fire if it is on the top of  
the
+      // stack (ie. the last one added).
+      if (event.isFirstHandler()) {
+        if (!listener.onEventPreview(event.getNativeEvent())) {
+          event.cancel();
+        }
+      }
+    }
+  }
+
+  public static class WindowClose extends  
ListenerWrapper<WindowCloseListener>
+      implements Window.ClosingHandler, CloseHandler<Window> {
      @Deprecated
      public static void add(WindowCloseListener listener) {
        WindowClose handler = new WindowClose(listener);
@@ -89,8 +127,8 @@
      }
    }

-  public static class WindowResize extends  
ListenerWrapper<WindowResizeListener> implements
-      ResizeHandler {
+  public static class WindowResize extends
+      ListenerWrapper<WindowResizeListener> implements ResizeHandler {
      @Deprecated
      public static void add(WindowResizeListener listener) {
        Window.addResizeHandler(new WindowResize(listener));
@@ -110,8 +148,8 @@
      }
    }

-  public static class WindowScroll extends  
ListenerWrapper<WindowScrollListener> implements
-      Window.ScrollHandler {
+  public static class WindowScroll extends
+      ListenerWrapper<WindowScrollListener> implements  
Window.ScrollHandler {
      @Deprecated
      public static void add(WindowScrollListener listener) {
        Window.addWindowScrollHandler(new WindowScroll(listener));
@@ -131,7 +169,6 @@
      }
    }

-
    // This is an internal helper method with the current formulation, we  
have
    // lost the info needed to make it safe by this point.
    @SuppressWarnings("unchecked")
@@ -153,7 +190,7 @@
        }
      }
    }
-
+
    /**
     * Listener being wrapped.
     */

Modified: releases/1.6/user/src/com/google/gwt/user/client/impl/DOMImpl.java
==============================================================================
--- releases/1.6/user/src/com/google/gwt/user/client/impl/DOMImpl.java   
(original)
+++ releases/1.6/user/src/com/google/gwt/user/client/impl/DOMImpl.java  Thu  
Jan 15 07:01:51 2009
@@ -157,9 +157,6 @@

    public abstract void insertChild(Element parent, Element child, int  
index);

-  /**
-   * Initialize the event system if it has not already been initialized.
-   */
    public void maybeInitializeEventSystem() {
      if (!eventSystemIsInitialized) {
        initEventSystem();

Modified:  
releases/1.6/user/src/com/google/gwt/user/client/ui/PopupPanel.java
==============================================================================
--- releases/1.6/user/src/com/google/gwt/user/client/ui/PopupPanel.java  
(original)
+++ releases/1.6/user/src/com/google/gwt/user/client/ui/PopupPanel.java Thu  
Jan 15 07:01:51 2009
@@ -829,7 +829,7 @@
    @SuppressWarnings("deprecation")
    protected void onPreviewNativeEvent(NativePreviewEvent event) {
      // Cancel the event based on the deprecated onEventPreview() method
-    if (!event.isCanceled() && !onEventPreview(event.getNativeEvent())) {
+    if (event.isFirstHandler() && !onEventPreview(event.getNativeEvent()))  
{
        event.cancel();
      }
    }

Modified: releases/1.6/user/test/com/google/gwt/user/client/EventTest.java
==============================================================================
--- releases/1.6/user/test/com/google/gwt/user/client/EventTest.java     
(original)
+++ releases/1.6/user/test/com/google/gwt/user/client/EventTest.java    Thu  
Jan 15 07:01:51 2009
@@ -132,17 +132,20 @@

    /**
     * Test that {...@link Event#fireNativePreviewEvent(Event)} fires handlers  
in
-   * reverse order. Also verify that the legacy EventPreview fires last.
+   * reverse order, and that the legacy EventPreview fires only if it is  
at the
+   * top of the stack.
     */
    @SuppressWarnings("deprecation")
    public void testFireNativePreviewEventReverseOrder() {
-    final TestEventPreview preview = new TestEventPreview(false);
+    final TestEventPreview preview0 = new TestEventPreview(false);
+    final TestEventPreview preview1 = new TestEventPreview(false);
      final TestNativePreviewHandler handler0 = new TestNativePreviewHandler(
          false, false) {
        @Override
        public void onPreviewNativeEvent(NativePreviewEvent event) {
          super.onPreviewNativeEvent(event);
-        preview.assertIsFired(false);
+        preview0.assertIsFired(false);
+        preview1.assertIsFired(true);
        }
      };
      final TestNativePreviewHandler handler1 = new TestNativePreviewHandler(
@@ -151,7 +154,8 @@
        public void onPreviewNativeEvent(NativePreviewEvent event) {
          super.onPreviewNativeEvent(event);
          handler0.assertIsFired(false);
-        preview.assertIsFired(false);
+        preview0.assertIsFired(false);
+        preview1.assertIsFired(true);
        }
      };
      final TestNativePreviewHandler handler2 = new TestNativePreviewHandler(
@@ -161,7 +165,8 @@
          super.onPreviewNativeEvent(event);
          handler0.assertIsFired(false);
          handler1.assertIsFired(false);
-        preview.assertIsFired(false);
+        preview0.assertIsFired(false);
+        preview1.assertIsFired(true);
        }
      };
      final TestNativePreviewHandler handler3 = new TestNativePreviewHandler(
@@ -172,25 +177,29 @@
          handler0.assertIsFired(false);
          handler1.assertIsFired(false);
          handler2.assertIsFired(false);
-        preview.assertIsFired(false);
+        preview0.assertIsFired(false);
+        preview1.assertIsFired(true);
        }
      };
+    DOM.addEventPreview(preview0);
      HandlerRegistration reg0 = Event.addNativePreviewHandler(handler0);
      HandlerRegistration reg1 = Event.addNativePreviewHandler(handler1);
      HandlerRegistration reg2 = Event.addNativePreviewHandler(handler2);
      HandlerRegistration reg3 = Event.addNativePreviewHandler(handler3);
-    DOM.addEventPreview(preview);
+    DOM.addEventPreview(preview1);
      assertTrue(DOM.previewEvent(null));
      handler0.assertIsFired(true);
      handler1.assertIsFired(true);
      handler2.assertIsFired(true);
      handler3.assertIsFired(true);
-    preview.assertIsFired(true);
+    preview0.assertIsFired(false);
+    preview1.assertIsFired(true);
      reg0.removeHandler();
      reg1.removeHandler();
      reg2.removeHandler();
      reg3.removeHandler();
-    DOM.removeEventPreview(preview);
+    DOM.removeEventPreview(preview0);
+    DOM.removeEventPreview(preview1);
    }

    /**

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to