Explore Eclipse's embedded Rich Client Platform

Your mobile device wants Eclipse

Get an introduction to the embedded Rich Client Platform (eRCP). Learn about the various components that make up eRCP and get some examples on how to use them in your applications.

Share:

Chris Aniszczyk, Software Engineer, IBM, Software Group

Chris AniszczykChris Aniszczyk is a software engineer at IBM Lotus focusing on OSGi related development. He is an open source enthusiast at heart, and he works on the Gentoo Linux distribution and is a committer on a few Eclipse projects (PDE, ECF, EMFT). He's always available to discuss open source and Eclipse over a frosty beverage.



Uriel Liu (liukl@tw.ibm.com), Software Engineer, IBM, Software Group

Uriel LiuUriel Liu is a software developer at the IBM China Software Development Lab and works in WED client technology. He is also a committer on the eRCP project.



21 March 2006

Also available in Japanese

Background

The embedded Rich Client Platform (eRCP) came about as a way to bring the advancements of the Eclipse Rich Client Platform (RCP) and apply it to the embedded space.

The eRCP is made up of the following components:

  • Standard Widget Toolkit (eSWT) -- Core, Expanded and Mobile extensions
  • eJFace
  • eWorkbench
  • eUpdate

We will discuss each of these components and use code examples where appropriate.


eSWT

The embedded Standard Widget Toolkit (eSWT) is a subset of the well-known Java™ graphics tool kit, the Standard Widget Toolkit (SWT). It provides a set of controls, panels, and other widgets commonly used as building blocks of user interfaces (UIs). In addition to what was originally included in SWT, eSWT introduced a new component: mobile extensions (a jointly designed specification among IBM, Nokia, and Motorola), primarily targeted for mobile devices like PDAs and smart phones.

The design of eSWT is different from its cousin SWT in terms of platform-independence. SWT uses the platform-independent approach by trying to keep the native code as simple as possible to increase portability among operating systems. The problem is that portability and performance are competing issues, so eSWT decided on another approach: the Universal Graphics Layer (UGL), which still preserves the Java Native Interface (JNI) on the native tool kit implementation. But, instead of acting as a 1:1 JNI wrapper, UGL tries to keep the native implementation as close as possible, only requiring the information to callback through JNI. eSWT's approach sacrifices portability since the native tool kit completely depends on what graphics system is used, but this approach increases performance dramatically (a major concern in mobile devices).

There are three components included in eSWT (see Figure 1):

  • Core
  • Expanded
  • Mobile Extensions
Figure 1. eSWT UI tool kit packages
eSWT UI ToolKit

The core and expanded components are subsets of eSWT. The newly invented mobile extensions component is targeted at mobile devices. This kind of componentization allows for flexibility to configure what components should be included on the device, based on device capability and purpose. The core component is mandatory and contains the minimum functions required to run a basic application. The expanded and mobile extensions components are optional.

In the following sections, we will walk through each component, along with sample applications.

eSWT Core contains the fundamental UI elements, including low-level graphics, events, and basic widget infrastructure. Table 1 shows the classes in eSWT Core.

eSWT Core
Table 1. eSWT Core org.eclipse classes
swt.widgetsswt.graphicsswt.eventsswt.layoutswt.swt
ButtonColorControlEventFormLayoutSWT
CanvasDeviceDisposeEventFormDataSWTException
ComboFontFocusEventFormAttachmentSWTError
CompositeFontDataKeyEvent--
ControlFontMetricsMenuEvent--
DecorationsGCModifyEvent--
DialogImageMouseEvent--
DisplayImageDataPaintEvent--
EventPaletteDataSelectionEvent--
FileDialogPointShellEvent--
ItemRectangleTraverseEvent--
LabelResourceTypedEvent--
LayoutRGBVerifyEvent--
List----
Menu/MenuItem----
MessageBox----
ProgressBar----
Scrollable----
Scrollbar----
Shell----
Slider----
Synchronizer----
Text----
TypedListener----

eSWT Core example

Let's start with a complete eSWT program that creates a window that displays "HelloWorld from eSWT" on the application title bar. Then we'll add a few core controls (text, button, list). For layout, we'll use FormLayout and FormData. We'll also add SelectionListener on a button to bring up a message box. The complete code can be seen in Listing 1.

Listing 1: HelloWorld, eSWT style
01 public class HelloWorldeSWT {
02 
03   public static void main(String[] args) {
04     Display display = new Display();
05     final Shell shell = new Shell(display);
06 		
07     Text text = new Text(shell,SWT.SINGLE);
08     text.setText("This is a text");		
09     Button buttonleft = new Button(shell, SWT.PUSH);
10     buttonleft.setText("Left Push!");
11     Button buttonright = new Button(shell, SWT.PUSH);
12     buttonright.setText("Right Push!");
13     buttonright.addSelectionListener(new SelectionListener(){
14       public void widgetSelected(SelectionEvent e) {
15         MessageBox messageBox = new MessageBox(shell,
16           SWT.ICON_INFORMATION| SWT.YES | SWT.NO);
17         messageBox.setText("MessageBox");
18         messageBox.setMessage("Can you see me?");
19         messageBox.open();
20       }
21       public void widgetDefaultSelected(SelectionEvent e) {
22       }});
23     List list = new List(shell,SWT.MULTI|SWT.BORDER);
24     for (int i=0; i<5; i++) {
25 list.add("item "+i);
26     }
27     
28     shell.setText("HelloWorld from eSWT");
29     FormLayout layout = new FormLayout();
30     layout.spacing = 5;
31     layout.marginHeight = layout.marginWidth = 9;
32     shell.setLayout(layout);
33     
34     FormData textData = new FormData();
35     textData.top = new FormAttachment(0);
36     textData.left = new FormAttachment(0);
37     textData.right = new FormAttachment(90);
38     text.setLayoutData(textData);
39     
40     FormData buttonleftData = new FormData();
41     buttonleftData.top = new FormAttachment(text);
42     buttonleftData.left = new FormAttachment(0);
43     buttonleftData.right = new FormAttachment(40);
44     buttonleft.setLayoutData(buttonleftData);
45     
46     FormData buttonrightData = new FormData();
47     buttonrightData.top = new FormAttachment(text);
48     buttonrightData.left = new FormAttachment(buttonleft);
49     buttonright.setLayoutData(buttonrightData);
50     FormData listData = new FormData();
51     
52     listData.top = new FormAttachment(buttonleft);
53     list.setLayoutData(listData);
54     
55     shell.setSize(240,320);
56     shell.open();
57     
58     while (!shell.isDisposed()) {
59 if (!display.readAndDispatch())
60 	display.sleep();
61     }
62     display.dispose();
63   }

Figure 2 shows the application running on a Japanese edition PocketPC device. Once the user taps the Right Push! button, a message box will appear (as shown in Figure 3). eSWT utilizes the underlying native graphics library support to provide a consistent UI (a native application look and feel, rather than inventing a new look).

Figure 2. HelloWorld, eSWT style
HelloWorld, eSWT style
Figure 3. MessageBox with a native look and feel
MessageBox with a native look and feel

Example evaluation

It's worthwhile to give a line-by-line explanation of what we accomplished in Listing 1.

Lines 04-05:
We create a display and a shell. The shell sets the display as its parent to make it become a top-level window. Top-level windows are automatically maximized on the PocketPC platform for consistency. We created the shell with a final modifier because it's used in the SelectionListener later.
Lines 07-08:
Creates text and calls setText() to set the text string.
Lines 09-22:
We create two buttons. In the right button, we add a SelectionListener to bring up a simple message box.
Lines 23-26:
We create a list containing five items.
Line 28:
We set the text on the window's title bar.
Lines 29-53:
We use FormLayout, FormData, and FormAttachment to assist with the layout process.
Lines 55-56:
We set the shell size and open it. setSize() doesn't take effect for top-level window in this case (due to the device).
Lines 58-61:
Inside the while() loop, we establish an explicit loop to keep reading and dispatching user events from the operating system. If no more events are available, display.sleep() gets called and goes to sleep waiting for the next event.
Line 62:
The display.dispose() call at the last line of code explicitly disposes the display and releases any associated resources from the eSWT application.

eSWT Expanded is an optional component that contains more sophisticated UI elements and layouts. This functionality is commonly found on high-end mobile devices and PDAs. Table 2 shows a detailed list of classes in eSWT Expanded.

eSWT Expanded
Table 2. eSWT Expanded classes
org.eclipse.swt.widgetsorg.eclipse.swt.browserorg.eclipse.swt.dndorg.eclipse.swt.graphics
ColorDialogBrowserByteArrayTransferImageLoader
DirectoryDialogLocationEventClipboard-
FontDialogProgressEventTextTransfer-
TableStatusTextEventTransfer-
TreeTitleEventTransferData-

eSWT Expanded example

The Browser widget is a fancy control in eSWT Expanded. We will create a fully functional Web browser using the Browser control (see Listing 2). We'll allow users to set the URL, move forward, backward, or reload the page in this example.

Listing 2. Simple HTML browser
public class BrowserTest {
	
	static Button prev, reload, next, go;
	static Text url;
	static Browser browser;
	
	
	public static void main(String[] args) {
		final Display display = new Display();
		Shell shell = new Shell(display);
		
		//set window title and size
		shell.setText("SimpleBrowser");
		shell.setSize(240,320);
		
		//previous button
		prev = new Button(shell, SWT.PUSH);
		prev.setText("<<");
		prev.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				browser.back();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		//reload button
		reload = new Button(shell, SWT.PUSH);
		reload.setText("R");
		reload.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				browser.refresh();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		//next button
		next = new Button(shell, SWT.PUSH);
		next.setText(">>");;
		next.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				browser.forward();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		// url text
		url = new Text(shell, SWT.SINGLE|SWT.BORDER);
		url.setText("http://");
		
		// go button
		go = new Button(shell, SWT.PUSH);
		go.setText("GO");
		go.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				// TODO Auto-generated method stub
				browser.setUrl(url.getText());
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		// browser
		browser = new Browser(shell, SWT.NONE);
		browser.setUrl("http://www.google.com");
		
		FormLayout formLayout = new FormLayout();
		shell.setLayout(formLayout);
		formLayout.spacing = 1;
		formLayout.marginHeight = formLayout.marginWidth = 2;
		
		FormData prevData = new FormData();
		prevData.left = new FormAttachment(0);
		prevData.top = new FormAttachment(0);
		prevData.width = 16;
		prev.setLayoutData(prevData);
		
		FormData reloadData = new FormData();
		reloadData.left = new FormAttachment(prev);
		reloadData.top = new FormAttachment(0);
		reloadData.width = 16;
		reload.setLayoutData(reloadData);
		
		FormData nextData = new FormData();
		nextData.left = new FormAttachment(reload);
		nextData.top = new FormAttachment(0);
		nextData.width = 16;
		next.setLayoutData(nextData);
		
		FormData urlData = new FormData();
		urlData.left =  new FormAttachment(next);
		urlData.top = new FormAttachment(0);
		urlData.right = new FormAttachment(89);
		urlData.bottom = new FormAttachment(browser);
		url.setLayoutData(urlData);
		
		FormData goData = new FormData();
		goData.left = new FormAttachment(url);
		goData.top = new FormAttachment(0);
		goData.width = 24;
		go.setLayoutData(goData);
		
		FormData browserData = new FormData();
		browserData.top = new FormAttachment(prev);
		browserData.left = new FormAttachment(0);
		browserData.right = new FormAttachment(100);
		browserData.bottom = new FormAttachment(100);
		browser.setLayoutData(browserData);
		
		shell.open();
		while( !shell.isDisposed() ) {
			if( !display.readAndDispatch() )
				display.sleep();
		}
		display.dispose();	
	}
}

Figure 4 shows the simple browser running on PocketPC.

Figure 4. A simple browser
Simple browser

eSWT Mobile Extensions is an optional component that provides UI elements commonly found on myriad mobile devices. Table 3 shows classes in the eSWT Mobile Extensions component.

eSWT Mobile Extensions
Table 3. eSWT Mobile Extension classes
org.eclipse.ercp.swt.mobile
CaptionedControl
Command
ConstrainedText
DateEditor
HyperLink
Input
ListBox/ListBoxItem
MobileDevice/MovileDeviceEvent/MobileDeviceListener
MobileShell
MultiPageDialog
QueryDialog
Screen/ScreenEvent/ScreenListener
SortedList
TaskTip
TextExtension
TimedMessageBox

eSWT Mobile Extensions example

In this example, we'll use MobileShell instead of Shell to provide full-screen functionality. MobileShell contains a SortedList on the top and a ListView on the bottom. Commands are associated with the MobileShell for the user to change full-screen mode and with ListView to change layout density. The source is in Listing 3.

Listing 3. MobileExtension example
public class MobileExtensionSample implements IPlatformRunnable {
	public static void main(String[] args) {
		Display display = new Display();
		final MobileShell shell = new MobileShell(display);
		final Button resetButton = new Button(shell, SWT.PUSH|SWT.BORDER);
		
		Command shellCommand = new Command(shell, Command.SELECT,0);
		shellCommand.setText("FullScreen");
		shellCommand.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				shell.setFullScreenMode(true);
				resetButton.setVisible(true);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		resetButton.setText("Normal Screen");
		resetButton.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				shell.setFullScreenMode(false);
				resetButton.setVisible(false);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		// Create SortedList and add items
		SortedList sortedList = new SortedList(
				shell, 
				SWT.MULTI|SWT.V_SCROLL|SWT.BORDER, 
				SortedList.FILTER);
		sortedList.add("banana");
		sortedList.add("123");
		sortedList.add("12");
		sortedList.add("happyhour");
		sortedList.add("toobad");
		sortedList.add("youknowwhat");
		sortedList.add("yes");
		sortedList.add("886222333");
		
		// Create ListView and add items with image set
		Image[] image = new Image[4];
		image[0] = new Image(
				Display.getDefault(), 
				MobileExtensionSample.class.getResource\
				AsStream("/icons/sample.gif"));
		image[1] = new Image(
				Display.getDefault(), 
				MobileExtensionSample.class.getResource\
				AsStream("/icons/sample.gif"));
		image[2] = new Image(
				Display.getDefault(), 
				MobileExtensionSample.class.getResource\
				AsStream("/icons/sample.gif"));
		image[3] = new Image(
				Display.getDefault(), 
				MobileExtensionSample.class.getResource\
				AsStream("/icons/sample.gif"));
		
		final ListView lv = new ListView(shell, SWT.MULTI|SWT.BORDER);
		for (int i=0; i<20; i++) {
			lv.add("item"+i, image[i % 4]);
		}
		
		//Create a Command for setting low density
		Command lowCommand = new Command(lv, Command.SELECT, 0);
		lowCommand.setText("LOW");
		lowCommand.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				lv.setLayoutDensity(ListView.LOW);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		//Create a Command for setting high density
		Command midCommand = new Command(lv, Command.SELECT, 0);
		midCommand.setText("MEDIUM");
		midCommand.addSelectionListener(new SelectionListener(){
			public void widgetSelected(SelectionEvent e) {
				lv.setLayoutDensity(ListView.MEDIUM);
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}});
		
		FormLayout layout = new FormLayout();
		layout.spacing = 2;
		layout.marginHeight = layout.marginHeight = 2;
		shell.setLayout(layout);
		FormData sortedListData = new FormData();
		sortedListData.top = new FormAttachment(0);
		sortedListData.left = new FormAttachment(0);
		sortedListData.right = new FormAttachment(100);
		sortedListData.height = 120;
		sortedList.setLayoutData(sortedListData);
		FormData lvData = new FormData();
		lvData.top = new FormAttachment(sortedList);
		lvData.right = new FormAttachment(100);
		lvData.left = new FormAttachment(0);
		lvData.height = 130;
		lv.setLayoutData(lvData);
		FormData resetData = new FormData();
		resetData.top = new FormAttachment(lv);
		resetData.left = new FormAttachment(0);
		resetButton.setLayoutData(resetData);
		resetButton.setVisible(false);
		
		shell.setSize(240,320);
		shell.setText("Mobile Example");
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}

Figure 5 shows the result running on the PocketPC platform, and the full-screen mode is shown in Figure 6.

Figure 5. MobileShell with SortedList and ListView
MobileShell with SortedList and ListView
Figure 6. Full-screen MobileShell
Full-screen MobileShell

eJFace

eJFace is a platform-independent UI tool kit that depends on eSWT. eJFace provides a set of components and help utilities that simplify the development of eSWT-based applications (by wrapping the eSWT widgets), just like JFace does for SWT. In fact, eJFace is a strict subset of JFace, so it shares many similarities with its cousin. eJFace provides support for resource management, viewers, actions, and preference pages. There are tutorials in Resources covering JFace that can aid in your eJFace endeavors.

Viewer types available in eJFace:

  • CheckBoxTableViewer
  • CheckBoxTreeViewer
  • ComboViewer
  • ListViewer
  • TableViewer
  • TreeViewer

eWorkbench

eWorkbench allows eRCP applications to run simultaneously inside a single workbench window, similar to how it is in RCP. eWorkbench clients provide views for specific display scenarios, and eWorkbench automatically decides which view to use based on the mobile device in use. In eWorkbench, there is no concept of perspectives -- it can be considered that there is only one perspective applications share -- due to the applicability of the concept to embedded devices.

eWorkbench application development

There are a couple steps (familiar to RCP developers) for creating an eWorkbench application. The process is similar to creating an Eclipse RCP application using the concept of contributions.

Step 1: Define your views

eWorkbench lets you define three types of views that extend org.eclipse.ui.part.ViewPart. The normal view is required; the other two views are optional.

  • Normal: The default view
  • Large: The view used when the display is large
  • Status: The view used when the display is small

Now we create a sample view to use.

Listing 4. Sample view
public class DefaultView extends ViewPart {

	public void createPartControl(Composite parent) { 
	//create a composite with fill layout to host a label
	Composite composite = new Composite(parent, SWT.NONE);
	composite.setLayout(new FillLayout());

	// create a label 
	Label label = new Label(composite,SWT.CENTER); 
	label.setText("Hello eWorkbench!"); }

	public void setFocus() {}
}

Let Eclipse know we have views available by using the extension point mechanism (see Listing 5).

Listing 5. plugin.xml
<extension point="org.eclipse.ui.views"> 
	<view allowMultiple="false"
		category="org.eclipse.ercp.eworkbench.viewCategory" 
		class="com.ibm.ercp.application.views.DefaultView" 
		icon="icons/sample.gif"
		id="com.ibm.ercp.application.defaultView" 
		name="Sample DefaultView"/> 
</extension>

Step 2: Define your eWorkbench contribution

To be considered an eWorkbench application, you have to extend the org.eclipse.ercp.eworkbench.applications extension point and provide some information (see Listing 6 for an example):

  • id: The unique identifier that will represent your eWorkbench application
  • name: The name of your application (displayed in the workbench)
  • views: The views that your application will support (normal, large, support)
Listing 6. plugin.xml
<extension point="org.eclipse.ercp.eworkbench.applications">
	<application id="com.ibm.ercp.application" name=\
	"IBM Sample Application" singleton="true"> 
		<views normal="com.ibm.ercp.application.views.normal" />
	</application> 
</extension>

Figure 7 shows a side-by-side screenshot of the eWorkbench application list, followed by the launch of our sample application.

Figure 7. Hello, eWorkbench
Hello, eWorkbench

eUpdate

An advantage RCP offers is the ability to update plug-ins from a centralized server using the update manager interface. There are also features associated with the update manager, such as scheduled updates. Also, by using the Open Services Gateway Initiative (OSGi) and plug-ins, features can be installed dynamically. eRCP's answer to these advantages is eUpdate, which at the time of this writing is being developed heavily.

eUpdate provides the logic and UI for plug-ins wishing to contain update management capabilities. You can write your own update functionality with the help of these plug-ins or by using an eUpdate workbench application that provides a complete GUI for configuring update-related information.


Conclusion

This article introduced the embedded Rich Client Platform (eRCP) and its various components, providing example code that includes the sample eWorkbench application and other code listings as self-contained examples.


Download

DescriptionNameSize
Sample codeos-ecl-rcp-com.ibm.ercp.application_1.0.0.jar25KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Open source on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source
ArticleID=106104
ArticleTitle=Explore Eclipse's embedded Rich Client Platform
publish-date=03212006