Package com.google.speedtracer.client.util.dom

Source Code of com.google.speedtracer.client.util.dom.MouseEventCapture$CaptureReleaser

/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.speedtracer.client.util.dom;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.events.client.Event;
import com.google.gwt.events.client.EventListener;
import com.google.gwt.events.client.EventListenerRemover;
import com.google.gwt.topspin.ui.client.MouseMoveEvent;
import com.google.gwt.topspin.ui.client.MouseUpEvent;
import com.google.gwt.topspin.ui.client.Window;

import java.util.ArrayList;
import java.util.List;

/**
* Utility class which allows simulation of Event Capture.
*/
public class MouseEventCapture {
  /**
   * Interface defining a handle to an object for releasing Capture.
   */
  interface CaptureReleaser {
    void release();
  }

  private static class RemoverImpl implements EventListenerRemover {

    private static native void removeImpl(String type, JavaScriptObject source,
        JavaScriptObject fn) /*-{
      source.removeEventListener(type, fn, false);
    }-*/;

    private final JavaScriptObject function;
    private final JavaScriptObject source;

    private final String type;

    public RemoverImpl(String type, JavaScriptObject source,
        JavaScriptObject listener) {
      this.type = type;
      this.source = source;
      this.function = listener;
    }

    public void remove() {
      removeImpl(type, source, function);
    }
  }

  /**
   * Current mouse capture owner.
   */
  private static MouseCaptureListener captureOwner;

  /**
   * These are the EventRemover objects for the hooks into Window that fire to
   * this class. We have exactly one listener per event type that supports
   * capture. When no UI component possesses capture (meaning that the
   * captureOwner stack is empty) we can disconnect these.
   */
  private static final List<EventListenerRemover> mouseRemovers = new ArrayList<EventListenerRemover>();

  /**
   * Capture happens on a per listener instance basis. We throw the
   * CaptureListener on the top of the capture stack and then provide a handle
   * to an object that can be used to
   *
   * @param listener
   */
  public static void capture(final MouseCaptureListener listener) {

    // Lazily initialize event hookups
    if (mouseRemovers.size() == 0) {
      registerEventCaptureHookups();
    }

    // Make sure to release the previous capture owner.
    if (captureOwner != null) {
      captureOwner.release();
    }

    captureOwner = listener;
    listener.setCaptureReleaser(new CaptureReleaser() {
      public void release() {
        // nuke the reference to this releaser in the listener (which should
        // still be the capture owner).
        listener.setCaptureReleaser(null);
        // nuke the captureOwner
        captureOwner = null;

        // Release the event listeners.
        for (int i = 0, n = mouseRemovers.size(); i < n; i++) {
          mouseRemovers.get(i).remove();
        }
        mouseRemovers.clear();
      }
    });
  }

  /**
   * Convenience method.
   *
   * @param event
   */
  public static native void stopPropagation(Event event) /*-{
    event.stopPropagation();
  }-*/;

  private static EventListenerRemover addCaptureEventListener(String type,
      JavaScriptObject source, EventListener listener) {
    return new RemoverImpl(type, source, addCaptureEventListenerImpl(type,
        source, listener));
  }

  private static native JavaScriptObject addCaptureEventListenerImpl(
      String type, JavaScriptObject source, EventListener listener) /*-{
    var f = function(event) {
      listener.
      @com.google.gwt.events.client.EventListener::handleEvent(Lcom/google/gwt/events/client/Event;)
      (event);
    };
    source.addEventListener(type, f, true);
    return f;
  }-*/;

  private static void forwardToCaptureOwner(Event event) {
    if (captureOwner != null) {
      captureOwner.handleEvent(event);
      stopPropagation(event);
    }
  }

  /**
   * TODO: Add hookups for the other event types. Currently I found capture
   * useful only for drag interactions.
   *
   * Registers for every event type on the Window.
   *
   * Capture should be lazily initialized, and then destroyed each time nothing
   * has capture (as to not cause useless event dispatch and handling for events
   * like moveevents).
   */
  private static void registerEventCaptureHookups() {

    // MOUSEMOVE
    mouseRemovers.add(addCaptureEventListener(MouseMoveEvent.NAME,
        Window.get(), new EventListener() {
          public void handleEvent(Event event) {
            forwardToCaptureOwner(event);
          }
        }));

    // MOUSEUP
    mouseRemovers.add(addCaptureEventListener(MouseUpEvent.NAME, Window.get(),
        new EventListener() {
          public void handleEvent(Event event) {
            forwardToCaptureOwner(event);
          }
        }));
  }
}
TOP

Related Classes of com.google.speedtracer.client.util.dom.MouseEventCapture$CaptureReleaser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.