Hi,
I'm a huge fan of Web Notifications (or Desktop Notifications as called by
Webkit/Chrome, see http://www.w3.org/TR/notifications/) so I started to hack
away a very rudimentary implementation of them in GWT. My implementation
consists basically of four components: A Notification class acting as a
wrapper around a NativeNotification class which extends JavaScriptObject.
For handling the "display" event (which is called "show" in the W3C spec) I
created a class DisplayEvent extending DomEvent<DisplayHandler>.
For creating a Notification I borrowed the mechanism used in the
experimental Storage API of GWT 2.3:
final Notification popup = Notification.createIfSupported("", "Title",
"Body");
This creates a Notification object wrapping a NativeNotification object.
Since I'm not THAT firm with DOM events and stuff I would like you to
comment on my implementation and if it is somewhat usable or leaking memory
or sth. Perhaps some day it's valid for inclusion into GWT itself since I've
not found any implementation on the web or in GWT's SVN trunk.
Please find attached my implementation.
Cheers!
Max
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors/**
* Created at 17 May 2011 19:33:39
* Created by Max Jonas Werner <[email protected]>
*
* (c) Copyright 2011 Just Software AG
*
* This file contains unpublished, proprietary trade secret information of
* just software AG. Use, transcription, duplication and
* modification are strictly prohibited without prior written consent of
* just software AG.
*/
package de.maxwerner.gwtplayground.client;
import com.google.gwt.event.dom.client.DomEvent;
/**
* Represents a native display event.
*/
public class DisplayEvent extends DomEvent<DisplayHandler> {
/**
* Event type for display events. Represents the meta-data associated with
* this event.
*/
private static final com.google.gwt.event.dom.client.DomEvent.Type<DisplayHandler> TYPE = new com.google.gwt.event.dom.client.DomEvent.Type<DisplayHandler>(
"display", new DisplayEvent());
/**
* Gets the event type associated with display events.
*
* @return the handler type
*/
public static Type<DisplayHandler> getType() {
return TYPE;
}
/**
* Protected constructor, use
* {@link DomEvent#fireNativeEvent(com.google.gwt.dom.client.NativeEvent, com.google.gwt.event.shared.HasHandlers)}
* to fire change events.
*/
protected DisplayEvent() {
}
@Override
public final Type<DisplayHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(DisplayHandler handler) {
handler.onDisplay(this);
}
}
/**
* Created at 17 May 2011 19:34:01
* Created by Max Jonas Werner <[email protected]>
*
* (c) Copyright 2011 Just Software AG
*
* This file contains unpublished, proprietary trade secret information of
* just software AG. Use, transcription, duplication and
* modification are strictly prohibited without prior written consent of
* just software AG.
*/
package de.maxwerner.gwtplayground.client;
import com.google.gwt.event.shared.EventHandler;
/**
*
*
* @author Max Jonas Werner <[email protected]>
*/
public interface DisplayHandler extends EventHandler {
public void onDisplay(DisplayEvent event);
}
/**
* Created at 17 May 2011 18:42:11
* Created by Max Jonas Werner <[email protected]>
*
* (c) Copyright 2011 Just Software AG
*
* This file contains unpublished, proprietary trade secret information of
* just software AG. Use, transcription, duplication and
* modification are strictly prohibited without prior written consent of
* just software AG.
*/
package de.maxwerner.gwtplayground.client;
import com.google.gwt.core.client.JavaScriptObject;
/**
*
*
* @author Max Jonas Werner <[email protected]>
*/
public class NativeNotification extends JavaScriptObject {
protected NativeNotification() {
}
public final native void show() /*-{
this.show();
}-*/;
public final native void cancel() /*-{
this.cancel();
}-*/;
}
/**
* Created at 17 May 2011 18:18:28
* Created by Max Jonas Werner <[email protected]>
*
* (c) Copyright 2011 Just Software AG
*
* This file contains unpublished, proprietary trade secret information of
* just software AG. Use, transcription, duplication and
* modification are strictly prohibited without prior written consent of
* just software AG.
*/
package de.maxwerner.gwtplayground.client;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.shared.HandlerRegistration;
public class Notification {
private NativeNotification _nativePopup;
private List<DisplayHandler> _displayEventHandlers;
protected JavaScriptObject jsHandler;
public static Notification createIfSupported(final String icon, final String title, final String body) {
return new Notification(icon, title, body);
};
public void show() {
_nativePopup.show();
}
public void cancel() {
_nativePopup.cancel();
}
public static native void requestPermission() /*-{
window.webkitNotifications.requestPermission();
}-*/;
public HandlerRegistration addDisplayHandler(final DisplayHandler handler) {
getDisplayEventHandlers().add(handler);
if (_displayEventHandlers.size() == 1) {
addDisplayEventHandler0(this);
}
return new HandlerRegistration() {
@Override
public void removeHandler() {
Notification.this.removeDisplayEventHandler(handler);
}
};
}
public void removeDisplayEventHandler(DisplayHandler handler) {
getDisplayEventHandlers().remove(handler);
// IMHO no need to remove event handler 0 because
// it will be removed when the widget is destroyed.
}
public void handleDisplayEvent(DisplayEvent event) {
if (!hasDisplayEventHandlers()) {
return;
}
UncaughtExceptionHandler ueh = GWT.getUncaughtExceptionHandler();
for (DisplayHandler handler : _displayEventHandlers) {
if (ueh != null) {
try {
handler.onDisplay(event);
} catch (Throwable t) {
ueh.onUncaughtException(t);
}
} else {
handler.onDisplay(event);
}
}
}
protected boolean hasDisplayEventHandlers() {
return _displayEventHandlers != null && !_displayEventHandlers.isEmpty();
}
protected native void addDisplayEventHandler0(final Notification notification) /*-{
[email protected]::jsHandler = $entry(function(
event) {
[email protected]::handleDisplayEvent(Lde/maxwerner/gwtplayground/client/DisplayEvent;)(event);
});
[email protected]::_nativePopup.ondisplay = [email protected]::jsHandler;
}-*/;
protected List<DisplayHandler> getDisplayEventHandlers() {
if (_displayEventHandlers == null) {
_displayEventHandlers = new ArrayList<DisplayHandler>();
}
return _displayEventHandlers;
}
private Notification(final String icon, final String title, final String body) {
createNative(icon, title, body);
}
private native void createNative(String icon, String title, String body) /*-{
[email protected]::_nativePopup = window.webkitNotifications
.createNotification("", "Notifier", "Tach");
}-*/;
}