"Excellence through total Moderation" - Cleobulus

Friday, February 15, 2008

Eclipse RCP Course

If you have found my Eclipse posts useful but still are not fully confident that you are getting the full picture of what Eclipse RCP is all about and how it works then fear not because my Zuhlke colleague and Eclipse Wizard, Stefanos, has released a specialised Eclipse RCP training course. I was one of the first ones to attend it and ... well I wouldn't be even near publishing any Eclipse blog posts if it wasn't for this course.

Highly recommended.

You can find more information here.

Thursday, February 14, 2008

Eclipse RCP Recipes: Creating Custom Eclipse Editors

In this blog entry I describe the model and basic steps towards creating a custom eclipse editor that is not necessarily bound to files or resources but a general object model. In this example we will describe the creation of a tree table editor.

The basic components needed for the editor’s development are:

  1. The class implementing the editor part (IEditorPart interface). In our example this class takes care of initialising the editor by constructing the table tree from a given object model.

  2. The class implementing the editor’s input (IEditorInput interface). This class will provide the editor with the necessary input data, as in the object model data, which will be displayed by the editor.

  3. The action delegate that binds the editor to the UI menu (IWorkbenchWindowActionDelegate interface).

  4. The object model.

  5. In case of a tree/tabular view such as the one in the example, we will need a content provider to provide the object model to the UI view elements and a label provider that will generate the correct UI output from the object model.

In this section I assume that the reader is familiar with the eclipse mechanisms of content and label providers for tree and table viewers.

  1. Create the Editor Part

    1. The first step is to extend the eclipse editors extension that will provide us with the basic skeleton for the editor part. In your plugin's MANIFEST.MF file editor, select the extensions page and add an org.eclipse.ui.editors extension (don’t use any templates just select and click Finsh).

    2. Then right click on that extension and go New->editor. Fill the fields:

      1. id = the id of the editor. You need it so that the editor can be identified by the action that will attempt to open it.

      2. name = the name of the editor in a human readable string. This will be shown on the editor tab.

      3. icon = the icon that will show on the editor’s tab.

      4. class = the editor’s implementing class. The extension point forces the implementation of the IEditorPart interface which offers the basic method declarations. However, you will normally be either subclassing the EditorPart or the MultiPageEditorPart abstract base classes that provide the basic functionality as well. In our example, since we are only using one page for our table tree we extend the EditorPart.

    3. Create the editor’s opening action

      1. We will add another extension to the plugin, in order to make our editor action that will open the editor from the menu. Once again at the extensions page of the MANIFEST.MF editor add the org.eclipse.ui.actionSets. Righ-click on it and go New->actionSet. On this set of actions you will need again to provide a unique id, a human readable label string, as well as set the visibility to true and providing a short description.

      2. Now we will add a submenu on the UI’s menubar. Right click on our new actionSet and go New->menu. Again give it an id and a label that will the text showing on the UI menubar. In the path field put “additions”. This will add it to the point of the menubar where new items can be added.

      3. Finally, we create our editor opening action. Right click on the actionSet, NOT the menu and go New->action. Besides the id and the UI visible label you will need to complete some other fields:

        1. menubarPath = this is the place where the action will be placed on the menu bar. Since we created our own submenu previously we would want to put it there. Thus for this field put the menu’s “[id]/content”.

        2. toolbarPath = this is the place you would put the action if you wanted to add it in the toolbar. Put it under “Normal/additions”.

        3. icon = the icon that will be shown both in the submenu option and the tool bar.

        4. class = the class that implements the action. In our case we will be implementing the IWorkbenchWindowActionDelegate interface.

  2. Create the editor’s input. Here we will be creating the class for the editor’s input that implements the EditorPart.

  3. Implement the action. In our action class we are mainly interested in the init(…) and the run(…) methods. The init method which initialises the action passes the workbench window which we will need so that we can extract the active page which is responsible for opening editors.

    1. In the init(…) simply store the window parameter as a field.

    2. In the run(…) method is where the magic happens, when the user selects the action from the UI menu. Here we create a new editor input object and pass it as a parameter to the active page’s openEditor(…) method along with the editor’s ID:

    IWorkbenchPage page = window.getActivePage();
    theEditorInput input = new theEditorInput();
    try {
    page.openEditor(input, theEditor.ID);
    } catch (PartInitException e) {
    LOGGER.error("Problem initialising the Editor");

  4. Implement the editor input. We are mainly interested here in implementing the getAdapter(…) method which is the method that the editor calls to get its input. The method gets as a parameter the class of the object that will be used as input for the editor, so we need to check that the object we pass is of the same class.

  5. Implement the editor part. Finally we come to our main class, the editor part. Here we are interested in the init(…) and the createPartControl(…) methods.

    1. The init(…) initialisation method is what basically gets called as a result of the propagation of the action’s run method that calls the page’s openEditor(…). Here we need to call the EditorPart superclass setSite(…) and setInput(…) to have our Editor initialise properly. We can then get the object model data by calling the getAdapter(…) method (seen above) from the editor input object parameter.

    2. The createPartControl(…) is called to construct and display the editor’s contents. Given that we have stored the object model data acquired from the init(…) method, inside the createPartControl(…) we can then do:

parent.setLayout(new FillLayout());
tableParent = parent;

... where createTable() is our method that initializes the table to be displayed by the editor, setting its content and label providers accordingly.

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");