This Tutorial describes how to extend the Eclipse IDE with custom plug-ins.

1. Extending the Eclipse IDE

The Eclipse platform and the Eclipse IDE is an extensible framework which allows to add additional functionality, remove or customize existing functionality.

Any download of the Eclipse IDE can be viewed as a special Eclipse application with the focus on supporting software development. An Eclipse application consists of individual software components, called plug-ins. For example, the Eclipse Java IDE provides the functionality to develop Java applications via the JDT plug-ins.

As Eclipse is build as an extensible framework, plug-ins can use and extend other plug-ins.

During development, you can start a new instance of the Eclipse IDE to test and debug your plug-ins. The new instance is sometimes called a runtime Eclipse or an inner Eclipse.

An easy way to start a runtime Eclipse is by selecting from the context menu of an plug-in or its manifest file. By default, this takes all the plug-ins from the workspace and the target environment, and start a runtime Eclipse with these plug-ins. If a plug-in is available in the workspace and the target environment, the one from the workspace is used.

eclipseideplugin70

You can also debug the runtime Eclipse. Put a breakpoint in a line of the source code which you want to inspect, right-click your plug-in and select .

When the execution flow reaches a statement marked with a breakpoint, the execution stops, and you are able to debug the related statement, and to inspect the current data.

2. Download the Eclipse SDK

If you plan to add functionalities to the Eclipse platform, you should download the latest Eclipse release. Official releases have stable APIs, therefore are a good foundation for adding your plug-ins and features.

The Eclipse IDE is provided in different flavors. While you can install the necessary tools in any Eclipse package, it is typically easier to download the Eclipse Standard distribution which contains all necessary tools for plug-in development. Other packages adds more tools which are not required for Eclipse plug-in development.

Download Eclipse Plug-in IDE

Eclipse provides also an Eclipse installer installer. The installer is useful, if you want to download several flavors of Eclipse. It uses a shared installation pool for common plug-ins, which reduces the required space.

3. Run configurations

3.1. What are run configurations?

The runtime Eclipse is based on the select set of plug-ins. These plug-ins are selected via a runtime configuration. This runtime configuration can be specified via:

  • a set of plug-ins or features or

  • a product which is used to create or update a run configuration

A run configuration also defines the environment which will be used to execute a generic launch. For example, it defines arguments to the Java virtual machine (VM), plug-in (classpath) dependencies, etc.

If you are starting an Eclipse runtime IDE for testing, and clear the workspace location the next run will prompt you to choose a workspace.

To review and edit your run configurations select from the Eclipse menu.

On the Main tab in the field Location, you specify where the configuration files for the runtime Eclipse are created.

Shows the run configuration

3.2. Defining arguments

The run configuration allows you to add additional start arguments for your application on the Arguments tab. By default Eclipse includes already several parameters, e.g. parameters for -os,-ws and -arch to specify the architecture on which the application is running.

-consoleLog in the run configuration

To pass system properties to your Eclipse application, you can add launch parameters using the -D switch. As example, if you add the argument -Dmy.product.loglevel=INFO, you can get the "INFO" value with System.getProperties("my.product.loglevel").

The following table lists several useful launch arguments.

Table 1. Launch parameters
Parameter Description

consoleLog

Error messages of the running Eclipse application are written to standard-out (System.out) which can be viewed in the Eclipse IDE Console view that started the RCP application.

nl

Specifies the locale used for your application. The locale defines the language specific settings, i.e., which translation is used and the number, date and currency formatting. For example -nl en starts your application using the English language. This is useful for testing translations.

console

Provides access to an OSGi console where you can check the status of your application.

noExit

Keeps the OSGi console open even if the application crashes. This allows to analyze the application dependencies even if the application crashes during startup.

clearPersistedState

Deletes cached runtime changes of the Eclipse 4 application model.

3.3. Launch configuration and Eclipse products

If you are developing Eclipse RCP applications, the launch configuration is created based on the product configuration file. The launch configuration is updated every time you start your application via the product.

You can use the created run configuration directly for starting the application again. In this case changes in the product configuration file are not considered.

Using an existing run configuration is a common source of frustration and time consuming error analysis. To ensure that you use the latest configuration from your product, start your application via the product file.

3.4. Checklist for common launch problems

Errors in the run configurations of Eclipse RCP application are frequently the source of problems. This chapter describes common problems related to the start of RCP applications. It can be used as a reference in case you face issues during the startup of your application.

The most common problem is that some required plug-ins are missing in your product. If you are using a feature based product configuration, you need to ensure that all plug-ins which are referred to in the MANIFEST.MF file are also included in your features. This error is reported in the Console view, typically it is one of the first error messages and you need to scroll up to see it.

The following listing shows how this message typically looks like (formating changed to make the text fit better).

                                      org                    .                    osgi                    .                    framework                    .                    BundleException                    :                    Could                    not                    resolve                    module:                    com                    .                    vogella                    .                    tasks                    .                    services                    [                    9                    ]                    Unresolved                    requirement:                    Require                    -                    Bundle:                    com                    .                    vogella                    .                    tasks                    .                    events                    ;                    bundle                    -                    version                    =                    "1.0.0"                                  

After identifying the missing plug-ins ensure that you add them to your product (if the product is plug-in based) or to your features (if the product is feature based).

Eclipse can check for missing dependencies automatically before you run the Launch configuration. On the Plug-ins Tab press the Validate Plug-ins button or select the Validate plug-ins automatically prior to launching option. This will check if you have all the required plug-ins in your run configuration.

Validate the runtime configuration

Avoid fixing problems with dependencies in the run configuration because the run configuration is created and updated based on the product configuration file. So always ensure that the product file is correctly configured instead of changing the derived information. The product configuration is used for the export of your product, hence an error in the product dependencies results in an exported application which cannot be started.

The following table lists potential problems and solutions.

Table 2. Run configuration problems
Problem Investigate

"Could not resolve module" message during start up.

Check that all required plug-ins are included in your product configuration. Make sure that your product defines dependencies to all required plug-ins or features. See the beginning of this section for a description how to solve the problem.

Bundles may also require a certain version of the Java virtual machine, e.g., a bundle may require Java 1.6 and will therefore not load in a Java 1.5 VM. Check the MANIFEST.MF file on the Overview tab in the Execution Environments section which Java version is required.

"java.lang.RuntimeException: No application id has been found." message during start up.

See "Could not resolve module" message during start up error. In most cases also triggered by a missing plug-in dependency.

Strange behavior but no error message.

Check if your run configuration includes the -consoleLog parameter. This option allows you to see errors from Eclipse based applications in the Console view of the Eclipse IDE.

Runtime configuration is frequently missing required plug-ins

Make sure that your product or your feature(s) includes all required dependencies.

A change in the product Dependencies tab is not reflected in the run configuration (e.g., a new plug-in is added but is not included in the run configuration)

A product updates an existing run configuration if you start the product directly from the product definition file. If you select the run configuration directly, it will not be updated.

Application model changes are not reflected in the Eclipse 4 application.

Eclipse 4 persists user changes in the application in a delta file which is restored at startup. During development this might lead to situations where model changes are not correctly applied to the runtime model, e.g., you define a new menu entry and this entry is not displayed in your application. Either set the Clear flag on the Main tab in your run configuration or add the clearPersistedState parameter for your product configuration file or run configuration.

Services, e.g., key bindings or the selection service, are not working in an Eclipse 4 application.

In Eclipse releases before 4.3 every part needed to implement a @Focus method which places the focus on an SWT control. This error does not occur anymore with Eclipse 4.3 or a higher release.

Menu entries are disabled in the Eclipse application.

Ensure that the HandlerProcessingAddon class in the package org.eclipse.e4.ui.internal.workbench.addons is registered as model add-on. The bundle symbolic name is org.eclipse.e4.ui.workbench.

Application "org.eclipse.ant.core.antRunner" could not be found in the registry or Application could not be found in the registry.

Ensure that you have pressed the New…​ button in the product configuration file and selected the E4Application as application to start. You can check the current setting in your plugin.xml file on the Extensions tab and in the details of the org.eclipse.core.runtime.products extension.

" Unresolved requirement: Require-Capability: osgi.extender; filter:='(&(osgi.extender=osgi.component)(version>=1.2)(!(version>=2.0)))' " message during start up or validation.

Add org.apache.felix.src and its dependencies to the product. Ensure you check the consistency of your product with the Validate button.

"Event Admin service is not available, unable to publish event org.osgi.service.event.Event" message during start up.

Add org.eclipse.equinox.event and its dependencies to the product. Ensure you check the consistency of your product with the Validate button.

4. Exercise: Creating and using a first plug-in

In this exercise you create an extension to the Eclipse IDE using a wizard.

4.1. Create a new plug-in project

Select to create a new plug-in.

Enter com.vogella.ide.first as name of the project.

eclipse plugin10

Press the Next button. On the next page enter the value as depicted on the following screenshot. Press the Next button.

eclipse plugin20

On the next page enable the Create a plug-in using one of the templates checkbox. Select the View contribution using 4.x API templates.

eclipse plugin30

Afterwards, press the Next button or the Finish button.

If you pressed the Next, now press Finish, otherwise the following page is not shown.

eclipse plugin40

The wizard creates now a new plug-in using the selected template. Use the Project Explorer to review the generated files.

4.2. Start runtime Eclipse with your new plug-in

You now start a runtime Eclipse with your generated plug-in.

Start a runtime Eclipse with all plug-ins from your current target (your IDE) and your own plug-in. For this, right-click on your project and select .

eclipse plugin50

This starts a new runtime Eclipse which contains a new example view.

4.3. Validate result

You should be able to open your Sample View view via the menu in your runtime IDE.

eclipse plugin60

eclipse plugin70

5. Using features and products to define your custom IDE

In this exercise you learn how to create features and products to configure and select the plug-ins selected for your runtime Eclipse.

5.1. Creating the feature

Create a new feature project called com.vogella.ide.feature via .

training feature ide10

On the second page of the wizard, select the plug-in you want to add to the feature

training feature ide20

Press the Finish button afterwards.

5.2. Validate content of the feature

Open the feature.xml file. Afterwards select the Included Plug-ins tab in the editor and ensure that the desired plug-ins from your workspace are included into this feature.

Ensure you have added the plug-in on the Included Plug-ins tab to include it into your feature. Using the Dependencies tab is wrong for this exercise.

5.3. Create a project to host the product configuration file

Create a new project called com.vogella.ide.product via .

productproject ide10

Enter the project name.

productproject ide20

Press Finish.

5.4. Create a product configuration file

Right-click on this project and select .

training product ide10

Create a product configuration file called ide.product inside your com.vogella.ide.product project folder.

training product ide12

Press the Finish button.

A new product file is created and opened in an editor.

5.5. Configure your product

Ensure you have the product editor open for your new file. On the Overview tab of the product editor press the New…​ button.

Entering the product details

Enter the com.vogella.ide.first plug-ins as Defining Plug-in. Use org.eclipse.ui.ide.workbench as application. Use name and id similar to the following screenshot.

Entering the product details

5.6. Enter version number

Enter the 1.0.0 version number into the product.

training product ide40

5.7. Enter includes features

Your product should be based on features. For this select the features option on the Overview tab.

ide switch to features

Select the Contents tab and add the following features via the Add…​ button.

  • com.vogella.ide.feature

  • org.eclipse.platform

Afterwards press Add Required button.

ide switch to features result

Save the ide.product file by pressing Ctrl S.

If you cannot add one of the listed features to your product, ensure that your product configuration is based on features.

5.8. Validate your setup by starting a runtime Eclipse

Select your product file and start the Eclipse IDE via the Run button.

training product ide60

As a result a runtime Eclipse IDE should start. It should contain only the features, which you have added to your product. For example, you should currently not be able to create a new Java project.

5.9. Add Java tooling to your IDE

Add org.eclipse.jdt.feature.group to your target platform. The target platform should look similar to the following listing.

                                      <?xml version="1.0" encoding="UTF-8" standalone="no"?>                    <?pde version="3.8"?>                    <target                    name=                    "target-platform"                    >                    <locations>                    <location                    includeAllPlatforms=                    "false"                    includeConfigurePhase=                    "true"                    includeMode=                    "planner"                    includeSource=                    "true"                    type=                    "InstallableUnit"                    >                    <repository                    location=                    "http://download.eclipse.org/releases/latest"                    />                    <unit                    id=                    "org.eclipse.equinox.sdk.feature.group"                    version=                    "0.0.0"                    />                    <unit                    id=                    "org.eclipse.platform.sdk"                    version=                    "0.0.0"                    />                    <unit                    id=                    "org.eclipse.jdt.feature.group"                    version=                    "0.0.0"                    />                    </location>                    </locations>                    </target>                                  

Afterwards, add the org.eclipse.jdt feature to your product and start a new runtime IDE via the product. Ensure that you now have the Java tooling installed, e.g., check via the new wizard, that you can create Java projects.

ide java wizard10

6. Exercise: Adding e4 part descriptors to 3.x based applications

In this exercise you add a model based part contribution to an Eclipse 3.x RCP application.

6.1. Adding a part descriptor

Create a simple plug-in named com.vogella.plugin.partdescriptor.

Add the following dependencies to your manifest file.

  • org.eclipse.core.runtime,

  • org.eclipse.jface,

  • org.eclipse.e4.ui.model.workbench,

  • org.eclipse.e4.ui.di

Create the following class

                                      package                    com.vogella.ide.ui                    ;                    import                    javax.annotation.PostConstruct                    ;                    import                    org.eclipse.e4.ui.di.Focus                    ;                    import                    org.eclipse.jface.viewers.ArrayContentProvider                    ;                    import                    org.eclipse.jface.viewers.LabelProvider                    ;                    import                    org.eclipse.jface.viewers.TableViewer                    ;                    import                    org.eclipse.swt.SWT                    ;                    import                    org.eclipse.swt.widgets.Composite                    ;                    public                    class                    PartEclipse4x                    {                    private                    TableViewer                    viewer                    ;                    @PostConstruct                    public                    void                    createPartControl                    (                    Composite                    parent                    )                    {                    viewer                    =                    new                    TableViewer                    (                    parent                    ,                    SWT                    .                    MULTI                    |                    SWT                    .                    H_SCROLL                    |                    SWT                    .                    V_SCROLL                    );                    viewer                    .                    setContentProvider                    (                    ArrayContentProvider                    .                    getInstance                    ());                    viewer                    .                    setLabelProvider                    (                    new                    LabelProvider                    ());                    viewer                    .                    setInput                    (                    new                    String                    []                    {                    "One"                    ,                    "Two"                    ,                    "Three"                    });                    }                    @Focus                    public                    void                    setFocus                    ()                    {                    viewer                    .                    getControl                    ().                    setFocus                    ();                    }                    }                                  

Add a new model fragment to this plug-in via .

Adding a part descriptor to the Eclipse IDE

Adding a part descriptor to the Eclipse IDE

Adding a part descriptor to the Eclipse IDE

6.2. Validate

Start an instance of the Eclipse IDE and validate that you can open the parts via the Quick Access box (shortcut CTRL+3 ).

You can also open the part via the menu entry.

7. Accessing the IEclipseContext from 3.x API

The Eclipse IDE uses the IEclipseContext data structure to store central information about the IDE. You can access this information also via the Eclipse 3.x API.

For example, to access the context from an Eclipse 3.x API view, you can use the following snippet.

                                  // get the context of a part                  IEclipseContext                  partContext                  =                  getViewSite                  ().                  getService                  (                  IEclipseContext                  .                  class                  );                  // or access directly a value in the context based on its key                  EModelService                  service                  =                  getViewSite                  ().                  getService                  (                  EModelService                  .                  class                  );                              

This snippet demonstrates the access via an Eclipse 3.x API handler.

                                  // the following example assumes you are in a handler                  // get context from active window                  IEclipseContext                  windowCtx                  =                  HandlerUtil                  .                  getActiveWorkbenchWindow                  (                  event                  ).                  getService                  (                  IEclipseContext                  .                  class                  );                  // get context from active part                  IEclipseContext                  ctx                  =                  HandlerUtil                  .                  getActivePart                  (                  event                  ).                  getSite                  ().                  getService                  (                  IEclipseContext                  .                  class                  );                              

8. Contributing model elements to the Eclipse IDE or 3.x RCP applications

8.1. Adding Eclipse 4.x parts to Eclipse 3.x applications via the org.eclipse.ui.views extension point

You can also use a e4 part in an extension for the org.eclipse.ui.views extension point. Use the e4view entry in the context menu of the extension to archive this. The resulting object is created via dependency injection.

For such a kind of view the existing toolbar and view extension point contributions do not work. To add for example a toolbar to your e4view, get the MToolbar injected into its implementation and construct the entries in your source code.

Menus, handlers and commands can be contributed to an Eclipse application via model fragments.

You can use the model spy from the e4 tools project to identify the ID of the element you want to contribute too.

With the correct ID you can create model fragments that contribute to the corresponding application model element. The following screenshot demonstrate how to contribute to the menuContributions feature of the Eclipse IDE.

Contributing to the Eclipse menu

After you added a MenuContribution item you can contribute a menu. The Parent-ID must be the ID of the menu your are contributing to.

Contributing to the Eclipse menu

Contributing to the Eclipse menu

The model fragment must be registered in the plugin.xml file via an extension to the org.eclipse.e4.workbench.model extension point, as demonstrated in the following listing.

                                      <?xml version="1.0" encoding="utf-8"?>                    <plugin>                    <extension                    id=                    "id1"                    point=                    "org.eclipse.e4.workbench.model"                    >                    <fragment                    apply=                    "notexists"                    uri=                    "fragment.e4xmi"                    >                    </fragment>                    </extension>                    </plugin>                                  

8.3. Error analysis

In case of problems, check the source code of plugin.xml and validate that your model fragment is included. Verify the name of the referred model fragment and ensure all the defined ID are available in the running configuration.

8.4. Adding e4 toolbar entries to the appliation window

Similar to menus you can contribute toolbar contributions.

This approach does currently not work for view toolbars.

8.5. Supporting part descriptors in an Eclipse IDE

The Eclipse IDE supports the contribution of part descriptor model elements via fragments or processors.

If you use the org.eclipse.e4.legacy.ide.application ID to contribute your part descriptors, the views can be opened via the dialog or via the Quick Access. This requires that you add the View tag to such a part descriptor.

Eclipse 3.x API RCP applications running on top of a 4.5 or higher runtime can use the same approach.

8.6. Adding perspectives to the Eclipse IDE via model snippets

Your model fragment or processor can also contribute a perspective to an Eclipse 4.x IDE. For this add a perspective via a snippet. This extended element id can be generic with xpath:/ and the Feature name is snippets.

This approach can also be used to contribute a perspective to your Eclipse 3.x API based RCP application running on top of an Eclipse 4.x runtime.

9. Exercise: Add a new perspective to the Eclipse IDE

In this exercise you contribute a new perspective to the Eclipse IDE.

9.1. Create model elements

In your com.vogella.contribute.parts plug-in, create the following model fragment.

e4 ide perspective10

Add at least one part to the perspective.

e4 ide perspective20

9.2. Validate

Start the Eclipse IDE and validate that you can open the new perspective via the perspective switcher dialog.

10. Optional Exercise: Adding POJO views via extension points

In this exercise you create a e4 based view extension via a separate plug-in. For this you use e4view element of the org.eclipse.ui.views extension point.

This extension can be contributed to the Eclipse IDE (or another Eclipse 3.x API based RCP application).

10.1. Create a plug-in

Create an plug-in called com.vogella.ide.e4view. Use the .

Call the project com.vogella.ide.e4view and select the options similar to the following screenshots.

eclipse3rcp e4viewexample10

eclipse3rcp e4viewexample20

eclipse3rcp e4viewexample30

eclipse3rcp e4viewexample40

10.2. Adjust Plug-in dependencies

Add org.eclipse.e4.ui.di as a dependency to the manifest of your new plug-in.

10.3. Create your e4 view

Adjust the created implementation of SampleE4View to the following.

                                      package                    com.vogella.ide.e4view.views                    ;                    import                    javax.annotation.PostConstruct                    ;                    import                    javax.inject.Inject                    ;                    import                    org.eclipse.e4.ui.di.Focus                    ;                    import                    org.eclipse.jface.action.Action                    ;                    import                    org.eclipse.jface.action.IMenuListener                    ;                    import                    org.eclipse.jface.action.IMenuManager                    ;                    import                    org.eclipse.jface.action.MenuManager                    ;                    import                    org.eclipse.jface.action.Separator                    ;                    import                    org.eclipse.jface.dialogs.MessageDialog                    ;                    import                    org.eclipse.jface.viewers.ArrayContentProvider                    ;                    import                    org.eclipse.jface.viewers.DoubleClickEvent                    ;                    import                    org.eclipse.jface.viewers.IDoubleClickListener                    ;                    import                    org.eclipse.jface.viewers.IStructuredSelection                    ;                    import                    org.eclipse.jface.viewers.ITableLabelProvider                    ;                    import                    org.eclipse.jface.viewers.LabelProvider                    ;                    import                    org.eclipse.jface.viewers.TableViewer                    ;                    import                    org.eclipse.swt.SWT                    ;                    import                    org.eclipse.swt.graphics.Image                    ;                    import                    org.eclipse.swt.widgets.Composite                    ;                    import                    org.eclipse.swt.widgets.Menu                    ;                    import                    org.eclipse.ui.ISharedImages                    ;                    import                    org.eclipse.ui.IWorkbench                    ;                    import                    org.eclipse.ui.IWorkbenchActionConstants                    ;                    public                    class                    SampleE4View                    {                    /**      * The ID of the view as specified by the extension.      */                    public                    static                    final                    String                    ID                    =                    "com.vogella.ide.e4view.views.SampleE4View"                    ;                    @Inject                    IWorkbench                    workbench                    ;                    private                    TableViewer                    viewer                    ;                    private                    Action                    action1                    ;                    private                    Action                    action2                    ;                    private                    Action                    doubleClickAction                    ;                    class                    ViewLabelProvider                    extends                    LabelProvider                    implements                    ITableLabelProvider                    {                    @Override                    public                    String                    getColumnText                    (                    Object                    obj                    ,                    int                    index                    )                    {                    return                    getText                    (                    obj                    );                    }                    @Override                    public                    Image                    getColumnImage                    (                    Object                    obj                    ,                    int                    index                    )                    {                    return                    getImage                    (                    obj                    );                    }                    @Override                    public                    Image                    getImage                    (                    Object                    obj                    )                    {                    return                    workbench                    .                    getSharedImages                    ().                    getImage                    (                    ISharedImages                    .                    IMG_OBJ_ELEMENT                    );                    }                    }                    @PostConstruct                    public                    void                    createPartControl                    (                    Composite                    parent                    )                    {                    viewer                    =                    new                    TableViewer                    (                    parent                    ,                    SWT                    .                    MULTI                    |                    SWT                    .                    H_SCROLL                    |                    SWT                    .                    V_SCROLL                    );                    viewer                    .                    setContentProvider                    (                    ArrayContentProvider                    .                    getInstance                    ());                    viewer                    .                    setInput                    (                    new                    String                    []                    {                    "One"                    ,                    "Two"                    ,                    "Three"                    });                    viewer                    .                    setLabelProvider                    (                    new                    ViewLabelProvider                    ());                    // Create the help context id for the viewer's control                    workbench                    .                    getHelpSystem                    ().                    setHelp                    (                    viewer                    .                    getControl                    (),                    "com.vogella.ide.e4view.viewer"                    );                    makeActions                    ();                    hookContextMenu                    ();                    hookDoubleClickAction                    ();                    }                    private                    void                    hookContextMenu                    ()                    {                    MenuManager                    menuMgr                    =                    new                    MenuManager                    (                    "#PopupMenu"                    );                    menuMgr                    .                    setRemoveAllWhenShown                    (                    true                    );                    menuMgr                    .                    addMenuListener                    (                    new                    IMenuListener                    ()                    {                    @Override                    public                    void                    menuAboutToShow                    (                    IMenuManager                    manager                    )                    {                    SampleE4View                    .                    this                    .                    fillContextMenu                    (                    manager                    );                    }                    });                    Menu                    menu                    =                    menuMgr                    .                    createContextMenu                    (                    viewer                    .                    getControl                    ());                    viewer                    .                    getControl                    ().                    setMenu                    (                    menu                    );                    }                    private                    void                    fillContextMenu                    (                    IMenuManager                    manager                    )                    {                    manager                    .                    add                    (                    action1                    );                    manager                    .                    add                    (                    action2                    );                    // Other plug-ins can contribute there actions here                    manager                    .                    add                    (                    new                    Separator                    (                    IWorkbenchActionConstants                    .                    MB_ADDITIONS                    ));                    }                    private                    void                    makeActions                    ()                    {                    action1                    =                    new                    Action                    ()                    {                    @Override                    public                    void                    run                    ()                    {                    showMessage                    (                    "Action 1 executed"                    );                    }                    };                    action1                    .                    setText                    (                    "Action 1"                    );                    action1                    .                    setToolTipText                    (                    "Action 1 tooltip"                    );                    action1                    .                    setImageDescriptor                    (                    workbench                    .                    getSharedImages                    ().                    getImageDescriptor                    (                    ISharedImages                    .                    IMG_OBJS_INFO_TSK                    ));                    action2                    =                    new                    Action                    ()                    {                    @Override                    public                    void                    run                    ()                    {                    showMessage                    (                    "Action 2 executed"                    );                    }                    };                    action2                    .                    setText                    (                    "Action 2"                    );                    action2                    .                    setToolTipText                    (                    "Action 2 tooltip"                    );                    action2                    .                    setImageDescriptor                    (                    workbench                    .                    getSharedImages                    ().                    getImageDescriptor                    (                    ISharedImages                    .                    IMG_OBJS_INFO_TSK                    ));                    doubleClickAction                    =                    new                    Action                    ()                    {                    @Override                    public                    void                    run                    ()                    {                    IStructuredSelection                    selection                    =                    viewer                    .                    getStructuredSelection                    ();                    Object                    obj                    =                    selection                    .                    getFirstElement                    ();                    showMessage                    (                    "Double-click detected on "                    +                    obj                    .                    toString                    ());                    }                    };                    }                    private                    void                    hookDoubleClickAction                    ()                    {                    viewer                    .                    addDoubleClickListener                    (                    new                    IDoubleClickListener                    ()                    {                    @Override                    public                    void                    doubleClick                    (                    DoubleClickEvent                    event                    )                    {                    doubleClickAction                    .                    run                    ();                    }                    });                    }                    private                    void                    showMessage                    (                    String                    message                    )                    {                    MessageDialog                    .                    openInformation                    (                    viewer                    .                    getControl                    ().                    getShell                    (),                    "e4view View"                    ,                    message                    );                    }                    @Focus                    public                    void                    setFocus                    ()                    {                    viewer                    .                    getControl                    ().                    setFocus                    ();                    }                    }                                  

If you now start this plug-in and open your view , you receive the com.vogella.ide.e4view.views.SampleE4View cannot be cast to org.eclipse.ui.IViewPart error message. The next step is required to use this adjusted class correctly.

10.4. Adjust the entries in the extension point

Replace the view attribute with an e4view attribute for the org.eclipse.ui.views extension point.

For this use the Extensions tab of the plugin.xml editor.

Adding e4view entry

Eclipse 4.x based view

The final relevant source code for the org.eclipse.ui.views extension in the plugin.xml file should look similar to the following:

                                      <?xml version="1.0" encoding="UTF-8"?>                    <?eclipse version="3.4"?>                    <plugin>                    <extension                    point=                    "org.eclipse.ui.views"                    >                    <category                    name=                    "Sample Category"                    id=                    "com.vogella.ide.e4view"                    >                    </category>                    <e4view                    category=                    "com.vogella.ide.e4view"                    class=                    "com.vogella.ide.e4view.views.SampleE4View"                    icon=                    "icons/sample.png"                    id=                    "com.vogella.ide.e4view.e4view1"                    name=                    "e4view View"                    restorable=                    "true"                    >                    </e4view>                    </extension>                    <!-- MORE ENTRIES, LEFT OUT FOR BREVITY -->                    </plugin>                                  

10.5. Validate the usage of the e4 view

Start your plug-in in the Eclipse IDE and validate that you can open the view via the menu entry. The view should look similar to the following and should provide a context menu on the items.

Adding clearPersistedState flag

To avoid seeing model persisted data, add the -clearPersistedState flag is set in your runtime configuration.

Adding clearPersistedState flag

10.6. Add the view to a perspective extension

To add the view to the Java perspective, adjust the existing org.eclipse.ui.perspectiveExtensions entry as depicted in the following screenshot.

Adding a view to an existing perspective

10.7. Optional exercise: Add a toolbar to your e4 view

The extension point processing currently expects the normal view extension not the e4view extension. To add a toolbar to your e4view you have to process the relevant information yourself. For example, you could get the EModelService injected and add the toolbar based on the extension registry or a model snippet. The following simply creates one toolbar entry for demonstration purposes.

                                      @PostConstruct                    public                    void                    createPartControl                    (                    Composite                    parent                    ,                    MPart                    part                    ,                    EModelService                    modelService                    )                    {                    viewer                    =                    new                    TableViewer                    (                    parent                    ,                    SWT                    .                    MULTI                    |                    SWT                    .                    H_SCROLL                    |                    SWT                    .                    V_SCROLL                    );                    viewer                    .                    setUseHashlookup                    (                    true                    );                    // use faster hash lookup of data model                    viewer                    .                    setContentProvider                    (                    ArrayContentProvider                    .                    getInstance                    ());                    viewer                    .                    setInput                    (                    new                    String                    []                    {                    "One"                    ,                    "Two"                    ,                    "Three"                    });                    viewer                    .                    setLabelProvider                    (                    new                    ViewLabelProvider                    ());                    // Create the help context id for the viewer's control                    workbench                    .                    getHelpSystem                    ().                    setHelp                    (                    viewer                    .                    getControl                    (),                    "com.vogella.ide.e4view.viewer"                    );                    makeActions                    ();                    hookContextMenu                    ();                    hookDoubleClickAction                    ();                    MToolBar                    toolbar                    =                    modelService                    .                    createModelElement                    (                    MToolBar                    .                    class                    );                    MHandledToolItem                    toolitem                    =                    modelService                    .                    createModelElement                    (                    MHandledToolItem                    .                    class                    );                    toolitem                    .                    setLabel                    (                    "View Tool Item"                    );                    // TODO set the icon and the command relevant for the toolbar item                    toolbar                    .                    getChildren                    ().                    add                    (                    toolitem                    );                    part                    .                    setToolbar                    (                    toolbar                    );                    }                                  

In this exercise you will add menu and toolbar contributions to the IDE via the com.vogella.tasks.ui plug-in.

11.1. Adding the plug-in dependencies

Ensure that the following dependencies are in the manifest file of com.vogella.tasks.ui.

  • org.eclipse.e4.core.di,

  • org.eclipse.jface

11.2. Creating the handler class

Create the following class based on the generated handler class.

                                  package                  com.vogella.tasks.ui.handlers                  ;                  import                  org.eclipse.e4.core.di.annotations.Execute                  ;                  import                  org.eclipse.jface.dialogs.MessageDialog                  ;                  import                  org.eclipse.swt.widgets.Shell                  ;                  public                  class                  TestHandler                  {                  @Execute                  public                  void                  execute                  (                  Shell                  shell                  )                  {                  MessageDialog                  .                  openInformation                  (                  shell                  ,                  "First"                  ,                  "Hello, e4 API world"                  );                  }                  }                              

11.3. Create a model fragment for your contributions

Create a new model fragment via from the context menu of the plug-in project.

Create Model Fragment

The file should be called commands.e4xmi.

Create Model Fragment

Press the Finish button.

Ensure that the new fragment is correctly registered in the plugin.xml as extension.

migrategenerated30

11.4. Define a command contribution

Create a model fragment contributing a command to the commands of the top-level element using the xpath:/ element id.

Use the following screenshots to define the new contribution.

migrategenerated40

migrategenerated50

Ensure to set the persistState flag to false. This ensures that the element is not available if the plug-in is not installed.

persistState false

11.5. Define a handler contribution

migrategenerated60

Add a handler for the defined command and use your TestHandler as implementation.

migrategenerated70

Ensure to set the persistState flag to false. This ensures that the element is not available if the plug-in is not installed.

persistState false

migrategenerated80

Ensure to set the persistState flag to false. This ensures that the element is not available if the plug-in is not installed.

persistState false

migrategenerated90

migrategenerated92

Add at least one menu entry to your menu, otherwise it will not be displayed.

migrategenerated94

Start a new instance of the Eclipse IDE and validate that your menu is visible and working. If it is not visible, check via the model spy for potential issues.

migrategenerated96

12. Exercise: Add a trimbar to the Eclipse IDE

12.1. Adding a trimbar contribution

Also add a trimbar contribution for the same command.

toolbarcontribution10

toolbarcontribution20

Ensure to set the persistState flag to false. This ensures that the element is not available if the plug-in is not installed.

persistState false

Add a toolbar to your trimbar.

toolbarcontribution30

Add a handled tool item to your contribution.

toolbarcontribution40

12.2. Validate the presence of the toolbar contribution

Start a new instance of the Eclipse IDE and validate that your new toolbar is available. If they are not visible in the window, check via the model spy for potential issues.

toolbarcontribution50

13. Optional Exercise: Add icon to your toolbar entry

Create an icons folder. Use the Plug-in Image Browser to save an icon in your project.

plugin image browser

Assign this icon to your toolbar entry.

toolbarcontribution60

14. Resources and Marker

Eclipse represents Resources like Projects, Files, Folders, Packages as IResource.

Marker represent additional information for resources, e.g., an error marker. This information is not stored within the resource (file) but as additional information in the workspace metadata.

Every marker can have attributes (key / value combination). Markers can be displayed in the standard view, e.g., the Task, Bookmark or the Problems view. To be displayed in these views, you have to use predefined attributes.

15. Exercise: Create Markers for resources

Create a plug-in project com.vogella.plugin.markers based on the e4 handler template.

marker plugin page1

marker plugin page2

marker plugin page3

marker plugin page4

This template will create a AddMarkerHandler handler, which should be used to create an IMarker for a selected resource.

Add the following dependencies:

  • org.eclipse.jface

  • org.eclipse.e4.ui.services

  • org.eclipse.e4.core.di.annotations

  • org.eclipse.core.resources

  • org.eclipse.core.runtime

  • org.eclipse.e4.core.services

Modify the AddMarkerHandler code to the following:

                                  package                  de.vogella.plugin.markers.handler                  ;                  import                  javax.inject.Named                  ;                  import                  org.eclipse.core.resources.IMarker                  ;                  import                  org.eclipse.core.resources.IResource                  ;                  import                  org.eclipse.e4.core.di.annotations.Execute                  ;                  import                  org.eclipse.e4.core.services.adapter.Adapter                  ;                  import                  org.eclipse.e4.ui.services.IServiceConstants                  ;                  import                  org.eclipse.jface.viewers.IStructuredSelection                  ;                  public                  class                  AddMarkerHandler                  {                  @Execute                  public                  void                  execute                  (                  @Named                  (                  IServiceConstants                  .                  ACTIVE_SELECTION                  )                  IStructuredSelection                  selection                  ,                  Adapter                  adapter                  )                  {                  if                  (                  selection                  ==                  null                  ||                  selection                  .                  isEmpty                  ())                  {                  return                  ;                  }                  Object                  firstElement                  =                  selection                  .                  getFirstElement                  ();                  IResource                  resource                  =                  adapter                  .                  adapt                  (                  firstElement                  ,                  IResource                  .                  class                  );                  if                  (                  resource                  !=                  null                  )                  {                  writeMarkers                  (                  resource                  );                  }                  }                  private                  void                  writeMarkers                  (                  IResource                  resource                  )                  {                  try                  {                  IMarker                  marker                  =                  resource                  .                  createMarker                  (                  IMarker                  .                  TASK                  );                  marker                  .                  setAttribute                  (                  IMarker                  .                  MESSAGE                  ,                  "This is a task"                  );                  marker                  .                  setAttribute                  (                  IMarker                  .                  PRIORITY                  ,                  IMarker                  .                  PRIORITY_HIGH                  );                  }                  catch                  (                  Exception                  e                  )                  {                  e                  .                  printStackTrace                  ();                  }                  }                  }                              

In the fragment.e4xmi file the command's name should be changed from "Hello World" to "Add Task Marker".

If you run, you can create a marker in the Tasks View if you select a Java project or any other IResource and click the menu entry.

marker40

16. Adapters

Adapters help to display information about objects in view without having to adjust the existing views.

17. Exercise - Adapters for the Properties view

We will simply use an adapter to show our data in the Properties view.

Create a new plug-in project de.vogella.plugin.adapter.

Add the following dependencies in the dependencies tab of the MANIFEST.MF file:

  • org.eclipse.core.runtime

  • org.eclipse.e4.ui.model.workbench

  • org.eclipse.e4.ui.services

  • org.eclipse.e4.ui.workbench

  • org.eclipse.ui

  • org.eclipse.ui.views

Create the following Todo class as data model.

                                  package                  de.vogella.plugin.adapter.model                  ;                  public                  class                  Todo                  {                  private                  String                  summary                  ;                  private                  String                  description                  ;                  private                  boolean                  done                  ;                  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                  ;                  }                  public                  boolean                  isDone                  ()                  {                  return                  done                  ;                  }                  public                  void                  setDone                  (                  boolean                  done                  )                  {                  this                  .                  done                  =                  done                  ;                  }                  }                              

Create a model fragment (fragment.e4xmi) and add a PartDescriptor called Sample View.

adapter todo descriptor

Create SampleView.java as part for the PartDescriptor implementation.

                                  package                  de.vogella.plugin.adapter.views                  ;                  import                  java.util.ArrayList                  ;                  import                  java.util.List                  ;                  import                  javax.annotation.PostConstruct                  ;                  import                  org.eclipse.e4.ui.workbench.modeling.ESelectionService                  ;                  import                  org.eclipse.jface.viewers.ArrayContentProvider                  ;                  import                  org.eclipse.jface.viewers.ISelectionChangedListener                  ;                  import                  org.eclipse.jface.viewers.ITableLabelProvider                  ;                  import                  org.eclipse.jface.viewers.LabelProvider                  ;                  import                  org.eclipse.jface.viewers.SelectionChangedEvent                  ;                  import                  org.eclipse.jface.viewers.TableViewer                  ;                  import                  org.eclipse.swt.SWT                  ;                  import                  org.eclipse.swt.graphics.Image                  ;                  import                  org.eclipse.swt.widgets.Composite                  ;                  import                  org.eclipse.ui.ISharedImages                  ;                  import                  org.eclipse.ui.PlatformUI                  ;                  import                  de.vogella.plugin.adapter.model.Todo                  ;                  public                  class                  SampleView                  {                  private                  TableViewer                  viewer                  ;                  class                  ViewLabelProvider                  extends                  LabelProvider                  implements                  ITableLabelProvider                  {                  public                  String                  getColumnText                  (                  Object                  obj                  ,                  int                  index                  )                  {                  Todo                  todo                  =                  (                  Todo                  )                  obj                  ;                  return                  todo                  .                  getSummary                  ();                  }                  public                  Image                  getColumnImage                  (                  Object                  obj                  ,                  int                  index                  )                  {                  return                  getImage                  (                  obj                  );                  }                  public                  Image                  getImage                  (                  Object                  obj                  )                  {                  return                  PlatformUI                  .                  getWorkbench                  ().                  getSharedImages                  ().                  getImage                  (                  ISharedImages                  .                  IMG_OBJ_ELEMENT                  );                  }                  }                  /**      * This is a callback that will allow us to create the viewer and initialize      * it.      */                  @PostConstruct                  public                  void                  createPartControl                  (                  Composite                  parent                  ,                  ESelectionService                  selectionService                  )                  {                  viewer                  =                  new                  TableViewer                  (                  parent                  ,                  SWT                  .                  MULTI                  |                  SWT                  .                  H_SCROLL                  |                  SWT                  .                  V_SCROLL                  );                  viewer                  .                  setContentProvider                  (                  new                  ArrayContentProvider                  ());                  viewer                  .                  setLabelProvider                  (                  new                  ViewLabelProvider                  ());                  viewer                  .                  addSelectionChangedListener                  (                  new                  ISelectionChangedListener                  ()                  {                  @Override                  public                  void                  selectionChanged                  (                  SelectionChangedEvent                  event                  )                  {                  selectionService                  .                  setSelection                  (                  event                  .                  getSelection                  ());                  }                  });                  viewer                  .                  setInput                  (                  getElements                  ());                  }                  // Build up a simple data model                  private                  List                  <                  Todo                  >                  getElements                  ()                  {                  List                  <                  Todo                  >                  todos                  =                  new                  ArrayList                  <>();                  Todo                  todo                  =                  new                  Todo                  ();                  todo                  .                  setSummary                  (                  "First Todo"                  );                  todo                  .                  setDescription                  (                  "A very good description"                  );                  todo                  .                  setDone                  (                  true                  );                  todos                  .                  add                  (                  todo                  );                  todo                  =                  new                  Todo                  ();                  todo                  .                  setSummary                  (                  "Second Todo"                  );                  todo                  .                  setDescription                  (                  "Second super description"                  );                  todos                  .                  add                  (                  todo                  );                  return                  todos                  ;                  }                  }                              

After this change, you should be able to run your project, open your view and see your to-do items.

To display the Todo values in the Properties view, add the extension point org.eclipse.core.runtime.adapters to your project.

The data of the extension point should be like the following:

                                  <extension                  point=                  "org.eclipse.core.runtime.adapters"                  >                  <factory                  adaptableType=                  "de.vogella.plugin.adapter.model.Todo"                  class=                  "de.vogella.plugin.adapter.TodoAdapterFactory"                  >                  <adapter                  type=                  "org.eclipse.ui.views.properties.IPropertySource"                  >                  </adapter>                  </factory>                  </extension>                              

Implement the IPropertySource interface to provide it for the Properties view.

                                  package                  de.vogella.plugin.adapter                  ;                  import                  org.eclipse.ui.views.properties.IPropertyDescriptor                  ;                  import                  org.eclipse.ui.views.properties.IPropertySource                  ;                  import                  org.eclipse.ui.views.properties.TextPropertyDescriptor                  ;                  import                  de.vogella.plugin.adapter.model.Todo                  ;                  public                  class                  TodoPropertySource                  implements                  IPropertySource                  {                  private                  final                  Todo                  todo                  ;                  public                  TodoPropertySource                  (                  Todo                  todo                  )                  {                  this                  .                  todo                  =                  todo                  ;                  }                  @Override                  public                  boolean                  isPropertySet                  (                  Object                  id                  )                  {                  return                  false                  ;                  }                  @Override                  public                  Object                  getEditableValue                  ()                  {                  return                  this                  ;                  }                  @Override                  public                  IPropertyDescriptor                  []                  getPropertyDescriptors                  ()                  {                  return                  new                  IPropertyDescriptor                  []                  {                  new                  TextPropertyDescriptor                  (                  "summary"                  ,                  "Summary"                  ),                  new                  TextPropertyDescriptor                  (                  "description"                  ,                  "Description"                  )                  };                  }                  @Override                  public                  Object                  getPropertyValue                  (                  Object                  id                  )                  {                  if                  (                  id                  .                  equals                  (                  "summary"                  ))                  {                  return                  todo                  .                  getSummary                  ();                  }                  if                  (                  id                  .                  equals                  (                  "description"                  ))                  {                  return                  todo                  .                  getDescription                  ();                  }                  return                  null                  ;                  }                  @Override                  public                  void                  resetPropertyValue                  (                  Object                  id                  )                  {                  }                  @Override                  public                  void                  setPropertyValue                  (                  Object                  id                  ,                  Object                  value                  )                  {                  String                  s                  =                  (                  String                  )                  value                  ;                  if                  (                  id                  .                  equals                  (                  "summary"                  ))                  {                  todo                  .                  setSummary                  (                  s                  );                  }                  if                  (                  id                  .                  equals                  (                  "description"                  ))                  {                  todo                  .                  setDescription                  (                  s                  );                  }                  }                  }                              

Implement the factory and the new class TodoPropertySource which implements IPropertySource.

                                  package                  de.vogella.plugin.adapter                  ;                  import                  org.eclipse.core.runtime.IAdapterFactory                  ;                  import                  org.eclipse.ui.views.properties.IPropertySource                  ;                  import                  de.vogella.plugin.adapter.model.Todo                  ;                  public                  class                  TodoAdapterFactory                  implements                  IAdapterFactory                  {                  // use a static final field so that the adapterList is only instanciated once                  private                  static                  final                  Class                  <?>[]                  adapterList                  =                  new                  Class                  <?>[]                  {                  IPropertySource                  .                  class                  };                  @Override                  public                  <                  T                  >                  T                  getAdapter                  (                  Object                  adaptableObject                  ,                  Class                  <                  T                  >                  adapterType                  )                  {                  if                  (                  adapterType                  ==                  IPropertySource                  .                  class                  &&                  adaptableObject                  instanceof                  Todo                  ){                  return                  adapterType                  .                  cast                  (                  new                  TodoPropertySource                  ((                  Todo                  )                  adaptableObject                  ));                  }                  return                  null                  ;                  }                  @Override                  public                  Class                  <?>[]                  getAdapterList                  ()                  {                  return                  adapterList                  ;                  }                  }                              

If you run your workbench and open your view via and you select a data element in your viewer you should see your data in the Properties view.

adapter40

18. Exercise - Adapters and the WorkbenchLabelProvider

The de.vogella.plugin.adapter plug-in from the Exercise - Adapters for the Properties view should be reused for this exercise.

Create another PartDescriptor called WorkbenchAdapter Sample, which also has the Sample Category category.

adapter todo workbenchadapter descriptor

Create SampleWorkbenchAdapterView.java as part for the PartDescriptor implementation. The only difference to the previous SampleView is that a DelegatingStyledCellLabelProvider is used as LabelProvider, which takes the WorkbenchLabelProvider as IStyledLabelProvider implementation.

                                  package                  de.vogella.plugin.adapter.views                  ;                  import                  java.util.ArrayList                  ;                  import                  java.util.List                  ;                  import                  javax.annotation.PostConstruct                  ;                  import                  org.eclipse.e4.ui.workbench.modeling.ESelectionService                  ;                  import                  org.eclipse.jface.viewers.ArrayContentProvider                  ;                  import                  org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider                  ;                  import                  org.eclipse.jface.viewers.ISelectionChangedListener                  ;                  import                  org.eclipse.jface.viewers.SelectionChangedEvent                  ;                  import                  org.eclipse.jface.viewers.TableViewer                  ;                  import                  org.eclipse.swt.SWT                  ;                  import                  org.eclipse.swt.widgets.Composite                  ;                  import                  org.eclipse.ui.model.WorkbenchLabelProvider                  ;                  import                  de.vogella.plugin.adapter.model.Todo                  ;                  public                  class                  SampleWorkbenchAdapterView                  {                  private                  TableViewer                  viewer                  ;                  /**      * This is a callback that will allow us to create the viewer and initialize      * it.      */                  @PostConstruct                  public                  void                  createPartControl                  (                  Composite                  parent                  ,                  ESelectionService                  selectionService                  )                  {                  viewer                  =                  new                  TableViewer                  (                  parent                  ,                  SWT                  .                  MULTI                  |                  SWT                  .                  H_SCROLL                  |                  SWT                  .                  V_SCROLL                  );                  viewer                  .                  setContentProvider                  (                  new                  ArrayContentProvider                  ());                  // make use of the DelegatingStyledCellLabelProvider with the WorkbenchLabelProvider as IStyledLabelProvider implementation                  viewer                  .                  setLabelProvider                  (                  new                  DelegatingStyledCellLabelProvider                  (                  new                  WorkbenchLabelProvider                  ()));                  viewer                  .                  addSelectionChangedListener                  (                  new                  ISelectionChangedListener                  ()                  {                  @Override                  public                  void                  selectionChanged                  (                  SelectionChangedEvent                  event                  )                  {                  selectionService                  .                  setSelection                  (                  event                  .                  getSelection                  ());                  }                  });                  viewer                  .                  setInput                  (                  getElements                  ());                  }                  // Build up a simple data model                  private                  List                  <                  Todo                  >                  getElements                  ()                  {                  List                  <                  Todo                  >                  todos                  =                  new                  ArrayList                  <>();                  Todo                  todo                  =                  new                  Todo                  ();                  todo                  .                  setSummary                  (                  "First Todo"                  );                  todo                  .                  setDescription                  (                  "A very good description"                  );                  todo                  .                  setDone                  (                  true                  );                  todos                  .                  add                  (                  todo                  );                  todo                  =                  new                  Todo                  ();                  todo                  .                  setSummary                  (                  "Second Todo"                  );                  todo                  .                  setDescription                  (                  "Second super description"                  );                  todos                  .                  add                  (                  todo                  );                  return                  todos                  ;                  }                  }                              

When using a WorkbenchLabelProvider the objects, which are supposed to be shown in the Viewer should provide an adapter for the IWorkbenchAdapter, IWorkbenchAdapter2 and IWorkbenchAdapter3 interface, but at least for the the IWorkbenchAdapter. These interfaces can be used by the WorkbenchLabelProvider in order to determine how the objects should be visualized.

To provide these adapters for the WorkbenchLabelProvider a TodoWorkbenchAdapter is created. It derives from WorkbenchAdapter, which is an abstract class that implements all three interfaces.

                                  package                  de.vogella.plugin.adapter                  ;                  import                  org.eclipse.jface.resource.ImageDescriptor                  ;                  import                  org.eclipse.jface.viewers.StyledString                  ;                  import                  org.eclipse.jface.viewers.StyledString.Styler                  ;                  import                  org.eclipse.swt.SWT                  ;                  import                  org.eclipse.swt.graphics.TextStyle                  ;                  import                  org.eclipse.swt.widgets.Display                  ;                  import                  org.eclipse.ui.ISharedImages                  ;                  import                  org.eclipse.ui.PlatformUI                  ;                  import                  org.eclipse.ui.model.WorkbenchAdapter                  ;                  import                  de.vogella.plugin.adapter.model.Todo                  ;                  public                  class                  TodoWorkbenchAdapter                  extends                  WorkbenchAdapter                  {                  @Override                  public                  ImageDescriptor                  getImageDescriptor                  (                  Object                  object                  )                  {                  return                  PlatformUI                  .                  getWorkbench                  ().                  getSharedImages                  ().                  getImageDescriptor                  (                  ISharedImages                  .                  IMG_OBJ_ELEMENT                  );                  }                  @Override                  public                  StyledString                  getStyledText                  (                  Object                  object                  )                  {                  if                  (                  object                  instanceof                  Todo                  )                  {                  Todo                  todo                  =                  (                  Todo                  )                  object                  ;                  StyledString                  styledString                  =                  new                  StyledString                  (                  todo                  .                  getSummary                  ());                  if                  (                  todo                  .                  isDone                  ())                  {                  Styler                  styler                  =                  new                  Styler                  ()                  {                  @Override                  public                  void                  applyStyles                  (                  TextStyle                  textStyle                  )                  {                  // Todos, which are done should have a green background                  textStyle                  .                  background                  =                  Display                  .                  getCurrent                  ().                  getSystemColor                  (                  SWT                  .                  COLOR_GREEN                  );                  }                  };                  styledString                  .                  setStyle                  (                  0                  ,                  todo                  .                  getSummary                  ().                  length                  (),                  styler                  );                  }                  return                  styledString                  ;                  }                  return                  super                  .                  getStyledText                  (                  object                  );                  }                  }                              

Now the TodoAdapterFactory has to be extended to also provide the TodoWorkbenchAdapter.

                                  package                  de.vogella.plugin.adapter                  ;                  import                  org.eclipse.core.runtime.IAdapterFactory                  ;                  import                  org.eclipse.ui.model.WorkbenchAdapter                  ;                  import                  org.eclipse.ui.views.properties.IPropertySource                  ;                  import                  de.vogella.plugin.adapter.model.Todo                  ;                  public                  class                  TodoAdapterFactory                  implements                  IAdapterFactory                  {                  // use a static final field so that the adapterList is only instanciated once                  private                  static                  final                  Class                  <?>[]                  adapterList                  =                  new                  Class                  <?>[]                  {                  IPropertySource                  .                  class                  ,                  WorkbenchAdapter                  .                  class                  };                  @Override                  public                  <                  T                  >                  T                  getAdapter                  (                  Object                  adaptableObject                  ,                  Class                  <                  T                  >                  adapterType                  )                  {                  if                  (                  adapterType                  ==                  IPropertySource                  .                  class                  &&                  adaptableObject                  instanceof                  Todo                  ){                  return                  adapterType                  .                  cast                  (                  new                  TodoPropertySource                  ((                  Todo                  )                  adaptableObject                  ));                  }                  else                  if                  (                  adapterType                  .                  isAssignableFrom                  (                  WorkbenchAdapter                  .                  class                  )                  &&                  adaptableObject                  instanceof                  Todo                  )                  {                  return                  adapterType                  .                  cast                  (                  new                  TodoWorkbenchAdapter                  ());                  }                  return                  null                  ;                  }                  @Override                  public                  Class                  <?>[]                  getAdapterList                  ()                  {                  return                  adapterList                  ;                  }                  }                              

Now that the TodoAdapterFactory can also return WorkbenchAdapter objects, it also has to be specified in the org.eclipse.core.runtime.adapters extension point.

adapter workbenchadapter extension point

The result should look similar this:

adapter todo workbenchadapter view

19. Eclipse Resources

You can register IResourceChangeListener on resources in Eclipse. For example, if you have a project, you can add or remove a resource listener to or from it.

                                  // add listener                  project                  .                  getWorkspace                  ().                  addResourceChangeListener                  (                  listener                  );                  // Remove listener                  project                  .                  getWorkspace                  ().                  removeResourceChangeListener                  (                  listener                  );                  // Example resource listener                  private                  IResourceChangeListener                  listener                  =                  new                  IResourceChangeListener                  ()                  {                  public                  void                  resourceChanged                  (                  IResourceChangeEvent                  event                  )                  {                  if                  (                  event                  .                  getType                  ()                  ==                  IResourceChangeEvent                  .                  PRE_CLOSE                  ||                  event                  .                  getType                  ()                  ==                  IResourceChangeEvent                  .                  PRE_DELETE                  )                  {                  if                  (                  event                  .                  getResource                  ().                  equals                  (                  project                  ))                  {                  // Project deleted or closed                  // do something                  }                  return                  ;                  }                  if                  (                  resource                  ==                  null                  )                  return                  ;                  IResourceDelta                  delta                  =                  event                  .                  getDelta                  ().                  findMember                  (                  new                  Path                  (                  resource                  .                  getURI                  ().                  toPlatformString                  (                  false                  )));                  if                  (                  delta                  ==                  null                  )                  {                  return                  ;                  }                  if                  (                  delta                  .                  getKind                  ()                  ==                  IResourceDelta                  .                  REMOVED                  )                  {                  // Resource delete                  // do something                  }                  }                  };                              

20. Exercise: Create a feature for your plug-in

20.1. Create a feature project

Create a feature project for your plug-in and add your plug-in to this feature. You create a feature project via .

Create the feature project according to the following screenshots.

Creating a feature project for the plug-in export

Creating a feature project for the plug-in export

20.2. Create a category definition

In your feature project create a new category definition, via the menu entry .

categorydefinition10

Press the New Category button and create a category with a name which describes your functionality. Add your feature to this category.

categorydefinition20

categorydefinition30

21. Exercise: Create an update site your plug-in

21.1. Create an update site

You can create an update site for your feature in a local directory on your machine. For this, select

pluginfeatureexport10

pluginfeatureexport20

To use your category, switch to the Options tab and select the path to your category.xml file in the Categorize repository option.

pluginfeatureexport30

21.2. Install feature via the Eclipse update manager

Use the Eclipse update manager via to install this new feature into your Eclipse IDE.

Use the update manager to point to your local directory. Then select and install your feature. In case you don't see your feature, try deselecting the Group items by category flag. In this case, you have forgotten to set your category during the export.

idepluginfeatureinstall10

idepluginfeatureinstall20

idepluginfeatureinstall30

If you put the resulting files on a webserver under a public accessible URL, your users could install your features from this URL.

21.3. Validate installation

Restart the Eclipse IDE after the installation. Ensure that your plug-in is available in your Eclipse installation and can be used.

idepluginfeatureinstall40