Author: [EMAIL PROTECTED]
Date: Wed Nov 12 13:27:13 2008
New Revision: 4030

Removed:
     
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/JavaHandlerRegistry.java
     
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/JsHandlerRegistry.java
Modified:
     
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/HandlerManager.java

Log:
Merging JavaHandlerRegistry and JsHandlerREgister into HandlerManager as  
private classes, adding privates where necessary.

Modified:  
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/HandlerManager.java
==============================================================================
---  
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/HandlerManager.java
       
(original)
+++  
branches/1_6_clean_events/user/src/com/google/gwt/event/shared/HandlerManager.java
       
Wed Nov 12 13:27:13 2008
@@ -16,9 +16,11 @@
  package com.google.gwt.event.shared;

  import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JavaScriptObject;
  import com.google.gwt.event.shared.GwtEvent.Type;

  import java.util.ArrayList;
+import java.util.HashMap;
  import java.util.List;

  /**
@@ -26,32 +28,251 @@
   * handlers on passed in events.
   */
  public class HandlerManager {
-  // Used to optimize the JavaScript handler container structure.
-  static int EXPECTED_HANDLERS = 5;
-  private static final boolean useJs = GWT.isClient();
-  private static int index;
-
    /**
-   * Is the given event live?
-   *
-   * @param event the event
-   * @return is the event live
+   * The default Handler manager's handler registry for running in Java  
code.
     */
-  public static boolean isLive(GwtEvent<?> event) {
-    return event.isLive();
+  private static class JavaHandlerRegistry extends
+      HashMap<GwtEvent.Type<?>, ArrayList<?>> {
+
+    public <H extends EventHandler> void addHandler(Type<H> type, H  
handler) {
+      ArrayList<H> l = get(type);
+      if (l == null) {
+        l = new ArrayList<H>();
+        super.put(type, l);
+      }
+      l.add(handler);
+    }
+
+    public <H extends EventHandler> void fireEvent(GwtEvent<H> event) {
+      Type<H> type = event.getAssociatedType();
+      int count = getHandlerCount(type);
+      for (int i = 0; i < count; i++) {
+        H handler = getHandler(type, i);
+        event.dispatch(handler);
+      }
+    }
+
+    public <H extends EventHandler> H getHandler(GwtEvent.Type<H> eventKey,
+        int index) {
+      ArrayList<H> l = get(eventKey);
+      return l.get(index);
+    }
+
+    public int getHandlerCount(GwtEvent.Type<?> eventKey) {
+      ArrayList<?> l = super.get(eventKey);
+      if (l == null) {
+        return 0;
+      } else {
+        return l.size();
+      }
+    }
+
+    public <H> void removeHandler(GwtEvent.Type<H> eventKey, H handler) {
+      ArrayList<H> l = get(eventKey);
+      if (l != null) {
+        l.remove(handler);
+      }
+    }
+
+    @SuppressWarnings("unchecked")
+    private <H> ArrayList<H> get(GwtEvent.Type<H> type) {
+      // This cast is safe because we control the puts.
+      return (ArrayList<H>) super.get(type);
+    }
    }

    /**
-   * Revives the given event.
+   * Default JavaScript handler registry. This is in the shared class but  
should
+   * never be called outside of a GWT runtime environment.
     *
-   * @param event the event
+   * The JsHandlerRegistry makes use of the fact that in the large  
majority of
+   * cases, only one or two handlers are added for each event type.  
Therefore,
+   * rather than storing handlers in a list of lists, we store then in a  
single
+   * flattened array with an escape clause to handle the rare case where  
we have
+   * more handlers then expected.
     */
-  public static void revive(GwtEvent<?> event) {
-    if (event.isLive() == false) {
-      event.revive();
+  private static class JsHandlerRegistry extends JavaScriptObject {
+
+    /**
+     * Required constructor.
+     */
+    protected JsHandlerRegistry() {
+    }
+
+    public final <H extends EventHandler> void addHandler(
+        HandlerManager manager, Type<H> type, H myHandler) {
+
+      // The base is the equivalent to a c pointer into the flattened  
handler
+      // data structure.
+      int base = type.hashCode();
+      int count = getCount(base);
+      boolean flattened = isFlattened(base);
+      H handler = myHandler;
+      // If we already have the maximum number of handlers we can store in  
the
+      // flattened data structure, store the handlers in an external list
+      // instead.
+      if ((count == EXPECTED_HANDLERS) & flattened) {
+        // As long as we are only adding to the end of a handler list,  
should
+        // not need to queue.
+        if (manager.firingDepth > 0) {
+          manager.enqueueAdd(type, myHandler);
+          return;
+        }
+        unflatten(base);
+        flattened = false;
+      }
+      if (flattened) {
+        setFlatHandler(base, count, handler);
+      } else {
+        setHandler(base, count, handler);
+      }
+      setCount(base, count + 1);
+    }
+
+    public final <H extends EventHandler> void fireEvent(GwtEvent<H>  
event) {
+      Type<H> type = event.getAssociatedType();
+      int base = type.hashCode();
+      int count = getCount(base);
+      boolean isFlattened = isFlattened(base);
+      if (isFlattened) {
+        for (int i = 0; i < count; i++) {
+          // Gets the given handler to fire.
+          H handler = getFlatHandler(base, i);
+          // Fires the handler.
+          event.dispatch(handler);
+        }
+      } else {
+        JavaScriptObject handlers = getHandlers(base);
+        for (int i = 0; i < count; i++) {
+          // Gets the given handler to fire.
+
+          H handler = getHandler(handlers, i);
+
+          // Fires the handler.
+          event.dispatch(handler);
+        }
+      }
+    }
+
+    public final <H extends EventHandler> H getHandler(GwtEvent.Type<H>  
type,
+        int index) {
+      int base = type.hashCode();
+      int count = getCount(base);
+      if (index >= count) {
+        throw new IndexOutOfBoundsException("index: " + index);
+      }
+      return getHandler(base, index, isFlattened(base));
      }
+
+    public final int getHandlerCount(GwtEvent.Type<?> eventKey) {
+      return getCount(eventKey.hashCode());
+    }
+
+    public final <H> void removeHandler(GwtEvent.Type<H> eventKey,
+        EventHandler handler) {
+      int base = eventKey.hashCode();
+
+      // Removing a handler is unusual, so smaller code is preferable then
+      // handling both flat and dangling list of pointers.
+      if (isFlattened(base)) {
+        unflatten(base);
+      }
+      boolean result = removeHelper(base, handler);
+      // Hiding this behind an assertion as we'd rather not force the  
compiler
+      // to
+      // have to include all handler.toString() instances.
+      assert result : handler + " did not exist";
+    }
+
+    private native int getCount(int index) /*-{
+      var count = this[index];
+      return count == null? 0:count;
+    }-*/;
+
+    private native <H extends EventHandler> H getFlatHandler(int base, int  
index) /*-{
+      return this[base + 2 + index];
+    }-*/;
+
+    private native <H extends EventHandler> H getHandler(int base, int  
index,
+        boolean flattened) /*-{
+      return flattened? this[base + 2 + index]: this[base + 1][index];
+    }-*/;
+
+    private native <H extends EventHandler> H getHandler(
+        JavaScriptObject handlers, int index) /*-{
+      return handlers[index];
+    }-*/;
+
+    private native JavaScriptObject getHandlers(int base) /*-{
+      return  this[base + 1];
+    }-*/;
+
+    private native boolean isFlattened(int base) /*-{
+      return this[base + 1] == null;
+    }-*/;
+
+    private native boolean removeHelper(int base, EventHandler handler)  
/*-{
+      // Find the handler.
+      var count = this[base];
+      var handlerList = this[base + 1];
+      var handlerIndex = -1;
+      for(var index = 0;  index < count; index++){
+        if(handlerList[index] == handler){
+          handlerIndex = index;
+          break;
+        }
+      }
+      if(handlerIndex == -1) {
+        return false;
+      }
+
+      // Remove the handler.
+      var last = count -1;
+      for(; handlerIndex < last; handlerIndex++){
+        handlerList[handlerIndex] = handlerList[handlerIndex+1]
+      }
+      handlerList[last] = null;
+      this[base] = this[base]-1;
+      return true;
+    }-*/;
+
+    private native void setCount(int index, int count) /*-{
+      this[index] = count;
+    }-*/;
+
+    private native void setFlatHandler(int base, int index, EventHandler  
handler) /*-{
+      this[base + 2 + index] = handler;
+    }-*/;
+
+    private native void setHandler(int base, int index, EventHandler  
handler) /*-{
+      this[base + 1][index] = handler;
+    }-*/;
+
+    private native void setHandlerList(int base, JavaScriptObject  
handlerList) /*-{
+      this[base + 1] = handlerList;
+    }-*/;
+
+    private native void unflatten(int base) /*-{
+      var handlerList = {};
+      var count = this[base];
+      var start = base + 2;
+       for(var i = 0; i < count;i++){
+         handlerList[i] = this[start + i];
+         this[start + i] = null;
+        }
+       this[base + 1] = handlerList;
+    }-*/;
    }

+  // Used to optimize the JavaScript handler container structure.
+  private static int EXPECTED_HANDLERS = 5;
+
+  private static final boolean useJs = GWT.isClient();
+
+  private static int index;
+
+  // Used to assign hash codes to gwt event types so they are easy to  
store in a
+  // js structure.
    static int createKeyIndex() {
      // Need to leave space for the size and the unflattened list if we end  
up
      // needing it.
@@ -59,12 +280,10 @@
      return index;
    }

-  // package protected to allow it to be used in JsHandlerRegistry
-  int firingDepth = 0;
-
+  private int firingDepth = 0;
    // Only one of JsHandlerRegistry and JavaHandlerRegistry are live at  
once.
-  private final JsHandlerRegistry javaScriptRegistry;
-  private final JavaHandlerRegistry javaRegistry;
+  private JsHandlerRegistry javaScriptRegistry;
+  private JavaHandlerRegistry javaRegistry;

    // source of the event.
    private final Object source;
@@ -82,11 +301,9 @@
     */
    public HandlerManager(Object source) {
      if (useJs) {
-      javaScriptRegistry = JsHandlerRegistry.create();
-      javaRegistry = null;
+      javaScriptRegistry = JavaScriptObject.createObject().cast();
      } else {
        javaRegistry = new JavaHandlerRegistry();
-      javaScriptRegistry = null;
      }
      this.source = source;
    }
@@ -94,7 +311,7 @@
    /**
     * Adds a handle.
     *
-   * @param <H> The type of handler.
+   * @param <H> The type of handler
     * @param type the event type associated with this handler
     * @param handler the handler
     * @return the handler registration, can be stored in order to remove the
@@ -102,16 +319,15 @@
     */
    public <H extends EventHandler> HandlerRegistration addHandler(
        GwtEvent.Type<H> type, final H handler) {
-
+
      /*
       * We used to keep the enqueue / dequeue entirely inside  
HandlerManager.
       * However, we found a 30% speed improvement in handler registration if
       * JsHandlerRegistry is allowed to make its own decision about  
queuing. Thus
-     * the funny code path here.
+     * the funny code path here.
       *
-     * No parallel optimization was made for removing handlers, as that
-     * rarely happens anyway, and is not a significant contributer to  
startup
-     * time.
+     * No parallel optimization was made for removing handlers, as that  
rarely
+     * happens anyway, and is not a significant contributer to startup  
time.
       */
      if (useJs) {
        javaScriptRegistry.addHandler(this, type, handler);
@@ -126,19 +342,6 @@
    }

    /**
-   * Clears all the handlers associated with the given type.
-   *
-   * @param type the type
-   */
-  public void clearHandlers(Type<?> type) {
-    if (useJs) {
-      javaScriptRegistry.clearHandlers(type);
-    } else {
-      javaRegistry.clearHandlers(type);
-    }
-  }
-
-  /**
     * Fires the given event to the handlers listening to the event's type.
     *
     * @param event the event
@@ -146,9 +349,9 @@
    // Final so we can manage buffering adds and removes without a subclass
    // throwing all our calculations off.
    public final void fireEvent(GwtEvent<?> event) {
-    // If it not live we should clear the source and make it live.
+    // If it not live we should revive it.
      if (event.isLive() == false) {
-      revive(event);
+      event.revive();
      }
      Object oldSource = event.getSource();
      event.setSource(source);
@@ -183,6 +386,9 @@
     * @return the given handler
     */
    public <H extends EventHandler> H getHandler(GwtEvent.Type<H> type, int  
index) {
+    assert index < getHandlerCount(type) : "handlers for " +  
type.getClass()
+        + " have size: " + getHandlerCount(type)
+        + " so do not have a handler at index:" + index;
      if (useJs) {
        return javaScriptRegistry.getHandler(type, index);
      } else {
@@ -223,6 +429,10 @@
     *
     * @param type the event type
     * @param handler the handler
+   * @deprecated We currently believe this method will not be needed after
+   * listeners are removed in GWT 2.0. If you have a use case for it after  
that
+   * time, please add your comments to issue
+   * http://code.google.com/p/google-web-toolkit/issues/detail?id=3102
     */
    public <H extends EventHandler> void removeHandler(GwtEvent.Type<H> type,
        final H handler) {
@@ -233,22 +443,21 @@
      }
    }

-  // Package protected so JsHandlerRegistry can call enqueueAdd.
-  <H extends EventHandler> void enqueueAdd(GwtEvent.Type<H> type,
-      final H handler) {
-    if (addQueue == null) {
-      addQueue = new ArrayList<Object>();
-      addQueue.add(type);
-      addQueue.add(handler);
-    }
-  }
-
    private <H extends EventHandler> void doRemove(GwtEvent.Type<H> type,
        final H handler) {
      if (useJs) {
        javaScriptRegistry.removeHandler(type, handler);
      } else {
        javaRegistry.removeHandler(type, handler);
+    }
+  }
+
+  private <H extends EventHandler> void enqueueAdd(GwtEvent.Type<H> type,
+      final H handler) {
+    if (addQueue == null) {
+      addQueue = new ArrayList<Object>();
+      addQueue.add(type);
+      addQueue.add(handler);
      }
    }


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

Reply via email to