Archive for December, 2009

Thanks for 2009

Thursday, December 31st, 2009

I would like to thank everyone for a fantastic 2009. I had a blast; privately as well as within the Java and Eclipse community.

I’m looking forward for 2010! :-)

 

Browser Tales – Java to JavaScript and vice versa with the SWT Browser Widget

Monday, December 21st, 2009

The SWT Browser widget makes it very easy to run HTML and JavaScript within Eclipse. This widget encapsulates a browser (system dependent) into a SWT widget.

The following screenshot is from the second example below. This example is based on a blog entry from Ian Bull and SWT Snippet 307.

swtexample

The following coding will be defining views for Eclipse RCP or via Eclipse plugins so I assume you are familiar with these topics.

Lets start with a simple example. Via the following coding you can setup a View in your Eclipse RCP and inject some JavaScript from your Java Code.

package de.vogella.javascript.simple;

import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
	public static final String ID = "de.vogella.javascript.simple.view";

	public void createPartControl(Composite parent) {
		// You need XULRunner installed to use this line
//		final Browser b = new Browser(parent, SWT.MOZILLA);
		final Browser b = new Browser(parent, SWT.NONE); // Uses IE on MS Windows
		b.setUrl("http://www.vogella.de");
		b.addProgressListener(new ProgressListener() {
			@Override
			public void completed(ProgressEvent event) {
				System.out.println("Page loaded");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				// Execute JavaScript in the browser
				b.execute("alert(\"JavaScript, called from Java\");");
			}
			@Override
			public void changed(ProgressEvent event) {
			}
		});
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
	}
}

The next example is a bit more complex (it is the example from the screenshot). This demonstarte how JavaScript can also call back to your Java Code.


package de.vogella.javascript.maps;

import java.io.File;

import org.eclipse.swt.SWT;
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.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.List;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {

	public static final String ID = "de.vogella.javascript.maps.view";
	private static List list;

	public void createPartControl(Composite parent) {
		SashForm sash = new SashForm(parent, SWT.HORIZONTAL);

		File f = new File("C:/temp/demofile/map.html");
		final Browser browser = new Browser(parent, SWT.NONE); // Uses IE on MS

		browser.addControlListener(new ControlListener() {
			public void controlResized(ControlEvent e) {
				// Use Javascript to set the browser width and height
				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) {
			}
		});

		 new CustomFunction (browser, "theJavaFunction");

		    Composite c = new Composite(sash, SWT.BORDER);
		    c.setLayout(new GridLayout(2, true));
		    Button b = new Button(c, SWT.PUSH);
		    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);
		        }
		    });

		    Button addMarker = new Button(c, SWT.PUSH);
		    addMarker.setText("Add Marker");
		    addMarker.addSelectionListener(new SelectionAdapter() {
		        public void widgetSelected(SelectionEvent e) {
		            browser.evaluate("createMarker();");

		        }
		    });
		    list = new List(c, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
		    GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
		    gridData.horizontalSpan=2;
		    list.setLayoutData(gridData);

		    browser.setUrl(f.toURI().toString());
//		    sash.setWeights(new int[] {4,1});
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {

	}

	 // Called by JavaScript
	 class CustomFunction extends BrowserFunction {
	    CustomFunctionData data = new CustomFunctionData(null);

		CustomFunction (Browser browser, String name) {
	        super (browser, name);
	        this.data.browser = browser;
	    }
	    public Object function (Object[] arguments) {
	        double lat = ((Double) arguments[0]).doubleValue();
	        double lng = ((Double) arguments[1]).doubleValue();
	        list.add(lat + " : " + lng);
	        data.browser.execute("document.getElementById('map_canvas').style.width= "+ (data.browser.getSize().x - 20) + ";");
	        data.browser.execute("document.getElementById('map_canvas').style.height= "+ (data.browser.getSize().y - 20) + ";");
	        return null;
	    }
	 }
}

The coding above reads a HTML (with some JavaScript code) file “C:/temp/demofile/map.html”. If you save it somewhere else you need to adjust line 28 in the coding above.

<!DOCTYPE html "-//W3C//DTD XHTML 1.0 Strict//EN" 

 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>

    <title>Google Maps JavaScript API Example</title>

    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=abcdefg&sensor=false"
            type="text/javascript"></script>
    <script type="text/javascript">

	var map;

    function initialize() {
      if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map_canvas"));
        map.setCenter(new GLatLng(37.4419, -122.1419), 13);
        map.setUIToDefault();

		// Callback to Java from JavaScript
	    theJavaFunction(map.getCenter().lat(), map.getCenter().lng());

      }

    }

    function createMarker(){
		var lat = map.getCenter().lat();
		var lng = map.getCenter().lng();
        var point = new GLatLng(lat,lng);
		var d=new Date();

		var marker = new GMarker(point, {draggable: true});

		GEvent.addListener(marker, "dragstart", function() {
			map.closeInfoWindow();
		});

		GEvent.addListener(marker, "dragend", function() {
		});

		map.addOverlay(marker);
		addMassiveData();

    }

	function addMassiveData(){
	// Add 10 markers to the map at random locations
		var bounds = map.getBounds();
        var southWest = bounds.getSouthWest();
        var northEast = bounds.getNorthEast();
        var lngSpan = northEast.lng() - southWest.lng();
        var latSpan = northEast.lat() - southWest.lat();
        for (var i = 0; i < 100; i++) {
         var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
               southWest.lng() + lngSpan * Math.random());
        map.addOverlay(new GMarker(point));
		}
	}

    </script>

  </head>

  <body onload="initialize()" >

    <div id="map_canvas" style="width: 600px; height: 400px"></div>

  </body>

</html>

This should demonstrate how easy you can integrate HTML and JavaScript into Eclipse. This is something the Eclipse E4 OpenSocial Gadget project also targets.

Check it out! The Open Social Gadgets with Eclipse E4 – Tutorial tries to give a little introduction.

 

Eclipse 3.6M4 – Tiny nice things

Saturday, December 12th, 2009

I personally believe that little things make a difference. Eclipse 3.6 is going to be great for new (and perhaps also for experienced) plugin and RCP developers.

Especially I like in the Eclipse 3.6M4 release:

-consoleLog included per default in a new launch configuration
RCP with a View

I believe the solution of Bug for -consoleLog will solve the most common problem with getting started for new Plugin / RCP developers. Also the update of the PDE RCP templates will hopefully guide new developers in using commands instead of actions.

The change in Bug for -consoleLog was also a community decision, which is a good example that Eclipse does consider user feedback.

Thanks to all involved parties and the Eclipse community for these changes. :-)

Update Unfortunately Mail Template was not part of M4.

 

Evolving EMF Models

Wednesday, December 9th, 2009

I recently wanted to evolve one of my EMF models. I started writting Java code for translating the EMF model and tweeted about this.

Seems like their are several very good options available for translating EMF models:

Even though ALT and COPE looked very interesting I always wanted to learn how to create my own XSLT style sheets (after all I’m a big Docbook user and David Carver was kind enough to took my XSLT Ant task as a starting point for the Ant task in the Eclipse XSL project).

In addition I believe XSLT can also be handy for me for other transformations in the future

Using XSLT was surprisingly easy. I believe one of the reason are the excellent Eclipse XSL Tools.

I only needed to add a few more hierarchies and to change a tag in my EMF model. In case you are interested I have describe the usage of XSLT for such simple cases here: XSLT with Eclipse XSL Tools – Tutorial.

Thanks to André Dietisheim (@adietisheim), Ian Bull (@irbull),David Carver (@kingargyle), BernhardMerkle (@BernhardMerkle) Michael Kay (@michaelhkay) and Jens von Pilgrim (@jensvp) for their help and advice via twitter.

 

Re-using the Eclipse proxy preference settings in your Eclipse RCP application

Tuesday, December 8th, 2009

The following demonstrates how to re-use the Eclipse proxy preferences in an Eclipse RCP application.

Create a project “de.vogella.rcp.net.proxy” and select the “RCP application with a view” as template.

Add the preferences command to your application. See Eclipse Preferences Tutorial for details.

Add the plugin “org.eclipse.ui.net” and “org.eclipse.core.net” as dependency to your plugin.

Run your plugin and open preferences.

proxy_settings

Fantastic! You already have the preference dialog.

Now change your view to the following.


package de.vogella.rcp.net.proxy;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

import org.eclipse.core.net.proxy.IProxyData;
import org.eclipse.core.net.proxy.IProxyService;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import org.osgi.framework.FrameworkUtil;
import org.osgi.util.tracker.ServiceTracker;

public class View extends ViewPart {
	public static final String ID = "de.vogella.rcp.net.proxy.view";
	private final ServiceTracker proxyTracker;

	public View() {
		proxyTracker = new ServiceTracker(FrameworkUtil.getBundle(
				this.getClass()).getBundleContext(), IProxyService.class
				.getName(), null);
		proxyTracker.open();
	}

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		StyledText text = new StyledText(parent, SWT.NONE);
		text.setText(readWebpage());
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
	}

	private String readWebpage() {
		BufferedReader in = null;
		StringBuffer sb = new StringBuffer();

		try {
			URI uri = new URI("http://www.vogella.de");
			IProxyService proxyService = getProxyService();
			IProxyData[] proxyDataForHost = proxyService.select(uri);

			for (IProxyData data : proxyDataForHost) {
				if (data.getHost() != null) {
					System.setProperty("http.proxySet", "true");
					System.setProperty("http.proxyHost", data.getHost());
				}
				if (data.getHost() != null) {
					System.setProperty("http.proxyPort", String.valueOf(data
							.getPort()));
				}
			}
			// Close the service and close the service tracker
			proxyService = null;

			URL url;

			url = uri.toURL();

			in = new BufferedReader(new InputStreamReader(url.openStream()));
			String inputLine;

			while ((inputLine = in.readLine()) != null) {
				// Process each line.
				sb.append(inputLine + "\n");
			}

		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

		}
		return sb.toString();

	}

	public IProxyService getProxyService() {
		return (IProxyService) proxyTracker.getService();
	}

	@Override
	public void dispose() {
		proxyTracker.close();
		super.dispose();
	}

}

If you run your application behind a firewall and if you have maintained the proxy correctly then the View should display the HTML code.

Hope this helps!

 

Eclipse Democamp Bay Area – OpenSocial Gadgets – Slides

Friday, December 4th, 2009

My slides from Eclipse Democamp Bay Area
about “Eclipse, the web and OpenSocial Gadgets” are available online. I tried to be coding heavy, so there are only a few slides.

Eclipse, the web and OpenSocial Gadgets

It was a fun event. I had the chance to talk to Mike Milinkovich and to plenty of Eclipse / Java hackers. :-)

Thanks to everybody for attending and Ashvin Radiya for organizing the event.

 

Defining menu entries (commands) at runtime in Eclipse RCP

Thursday, December 3rd, 2009

A common question I receive is how menu entries can be defined at runtime in an RCP application. The following gives an example how this can be done.

Create the RCP project “de.vogella.rcp.commands.runtimecommands” using the “Hello RCP” template.

Define a menu contribution. Maintain the class “de.vogella.rcp.commands.runtimecommands.DefineCommands” in this menu contribution.


<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>

   <extension
         id="application"
         point="org.eclipse.core.runtime.applications">
      <application>
         <run
               class="de.vogella.rcp.commands.runtimecommands.Application">
         </run>
      </application>
   </extension>
   <extension
         point="org.eclipse.ui.perspectives">
      <perspective
            name="RCP Perspective"
            class="de.vogella.rcp.commands.runtimecommands.Perspective"
            id="de.vogella.rcp.commands.runtimecommands.perspective">
      </perspective>
   </extension>
   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            class="de.vogella.rcp.commands.runtimecommands.DefineCommands"
            locationURI="menu:org.eclipse.ui.main.menu">
      </menuContribution>
   </extension>

</plugin>

Create the following class.

package de.vogella.rcp.commands.runtimecommands;

import org.eclipse.swt.SWT;
import org.eclipse.ui.menus.CommandContributionItem;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.menus.ExtensionContributionFactory;
import org.eclipse.ui.menus.IContributionRoot;
import org.eclipse.ui.services.IServiceLocator;

public class DefineCommands extends ExtensionContributionFactory {

	@Override
	public void createContributionItems(IServiceLocator serviceLocator,
			IContributionRoot additions) {
		CommandContributionItemParameter p = new CommandContributionItemParameter(
				serviceLocator, "",
				"org.eclipse.ui.file.exit",
				SWT.PUSH);
		p.label = "Exit the application";
		p.icon = Activator.getImageDescriptor("icons/alt_window_16.gif");

		CommandContributionItem item = new CommandContributionItem(p);
		item.setVisible(true);
		additions.addContributionItem(item, null);
	}

}

Run the example, your application should have the Exit command in the menu.

Thanks to Robert Einsle for the tip.

This description has also be added to my Eclipse command tutorial.