| /* |
| * Copyright 2012 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 $PACKAGE; |
| $IMPORTS |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.core.client.JavaScriptObject; |
| |
| import elemental.events.*; |
| import elemental.util.*; |
| import elemental.dom.*; |
| import elemental.html.*; |
| import elemental.svg.*; |
| import elemental.js.util.JsElementalBase; |
| |
| import java.util.Date; |
| |
| /** |
| * A base class containing all of the IDL interfaces which are shared |
| * between disjoint type hierarchies. Because of the GWT compiler |
| * SingleJsoImpl restriction that only a single JavaScriptObject |
| * may implement a given interface, we hoist all of the explicit |
| * mixin classes into a base JSO used by all of elemental. |
| */ |
| public class JsElementalMixinBase $EXTENDS $IMPLEMENTS { |
| protected JsElementalMixinBase() {} |
| $!MEMBERS |
| |
| private static class Remover implements EventRemover { |
| private final EventTarget target; |
| private final String type; |
| private final JavaScriptObject handler; |
| private final boolean useCapture; |
| |
| private Remover(EventTarget target, String type, JavaScriptObject handler, |
| boolean useCapture) { |
| this.target = target; |
| this.type = type; |
| this.handler = handler; |
| this.useCapture = useCapture; |
| } |
| |
| @Override |
| public void remove() { |
| removeEventListener(target, type, handler, useCapture); |
| } |
| |
| private static Remover create(EventTarget target, String type, JavaScriptObject handler, |
| boolean useCapture) { |
| return new Remover(target, type, handler, useCapture); |
| } |
| } |
| |
| // NOTES: |
| // - This handler/listener structure is currently the same in DevMode and ProdMode but it is |
| // subject to change. In fact, I would like to use: |
| // { listener : listener, handleEvent : function() } |
| // but Firefox doesn't properly support that form of handler for onEvent type events. |
| // - The handler property on listener can be removed when removeEventListener is removed. |
| private native static JavaScriptObject createHandler(EventListener listener) /*-{ |
| var handler = listener.handler; |
| if (!handler) { |
| handler = $entry(function(event) { |
| @elemental.js.dom.JsElementalMixinBase::handleEvent(Lelemental/events/EventListener;Lelemental/events/Event;)(listener, event); |
| }); |
| handler.listener = listener; |
| // TODO(knorton): Remove at Christmas when removeEventListener is removed. |
| listener.handler = handler; |
| } |
| return handler; |
| }-*/; |
| |
| private static class ForDevMode { |
| private static java.util.Map<EventListener, JavaScriptObject> handlers; |
| |
| static { |
| if (!com.google.gwt.core.client.GWT.isScript()) { |
| handlers = new java.util.HashMap<EventListener, JavaScriptObject>(); |
| } |
| } |
| |
| private static JavaScriptObject getHandlerFor(EventListener listener) { |
| if (listener == null) { |
| return null; |
| } |
| |
| JavaScriptObject handler = handlers.get(listener); |
| if (handler == null) { |
| handler = createHandler(listener); |
| handlers.put(listener, handler); |
| } |
| return handler; |
| } |
| |
| private native static JavaScriptObject createHandler(EventListener listener) /*-{ |
| var handler = $entry(function(event) { |
| @elemental.js.dom.JsElementalMixinBase::handleEvent(Lelemental/events/EventListener;Lelemental/events/Event;)(listener, event); |
| }); |
| handler.listener = listener; |
| return handler; |
| }-*/; |
| |
| private native static EventListener getListenerFor(JavaScriptObject handler) /*-{ |
| return handler && handler.listener; |
| }-*/; |
| } |
| |
| private static class ForProdMode { |
| private static JavaScriptObject getHandlerFor(EventListener listener) { |
| return listener == null ? null : createHandler(listener); |
| } |
| |
| private native static EventListener getListenerFor(JavaScriptObject handler) /*-{ |
| return handler && handler.listener; |
| }-*/; |
| } |
| |
| private static void handleEvent(EventListener listener, Event event) { |
| listener.handleEvent(event); |
| } |
| |
| private static EventListener getListenerFor(JavaScriptObject handler) { |
| return com.google.gwt.core.client.GWT.isScript() |
| ? ForProdMode.getListenerFor(handler) |
| : ForDevMode.getListenerFor(handler); |
| } |
| |
| private static JavaScriptObject getHandlerFor(EventListener listener) { |
| return com.google.gwt.core.client.GWT.isScript() |
| ? ForProdMode.getHandlerFor(listener) |
| : ForDevMode.getHandlerFor(listener); |
| } |
| |
| public native final EventRemover addEventListener(String type, EventListener listener, boolean useCapture) /*-{ |
| var handler = @elemental.js.dom.JsElementalMixinBase::getHandlerFor(Lelemental/events/EventListener;)(listener); |
| this.addEventListener(type, handler, useCapture); |
| return @elemental.js.dom.JsElementalMixinBase.Remover::create(Lelemental/events/EventTarget;Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;Z) |
| (this, type, handler, useCapture); |
| }-*/; |
| |
| public final EventRemover addEventListener(String type, EventListener listener) { |
| return addEventListener(type, listener, false); |
| } |
| |
| @Deprecated |
| public final void removeEventListener(String type, EventListener listener, boolean useCapture) { |
| final JavaScriptObject handler = getHandlerFor(listener); |
| if (handler != null) { |
| removeEventListener(this, type, handler, useCapture); |
| } |
| } |
| |
| @Deprecated |
| public final void removeEventListener(String type, EventListener listener) { |
| final JavaScriptObject handler = getHandlerFor(listener); |
| if (handler != null) { |
| removeEventListener(this, type, handler); |
| } |
| } |
| |
| private static native void removeEventListener(EventTarget target, String type, |
| JavaScriptObject handler, boolean useCapture) /*-{ |
| target.removeEventListener(type, handler, useCapture); |
| }-*/; |
| |
| private static native void removeEventListener(EventTarget target, String type, |
| JavaScriptObject handler) /*-{ |
| target.removeEventListener(type, handler); |
| }-*/; |
| |
| } |