on Jun 16th, 2009Enhanced JavaScript Bridge, Eclipse Galileo Feature #9
With Eclipse 3.5 — Galileo — just around the corner, I am counting down the top 10 features I’m most excited about. Number 9 on my list is the improved Java 2 Javascript bridge available in the SWT Browser widget. The SWT Browser now supports both calling Javascript from Java and calling Java from Javascript. Leveraging the growing number of “Web Widgets” (Google maps for example) in your rich client applications is now very easy.

By tightly integrating the contents of the browser with the application, you can properly respond to events and update the UI accordingly. For example, if you resize the window, the map can be resized and Google Maps updates the controls automatically. Also, when you click Where Am I, the location at the center of the map is recorded in an SWT List widget.

The code for this is quite simple and the SWT team has even provided snippet 307 and 308 to help you get started.
Kudos for this feature goes out to Grant Gayed.
The code for my example is below:
package org.eclipse.swt.snippets; import java.io.File; import java.io.IOException; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.BrowserFunction; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Shell; public class Snippet308 { static List list; static Browser browser; public static void main(String [] args) throws IOException { File f = new File("map.html"); Display display = new Display(); final Shell shell = new Shell(display); shell.setLayout(new FillLayout()); SashForm sash = new SashForm(shell, SWT.HORIZONTAL); try { browser = new Browser(sash, SWT.MOZILLA); browser.addControlListener(new ControlListener() { public void controlResized(ControlEvent e) { browser.execute("document.getElementById('map_canvas').style.width= "+ (browser.getSize().x - 20) + ";"); browser.execute("document.getElementById('map_canvas').style.height= "+ (browser.getSize().y - 20) + ";"); } public void controlMoved(ControlEvent e) { } }); } catch (SWTError e) { System.out.println("Could not instantiate Browser: " + e.getMessage()); display.dispose(); return; } new CustomFunction (browser, "theJavaFunction"); Composite c = new Composite(sash, SWT.BORDER); c.setLayout(new GridLayout(1, true)); Button b = new Button(c, SWT.PUSH); list = new List(c, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); b.setText("Where Am I ?"); b.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { double lat = ((Double) browser.evaluate("return map.getCenter().lat();")).doubleValue(); double lng = ((Double) browser.evaluate("return map.getCenter().lng();")).doubleValue(); list.add(lat + " : " + lng); } }); browser.setUrl(f.toURI().toString()); sash.setWeights(new int[] {4,1}); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); } static class CustomFunction extends BrowserFunction { Browser browser = null; CustomFunction (Browser browser, String name) { super (browser, name); this.browser = browser; } public Object function (Object[] arguments) { double lat = ((Double) arguments[0]).doubleValue(); double lng = ((Double) arguments[1]).doubleValue(); list.add(lat + " : " + lng); browser.execute("document.getElementById('map_canvas').style.width= "+ (browser.getSize().x - 20) + ";"); browser.execute("document.getElementById('map_canvas').style.height= "+ (browser.getSize().y - 20) + ";"); return null; } } }
The map.html file is here:
<script src="http://maps.google.com/maps?file=api&v=2&key=abcdefg&sensor=false" type="text/javascript"><!--mce:0--></script>
<script type="text/javascript"><!--mce:1--></script>Related posts:

Great! I was waiting for this. For those of you who have a portable Firefox or none installed.
Use “new Browser(sash, SWT.NONE);” instead of “new Browser(sash, SWT.MOZILLA);”
I read about this feature but I did not grasp the reach of it. This is seriously cool! Great work Grant Gayed!
I like this feature too. Been using it with BIRT reports.
I got several questions about this Javascript bridge:
1. On windows platform, when the browser was created as SWT.NONE, it relies on IE core. But on linux, which engine will it rely on?
2. It seems when the browser was created as SWT.MOZILLA, it doesn’t rely on FireFox but XULRunner, so how can I use the latest features of Firefox 3.5?
3. Can I use SWT without X11?
on windows platform…
I tried to create browser as SWT.MOZILLA and tried this feature,
however, it seems the program always crash…
but if I use SWT.NONE, it works fine
0SECTION THREADS subcomponent dump routine
NULL =================================
NULL
1XMCURTHDINFO Current Thread Details
NULL ———————-
3XMTHREADINFO “main” TID:0x4009B300, j9thread_t:0x003A5D94, state:R, prio=5
3XMTHREADINFO1 (native thread ID:0x12CC, native priority:0×5, native policy:UNKNOWN)
4XESTACKTRACE at org/eclipse/swt/internal/mozilla/XPCOM._JS_EvaluateUCScriptForPrincipals(Native Method)
4XESTACKTRACE at org/eclipse/swt/internal/mozilla/XPCOM.JS_EvaluateUCScriptForPrincipals(XPCOM.java:161)
4XESTACKTRACE at org/eclipse/swt/browser/Mozilla.execute(Mozilla.java:1777)
4XESTACKTRACE at org/eclipse/swt/browser/WebBrowser.createFunction(WebBrowser.java:327)
4XESTACKTRACE at org/eclipse/swt/browser/BrowserFunction.(BrowserFunction.java:86)
4XESTACKTRACE at org/eclipse/swt/browser/BrowserFunction.(BrowserFunction.java:75)
4XESTACKTRACE at com/ibm/html/browser/Main$CustomFunction.(Main.java:71)
I don’t know much about how this is handled on Windows, but I know you need to have XPCom properly setup for SWT.MOZILLA to work. There is some information in the FAQ http://www.eclipse.org/swt/faq.php#howusejavaxpcom. If this fails, you should try the SWT newsgroup.
@Ian Finally found the time to try this out. Cool example, thank you very much. Finally I have a tool to get the geocoordinates for any location.
@shudong I believe SWT.MOZILLA required XULrunner to be installed.
Hi,
Is it possible to do this sort of thing in a single-sourced RCP/RAP application?