vogella.de

Follow me on twitter
About Lars Vogel
Flattr this

Eclipse 4.0 Application Platform - Tutorial

Lars Vogel

Version 4.3

22.08.2010

Revision History
Revision 0.114.02.2009Lars Vogel
First version of Eclipse e4
Revision 0.2 - 3.916.02.2009 - 26.07.2010 Lars Vogel
bug fixes and enhancements
Revision 4.028.07.2010 Lars Vogel
Update to Eclipse 4.0 SDK
Revision 4.1 - 4.320.08.2010 - 22.08.2010 Lars Vogel
bug fixes and enhancements

Eclipse e4

This article gives an overview about the Eclipse 4.0 application platform which was created as part of the Eclipse e4 project. This tutorial is based on Eclipse 4.0 SDK.


Table of Contents

1. Eclipse 4.0 SDK and Eclipse e4
2. Installation
3. Known Issues
4. Your first e4 application via the wizard
4.1. Create project
4.2. Launch
5. The concept of the modeled workbench
5.1. The model
5.2. e4 WorkbenchModel Editor
5.3. Contributing to the e4 model
5.4. Merging model elements
5.5. Where to find the meta-model
6. Programming model
6.1. e4 runtime
6.2. Using Dependency Injection
6.3. IEclipseContext
6.4. Available services
6.5. Other Annotations
6.6. Example
7. Gettings started with the Todo application
7.1. Create project
7.2. Add dependencies
7.3. Create product configuration
7.4. Maintain Extension points
7.5. Create the initial workbench model
7.6. Run your application
7.7. Model access at runtime
8. Parts, Toolbar and Menu
8.1. Add a part to the application
8.2. Menu, Toolbar and command handler
8.3. Add a container
9. Styling your UI with css
9.1. Defining the stylesheet
9.2. Using the styling
9.3. Excurse: Styling Eclipse 4.0 SDK
10. Styling the todo application
10.1. Create stylesheet
10.2. Via property at startup
10.3. Theme Manager and switching styles
11. Services
11.1. Using services
11.2. Todo model and service interface
11.3. Todo model service
11.4. Using the model service
12. Using the selection service
13. More to come
14. Deployment
15. e4 and Eclipse RAP
16. Key classes in e4
17. Thank you
18. Questions and Discussion
19. Links and Literature
19.1. Source Code

1. Eclipse 4.0 SDK and Eclipse e4

Eclipse e4 project introduces a new set of technologies into the Eclipse platform that make Eclipse plugins and Eclipse RCP applications easier to write, more configurable and easier to reuse. The first release of the Eclipse e4 project is Eclipse 4.0 SDK. This article is based on the Eclipse 4.0 SDK.

The major enhancements in Eclipse e4 compared to Eclipse 3.x are:

  • The Eclipse workbench UI is described by an EMF model

  • The model is available at design- and runtime

  • Eclipse widgets can be styled via CSS style sheets

  • The existing Eclipse API's are re-worked to make them simpler

  • Eclipse e4 supports dependency injection for services into model components

  • The model elements are decoupled from their presentation via a Renderer Framework

The following description will start with the creation of a e4 based application via a wizard to allow people to get quickly started. It describes the modeled workbench concept and the new programming model which is based on annotations and dependency injection. The remaineder of the tutorial will be used to develop a e4 based todo application.

2. Installation

The Eclipse 4.0 SDK comes as a complete all-in-one download version, you find the latest version in http://download.eclipse.org/e4/sdk/ .

The e4 wizards are not included in the download, please use the update site "http://download.eclipse.org/e4/updates/2010" to install the additional tools via the Eclipse update manager .

You also need to install the CSS tools "Eclipse e4 CSS Support" and "Eclipse E4 UI CSS Source". This is required because the extension point "org.eclipse.e4.ui.css.swt.theme" requires the source bundle. Install also the "Eclipse e4 Model Workbench" and "Eclipse e4 Model Workbench Source" as the extension "org.eclipse.e4.workbench.model" requires the source feature. The reason for this is that the ".exsd" files for the extension points are part of the source features.

3. Known Issues

In some cases starting your application fails. In this case you have to manually adjust the launch configuration for this product. Select your product, right click it and select Run -> Run Configuration. Select the tab "Plugin" and press the button "Add required Plugin". Please comment on bug Bug report for incorrect launch config to get this resolved.

4. Your first e4 application via the wizard

This chapter guides you through the first creation of an e4 based application via the available wizard.

4.1. Create project

Eclipse e4 provides a wizard for creating e4 applications. Select File -> New -> Others -> e4 -> "e4 Application Project". Create the project "de.vogella.e4.rcp.wizard" based on the following screenshots.

4.2. Launch

Open your product file "de.vogella.e4.rcp.wizard.product". Switch to the "Overview" tab and launch your product.

5. The concept of the modeled workbench

5.1. The model

The Eclipse e4 workbench is modeled via Eclipse EMF . This model contains the graphical elements of the workbench, e.g. the parts (views, editors, menu bars) and some non-visual parts of the command framework, e.g. handlers, commands and keybindings. This model of the workbench is available at runtime, e.g. the programmer can access the running model and change it during runtime.

Eclipse 3.X had a different concept of the workbench, in Eclipse 3.X the Ui can handled via registries. Eclipse 4.0 models the workbench explicitely and is much more flexible compared to the Eclipse 3.6. For example you do not need to have perspectives and there is not an inherent distinction anymore between editors and views (both are called "Parts").

The e4 model consists out of the following packages:

  • application: main elements, like IEclipeContext, Application and the following subpackages

  • ui - contains general components, e.g. the Context, menus, toolbars, parts and other UI related model components

  • commands - definition of commands, handlers and keybinding

  • descriptor - used to store information about the ui components

5.2. e4 WorkbenchModel Editor

In e4 the application is based on a model. To open the model editor double-click on "Application.e4xmi" (or right click on it and select "Open-with"-> "e4 Workbenchmodel Editor".

5.3. Contributing to the e4 model

The base e4 application model is placed in an XMI file. This file is provided the e4 application via the parameter "applicationXMI" of the extension point "org.eclipse.core.runtime.products". This file is a standard XMI / text file. This file is read during startup from the application.

Model elements can also be supplied via the extension point "org.eclipse.e4.workbench.model". Model elements can be contributed via xmi (fragments) or via code (processors). These elements are merged into the application model. User changes are also recorded an saved independently.

The model information is read during startup and the contained information is to construct the workbench. The complete constructed model is available during runtime. Changes during runtime, e.g. the user moves a part, are written back to the model.

5.4. Merging model elements

The e4 model has three components which will be combined.

  1. The application defines in its "Application.e4xmi" file a base model (for example, main menu, perhaps UI elements like views that are always there, etc). This file changes over time as new versions of the application are being developed and released.

  2. Other plug-ins add to that model through our model extension point. Plug-ins can be installed and un-installed. This means that we have a model that results from combining the base model with these contributions. Of course, this means that there is an additional source of change to the model, but it is pretty clear how these contributions get merged into the model.

  3. While the application is running, the model objects can be changed. For example, views are closed, or menus/toolbars were customized, new views were opened, etc. These changes need to be persisted across sessions, and ideally even across updating plug-ins or the base application. The model delta are captured based on the difference to the real model, e.g. if you move View A to another place and move it back to the original position no delta is saved

The workbench model needs to the user changes and must be able to react to changes in the Application.e4xmi and the model contributions. The workbench models handles this as follows: On first startup, populate the model as described under 1 and 2. Changes during the session will be recorded as deltas, and we persist these deltas instead of the whole model when we shut down. Then, for subsequent startups, populate the model as described under 1 and 2 and then apply any persisted deltas from 3. If there are deltas that don't make any sense then skip them. The delta are applied to the model based on the ID's of the UI component.

5.5. Where to find the meta-model

The workbench model is defined in the plugin "org.eclipse.e4.ui.model.workbench" in the file "model/UIElements.ecore". The "UIElements.genmodel" defines among other things that interfaces for the workbench model starts with M.

6. Programming model

Eclipse e4 introduces a new programming model based on annotations and dependency injection. This new programming approach allows to avoid the usage of Singletons and emphasis loosely coupled components.

6.1. e4 runtime

The life cyle of every model element is controlled by the e4 runtime. The e4 runtime instanziated and destroys the Java objects which are referred to by model elements. The e4 runtimes scans every objects for certain annotations and based on the annotations is finds is performs certain actions. For example the @inject annotation indicates that the e4 framework should inject other Java Objects or OSGi Services into the Java Object for the model element. Otherannotations control which methods are called at certain points of the object life cycles, e.g. the @execute annotations describes which method should be called in a command handler is called.

6.2. Using Dependency Injection

Eclipse e4 introduces the concept of dependency injection for Eclipse plugin and RCP development. In every model elements you can automatically retrieve services and other objects via annotations. These services may be pre-defined by the Eclipse platform in the so-called IEclipseContext. This Context can be extended via additional OSGi services.

The following annotations are available.

Table 1. Annotations for dependency injection

AnnotationDescription
@javax.inject.InjectMark a field/constructor/method to be injected by the DI-Framework
@javax.inject.NamedDefine the key for the value which should be injected. By default the fully qualified class name is used.
@org.eclipse.e4.core.di.annotations.OptionalMark an inject value to be optional so if it can’t be found no error is thrown. This also ensures that the value is unset if the inject value is set to null.
@org.eclipse.e4.core.di.extensions.PreferenceMarked field/method-parameter will be filled with a value from the preference store

6.3. IEclipseContext

For the purpose of dependency injection Eclipse provides the IEclipseContext. IEclipseContext is a mechanism to find for a service or object request the fitting one. The IEclipseContext is hierarchical structured and every model elements has its own context. If a service cannot be found in a local context then the parent context is searched. OSGi services are part of the application context which is the highest level is the hierarchy. The application context is the interface to the OSGi services.

The IEclipseContext contains two types of elements: workbench model objects and service. The IEclipseContext is hierarchical and every Model objects that are themselves MContext instances will have their own content. This content will also include a reference to the Model object itself.

Services and model compoenents can be injected into a Eclipse e4 model component via the @Inject annotation. As said the content is hierarchical and the Eclipse dependency injection framework will first try to find the object in the content closest to the object and then move up to the next level. If the service cannot be found in the context then the framework will try to find the object as OSGi service.

See Eclipse e4 services Wiki for an overview of the available services. The usage of these services is also described Available services for dependency injection .

6.4.  Available services

Workbench Services follow usually with E*Service pattern. For example you have:

  • org.eclipse.e4.core.commands.ECommandService

  • org.eclipse.e4.core.commands.EHandlerService

  • org.eclipse.e4.workbench.modeling.EPartService

  • org.eclipse.e4.workbench.modeling.EModelService

  • org.eclipse.e4.workbench.modeling.ESelectionService

  • org.eclipse.e4.ui.bindings.EBindingService

  • org.eclipse.e4.ui.services.EContextService

Other available services are:

  • org.eclipse.e4.core.services.Adapter

  • org.eclipse.e4.core.services.StatusReporter

  • org.eclipse.e4.core.services.Logger

  • org.eclipse.e4.core.services.events.IEventBroker

  • org.eclipse.e4.workbench.ui.IPresentationEngine

  • org.eclipse.jface.window.IShellProvider

6.5. Other Annotations

Eclipse e4 uses annotations to indicate that certain behavior is expected from the framework. These annotations can indicate that certain values should be injected in model parts (see later the description of dependency injection), or are used to indicate that methods should be called at certain events. The following annotations stear workbench behavior; we will later see the annotations for dependency injections. are most important.

Table 2. Eclipse e4 annotations with no relationship to DI

AnnotationDescription
@org.eclipse.e4.core.di.annotations.ExecuteMarks a method in a command to be executed
@org.eclipse.e4.core.di.annotations.CanExecuteMark a method to be visited by the Command- Framework to check if a command is enabled
@org.eclipse.e4.workbench.ui.Persistannotates method. If used in a Part-POJO this method will be called when the workbench issues a save-request

6.6.  Example

The following shows a part (view). Via the @inject annotation it specifies that it requires object of type Logger, the IEcipseContext and a Composite. At runtime the e4 runtime will create an instance of this part. During this creation it checks of annotations and injects the required objects into the view if they are available.

				
package de.vogella.e4.rcp.first.parts;

import javax.inject.Inject;

import org.eclipse.e4.core.services.Logger;
import org.eclipse.e4.core.services.annotations.PostConstruct;
import org.eclipse.e4.core.services.context.IEclipseContext;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

public class View1 {
	
	@Inject private Logger logger;
	@Inject private IEclipseContext context;
	@Inject private Composite parent;
	
	// PostConstruct ensures that the dependency injection has been finished 
	// this this method is called 
	@PostConstruct
	public void init() {
		// If you don't inject the Logger you could alternatively 
		// get it via the IEclipseContext with the following statement
		// Logger log= (Logger) context.get(Logger.class.getName());
		System.out.println(context!=null);
		System.out.println(logger!=null);
		logger.info("UI will start to build");
		
		Label label = new Label(parent, SWT.NONE);
		label.setText("E4 is new");
		Text text = new Text(parent, SWT.NONE);
		text.setText("and different");
	}

}

			

7. Gettings started with the Todo application

In the following chapters we will create a basis for a Todo application with the e4 framework. The e4 wizard allows to create an e4 application but sometimes it is nice to understand the different parts by creating them one by one. This is explained in the following.

7.1. Create project

Create a new Plugin project "de.vogella.e4.todo", based on the Equinox runtime. Do not select "Generate an activator". Do not select a template.

Create the package "de.vogella.e4.todo".

7.2. Add dependencies

You need to add several dependencies to your MANIFEST.MF to be able to use the programming model of e4. We also add the SWT plugin which we later require.

  • org.eclipse.core.runtime

  • org.eclipse.e4.ui.workbench

  • org.eclipse.e4.ui.workbench.swt

  • org.eclipse.e4.ui.workbench.renderers.swt

  • org.eclipse.e4.ui.css.swt.theme

  • org.eclipse.e4.core.services

  • org.eclipse.e4.core.di

  • org.eclipse.e4.core.contexts

  • org.eclipse.e4.ui.services

  • javax.inject

  • javax.annotation

  • org.eclipse.equinox.ds

  • org.eclipse.equinox.event

  • org.eclipse.swt

The resulting "MANIFEST.MF" should look like the following. I have removed the version so that you should be able to copy the MANIFEST.MF.

				
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Todo
Bundle-SymbolicName: de.vogella.e4.todo
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: org.eclipse.core.runtime,
 org.eclipse.e4.ui.workbench,
 org.eclipse.e4.ui.workbench.swt,
 org.eclipse.e4.ui.workbench.renderers.swt,
 org.eclipse.e4.ui.css.swt.theme,
 org.eclipse.e4.core.services,
 org.eclipse.e4.ui.services,
 javax.inject,
 javax.annotation,
 org.eclipse.equinox.ds,
 org.eclipse.equinox.event,
 org.eclipse.swt,
 org.eclipse.e4.core.di,
 org.eclipse.e4.core.contexts

			

7.3. Create product configuration

Create a new product configuration "Todo.product".

Make sure you select "org.eclipse.e4.ui.workbench.swt.E4Application" as the application.

The result should look like the following.

Switch the "Dependencies" tab on your product file and add as dependency the plugin "de.vogella.e4.todo".

7.4. Maintain Extension points

During the product creation the extension point "org.eclipse.core.runtime.products" was autommatically added to the file "plugin.xml". Open this file and select the tab "Extensions". If the tab extension is hidden, select "Extensions" on the tab Overview. Verify that "org.eclipse.e4.ui.workbench.swt.E4Application" is selected as application.

Maintain the properties "applicationXMI" with the value "de.vogella.e4.todo/Application.e4xmi". The resulting plugin.xml should look like the following.

				
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension
         id="product"
         point="org.eclipse.core.runtime.products">
      <product
            application="org.eclipse.e4.ui.workbench.swt.E4Application"
            name="Todo">
         <property
               name="appName"
               value="Todo">
         </property>
         <property
               name="applicationXMI"
               value="de.vogella.e4.todo/Application.e4">
         </property>
      </product>
   </extension>

</plugin>

			

7.5. Create the initial workbench model

Create the file "Application.e4xmi" via File -> New -> Other -> Model -> Application Model.

This will create the file "Application.e4xmi" which is a representation on an EMF model. It describes a workbench model which currently has not even a window. You can create the file directly with the content from below.

				
<?xml version="1.0" encoding="ASCII"?>
<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmi:id="_CTN90JpoEd-Ew9wBM3AFmg" elementId="de.vogella.e4.todo.application"/>

			

Open "Application.e4xmi" with the "e4 WorkbenchModel Editor". This editor allows you to modify your "Application.e4xmi" file.

Select the entry window and add a new TrimmedWindow. Maintain the width, height and Label.

Your model now describes an application with an empty window.

7.6. Run your application

This should be sufficient to run your application. Create a launch configuration based for your product and run your application. The result should look like the following.

Congratulations. You have hand-crafted your first full featured Eclipse e4 application.

7.7. Model access at runtime

The model can be accessed at runtime. To see the current model include the plugin "org.eclipse.e4.tools.emf.liveeditor" and its dependencies into your launch configuration. You should then be able to open the model editor of your running application via the shortcut ALT+Shift+F9 depending on your version.

8. Parts, Toolbar and Menu

We will extend our minimal e4 application with parts, a menu and a toolbar. Remember that e4 does not make anymore a distinction between editors and views, both are parts.

8.1. Add a part to the application

To add a part to an Eclipse 4.0 application you add a model element to your application model "Application.e4xmi" and define the class which represents the part via the URL model property.

Create the following class. Notice that the TodoOverview.java code does not have any dependency to the Eclipse / OSGi framework. Just a simple POJO. By using the @inject annotation you are telling the Eclipse framework to inject a composite into the view.

				
package de.vogella.e4.todo.parts;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

public class TodoOverview {

	@Inject
	private Logger logger;
	@Inject
	private IEclipseContext context;

	// PostConstruct ensures that the dependency injection has been finished
	// this this method is called

	private final Composite parent;

	// e4 will inject the composite "parent" into the view
	@Inject
	public TodoOverview(Composite parent) {
		// the following is standard SWT Stuff
		this.parent = parent;
	}

	@PostConstruct
	public void buildUI() {
		logger.info("Start building UI");
		final GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		createLable("e4 Release");
		createText("Eclipse 4.0 SDK");
		createLable("Purpose");
		createText("Doing awesome stuff");

	}

	// Standard SWT Stuff
	private void createLable(String text) {
		Label label = new Label(parent, SWT.NONE);
		label.setText(text);
		GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		gridData.horizontalIndent = 20;
		label.setLayoutData(gridData);
	}

	// Standard SWT Stuff
	private void createText(String text) {
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		Text textField = new Text(parent, SWT.NONE);
		textField.setText(text);
		textField.setLayoutData(gridData);
	}

}

			

To add this view to your application open the "Application.e4xmi" in the editor, switch to controls under Windows, select "Part" and press add and maintain the values displayed below.

The URI describes the location of your view. The first part of this URI is the plugin and the second one the package. Make sure you don't have a typo here.

Run again your application you it should look like the following.

8.2. Menu, Toolbar and command handler

To add a menu entry or a toolbar entry you have to follow the same approach as with the Part. You have to create the model elements and these model elements must point to classes if required. Create the class which will handle the command. The @Execute annotation tells the framework which method should be called if this class is used as a handler.

				
package de.vogella.e4.todo.handler;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.workbench.IWorkbench;

public class ExitHandler {
	@Execute
	public void execute(IWorkbench workbench) {
		workbench.close();
	}
}


			

Tip

The following might be difficult to get right via the editor. You can copy and paste the resulting "Application.e4xmi" at the end of this description.

Select "Application.e4xmi" and add a menu and a toolbar. To add a menu select the window and press the right mouse button and select "Add main menu".

Add a menu with one direct and a toolbar and The result should look like the following screenshot.

Also add a trimbar.

				
<?xml version="1.0" encoding="ASCII"?>
<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_CTN90JpoEd-Ew9wBM3AFmg" elementId="de.vogella.e4.todo.application">
  <children xsi:type="basic:TrimmedWindow" xmi:id="_qVxQwJpoEd-Ew9wBM3AFmg" label="Window of Todo Application" width="640" height="400">
    <children xsi:type="basic:Part" xmi:id="_v7xy0JpvEd-Ew9wBM3AFmg" elementId="de.vogella.e4.todo" contributionURI="platform:/plugin/de.vogella.e4.todo/de.vogella.e4.todo.parts.TodoOverview" label="Todo OverView"/>
    <mainMenu xmi:id="_2JNDwJqCEd-Ew9wBM3AFmg" elementId="menu:org.eclipse.ui.main.menu">
      <children xsi:type="menu:Menu" xmi:id="_5B-nsJqCEd-Ew9wBM3AFmg" elementId="File" label="File">
        <children xsi:type="menu:DirectMenuItem" xmi:id="_3foEIJqCEd-Ew9wBM3AFmg" elementId="exit" label="Exit" contributionURI="platform:/plugin/de.vogella.e4.todo/de.vogella.e4.todo.handler.ExitHandler"/>
      </children>
    </mainMenu>
    <trimBars xmi:id="_HNmY4JqDEd-Ew9wBM3AFmg" elementId="toolbar:org.eclipse.ui.main.toolbar">
      <children xsi:type="menu:ToolBar" xmi:id="_rFbX0JqDEd-Ew9wBM3AFmg" elementId="main">
        <children xsi:type="menu:DirectToolItem" xmi:id="_sNP7gJqDEd-Ew9wBM3AFmg" elementId="Exit" label="Exit" contributionURI="platform:/plugin/de.vogella.e4.todo/de.vogella.e4.todo.handler.ExitHandler"/>
      </children>
    </trimBars>
  </children>
</application:Application>

			

If you run the application it should look like.

8.3. Add a container

You can either use a sash or a stack to display other containers or parts. A sash will divide the space between its container elements will a stack will only show the select element on top. We will now add another part and use a sash to show both parts.

Lets first add another part to our application. Add the following Java class.

				
package de.vogella.e4.todo.parts;
import javax.inject.Inject;

import org.eclipse.swt.SWT;
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.Label;

public class TodoDetails {

	private final Composite parent;

	// e4 will inject the composite "parent" into the view
	@Inject
	public TodoDetails(Composite parent) {
		// the following is standard SWT Stuff
		this.parent = parent;
		
		final GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		
		createLable("Release");
		Button button = new Button(parent, SWT.BORDER);
		button.setText("Do nothing");
	}

	// Standard SWT Stuff
	private void createLable(String text) {
		Label label = new Label(parent, SWT.NONE);
		label.setText(text);
		GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		gridData.horizontalIndent = 20;
		label.setLayoutData(gridData);
	}

	
}

			

Using the e4 editor add a sash container. The model editor allow you to set the model properties. Set the "orientation" to horizontal. Add two stacks to the sash. Use drag and drop to assign the first part to the first stack and then add the second part to the second stack. The result should look like.

The resulting "Application.e4xmi" should look like:

				
<?xml version="1.0" encoding="ASCII"?>
<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_CTN90JpoEd-Ew9wBM3AFmg" elementId="de.vogella.e4.todo.application">
  <children xsi:type="basic:TrimmedWindow" xmi:id="_qVxQwJpoEd-Ew9wBM3AFmg" label="Window of Todo Application" width="640" height="400">
    <children xsi:type="basic:PartSashContainer" xmi:id="_Pd4XkJqEEd-Ew9wBM3AFmg" elementId="sash" horizontal="true">
      <children xsi:type="basic:Part" xmi:id="_v7xy0JpvEd-Ew9wBM3AFmg" elementId="de.vogella.e4.todo" contributionURI="platform:/plugin/de.vogella.e4.todo/de.vogella.e4.todo.parts.TodoOverview" label="Todo OverView"/>
      <children xsi:type="basic:Part" xmi:id="_XpqGMJqEEd-Ew9wBM3AFmg" elementId="de.vogella.e4.tododetails" contributionURI="platform:/plugin/de.vogella.e4.todo/de.vogella.e4.todo.parts.TodoDetails" label="Todo Details"/>
    </children>
    <mainMenu xmi:id="_2JNDwJqCEd-Ew9wBM3AFmg" elementId="menu:org.eclipse.ui.main.menu">
      <children xsi:type="menu:Menu" xmi:id="_5B-nsJqCEd-Ew9wBM3AFmg" elementId="File" label="File">
        <children xsi:type="menu:DirectMenuItem" xmi:id="_3foEIJqCEd-Ew9wBM3AFmg" elementId="exit" label="Exit" contributionURI="platform:/plugin/de.vogella.e4.todo/de.vogella.e4.todo.handler.ExitHandler"/>
      </children>
    </mainMenu>
    <trimBars xmi:id="_HNmY4JqDEd-Ew9wBM3AFmg" elementId="toolbar:org.eclipse.ui.main.toolbar">
      <children xsi:type="menu:ToolBar" xmi:id="_rFbX0JqDEd-Ew9wBM3AFmg" elementId="main">
        <children xsi:type="menu:DirectToolItem" xmi:id="_sNP7gJqDEd-Ew9wBM3AFmg" elementId="Exit" label="Exit" contributionURI="platform:/plugin/de.vogella.e4.todo/de.vogella.e4.todo.handler.ExitHandler"/>
      </children>
    </trimBars>
  </children>
</application:Application>

			

Launch your application. It should look like:

9. Styling your UI with css

9.1. Defining the stylesheet

Eclipse e4 allows to style your UI widgets via CSS properties. This is similar to styling webpages with Cascading Style Sheets (CSS) .

To style an Eclipse 4.0 based application you first define a file which contains the styling information. Each UI widget can be addressed via the corresponding CSS class. Colors of widgets can defined via differences ways, e.g. the color white can be described via #white, rgb(255,255,2555) or #ffffff. The Eclipse wiki describes the details of the possible mapping in Eclipse Wiki Entry for SWT Mapping .

It is also to set a data tag for a specific SWT UI element and use this data tag in the CSS. For example you can set the tag for an label via:

				
Label label = new Label(parenet, SWT.NONE);
label.setData("org.eclipse.e4.ui.css.id","MyCSSTagForLabel");
			

This element can be addressed in the CSS via:

				
#MyCSSTagForLabel{
	color:#blue;
}
			

Styling supports gradients for the background color of UI controls. Linear and radial gradients are supported. To define a gradient use:

				
// linear gradient
background-color: gradient linear color_1 [color_2]* [percentage]*

// For example
background-color: gradient linear white black 
background-color: gradient linear white black blue
background-color: gradient linear white black 50%
background-color: gradient linear white black 50% 20%

// radial gradient
background-color: gradient linear color_1 color_2 [percentage]

// For example
background-color: gradient radial white black
background-color: gradient radial white black 50%

			

If you use the optional percentage in the definition then the color change will be done after the defined percentage.

9.2. Using the styling

After defining your style sheet you have to tell your application to use it. Here you have two different options.

  • Specify the property css on the product

  • Use the theme manager

The first approach is simple, you just define the property "applicationCSS" on the product in "plugin.xml" pointing to the file. This way your application will be styled at startup.

The second approach is more flexible but requires a bit more work. You define an extension for the extension point "org.eclipse.e4.ui.css.swt.theme" which basically defines an id and a pointer to the CSS file. You then you define the property "cssTheme" as a property in your product. The theme manager allow to switch styles at runtime and allow to register new themes.

9.3. Excurse: Styling Eclipse 4.0 SDK

You can use the ThemeManager to style the Eclipse 4.0 SDK itself. In the Eclipse 4.0 SDK the active theme is selected via Window -> Preferences -> General -> Appearance. These style sheets are stored in the plugin "org.eclipse.platform". This plugin_contains a folder /css which contains the style sheets for the individual platforms (os based).

You can also contribute a new theme via your own plugin. Create a simple plugin (no activator required) which has a single dependency to the plugin "org.eclipse.e4.ui.css.swt.theme". Add the extension point "org.eclipse.e4.ui.css.swt.theme" and add a theme to this extension point. Create a css file and point the theme to this file. If you export your plugin (including the css file )and put it into your Eclipse installation folder into dropin you should be able to select your new theme after restarting the Eclipse 4.0 SDK.

10. Styling the todo application

10.1. Create stylesheet

We first create the css file and then demonstrate both possible ways to use the css file. Create the folder "css" in your application and create the following file "default.css".

				
Label {
	font: Verdana 8px;
	color: black;
}

Composite Label {
	color: black;
}


Text {
	font: Verdana 8px;
}

Composite Text {
	background-color: white;
	color: black;
}

SashForm {
	background-color: #c1d5ef;
}


.MTrimBar {
	background-color: #e3efff #c1d5ef;
	color: white;
	font: Verdana 8px;
}

Shell {
    background-color: #e3efff #c1d5ef 60%;
}

			

10.2. Via property at startup

Add the property "applicationCSS" with the value "platform:/plugin/de.vogella.e4.todo/css/default.css"to your application in extension point "org.eclipse.core.runtime.products". This property points to the css file.

Run your application it should look like the following.

10.3. Theme Manager and switching styles

Remove the "applicationCSS" property again and create two extension for extension point "org.eclipse.e4.ui.css.swt.theme".

Add the "cssTheme" parameter to your product.

				
package de.vogella.e4.todo.handler;

import javax.inject.Named;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;
import org.eclipse.e4.ui.workbench.IWorkbench;


public class ThemeSwitchHandler {
	@Execute
	public void switchTheme(IThemeEngine engine) {
		engine.setTheme("de.vogella.e4.todo.redtheme", true);
	}
}

			

Create the following file "css/red.css".

				
CTabItem, ToolBar, Button, CBanner, CoolBar {
	font-size: 9;
	background-color: red;
}


			

Add the menu entry to your application.

				
<?xml version="1.0" encoding="ASCII"?>
<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2008/UIModel" xmi:id="org.eclipse.e4.ide.application" id="org.eclipse.e4.ide.application">
  <children xsi:type="application:Window" xmi:id="_m2gAMSXKEd-_CYGF7uzu5g" id="Window" width="400" height="380">
    <children xsi:type="application:PartSashContainer" xmi:id="_5WbB4DShEd-GJIPgLgXKaw" id="_5WbB4DShEd-GJIPgLgXKaw" horizontal="true">
      <children xsi:type="application:PartStack" xmi:id="_-V9zIDSjEd-GJIPgLgXKaw" id="_-V9zIDSjEd-GJIPgLgXKaw">
        <children xsi:type="application:Part" xmi:id="_KSCOcDSiEd-GJIPgLgXKaw" id="_KSCOcDSiEd-GJIPgLgXKaw" URI="platform:/plugin/de.vogella.e4.rcp.css/de.vogella.e4.rcp.css.parts.View1" label="View1"/>
        <children xsi:type="application:Part" xmi:id="_KSCOcDSiEd-GJIPgLgXKaw" id="_KSCOcDSiEd-GJIPgLgXKaw" URI="platform:/plugin/de.vogella.e4.rcp.css/de.vogella.e4.rcp.css.parts.View2" label="View2"/>
      </children>
    </children>
    <mainMenu xmi:id="menu:org.eclipse.ui.main.menu" id="menu:org.eclipse.ui.main.menu">
      <children xsi:type="application:MenuItem" xmi:id="_3vOREzSVEd-GJIPgLgXKaw" id="_3vOREzSVEd-GJIPgLgXKaw" label="File">
        <children xsi:type="application:DirectMenuItem" xmi:id="de.vogella.e4.rcp.css.handlers.ReSkinnerHandler" id="de.vogella.e4.rcp.css.handlers.ReSkinnerHandler" URI="platform:/plugin/de.vogella.e4.rcp.css/de.vogella.e4.rcp.css.handlers.ReSkinnerHandler" label="Change CSS Style"/>
        <children xsi:type="application:DirectMenuItem" xmi:id="_nXksIDSgEd-GJIPgLgXKaw" id="_nXksIDSgEd-GJIPgLgXKaw" URI="platform:/plugin/de.vogella.e4.rcp.css/de.vogella.e4.rcp.css.handlers.QuitHandler" label="Exit"/>
      </children>
    </mainMenu>
  </children>
</application:Application>

			

If you run your application you should be able to select the "Themes" and switch your application to a red style.

11. Services

11.1. Using services

As explained earlier you can use DI to inject your own OSGi services into your model elements. This removes the need for you to create your own singletons. In the following we will use declarative services to define a service which maintains our current todo items. You could use other approaches but declarative services are a simple way to creating services.

A service in OSGi is defined by a standard Java class or interface. It is common practice to define the service via a bundle which only contains the interface definition. This allows to change the implementation of the service via a different bundle.

11.2. Todo model and service interface

Create a plugin project "de.vogella.e4.todo.model" which will contains the model and the definition of the service interface. Create also the package "de.vogella.e4.todo.model". Do not use a template. You do not need an activator. Select ""and the "Runtime" tab. Add "de.vogella.e4.todo.model" to the exported packages.

First create this simple data model.

				
package de.vogella.e4.todo.model;

public class Todo {
	private String summary;
	private String description;
	
	public Todo(String summary) {
		this.summary = summary;
	}
	
	public Todo(String summary, String description){
		this.summary = summary;
		this.description = description;
		
	}
	
	public String getSummary() {
		return summary;
	}
	public void setSummary(String summary) {
		this.summary = summary;
	}
	public String getDescription() {
		return description;	}
	public void setDescription(String description) {
		this.description = description;
	}
	
	
}

			

Create the following interface "ITodoModel".

				
package de.vogella.e4.todo.model;

import java.util.List;

public interface ITodoModel {
	List<Todo> getTodos();
}

			

11.3. Todo model service

Create a plugin project "de.vogella.e4.todo.model.servicemock"andthe package "de.vogella.e4.todo.model.servicemock". Do not use a template. You do not need an activator. Add "de.vogella.e4.todo.model" as a dependency. Also set the overview tab "MANIFEST.MF" and set the flag "Activate this plugin when one of its classed id loaded".

Create the Folder "OSGI-INF" in your project. Select the new folder, right-click on it and select New -> Other -> Plug-in Development -> Component Definition. Create the file with the following content. For details on creating DS Services please see OSGi Tutorial .

				
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="de.vogella.e4.todo.model">
   <implementation class="de.vogella.e4.todo.model.servicemock.TodoMockModel"/>
   <service>
      <provide interface="de.vogella.e4.todo.model.ITodoModel"/>
   </service>
</scr:component>

			

Create the implementation class for this service.

				
package de.vogella.e4.todo.model.servicemock;

import java.util.ArrayList;
import java.util.List;

import de.vogella.e4.todo.model.ITodoModel;
import de.vogella.e4.todo.model.Todo;

public class TodoMockModel implements ITodoModel {

	@Override
	public List<Todo> getTodos() {
		List<Todo> todos = new ArrayList<Todo>();
		Todo todo = new Todo("Write more about e4");
		todos.add(todo);	
		todo = new Todo("Android", "Write a widget.");
		todos.add(todo);	
		return todos;
	}

}

			

Also make sure that the entry "Service-Component: OSGI-INF/component.xml" is available in "MANIFEST.MF".

				
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Servicemock
Bundle-SymbolicName: de.vogella.e4.todo.model.servicemock
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Require-Bundle: de.vogella.e4.todo.model;bundle-version="1.0.0"
Service-Component: OSGI-INF/component.xml

			

11.4. Using the model service

Add the two new bundles to your runtime configuration and add a dependency to "de.vogella.e4.todo.model" in the plugin "de.vogella.e4.todo". Change your view so that the new services gets injected into your view. Currently we will just verfify that the service was injected by displaying the total number of todos.

				
package de.vogella.e4.todo.parts;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import de.vogella.e4.todo.model.ITodoModel;

public class TodoOverview {

	@Inject
	private Logger logger;
	@Inject
	private IEclipseContext context;
	@Inject 
	private ITodoModel model;

	// PostConstruct ensures that the dependency injection has been finished
	// this this method is called

	private final Composite parent;

	// e4 will inject the composite "parent" into the view
	@Inject
	public TodoOverview(Composite parent) {
		// the following is standard SWT Stuff
		this.parent = parent;
	}

	@PostConstruct
	public void buildUI() {
		logger.info("Start building UI");
		final GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		createLable("Number of Todo entries:");
		createText(String.valueOf(model.getTodos().size()));

	}

	// Standard SWT Stuff
	private void createLable(String text) {
		Label label = new Label(parent, SWT.NONE);
		label.setText(text);
		GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		gridData.horizontalIndent = 20;
		label.setLayoutData(gridData);
	}

	// Standard SWT Stuff
	private void createText(String text) {
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		Text textField = new Text(parent, SWT.NONE);
		textField.setText(text);
		textField.setLayoutData(gridData);
	}

}

			
			

12. Using the selection service

Eclipse e4 provides several services which can be used in your RCP application. For example the selection service. A client can get the selection service via @Inject ESelectionService and the set the selection. The consumer simple defines a method with a named parameter (IServiceConstants.ACTIVE_SELECTION) and a type. The e4 framework will make sure that selections are only injected if they have the fitting type.

We will now create a tree on the TodoOverview part which will display the Todos. Add "org.eclipse.jface" to the dependencies in "de.vogella.e4.todo".

We will display the Todo in a Eclipse JFace Tree. Create the following content provider.

			
package de.vogella.e4.todo.provider;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;

import de.vogella.e4.todo.model.ITodoModel;

public class TodoContentProvider implements ITreeContentProvider {

	private ITodoModel model;

	@Override
	public void dispose() {
	}

	@Override
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		this.model = (ITodoModel) newInput;
	}

	@Override
	public Object[] getElements(Object inputElement) {
		return model.getTodos().toArray();
	}

	@Override
	public Object[] getChildren(Object parentElement) {
		return null;
	}

	@Override
	public Object getParent(Object element) {
		return null;
	}

	@Override
	public boolean hasChildren(Object element) {
		return false;
	}

}

		

Change the TodoOvervier.java to the following. This class will aquire the selection service and set it once the user selects a value in the tree.

			
package de.vogella.e4.todo.parts;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import de.vogella.e4.todo.model.ITodoModel;
import de.vogella.e4.todo.model.Todo;
import de.vogella.e4.todo.provider.TodoContentProvider;

public class TodoOverview {

	@Inject ESelectionService selectionService;
	@Inject
	private Logger logger;
	@Inject 
	private ITodoModel model;

	// PostConstruct ensures that the dependency injection has been finished
	// this this method is called

	private final Composite parent;
	private TreeViewer viewer;

	// e4 will inject the composite "parent" into the view
	@Inject
	public TodoOverview(Composite parent) {
		// the following is standard SWT Stuff
		this.parent = parent;
	}

	@PostConstruct
	public void buildUI() {
		logger.info("Start building UI");
		
		final GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		
		createLable("Number of Todo entries:");
		createText(String.valueOf(model.getTodos().size()));
		
		viewer = new TreeViewer(parent);
		viewer.setLabelProvider(new ColumnLabelProvider(){
			@Override
			public String getText(Object element) {
				return ((Todo) element).getSummary();
			}
		});
		
		viewer.setContentProvider(new TodoContentProvider());
		viewer.setInput(model);
		GridData data = new GridData();
		data.horizontalSpan=2;
		viewer.getControl().setLayoutData(data);
		viewer.addSelectionChangedListener(new ISelectionChangedListener() {
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
				selectionService.setSelection(selection.getFirstElement());
			}
		});
	
		

	}

	// Standard SWT Stuff
	private void createLable(String text) {
		Label label = new Label(parent, SWT.NONE);
		label.setText(text);
		GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		gridData.horizontalIndent = 20;
		label.setLayoutData(gridData);
	}

	// Standard SWT Stuff
	private void createText(String text) {
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		Text textField = new Text(parent, SWT.NONE);
		textField.setText(text);
		textField.setLayoutData(gridData);
	}

}

			
		

Change the TodoDetails.java to the following. This class defines the method setTodo which gets as a named parameter the current selection, if this selection is of type Todo.

			
package de.vogella.e4.todo.parts;

import javax.inject.Inject;
import javax.inject.Named;

import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import de.vogella.e4.todo.model.Todo;

public class TodoDetails {

	private final Composite parent;
	private Todo todo;
	private Text summary;
	private Text description;

	// e4 will inject the composite "parent" into the view
	@Inject
	public TodoDetails(Composite parent) {
		// the following is standard SWT Stuff
		this.parent = parent;
		
		final GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		
		createLable("Summary:");
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		summary = new Text(parent, SWT.NONE);
		summary.setTextLimit(100);
		summary.setLayoutData(gridData);
		
		createLable("Description:");
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		description = new Text(parent, SWT.NONE);
		description.setSize(30, 400);
		description.setLayoutData(gridData);
	}

	// Standard SWT Stuff
	private void createLable(String text) {
		Label label = new Label(parent, SWT.NONE);
		label.setText(text);
		GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		gridData.horizontalIndent = 20;
		label.setLayoutData(gridData);
	}
	
	@Inject 
	public void setTodo(@Optional @Named(IServiceConstants.ACTIVE_SELECTION) Todo todo){
			if (todo!= null){
				this.todo = todo;
				summary.setText(todo.getSummary());
				description.setText(todo.getDescription());
			}
	}



	
}

		

If you now select a Todo in the tree, this will be propagated via the selection service to the TodoDetails view.

13. More to come

At this point we have created a simple shell for our application, added two parts and styled them a bit. Obviously this is not a full features Todo application. ;-) I'm publishing this anyhow in the hope that this helps people getting started and I'm planning to extend this application and create a full featured Todo application. '

14. Deployment

Deployment of an Eclipse e4 application works similar to the deployment of an Eclipse RCP application. Please see Eclipse RCP .

Please make sure that you include all the e4 artifacts in your "build.properties".

15. e4 and Eclipse RAP

If you want to run Eclipse e4 and the RAP runtime you can look at the following wike Eclipse e4 and Eclipse RAP integration .

16. Key classes in e4

The following is a list of important classes in Eclipse e4.

Table 3. e4 classes

ClassPluginDescription
org.eclipse.e4.ui.internal.workbench.swt.E4Application Implementation of the e4 application 
org.eclipse.e4.workbench.ui.internal.E4Workbenche4 workbench implementation 
org.eclipse.e4.core.services.internal.annotations.AnnotationsSupport Checks for annotations 
org.eclipse.e4.workbench.ui.renderers.swt.WorkbenchRendererFactory SWT renderer factory, implements IRendererFactory 

17. Thank you

Thank you for practicing with this tutorial.

I maintain this tutorial in my private time. If you like the information please help me by using flattr or donating or by recommending this tutorial to other people.

Flattr this

18. Questions and Discussion

Before posting questions, please see the vogella FAQ . If you have questions or find an error in this article please use the www.vogella.de Google Group . I have created a short list how to create good questions which might also help you. .

19. Links and Literature

19.1. Source Code

Source Code of Examples

http://wiki.eclipse.org/E4 Eclipse E4 - Wiki

Eclipse 4.0 SDK - What is New?