blob: d80bd1b06d4474d0d9338281f43d9a263484bd97 [file] [log] [blame]
/*
* Copyright 2010 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.user.cellview.client;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Widget;
import java.util.HashSet;
import java.util.Set;
/**
* Standard implementation used by most cell based widgets.
*/
class CellBasedWidgetImplStandard extends CellBasedWidgetImpl {
/**
* The method used to dispatch non-bubbling events.
*/
private static JavaScriptObject dispatchNonBubblingEvent;
/**
* Dispatch an event through the normal GWT mechanism.
*/
private static native void dispatchEvent(
Event evt, Element elem, EventListener listener) /*-{
@com.google.gwt.user.client.DOM::dispatchEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/user/client/Element;Lcom/google/gwt/user/client/EventListener;)(evt, elem, listener);
}-*/;
/**
* Handle an event from a cell. Used by {@link #initEventSystem()}.
*
* @param event the event to handle.
*/
@SuppressWarnings("unused")
private static void handleNonBubblingEvent(Event event) {
// Get the event target.
EventTarget eventTarget = event.getEventTarget();
if (!Element.is(eventTarget)) {
return;
}
com.google.gwt.user.client.Element target = eventTarget.cast();
// Get the event listener.
EventListener listener = DOM.getEventListener(target);
while (target != null && listener == null) {
target = target.getParentElement().cast();
listener = (target == null) ? null : DOM.getEventListener(target);
}
// Fire the event.
if (listener != null) {
dispatchEvent(event, target, listener);
}
}
/**
* The set of non bubbling event types.
*/
private final Set<String> nonBubblingEvents;
public CellBasedWidgetImplStandard() {
// Initialize the set of non-bubbling events.
nonBubblingEvents = new HashSet<String>();
nonBubblingEvents.add("focus");
nonBubblingEvents.add("blur");
nonBubblingEvents.add("load");
nonBubblingEvents.add("error");
}
@Override
protected int sinkEvent(Widget widget, String typeName) {
if (nonBubblingEvents.contains(typeName)) {
// Initialize the event system.
if (dispatchNonBubblingEvent == null) {
initEventSystem();
}
// Sink the non-bubbling event.
Element elem = widget.getElement();
String attr = "__gwtCellBasedWidgetImplDispatching" + typeName;
if (!"true".equals(elem.getAttribute(attr))) {
elem.setAttribute(attr, "true");
sinkEventImpl(elem, typeName);
}
return -1;
} else {
return super.sinkEvent(widget, typeName);
}
}
/**
* Initialize the event system.
*/
private native void initEventSystem() /*-{
@com.google.gwt.user.cellview.client.CellBasedWidgetImplStandard::dispatchNonBubblingEvent = $entry(function(evt) {
@com.google.gwt.user.cellview.client.CellBasedWidgetImplStandard::handleNonBubblingEvent(Lcom/google/gwt/user/client/Event;)(evt);
});
}-*/;
/**
* Sink an event on the element.
*
* @param elem the element to sink the event on
* @param typeName the name of the event to sink
*/
private native void sinkEventImpl(Element elem, String typeName) /*-{
elem.addEventListener(typeName, @com.google.gwt.user.cellview.client.CellBasedWidgetImplStandard::dispatchNonBubblingEvent, true);
}-*/;
}