Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I wrap a callback using JavaScript Overlay types (GWT)?

In the Display Object class, I have everything wrapped excepted the events. I can't not figure out the pattern and really need an example.

In JavaScript, you create a callback for the object like this:

displayObject.onPress = function(event) {
    $wnd.alert("object pressed");
}

I have wrapped the Mouse Event parameter:

public class MouseEventImpl extends JavaScriptObject {
    protected MouseEventImpl() {}

    public static native MouseEventImpl create(String type, int stageX, int stageY, DisplayObjectImpl target, JavaScriptObject nativeEvent) /*-{
        return new $wnd.MouseEvent(type, stageX, stageY, target, nativeEvent);
    }-*/;

    ...other methods excluded...
}

public class MouseEvent {
    private MouseEventImpl impl;

    public MouseEvent(String type, int stageX, int stageY, DisplayObject target, JavaScriptObject nativeEvent) {
        this.impl = MouseEventImpl.create(type, stageX, stageY, target.getOverlay(), nativeEvent);
    }

    ...other methods excluded...
}

The display object uses the same overlay pattern. How am I able to write a callback in java and pass it through to the JSO? Please provide an example if you can. :)

like image 509
LoneWolf Avatar asked Mar 07 '12 17:03

LoneWolf


1 Answers

Pre-post edit: I wrote up this answer without actually trying to see why you were trying to do this thing, under the assumption that you were using some non-browser event, which is already wrapped up pretty nicely, and if you want more data from the NativeEvent instance, you can write JSNI methods in your own classes to get access to it, or further subclass NativeEvent to add more methods and .cast() to your class. Add the handler to a widget using the Widget.addDomHandler method and the appropriate MouseEvent subclass to get the type instance.


In JavaScript, callbacks are just functions that will be invoked when something happens. Unless specifically specified where they are passed in, they will generally be called on the global context, not on a specific object instance.

var callback = function() { alert("callback called!"); };

// later, in something that consumes that callback:
callback();

To invoke a function on an instance (i.e. make it a method invocation), one can wrap that invocation in a function that doesn't need an instance:

var obj = {};
obj.name = "Me";
obj.whenSomethingHappens = function() {
    alert("my name is " + this.name);
};

// wont work, so commented out:
//var callback = obj.whenSomethingHappens;

// instead we wrap in a function
// this is making a closure (by closing over obj)
var callback = function() {
    obj.whenSomethingHappens();
};

// later, in something that consumes that callback:
callback();

In Java, one cannot refer specifically to a method (without reflection), but only to object instances. The easiest way to build a simple callback is to implement an interface, and the code that takes the callback takes an instance of the interface, and invokes the defined method.

GWT declares a Command interface for zero-arg functions, and a generic Callback<T,F> interface for cases that may pass or fail, with one generic arg for each option. Most event handlers in GWT just define one method, with specific data passed into that method.

We need to use all of this knowledge to pass Java instances, with a function to call, into JavaScript, and make sure they are invoked on the right instance. This example is a function that takes a Callback instance and using JSNI wraps a call to it JS.

// a callback that has a string for either success or failure
public native void addCallback(Callback<String, String> callback) /*-{
    var callbackFunc = function() {
        // obviously the params could come from the function params
        [email protected]::onSuccess(Ljava/lang/String;)("success!");
    };
    doSomethingWith(callbackFunc);//something that takes (and presumably calls) the callback
}-*/;

One last piece - to let GWT's error handling and scheduling work correctly, it is important to wrap the call back to java in $entry - that last line should really be

    doSomething($entry(callbackFunc));
like image 70
Colin Alworth Avatar answered Nov 10 '22 13:11

Colin Alworth