com.google.gwt.event.dom.client.DomEvent.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.event.dom.client.DomEvent.java

Source

/*
 * Copyright 2009 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.gwt.event.dom.client;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HasHandlers;

/**
 * {@link DomEvent} is a subclass of {@link GwtEvent} that provides events that
 * underlying native browser event object as well as a subclass of {@link Type}
 * that understands GWT event bits used by sinkEvents().
 * 
 * @param <H> handler type
 * 
 */
public abstract class DomEvent<H extends EventHandler> extends GwtEvent<H> implements HasNativeEvent {

    /**
     * Type class used by dom event subclasses. Type is specialized for dom in
     * order to carry information about the native event.
     * 
     * @param <H> handler type
     */
    public static class Type<H extends EventHandler> extends GwtEvent.Type<H> {
        private DomEvent<H> flyweight;
        private String name;

        /**
         * This constructor allows dom event types to be triggered by the
         * {@link DomEvent#fireNativeEvent(com.google.gwt.dom.client.NativeEvent, HasHandlers)}
         * method. It should only be used by implementors supporting new dom events.
         * 
         * <p>
         * Any such dom event type must act as a flyweight around a native event
         * object.
         * </p>
         * 
         * @param eventName the raw native event name
         * @param flyweight the instance that will be used as a flyweight to wrap a
         *          native event
         */
        public Type(String eventName, DomEvent<H> flyweight) {
            this.flyweight = flyweight;

            // Until we have eager clinits implemented, we are manually initializing
            // DomEvent here.
            if (registered == null) {
                init();
            }
            registered.unsafePut(eventName, this);
            name = eventName;
        }

        /**
         * Gets the name associated with this event type.
         * 
         * @return the name of this event type
         */
        public String getName() {
            return name;
        }
    }

    private static PrivateMap<Type<?>> registered;

    /**
     * Fires the given native event on the specified handlers.
     * 
     * @param nativeEvent the native event
     * @param handlerSource the source of the handlers to fire
     */
    public static void fireNativeEvent(NativeEvent nativeEvent, HasHandlers handlerSource) {
        fireNativeEvent(nativeEvent, handlerSource, null);
    }

    /**
     * Fires the given native event on the specified handlers.
     * 
     * @param nativeEvent the native event
     * @param handlerSource the source of the handlers to fire
     * @param relativeElem the element relative to which event coordinates will be
     *          measured
     */
    public static void fireNativeEvent(NativeEvent nativeEvent, HasHandlers handlerSource, Element relativeElem) {
        assert nativeEvent != null : "nativeEvent must not be null";

        if (registered != null) {
            final DomEvent.Type<?> typeKey = registered.unsafeGet(nativeEvent.getType());
            if (typeKey != null) {
                // Store and restore native event just in case we are in recursive
                // loop.
                NativeEvent currentNative = typeKey.flyweight.nativeEvent;
                Element currentRelativeElem = typeKey.flyweight.relativeElem;
                typeKey.flyweight.setNativeEvent(nativeEvent);
                typeKey.flyweight.setRelativeElement(relativeElem);

                handlerSource.fireEvent(typeKey.flyweight);

                typeKey.flyweight.setNativeEvent(currentNative);
                typeKey.flyweight.setRelativeElement(currentRelativeElem);
            }
        }
    }

    // This method can go away once we have eager clinits.
    static void init() {
        registered = new PrivateMap<Type<?>>();
    }

    private NativeEvent nativeEvent;
    private Element relativeElem;

    @Override
    public abstract DomEvent.Type<H> getAssociatedType();

    public final NativeEvent getNativeEvent() {
        assertLive();
        return nativeEvent;
    }

    /**
     * Gets the element relative to which event coordinates will be measured.
     * If this element is <code>null</code>, event coordinates will be measured
     * relative to the window's client area.
     * 
     * @return the event's relative element
     */
    public final Element getRelativeElement() {
        assertLive();
        return relativeElem;
    }

    /**
     * Prevents the wrapped native event's default action.
     */
    public void preventDefault() {
        assertLive();
        nativeEvent.preventDefault();
    }

    /**
     * Sets the native event associated with this dom event. In general, dom
     * events should be fired using the static firing methods.
     * 
     * @param nativeEvent the native event
     */
    public final void setNativeEvent(NativeEvent nativeEvent) {
        this.nativeEvent = nativeEvent;
    }

    /**
     * Gets the element relative to which event coordinates will be measured.
     * 
     * @param relativeElem the event's relative element
     */
    public void setRelativeElement(Element relativeElem) {
        this.relativeElem = relativeElem;
    }

    /**
     * Stops the propagation of the underlying native event.
     */
    public void stopPropagation() {
        assertLive();
        nativeEvent.stopPropagation();
    }
}