RSS

Search Engine

Showing posts with label Eclipse RCP Tutorial. Show all posts
Showing posts with label Eclipse RCP Tutorial. Show all posts

Monday, June 14, 2010

Eclipse RCP

1.1. Overview

Eclipse RCP allows developers to use the Eclipse architecture to design flexible and extensible stand-alone applications re-using a lot of already existing functionality and coding patterns inherent in Eclipse.

For an brief introduction into Eclipse, the concepts and terminology (perspective, views, editors) please see Eclipse IDE Tutorial .

Eclipse is build upon a plugin architecture. This allows Eclipse to get easily extended. See Eclipse Plugin Tutorial for a guide on how-to extend the Eclipse IDE. Eclipse RCP provides the same modular concept for stand-alone applications.

To create an Eclipse RCP application you would create a plugin which contains the application. This application can use the existing hooks of Eclipse (called Extension Points) to define functionality and / or the user interface and / or provide its own extension points to get extended by other plugins.

1.2. Eclipse RCP Architecture - Plugins, Extensions and Extension-Points

The most important architectural characteristics of Eclipse is the Plugin architecture. The Eclipse IDE is build as a number of plugins which are dependent on each other.

Plugins are the smallest deployable and installable software components of Eclipse.

Each plugin can define extension-points which define possibilities for functionality contributions ( code and non-code ) by other plugins. Non-code functionality contributions are for example the provision of help content.

A plugin can use extensions, e.g. provide functionality to these extension points. In general an extension point can be used several times (either by the same plugin or by other plugins). See Eclipse Extension Points and Extensions - Tutorial for details.

The basis for this architecture is the runtime environment Equinox of Eclipse which is the reference implementation of OSGI. See OSGi development - Tutorial for details. The Plugin concept of Eclipse is the same as the bundle concept of OSGI. Generally speaking a OSGI bundle equals a Plugin and vice-versa.

The used extensions and the provided extension-points are described in the file plugin.xml. This file is a XML file which can be edited via the PDE (Plugin Development Environment) which provides a nice user interface for editing this file.

Eclipse RCP provides and uses the same framework as the Eclipse Workbench hence allowing the programmer to divide the application functionality into several plugins, to use existing extension points and to provide additional extension points. This concept of Eclipse allows every programmer to structure his RCP application into several independent components and to easily declare extensions to existing extensions points.

1.3. Main components of an Eclipse RCP application

An Eclipse RCP application requires:

  • Main program - A RCP main application class implements the interface IApplication. Eclipse expects that the application class is defined via the extension point org.eclipse.core.runtime.application.

  • A Perspective - The perspective is extended from org.eclipse.ui.perspective

  • Workbench Advisor- invisible technical component which controls the appearance of the application (menus, toolbars, perspectives, etc)

All plugins must provide a so-called manifest named "plugin.xml".

The minimal required plugins to create and run an Eclipse RCP application are the two plugins "org.eclipse.core.runtime" and "org.eclipse.ui"

1.4. Application versus Product

To run an Eclipse RCP program you have to define an application . The application can be seen as the main() method of a standard Java program. If this application shuts down the complete program is terminated.

In Eclipse terms a product is everything that goes with your application, e.g. icons, splash screen, external jars, other plugins, etc.

1.5. Important files

The plugin configuration is contained in the two files:

  • MANIFEST.MF - the OSGi bundle manifest is stored in MANIFEST.MF

  • plugin.xml - additional Eclipse specific (non standard OSGi) configuration, e.g. the extension points

The PDE provides an editor for editing the "MANIFEST.MF" and "plugin.xml".

In addition to these files you have the .project file. The .project contains the description of your project. It contains a XML tag "natures" where the nature of the project is described. A plugin project has the nature "org.eclipse.pde.PluginNature" and a java project has the nature "org.eclipse.jdt.core.javanature". These tags will also steer some behavior of the development environment, e.g. a project with PluginNature will update the java class path if you change the dependency information in a plugin project.

Installation

On the webpage of eclipse (www.eclipse.org), click on DOWNLOADS. Download the package "Eclipse for RCP/Plug-in Developers".

Tip

You might have to click on "More Packages" to see the RCP download package.

Tip

Don’t extract Eclipse into a directory tree that contains special characters. I also recommend to avoid spaces in the directory name.

In case you have downloaded the Eclipse Java IDE (or any other non RCP flavor) distribution you can use the Eclipse Update Manager to install the plugins required for RCP development. See Eclipse Update Manager for details on using the update manager.

Install "General Purpose Tools" -> "Eclipse Plug-in Development Environment" and "Eclipse RCP Plug-in Developer Resources" from the Galileo update site. You may have to remove the "Group items by category" flag to see these features.

Create your first RCP application

The following gives a quick guide on how to create a simple RCP application.

3.1. Create a RCP application

In Eclipse select File-> New Project. From the list select "Plug-In Project".

Give your plugin the name "de.vogella.rcp.intro.first" .

Press "Next" and make the following settings. As we are going to develop a RCP application, select "Yes" at the question "Would you like to create a rich client application".

Press next and select the template "Hello RCP" .

Press next and select "Add branding" and press Finish.

As a result a project with the following project structure will be created. Have a look at the different files especially the Java files to get a first feeling about the project structure.

Tip

As this tutorial is about RCP development I will use the following interchangable: "create a new plugin project " or "create a new RCP project". Both mean the same, create a plugin project with the flag "Would you like to create a rich client application" enabled.

3.2. Start your RCP application

Search in the menu path for the file "MANIFEST.MF" and double-click on it. You should see an editor and the tab "Overview" should be selected. Click the link "Launch an Eclipse Application".

Tip

Alternatively you can run your Eclipse RCP application by selecting the automatically created "plugin.xml", right mouse click and select "Run as" -> "Eclipse Application".

The result should look like the following:

Congratulations, you have created your first RCP application.

Startup process of an RCP application

During the startup of an Eclipse RCP application the Eclipse runtime will evaluate which class is defined via the "org.eclipse.core.runtime.application" extension point.

This class will then be loaded. This class creates and runs a Workbench. The Workbench is configured via a WorkbenchAdvisor. The Workbench will start a WorkbenchWindow which is configured via a WorkbenchWindowAdvisor. This WorkbenchWindow will create the toolbar of the application which can get configured at startup via the ActionBarAdvisor.

Each adviser allow to configure certain behavior of the application, e.g. the WorkbenchAdvisor allows to perform certain actions at startup or shutdown by overriding the methods preStartUp() and preShutdown().

Run configuration

5.1. Overview

A run configuration in Eclipse defines the environment under which your application will be started, e.g. compiler flag, plugin (classpath) dependencies etc. Sometime a run configuration is called referred to as "launch configuration".

If you start your application a default run configuration will be automatically created for you.

To see and edit your run configuration select your plugin.xml -> Run As -> Run Configurations

In the field "location" you specify their the files will be created which are necessary to run your RCP application.

5.2. Check your runtime configuration

On the Plug-ins Tab select "Validate plug-ins prior to launching". This will check if you have all required plugins in your launch configuration.

Tip

In my opinion this option should be flagged per default. I submitted a patch for this. Please share you opinion in Bug: Validate should be flagged as default

If this check reports that some plugins are missing, try clicking the "Add Required-Plug-Ins" button.

Tip

This may solve errors like "One or more bundles are not resolved because the following root constraints are not resolved" or "java.lang.RuntimeException: No application id has been found."

5.3. Important Parameters

On the tab Arguments you should add the parameter -consoleLog. This will send error message of your Eclipse RCP application to your Eclipse development IDE. Otherwise you will not necessary know that your Eclipse RCP application has a problem.

Tip

Under Windows -> Preference -> Plug-in Development -> Target Platform it is possible to maintain -consoleLog in the tab launching Arguments -> Program Arguments. Then the parameter will always be set for your RCP runtime configurations.

Commands

6.1. Overview

A command is a declarative description of a component and is independent from the implementation details. A command can be categorized and a hot key (key binding) can be assigned to the command.

Commands can be used in menus, toolbars and / or context menus.

The following will focus on a simple definition and usage of commands. For details on the usage of commands please see Eclipse Commands - Tutorial

6.2. Defining commands

Tip

Commands are superior to Actions. In my opinion Actions should be marked as deprecated as having both is confusing for new Eclipse platform developers. Please share your opinion in Bug for deprecating Actions

Our first example will be a command which will exit the application. Create a new RCP project "de.vogella.rcp.commands.first" and use the "Hello RCP" Template.

Click on the plugin.xml and select the Extensions tab.

Press the add button and search for the extension org.eclipse.ui.commands. Select it and press finish.

Create a new command by right-clicking New -> command.

Tip

Lots of people report that if they try this they can only select a "Generic" entry. The common source of this problem seems to be that you did not download the package "Eclipse for RCP/Plug-in Developers". Please see Eclipse Installation .

Set the ID to "de.vogella.rcp.commands.first.commands.Exit" and the name to "Exit". Enter the class "de.vogella.rcp.commands.first.commands.ExitHandler" as defaultHandler.

Press the hyperlink "defaultHandler" to create this class.

Choose org.eclipse.core.commands.AbstractHandler as Superclass.

Implement the following coding

   
package de.vogella.rcp.commands.first.commands;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.handlers.HandlerUtil;

public class ExitHandler extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
HandlerUtil.getActiveWorkbenchWindow(event).close();
return null;
}

}

You have correctly implemented the command. This command can now be used in various places in your application.

6.3. Using commands in menus

The command which we just defined should now be used in a new menu.

Add the extension point "org.eclipse.ui.menus" to your application. Select therefore again plugin.xml and the tab "Extensions". Press Add, select the extension point "org.eclipse.ui.menus" and press Finish.

Right click on the extension point and select new -> menuContribution.

Create a new menu contribution with the location URI "menu:org.eclipse.ui.main.menu".

Tip

Make sure the URL must is correct, otherwise the menu will not get displayed.

Right click your menucontribution and select New -> Menu. Add a menu with the label "File" and the id "fileMenu".

Now select your menu, right-click on it and select New-> Command. Maintain the commandID you used earlier. Set the label to "Exit" and the tooltip to "Exit the application".

Your work should result in a plugin.xml file which looks like the following.

   




id="application"
point="org.eclipse.core.runtime.applications">

class="de.vogella.rcp.commands.first.Application">



point="org.eclipse.ui.perspectives">
name="RCP Perspective"
class="de.vogella.rcp.commands.first.Perspective"
id="de.vogella.rcp.commands.first.perspective">


point="org.eclipse.ui.commands">
defaultHandler="de.vogella.rcp.commands.first.commands.ExitHandler"
id="de.vogella.rcp.commands.first.commands.Exit"
name="Exit">


point="org.eclipse.ui.menus">
locationURI="menu:org.eclipse.ui.main.menu">
id="fileMenu"
label="File">
commandId="de.vogella.rcp.commands.first.commands.Exit"
label="Exit"
style="push"
tooltip="Exit the application">







If you run the example you should see menu with the file. Selecting Exit should end your application.

System Tray

In the following we will add an icon to the system tray.

We also add the functionality that if the window is minimized then the program is not visible in the taskpane (only via the tray icon) and we will add a menu with one entry to system tray icon.

Create a new project "de.vogella.rcp.intro.traytest". Use the "Hello RCP" as a template.

Create a command which the id "de.vogella.rcp.intro.traytest.exitCommand" which exists the application (see Eclipse commands for details).

Maintain the following code in class ApplicationWorkbenchWindowAdvisor.

   
package de.vogella.rcp.intro.traytest;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tray;
import org.eclipse.swt.widgets.TrayItem;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.plugin.AbstractUIPlugin;

public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {
private IWorkbenchWindow window;
private TrayItem trayItem;
private Image trayImage;
private final static String COMMAND_ID = "de.vogella.rcp.intro.traytest.exitCommand";

public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
super(configurer);
}

@Override
public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
return new ApplicationActionBarAdvisor(configurer);
}

@Override
public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
configurer.setInitialSize(new Point(400, 300));
configurer.setShowCoolBar(false);
configurer.setShowStatusLine(false);
configurer.setTitle("Hello RCP");
}

@Override
public void postWindowOpen() {
super.postWindowOpen();
window = getWindowConfigurer().getWindow();
trayItem = initTaskItem(window);
if (trayItem != null) {
createMinimize();
// Create exit and about action on the icon
hookPopupMenu();
}
}

// Add a listener to the shell
// If the window is minimized hide the window
private void createMinimize() {
window.getShell().addShellListener(new ShellAdapter() {
public void shellIconified(ShellEvent e) {
window.getShell().setVisible(false);
}
});
// If user double-clicks on the tray icons the application will be visible again
trayItem.addListener(SWT.DefaultSelection, new Listener() {
public void handleEvent(Event event) {
Shell shell = window.getShell();
if (!shell.isVisible()) {
shell.setVisible(true);
window.getShell().setMinimized(false);
}
}
});
}

// We hook up on menu entry which allows to close the application
private void hookPopupMenu() {
trayItem.addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
Menu menu = new Menu(window.getShell(), SWT.POP_UP);

// Creates a new menu item that terminates the program
// when selected
MenuItem exit = new MenuItem(menu, SWT.NONE);
exit.setText("Goodbye!");
exit.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
// Lets call our command
IHandlerService handlerService = (IHandlerService) window
.getService(IHandlerService.class);
try {
handlerService.executeCommand(COMMAND_ID, null);
} catch (Exception ex) {
throw new RuntimeException(COMMAND_ID);
}
}
});
// We need to make the menu visible
menu.setVisible(true);
}
});
}

private TrayItem initTaskItem(IWorkbenchWindow window) {
final Tray tray = window.getShell().getDisplay().getSystemTray();
TrayItem trayItem = new TrayItem(tray, SWT.NONE);
trayImage = AbstractUIPlugin.imageDescriptorFromPlugin(
"de.vogella.rcp.intro.traytest", "/icons/alt_about.gif").createImage();
trayItem.setImage(trayImage);
trayItem.setToolTipText("TrayItem");
return trayItem;

}

// We need to clean-up after ourself
@Override
public void dispose() {
if (trayImage != null) {
trayImage.dispose();
trayItem.dispose();
}
}

}

Run your application and see that you have a system tray icon. Test the menu and the minimized behavior. If the application is minized it should not be vislble in the taskbar but only in the system tray.

Views

8.1. Overview

Views provide information for a given task. A view is typically used to navigate a hierarchy of information, open an editor, or display properties for the active editor.

The following will explain how to add views to your application.For this example create a new RCP project "de.vogella.rcp.intro.view". Use the "Hello RCP" as a template.

8.2. Create a view

Select the file "plugin.xml" and the tab "Extensions". Press the "add" button and add "org.eclipse.ui.views" as an extension.

Right mouse-click on your new view extension and select New -> View

Maintain the id "de.vogella.rcp.intro.view.MyView" and the class "de.vogella.rcp.intro.view.MyView".

Create the class of the view by clicking on the class hyperlink.

Maintain the following code in your new class.

    
package de.vogella.rcp.intro.view;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

public class MyView extends ViewPart {

@Override
public void createPartControl(Composite parent) {
Text text = new Text(parent, SWT.BORDER);
text.setText("Imagine a fantastic user interface here");
}

@Override
public void setFocus() {
}
}

8.3. Add the view to your perspective.

After creating the view you have to add this view to your perspective. We will do this by using another extension point.

Select again "plugin.xml" and the tab "Extensions". Press add and add the extension "org.eclipse.ui.perspectiveExtensions".

Right click it and select view.

Maintain your view id "de.vogella.rcp.intro.view.MyView". Make the view relative to "org.eclipse.ui.editorss" which is the currently invisible editor area and make the view use all the space by selecting the maximum ratio of "0.95f".

8.4. Result

Run your application to see the result.

8.5. Add view to perspective via code

Alternatively to the usage of the extension point "org.eclipse.ui.perspectiveExtensions" you could have add the view also via coding to your perspective. To to this you could modify "Perspective.java" to the following.

    
package de.vogella.rcp.intro.view;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

public class Perspective implements IPerspectiveFactory {

public void createInitialLayout(IPageLayout layout) {
layout.addView("de.vogella.rcp.intro.view.MyView", IPageLayout.TOP,
IPageLayout.RATIO_MAX, IPageLayout.ID_EDITOR_AREA);
}
}

Tip

If possible use extension points over code.

Working with Editors, View Interaction and Model Updates

9.1. Overview

In the following we create a project which demonstrate the usage of editors and its interaction with an view.

We will create a view which shows several person. Once the user double-clicks on the name an editor is opened in which the user can edit the address of this person.

The following data model makes the assumption that the last name of a person is unique. This assumption is of course not true in the real world.

9.2. Create project

Create a new RCP project "de.vogella.rcp.intro.editor" . Use the "RCP application with a view" as a template.

9.3. Create and prepare the domain model

Create a package "de.vogella.rcp.intro.editor.model". Create the following classes in this package.

    
package de.vogella.rcp.intro.editor.model;

public class Address {

private String street;
private String number;
private String postalCode;
private String city;
private String country;

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}

public String getPostalCode() {
return postalCode;
}

public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}

public String toString() {
return street + " " + number + " " + postalCode + " " + city + " "
+ country;
}
}

    
package de.vogella.rcp.intro.editor.model;

public class Person {
private String firstName;
private String lastName;
private Address address;

public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
}

@Override
public String toString() {
return firstName + " " + lastName;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result
+ ((lastName == null) ? 0 : lastName.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}

}

    
package de.vogella.rcp.intro.editor.model;

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

public class MyModel {

private List persons = new ArrayList();

public List getPersons() {
return persons;
}

public MyModel() {
// Just for testing we hard-code the persons here:
Person person = new Person("Lars", "Vogel");
person.setAddress(new Address());
person.getAddress().setCountry("Germany");
persons.add(person);
person = new Person("Jim", "Knopf");
person.setAddress(new Address());
person.getAddress().setCountry("Germany");
persons.add(person);
}
}

Tip

Please note that we override the equals (and the hashcode method). This allows us later to identify the right editor for each person.

9.4. Content and Label provider

Create a new package "de.vogella.rcp.intro.editor.provider"

Create a new class "MyContentProvider" which implements the interface IStructuredContentProvider.

Adjust the coding according to the following example:

    package de.vogella.rcp.intro.editor.provider;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

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

import de.vogella.rcp.intro.editor.model.MyModel;

public class MyContentProvider implements IStructuredContentProvider,
PropertyChangeListener {

private final Viewer viewer;

public MyContentProvider(Viewer viewer) {
this.viewer = viewer;
}

@Override
public Object[] getElements(Object inputElement) {
MyModel content = (MyModel) inputElement;
return content.getPersons().toArray();
}

@Override
public void dispose() {
}

@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}

@Override
public void propertyChange(PropertyChangeEvent arg0) {
viewer.refresh();
}

}

Create a new class "MyLabelProvider" which implements the interface ILabelProvider. Use the following code.

    
package de.vogella.rcp.intro.editor.provider;

import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;

import de.vogella.rcp.intro.editor.model.Person;

public class MyLabelProvider implements ILabelProvider {

@Override
public Image getImage(Object element) {
return PlatformUI.getWorkbench().getSharedImages().getImage(
ISharedImages.IMG_OBJ_ELEMENT);
}

@Override
public String getText(Object element) {
Person person = (Person) element;
return (person.getLastName());
}

@Override
public void addListener(ILabelProviderListener listener) {
}

@Override
public void dispose() {
}

@Override
public boolean isLabelProperty(Object element, String property) {
return false;
}

@Override
public void removeListener(ILabelProviderListener listener) {
}
}

9.5. Use the domain model in the view

Change the class View to use your new content providers.

    
package de.vogella.rcp.intro.editor;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

import de.vogella.rcp.intro.editor.model.MyModel;
import de.vogella.rcp.intro.editor.provider.MyContentProvider;
import de.vogella.rcp.intro.editor.provider.MyLabelProvider;

public class View extends ViewPart {
public static final String ID = "de.vogella.rcp.intro.editor.view";

private TableViewer viewer;

/**
* This is a callback that will allow us to create the viewer and initialize
* it.
*/
public void createPartControl(Composite parent) {
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
viewer.setContentProvider(new MyContentProvider(viewer));
viewer.setLabelProvider(new MyLabelProvider());
viewer.setInput(new MyModel());
getSite().setSelectionProvider(viewer);
}

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

The view makes his viewer available as selection provider via the following line:" getSite().setSelectionProvider(viewer);". This make is possible for the command which opens the editor to get the selection of the view.

Tip

All workbench parts have a site, which can be accessed via the method getSite(). A site is a Facade which allows access to other parts of the workbench, e.g. the shell, the workbench window, etc. Whenever possible use the site to access Workbench objects.

Run your application. The view should now display the last names for your content provider. Currently nothing happens if you click on the names.

9.6. Editor area

Make the editor area visible by changing your Perspective.java.

    
package de.vogella.rcp.intro.editor;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

public class Perspective implements IPerspectiveFactory {

public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(true);
layout.setFixed(true);
layout.addStandaloneView(View.ID, false, IPageLayout.LEFT, 1.0f,
editorArea);
}

}

9.7. Editor Input

In package "de.vogella.rcp.intro.editor.editors" create a new class "MyPersonEditorInput" which implements IEditorInput. IEditorInput serves as the model for the editor.

It is recommended to overwrite the method equals and hashcode in an implementation of IEditor. Based on the equals method the system will determine if the corresponding editor is already open or not.

Change the created code to the following.

    
package de.vogella.rcp.intro.editor.editors;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IPersistableElement;

import de.vogella.rcp.intro.editor.model.Person;

public class MyPersonEditorInput implements IEditorInput {

private final Person person;

public MyPersonEditorInput(Person person) {
this.person = person;
}

public Person getPerson() {
return person;
}

@Override
public boolean exists() {
return false;
}

@Override
public ImageDescriptor getImageDescriptor() {
return null;
}

@Override
public String getName() {
return person.toString();
}

@Override
public IPersistableElement getPersistable() {
return null;
}

@Override
public String getToolTipText() {
return person.toString();
}

@Override
public Object getAdapter(Class adapter) {
return null;
}

@Override
public boolean equals(Object obj) {
if (super.equals(obj)) {
return true;
}
if (obj instanceof MyPersonEditorInput) {
return person.equals(((MyPersonEditorInput) obj).getPerson());
}
return false;
}

@Override
public int hashCode() {
return person.hashCode();
}
}

9.8. Adding the editor

Go to plugin.xml and select the tab extensions. Add the extension org.eclipse.ui.editors. Do not use a template. Use the ID "de.vogella.rcp.intro.editor.editors.MyPersonEditor", any name you want and the class "de.vogella.rcp.intro.editor.editors.MyPersonEditor".

Tip

Make also sure to select an icon! Otherwise your editor will not work.

Click on the class hyperlink to create the class. Create the following class. Important is the class variable "ID" which we will later use to reference to this class. The variable ID must match the id defined in the editor extension.

    
package de.vogella.rcp.intro.editor.editors;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.swt.SWT;
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 org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;

import de.vogella.rcp.intro.editor.model.Person;

public class MyPersonEditor extends EditorPart {
public static final String ID = "de.vogella.rcp.intro.editor.editors.MyPersonEditor";
private Person person;
private Text text2;

public MyPersonEditor() {
}

@Override
public void doSave(IProgressMonitor monitor) {
person.getAddress().setCountry(text2.getText());
}

@Override
public void doSaveAs() {
}

@Override
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
setSite(site);
setInput(input);
person = ((MyPersonEditorInput) input).getPerson();
setPartName(person.getFirstName());

}

@Override
public boolean isDirty() {
if (person.getAddress().getCountry().equals(text2.getText())) {
return false;
}
return true;
}

@Override
public boolean isSaveAsAllowed() {
return false;
}

@Override
public void createPartControl(Composite parent) {

GridLayout layout = new GridLayout();
layout.numColumns = 2;
parent.setLayout(layout);
Label label1 = new Label(parent, SWT.BORDER);
label1.setText("Person: ");
Label personName = new Label(parent, SWT.BORDER);
personName.setText(person.toString());
Label label2 = new Label(parent, SWT.BORDER);
label2.setText("Country");
text2 = new Text(parent, SWT.BORDER);
text2.setText(person.getAddress().getCountry());
}

@Override
public void setFocus() {
}

}

9.9. Creating a command for calling the editor

Create a command "de.vogella.rcp.intro.editor.callEditor" with the default handler "de.vogella.rcp.intro.editor.handler.CallEditor".

Create the following class "de.vogella.rcp.intro.editor.handler.CallEditor".

    
package de.vogella.rcp.intro.editor.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.handlers.HandlerUtil;

import de.vogella.rcp.intro.editor.View;
import de.vogella.rcp.intro.editor.editors.MyPersonEditor;
import de.vogella.rcp.intro.editor.editors.MyPersonEditorInput;
import de.vogella.rcp.intro.editor.model.Person;

public class CallEditor extends AbstractHandler implements IHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
// Get the view
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);
IWorkbenchPage page = window.getActivePage();
View view = (View) page.findView(View.ID);
// Get the selection
ISelection selection = view.getSite().getSelectionProvider()
.getSelection();
if (selection != null && selection instanceof IStructuredSelection) {
Object obj = ((IStructuredSelection) selection).getFirstElement();
// If we had a selection lets open the editor
if (obj != null) {
Person person = (Person) obj;
MyPersonEditorInput input = new MyPersonEditorInput(person);
try {
page.openEditor(input, MyPersonEditor.ID);

} catch (PartInitException e) {
System.out.println(e.getStackTrace());
}
}
}
return null;
}

}

9.10. Calling the editor

Add a double-click listener to your view which call the editor.

    
package de.vogella.rcp.intro.editor;

import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.ViewPart;

import de.vogella.rcp.intro.editor.provider.MyContentProvider;
import de.vogella.rcp.intro.editor.provider.MyLabelProvider;

public class View extends ViewPart {
public static final String ID = "de.vogella.rcp.intro.editor.view";

private TableViewer viewer;

/**
* This is a callback that will allow us to create the viewer and initialize
* it.
*/
public void createPartControl(Composite parent) {
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
viewer.setContentProvider(new MyContentProvider(viewer));
viewer.setLabelProvider(new MyLabelProvider());
viewer.setInput(new MyModel());
getSite().setSelectionProvider(viewer);
// New
hookDoubleClickCommand();
}

// New
private void hookDoubleClickCommand() {
viewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
IHandlerService handlerService = (IHandlerService) getSite()
.getService(IHandlerService.class);
try {
handlerService.executeCommand(
"de.vogella.rcp.intro.editor.callEditor", null);
} catch (Exception ex) {
throw new RuntimeException(
"de.vogella.rcp.intro.editor.callEditor not found");
}
}
});
}

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

Run the application. If you double-click on an item in the view, the editor should open and the counry should get displayed. If you close the editor and re-open it, changes in the address should be displayed.

Dialog

10.1. Overview

Eclipse supports several predefined dialogs. For example

  • org.eclipse.swt.widgets.FileDialog

  • org.eclipse.swt.widgets.DirectoryDialog

  • org.eclipse.swt.widgets.MessageDialog

  • org.eclipse.jface.dialogs.ErrorDialog

Eclipse supports also user defined dialogs. Usually the class TitleAreaDialog is then extended.

10.2. Using standard dialogs

The following will describe how to use standard dialogs.

Create a new project "de.vogella.rcp.intro.dialogs.standard". Use the "Hello RCP" as a template.

Add one command "de.vogella.rcp.intro.dialogs.standard.openDialog" and create the default handler "de.vogella.rcp.intro.dialogs.standard.handler.OpenDialog" for the command. Add the command to the menu.

Define the following code for the default handler.

    
package de.vogella.rcp.intro.dialogs.standard.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.FontDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.handlers.HandlerUtil;

public class OpenDialog extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
Shell shell = HandlerUtil.getActiveWorkbenchWindow(event).getShell();

// File standard dialog
FileDialog fileDialog = new FileDialog(shell);
// Set the text
fileDialog.setText("Select File");
// Set filter on .txt files
fileDialog.setFilterExtensions(new String[] { "*.txt" });
// Put in a readable name for the filter
fileDialog.setFilterNames(new String[] { "Textfiles(*.txt)" });
// Open Dialog and save result of selection
String selected = fileDialog.open();
System.out.println(selected);

// Directly standard selection
DirectoryDialog dirDialog = new DirectoryDialog(shell);
dirDialog.setText("Select your home directory");
String selectedDir = dirDialog.open();
System.out.println(selectedDir);

// Select Font
FontDialog fontDialog = new FontDialog(shell);
fontDialog.setText("Select your favorite font");
FontData selectedFont = fontDialog.open();
System.out.println(selectedFont);

// Select Color
ColorDialog colorDialog = new ColorDialog(shell);
colorDialog.setText("Select your favorite color");
RGB selectedColor = colorDialog.open();
System.out.println(selectedColor);

// Now a few messages
MessageDialog.openConfirm(shell, "Confirm", "Please confirm");
MessageDialog.openError(shell, "Error", "Error occured");
MessageDialog.openInformation(shell, "Info", "Info for you");
MessageDialog.openQuestion(shell, "Question", "Really, really?");
MessageDialog.openWarning(shell, "Warning", "I warn you");

return null;
}

}

Run the application. If you select your command the dialogs will be called after each other.

10.3. Selection

Eclipse provides the ElementListSelectionDialog which allows to select elements from a list.

Create a new project "de.vogella.rcp.intro.dialogs.selection". Use the "Hello RCP" as a template.

Add one command "de.vogella.rcp.intro.dialogs.selection.selectionDialog" and create the default handler "de.vogella.rcp.intro.dialogs.selection.handler.SelectionDialog" for the command. Add the command to the menu.

Define the following code in your handler.

    
package de.vogella.rcp.intro.dialogs.selection.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.handlers.HandlerUtil;

public class SelectionDialog extends AbstractHandler {

private Object[] result;

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
Shell shell = HandlerUtil.getActiveWorkbenchWindow(event).getShell();
ElementListSelectionDialog dialog = new ElementListSelectionDialog(
shell, new LabelProvider());
dialog.setElements(new String[] { "Linux", "Mac", "Windows" });
dialog.setTitle("Which operating system are you using");
dialog.open();
result = dialog.getResult();
for (Object s : result) {
System.out.println(s.toString());
}
return null;
}
}

Run the application. If you select your command then the dialog will be displayed.

10.4. User defined dialogs

You can also define your own dialogs. Create a new project "de.vogella.rcp.intro.dialogs.custom". Use the "Hello RCP" as a template.

Create the following class MyDialog.

    
package de.vogella.rcp.intro.dialogs.custom.dialogs;

import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
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.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class MyDialog extends TitleAreaDialog {

private Text firstNameText;
private Text lastNameText;
private String firstName;
private String lastName;

public MyDialog(Shell parentShell) {
super(parentShell);
}

@Override
public void create() {
super.create();
// Set the title
setTitle("This is my first own dialog");
// Set the message
setMessage("This is a TitleAreaDialog", IMessageProvider.INFORMATION);

}

@Override
protected Control createDialogArea(Composite parent) {
GridLayout layout = new GridLayout();
layout.numColumns = 2;
// layout.horizontalAlignment = GridData.FILL;
parent.setLayout(layout);

// The text fields will grow with the size of the dialog
GridData gridData = new GridData();
gridData.grabExcessHorizontalSpace = true;
gridData.horizontalAlignment = GridData.FILL;

Label label1 = new Label(parent, SWT.NONE);
label1.setText("First Name");

firstNameText = new Text(parent, SWT.BORDER);
firstNameText.setLayoutData(gridData);
Label label2 = new Label(parent, SWT.NONE);
label2.setText("Last Name");
lastNameText = new Text(parent, SWT.BORDER);
lastNameText.setLayoutData(gridData);
return parent;
}

@Override
protected void createButtonsForButtonBar(Composite parent) {
GridData gridData = new GridData();
gridData.verticalAlignment = GridData.FILL;
gridData.horizontalSpan = 3;
gridData.grabExcessHorizontalSpace = true;
gridData.grabExcessVerticalSpace = true;
gridData.horizontalAlignment = SWT.CENTER;

parent.setLayoutData(gridData);
// Create Add button
// Own method as we need to overview the SelectionAdapter
createOkButton(parent, OK, "Add", true);
// Add a SelectionListener

// Create Cancel button
Button cancelButton = createButton(parent, CANCEL, "Cancel", false);
// Add a SelectionListener
cancelButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
setReturnCode(CANCEL);
close();
}
});
}

protected Button createOkButton(Composite parent, int id, String label,
boolean defaultButton) {
// increment the number of columns in the button bar
((GridLayout) parent.getLayout()).numColumns++;
Button button = new Button(parent, SWT.PUSH);
button.setText(label);
button.setFont(JFaceResources.getDialogFont());
button.setData(new Integer(id));
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
if (isValidInput()) {
okPressed();
}
}
});
if (defaultButton) {
Shell shell = parent.getShell();
if (shell != null) {
shell.setDefaultButton(button);
}
}
setButtonLayoutData(button);
return button;
}

private boolean isValidInput() {
boolean valid = true;
if (firstNameText.getText().length() == 0) {
setErrorMessage("Please maintain the first name");
valid = false;
}
if (lastNameText.getText().length() == 0) {
setErrorMessage("Please maintain the last name");
valid = false;
}
return valid;
}

// We allow the user to resize this dialog
@Override
protected boolean isResizable() {
return true;
}

// We need to have the textFields into Strings because the UI gets disposed
// and the Text Fields are not accessible any more.
private void saveInput() {
firstName = firstNameText.getText();
lastName = lastNameText.getText();

}

@Override
protected void okPressed() {
saveInput();
super.okPressed();
}

public String getFirstName() {
return firstName;
}

public String getLastName() {
return lastName;
}
}

Add one command "de.vogella.rcp.intro.dialogs.custom.openMyDialog" and create the following handler "de.vogella.rcp.intro.dialogs.custom.handler.OpenMyDialog". Add the command to the menu.

    
package de.vogella.rcp.intro.dialogs.custom.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.handlers.HandlerUtil;

import de.vogella.rcp.intro.dialogs.custom.dialogs.MyDialog;

public class OpenMyDialog extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
MyDialog dialog = new MyDialog(HandlerUtil.getActiveWorkbenchWindow(
event).getShell());
dialog.create();
if (dialog.open() == Window.OK) {
System.out.println(dialog.getFirstName());
System.out.println(dialog.getLastName());
}

return null;
}

}

Run the application. You should be able to open the dialog. To press Ok you need to maintain the first and last name. If you press "Ok" both fields should be written to the console.

Field Assist

Field Assit can be used to provide information about the possible inputs and status of a simple field, e.g. text field or combo box.

The org.eclipse.jface.fieldassist package provides assistance in two ways. Control decorations allow you to place image decorations to show the status of a field. Content proposal allows to provide a popup that which provides possible choices for this field. user. The following will demonstrate the content proposal.

Create a new project "de.vogella.rcp.intro.fieldassist". Use "RCP application with a view" as an example.

In our example the content proposal should get activated via certain keys ("." and "#") as well as the key combination "Cntrl+Space".

Change the View.java to the following.

  
package de.vogella.rcp.intro.fieldassist;

import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.bindings.keys.ParseException;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
public static final String ID = "de.vogella.rcp.intro.fieldassist.view";

public void createPartControl(Composite parent) {
Text text = new Text(parent, SWT.BORDER);
text.setText("Example");

// "." and "#" will also activate the content proposals
char[] autoActivationCharacters = new char[] { '.', '#' };
KeyStroke keyStroke;
try {
keyStroke = KeyStroke.getInstance("Ctrl+Space");
// assume that myTextControl has already been created in some way
ContentProposalAdapter adapter = new ContentProposalAdapter(text,
new TextContentAdapter(),
new SimpleContentProposalProvider(new String[] {
"ProposalOne", "ProposalTwo", "ProposalThree" }),
keyStroke, autoActivationCharacters);
} catch (ParseException e) {
e.printStackTrace();
}
}

public void setFocus() {
}
}

Run the application and check the content proposal works.

Wizards

12.1. Overview

Wizards provide a flexible ways to systematically gather user input and perform input validation. A wizard guides a user step by step through a process.

Eclipse implements a Wizard via class WizardDialog. The WizardDialog controls the process (Navigation, process bar, area for error and information messages). The Wizard content and is provided by the class Wizard and the pages are provided via class WizardPages.

12.2. Example

Create a new project "de.vogella.rcp.intro.wizards". Use the "Hello RCP" as a template.

Create the command "de.vogella.rcp.intro.wizards.showWizard" with the default handler "de.vogella.rcp.intro.wizards.handler.ShowWizard". Add the command to the menu.

Create a package "de.vogella.rcp.intro.wizards.wizard". Create the classes "MyPageOne" and "MyPageTwo" MyWizard which extends org.eclipse.jface.wizard.WizardPage.

Maintain the following code for the classes.

    
package de.vogella.rcp.intro.wizards.wizard;

import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

public class MyPageOne extends WizardPage {
private Text text1;
private Composite container;

public MyPageOne() {
super("First Page");
setTitle("First Page2");
setDescription("This wizard does not really do anything. But this is the first page");
}

@Override
public void createControl(Composite parent) {
container = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
container.setLayout(layout);
layout.numColumns = 2;
Label label1 = new Label(container, SWT.NULL);
label1.setText("Put here a value");

text1 = new Text(container, SWT.BORDER | SWT.SINGLE);
text1.setText("");
text1.addKeyListener(new KeyListener() {

@Override
public void keyPressed(KeyEvent e) {
}

@Override
public void keyReleased(KeyEvent e) {
if (!text1.getText().isEmpty()) {
setPageComplete(true);

}
}

});
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
text1.setLayoutData(gd);
// Required to avoid an error in the system
setControl(container);
setPageComplete(false);

}

public String getText1() {
return text1.getText();
}
}

    
package de.vogella.rcp.intro.wizards.wizard;

import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
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.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

public class MyPageTwo extends WizardPage {
private Text text1;
private Composite container;

public MyPageTwo() {
super("Second Page");
setTitle("Second Page");
setDescription("Now this is the second page");
setControl(text1);
}

@Override
public void createControl(Composite parent) {
container = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
container.setLayout(layout);
layout.numColumns = 2;
Label label1 = new Label(container, SWT.NULL);
label1.setText("Say hello to Fred");

text1 = new Text(container, SWT.BORDER | SWT.SINGLE);
text1.setText("");
text1.addKeyListener(new KeyListener() {

@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub

}

@Override
public void keyReleased(KeyEvent e) {
if (!text1.getText().isEmpty()) {
setPageComplete(true);
}
}

});
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
text1.setLayoutData(gd);
Label labelCheck = new Label(container, SWT.NONE);
labelCheck.setText("This is a check");
Button check = new Button(container, SWT.CHECK);
check.setSelection(true);
// Required to avoid an error in the system
setControl(container);
setPageComplete(false);
}

public String getText1() {
return text1.getText();
}

}

Create a new class MyWizard which extends org.eclipse.jface.wizard.Wizard.

>

    
package de.vogella.rcp.intro.wizards.wizard;

import org.eclipse.jface.wizard.Wizard;

public class MyWizard extends Wizard {

private MyPageOne one;
private MyPageTwo two;

public MyWizard() {
super();
setNeedsProgressMonitor(true);
}

@Override
public void addPages() {
one = new MyPageOne();
two = new MyPageTwo();
addPage(one);
addPage(two);
}

@Override
public boolean performFinish() {

// just put the result to the console, imagine here much more
// intelligent stuff.
System.out.println(one.getText1());
System.out.println(two.getText1());

return true;
}
}

Implement the handler for the command.

    
package de.vogella.rcp.intro.wizards.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.ui.handlers.HandlerUtil;

import de.vogella.rcp.intro.wizards.wizard.MyWizard;

public class ShowWizard extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
MyWizard wizard = new MyWizard();
WizardDialog dialog = new WizardDialog(HandlerUtil
.getActiveShell(event), wizard);
dialog.open();
return null;
}

}

If you run your application and select the menu entry the wizard should get displayed and after pressing "Finish" you should see the result on the console.

Adding a status line

13.1. Setup Status line

Create a new RCP project "de.vogella.rcp.intro.statusline". Use the "Hello RCP" as the template. Open the class "ApplicationWorkbenchWindowAdvisor" and change method preWindowOpen(). The relevant line in the coding is: "configurer.setShowStatusLine(true);"

    
package de.vogella.rcp.intro.statusline;

import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;

public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {

public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
super(configurer);
}

public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
return new ApplicationActionBarAdvisor(configurer);
}

@Override
public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
configurer.setInitialSize(new Point(400, 300));
configurer.setShowCoolBar(false);
configurer.setShowStatusLine(false);
configurer.setTitle("Status Line Example");
configurer.setShowStatusLine(true);
}
}

If you run the application you should already see a status line. At this point the status line does not contain text.

13.2. Shared Status Line

The shared message area can be used by all parts of the application to write messages to this area.

Tip

Whole RCP application has access to the information in the shared status line therefore the information in the shared status line might be overwritten.

The following write a text to the status line.

    
package de.vogella.rcp.intro.statusline;

import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;

public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {

public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
super(configurer);
}

public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer) {
return new ApplicationActionBarAdvisor(configurer);
}

@Override
public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
configurer.setInitialSize(new Point(400, 300));
configurer.setShowCoolBar(false);
configurer.setShowStatusLine(false);
configurer.setTitle("Status Line Example");
configurer.setShowStatusLine(true);
}

// This is the new method
@Override
public void postWindowOpen() {
IStatusLineManager statusline = getWindowConfigurer()
.getActionBarConfigurer().getStatusLineManager();
statusline.setMessage(null, "Status line is ready");
}
}

Run your application. You should now see the following.

Add a view with the ID "de.vogella.rcp.intro.statusline.View1" and the implementation class "de.vogella.rcp.intro.statusline.ViewPart1" to your application. This view contains a button to set the status line.

    
package de.vogella.rcp.intro.statusline;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;

public class ViewPart1 extends ViewPart {

boolean pressed = false;

@Override
public void createPartControl(Composite parent) {
Button setStatusLine = new Button(parent, SWT.PUSH);
setStatusLine.setText("Set Statusline ");

setStatusLine.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {

String message = "I would like to say hello to you.";
if (pressed) {
message = "Thank you for using me";
}
setStatusLine(message);
pressed = !pressed;
}
});
}

private void setStatusLine(String message) {
// Get the status line and set the text
IActionBars bars = getViewSite().getActionBars();
bars.getStatusLineManager().setMessage(message);
}

@Override
public void setFocus() {
}

}

If you run it the result should look like the following.

Tip

From an editor you can access the status line via the following:

     
IEditorPart.getEditorSite().getActionBars();

Perspectives

Perspectives group together and organize UI element that relate to a specific task. Eclipse RCP allows you to add perspectives to your application. The following presents an example.

14.1. Adding a perspective to your application

Create a new RCP project called "de.vogella.rcp.intro.perspective". Use the "RCP application with a view" as a template.

In plugin.xml add a new perspective extension point.

Give the perspective the id "de.vogella.rcp.intro.perspective.perspective" and the name "Perspective". Change the class name to "de.vogella.rcp.intro.perspective.Perspective".

Click on the "class*" link to create the class.

The method createInitialLayout() in your new class is responsible for creating the new perspective. We re-use the existing view in the coding.

    package de.vogella.rcp.intro.perspective;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

public class Perspective implements IPerspectiveFactory {

public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(false);
layout.setFixed(true);

layout.addStandaloneView(View.ID, false, IPageLayout.LEFT, 1.0f, editorArea);
}

}

The perspective is defined but not yet reachable via the application.

14.2. Select the perspective

14.2.1. Select perspective via the toolbar / coolbar

You can activate the switch between perspectives the ApplicationWorkbenchWindowAdvisor in method preWindowOpen() with configurer.setShowPerspectiveBar(true);

     
package perspectivetest;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;

public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {

public ApplicationWorkbenchWindowAdvisor(
IWorkbenchWindowConfigurer configurer) {
super(configurer);
}

public ActionBarAdvisor createActionBarAdvisor(
IActionBarConfigurer configurer) {
return new ApplicationActionBarAdvisor(configurer);
}

public void preWindowOpen() {
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
configurer.setInitialSize(new Point(400, 300));
configurer.setShowCoolBar(false);
configurer.setShowStatusLine(false);
configurer.setTitle("RCP Application");
configurer.setShowPerspectiveBar(true);
// Set the preference toolbar to the left place
// If other menus exists then this will be on the left of them
IPreferenceStore apiStore = PlatformUI.getPreferenceStore();
apiStore.setValue(IWorkbenchPreferenceConstants.DOCK_PERSPECTIVE_BAR,
"TOP_LEFT");
}
}

You should now be able to select your perspective interactively.

14.2.2. Select perspective via the menu

You can re-use the Eclipse perspective switch in a menu via the following standard command "org.eclipse.ui.perspectives.showPerspective".