Enhanced 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.

where am i Enhanced JavaScript Bridge, Eclipse Galileo Feature #9

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.

where am i 2 Enhanced JavaScript Bridge, Eclipse Galileo Feature #9

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&amp;v=2&amp;key=abcdefg&amp;sensor=false" type="text/javascript"><!--mce:0--></script>
    <script type="text/javascript"><!--mce:1--></script>

9 Responses to “Enhanced JavaScript Bridge, Eclipse Galileo Feature #9”

  1. Peter Kirschner says:

    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);”

  2. Wim Jongman says:

    I read about this feature but I did not grasp the reach of it. This is seriously cool! Great work Grant Gayed!

  3. Mark says:

    I like this feature too. Been using it with BIRT reports. :)

  4. zzeric says:

    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?

  5. shudong says:

    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)

  6. Ian Bull says:

    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.

  7. Lars Vogel says:

    @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.

  8. Mat Booth says:

    Hi,

    Is it possible to do this sort of thing in a single-sourced RCP/RAP application?

  9. mig says:

    Nice!
    A question, though. What does this line

    mean? Is it essential for the java code to communicate with the javascript in the html?

9 responses so far

Written by . Published in Categories: EclipseSource News, Planet Eclipse