10/24/2008

gwt-fabridge 1.2.1 released

With GWT 1.5 the JavaScriptObject has changed and caused some problems in gwt-fabridge 1.2. This release fixes these compatibility issues. If you work with GWT 1.5 please update your version of gwt-fabridge.

8/21/2008

gwt-fabridge 1.2 released

gwt-fabridge 1.2 updates the underyling version of gwt2swf to the current version 0.6 (upgrade to swfobject 2).

These changes will not affect your code except for the instantiation of SWFABridgeWidget. Thanks to changes in gwt2swf it's easier now. One way to do it is this:

//SWFABridgeWidget(String swfName, int width, int height, String bridgeName)
SWFABridgeWidget swfWidget = new SWFABridgeWidget("app.swf",400,400,"example");

Everything else stays the same.

Again, there are some problems with the fabridge.js. This time it's not the combination with gwt, but with swfobject that is causing problems. Gladly, the swfobject developers have found a way to get things working, but they had to modify the javascript file (read more about it here).

To fix a problem between fabridge and gwt I already had modified the file myself for gwt-fabridge. So I could not use the new version. Instead I have integrated the new changes into my modified version that is compatible with gwt (inline frame problem). Please do not use any other version of fabridge.js!

Let's hope that Adobe will someday integrate all these changes into the official version.

You can download gwt-fabridge here

12/11/2007

gwt-fabridge 1.1.1 released

You can download the new version here.

This release integrates new versions of gwt2swf and the fabridge. Rafal Malinowski has now updated gwt2swf with the changes necessary for gwt-fabridge. You can use his original library directly with gwt-fabridge.

gwt-fabridge itself has become more stable and convenient. You can now use addCompleteListener, addChangeListener, addClickListener and addOpenListener instead of the generic addEventListener. More importantly you can use JSNIUtils.convertArray(JavaScriptObject) to convert Javascript arrays to a Java ArrayList (this is convenient for Actionscript methods that return arrays).

The new version of fabridge from Devin Garner "allows access to the toString, statics, constants" (more info here). For now I have only integrated his first version, not his second. The latter did not work with my createASObject method. Thanks to Vasile Dumitrascu for the tip!

There still is no official version of FABridge, which fixes this problem. You have to change your version of fabridge.js accordingly or you have to use the version that comes with gwt-fabridge.

For code examples and more tips how to use the library, please read the previous post for 1.0

10/27/2007

GWT, Flex and the FABridge

Earlier this year Alistair Rutherford wrote:
A recent thread on the GWT forum got me interested in the possibility of interfacing GWT to Adobe Flex. Adobe have released a javascript to flex ‘bridge’ component called FABridge.
I have put together a (very) quick and dirty demo the two components talking to each other through the FABridge. This is far from finished but is does demonstrate the basic concepts.
At that time, the integration of FABridge didn't work in IE. I don't know, what exactly has changed since then. But FABridge is working now in IE. Since I am currently developing a GWT-Flex application anyhow, it was a small step to write a GWT-FABridge library for general purposes.

Here you can see this small library in action. It is now possible to access actionscript objects from GWT, get and set actionscript properties, invoke actionscript methods and even register GWT objects as Flex event listeners. The most important new classes are BridgeObject which wraps ActionscriptObjects (or to be precise the ASProxyObjects from FABridge) and SWFABridgeWidget, which extends the SWFWidget from Rafal Malinowski's great gwt2swf library. Gwt2swf wraps the SWFObject javascript library for GWT. This means, that gwt-fabridge can be used with multiple swf-files, just like gwt2swf.

Rafal Malinowski is planning to write his own extension SWFCallableWidget in the near future. SWFCallableWidget will be compatible with Actionscript 2 and will essentially do for GWT, what FABridge does for Javascript. Probably, this will be a better approach than mine, since wrapping the FABridge has created some redundancy. Be that as it may, for the moment gwt-fabridge surely is a better and easier method for controlling swfs from GWT, than hacking your own native methods from scratch.

Here is the library and the simple demo for download. I would be glad to get some comments (I am fairly new to GWT). Please note, that you have to access the files through a http:// server address (like http://localhost) because of the swf's security sandbox.

I have made some small changes in the gwt2swf classes. These changes are already in the gwt2swf cvs, but not in the current jar release, so please use the jar in the rar.

The same goes for the FABridge.js. I had to change one line, because FABridge could not be called from iframes and hence not from GWT (I needed several days to figure this out and nearly gave up). More about this here. I hope that this iframe-support will be added in the next version of FABridge.

Here are some code snippets which show you how to use the new classes (all code comes from the example class, in which I used the app.swf from Adobes example):

Creating a New SWFABridgeWidget

//Parameter for SWFObject
SWFParams params = new SWFParams("app.swf", new Integer(400),new Integer(400));

// set bridge name flashVar for FABridge
params.addVar("bridgeName", "example");
swfWidget = new SWFABridgeWidget(params);

// add swfWidget to RootPanel
RootPanel.get().add(swfWidget);

//show swf movie
swfWidget.show();

Adding an Initialization Callback

// add initialization listener
swfWidget.addInitializationListener(new IInitializationListener(){
public void onInitialization() {
// get width of the swf
Object width = swfWidget.root().getProperty("width").getContent();
Integer test = new Integer(width.toString());
Window.alert("Swf Initialized. Width: " + test);
}
});

Getting and Setting an Actionscript Property

// get check box
BridgeObject check = swfWidget.root().getObject("check");
// get check box status
Boolean status = new Boolean(check.getProperty("selected").getContent().toString());
// change check box status
check.setProperty("selected", !status.booleanValue());

How to register an Actionscript EventListener

// add click listener to flex button
swfWidget.root().getObject("button").addEventListener("click",
new ISWFListener() {

public void onSWFEvent(JavaScriptObject event) {
Window.alert("Hello, GWT! Love, Actionscript...");
}

});

// add change listener to flex slider
swfWidget.root().getObject("slider").addEventListener("change",
new ISWFListener() {
public void onSWFEvent(JavaScriptObject event) {
// wrap event object into bridge object
BridgeObject e = new BridgeObject(event);
// get slider value from event object
sliderLabel.setText(e.getProperty("value").getContent().toString());

}
});

How to create a new DataGrid

BridgeObject flexApp = swfWidget.root();

// create new data grid
BridgeObject grid = swfWidget.create("mx.controls.DataGrid");

// create first column
BridgeObject col1 = swfWidget.create("mx.controls.dataGridClasses.DataGridColumn");
col1.setProperty("dataField", "apples");

// create second column
BridgeObject col2 = swfWidget.create("mx.controls.dataGridClasses.DataGridColumn");
col2.setProperty("dataField", "oranges");

// add columns to data grid
JavaScriptObject jsArray = JSNIUtils
.convertArray(new JavaScriptObject[] {
col1.getJSContent(), col2.getJSContent() });
grid.setProperty("columns", jsArray);
grid.setProperty("width", 300);

// create first row
BridgeParameterObject row1 = new BridgeParameterObject();
row1.addProperty("apples", 12);
row1.addProperty("oranges", 32);

// create second row
BridgeParameterObject row2 = new BridgeParameterObject();
row2.addProperty("apples", 15);
row2.addProperty("oranges", 24);

// set dataProvider
grid.setProperty("dataProvider", JSNIUtils
.convertArray(new JavaScriptObject[] {
row1.getObject(), row2.getObject() }));

// add grid to panel
BridgeParameter params = new BridgeParameter();
params.addParameter(grid.getJSContent());
flexApp.getObject("panel").invokeMethod("addChild",params.getParameter());