"Excellence through total Moderation" - Cleobulus

Wednesday, February 13, 2008

Eclipse RCP Recipes: Adding Wizards to your main Perspective

In Eclipse Rich Client Platform (RCP), one of the nice mechanisms it offers to decouple presentation from business logic is to allow you to define different, independent plugins that can contribute to the UI. As a result, in an RCP Application, it is very useful to have a basic generic UI plugin that deals with setting up the fundamental UI elements such as the perspective and views and then have some domain specific plugins that will contribute domain specific UI elements for the toolbar, menu and actions. The Eclipse magic (a term that we have been widely using, me and my colleagues, just by the mere fact that it’s not always crystal clear what and how Eclipse does what it does!) happens when you want to glue/bind domain specific UI to the generic one. One of those cases is when you want to add a domain specific Wizard item on the application’s menu.

I believe that the proper Eclipse way of doing it, using as much of the framework as possible with minimum code and maximum decoupling, is by adding an extension point to the generic UI plugin. This extension point will then be available to any domain specific UI plugin that wishes to add wizards to it. This can be achieved by extending that point with very little code.

Assuming that you have the generic and domain specific plugins, here is how it is done:

  1. Create an extension point to the generic UI plugin where New Wizards will be added.

    1. Open the manifest file MANIFEST.MF of the generic UI plugin and select the Extension Points tab.

    2. Click the Add… button and:

      1. Enter the ID of the Extension Point. Note that the resulting ID will be your input prefixed by the plugin’s name. In our case “perspective” was the input ID, while the actual ID is “com.generic.ui.perspective”.

      2. Enter the Name of the Extension Point – a human readable String representing your extension point. In our case – “Perspective”.

      3. Select the name of the XML Schema file. This file contains all the information about what this Extension Point is, how it is used, documentation and constraints. You should create a separate schema folder in your source (Eclipse has done that for you). In our case the file’s path will be “schema/perspective.exsd”.

      4. Press OK.

  2. Now we edit the schema file to define what the extension point will do

    1. Eclipse should have opened the editor for the schema file. The first tab is about its documentation.

      1. In the Description Tab you should add some text saying what the extension point offers.

      2. In the API Information Tab you should describe how the client plugin of that extension should use it.

      3. In the Examples Tab you should offer an XML example of usage of the extension point. You can do that after you have sorted everything else. In our case the example looks like this

  3. Finally define what the extension point does. Select the Definition Page (look at the bottom). The default schema file has an extension element. We will add a new element that describes the wizard to be added to the generic UI perspective.

    1. Select the New Element button. We’ll name the element as wizardShortcut.

    2. Under that element we want to define an attribute that will hold the ID of the wizard to be added. This way we can pass the wizard’s ID to the generic UI plugin, where we can then manipulate it to add it to the perspective.

          1. Select New Attribute and name it id. Make sure that in the Use option you select required and that the type is String. You can also add a little description of this attribute.

          2. Then you need to bind the wizardShortcut element to the main extension element. You can do that by adding a sequence Compositor to the extension element. Right click on the extension element and go New->Compositor->Sequence. In the sequence compositor you can add the wizardShortcut simply by dragging and dropping it on it. Finally you have to specify the occurrences bounds. For this example we have a minimum of one occurrence and an unbounded maximum. This should look like this:

  4. Our extension point is DONE! Now all we need to do is extend it from our domain UI plugin. Go to your domain UI MANIFEST.MF file and select the extensions page. Click on the Add… button and look for the ID of our new extension point. In our case it should be “com.generic.ui.perspective”. Press Finish. Then right click on it and select New->wizardShortcut. Now given that you already have implemented your wizard by extending the eclipse wizards extension (org.eclipse.ui.newWizards), you should have already defined an ID for your wizard (look at you wizard extension definition). The only thing that you have to do now is to add that ID to the perspective extension … and you are DONE!

  5. At this current state we have managed to pass in a decoupled fashion the ID of our wizards to the generic UI plugin and perspective. The only thing that is left now is to manipulate it on the generic side to add it to the UI.

    1. In your DefaultPerspective class of the generic UI plugin that implements the default perspective of the application, create a method that will add the domain wizards to the UI. In our example it is addWizardMenuFromExtensions and it has and IPageLayout as a parameter. This method can be called by the class’s createInitialLayout method which can pass that page layout. The way this method works is by calling the Eclipse platform extension registry and performing a lookup to find the extensions for the generic UI plugin. It then looks up for the perspective extensions and in particular for the wizardShortcut elements. For each one that it finds it extracts the ID of the extending wizard and finally calls the page layouts method to add the wizard shortcut giving its ID.

    2. Here is the code for it:

private void addWizardMenuFromExtensions(IPageLayout layout) {
// get the extensions of the plugins perspectives extension point
Extension[] extensions = Platform.getExtensionRegistry().
getExtensionPoint(GenericUIPluginActivator.PLUGIN_ID, "perspective").getExtensions();
// for every extension (as in for every plugin extending our extension point)
// find the WizardShortcut element and extract the ID of the wizard to add it on
// the layout's wizard shortcuts
for (IExtension extension : extensions) {
IConfigurationElement[] configurationElements = extension.getConfigurationElements();
for (IConfigurationElement configurationElement : configurationElements) {
if (configurationElement.getName().equals("wizardShortcut")) {
String extenderName = configurationElement.getAttribute("id");

No comments: