Reader small image

You're reading from  Eclipse Plug-in Development Beginner's Guide - Second Edition

Product typeBook
Published inAug 2016
Reading LevelExpert
Publisher
ISBN-139781783980697
Edition2nd Edition
Languages
Tools
Right arrow
Author (1)
Alex Blewitt
Alex Blewitt
author image
Alex Blewitt

contacted on 30 aug 16 _____________ Dr Alex Blewitt has over 20 years of experience in Objective-C and has been using Apple frameworks since NeXTstep 3.0. He upgraded his NeXTstation for a TiBook when Apple released Mac OS X in 2001 and has been developing on it ever since. Alex currently works for an investment bank in London, writes for the on-line technology news site InfoQ and has published two other books for Packt publishing. He also has a number of apps on the Apple AppStore through Bandlem Limited. When he's not working on technology, and if the weather is nice, he likes to go flying from the nearby Cranfield airport. Alex writes regularly at his blog, http://alblue.bandlem.com, as well tweeting regularly from Twitter as @alblue. Acknowledgements This book would not have been possible without the ongoing love and support of my wife Amy, who has helped me through both the highs and lows of life. She gave me the freedom to work during the many late nights and weekends that it takes to produce a book and its associated code repository. She truly is the Lem of my life. I'd also like to thank my parents, Ann and Derek, for their encouragement and support during my formative years. It was this work ethic that allowed me to start my technology career as a teenager and to incorporate my first company before I was 25. I'd also like to congratulate them on their 50th wedding anniversary in 2015, and I look forward to reaching that goal with Amy. Thanks are due especially to the reviewer of this version of the book: Antonio Bello, as well as the previous version of this book: Nate Cook, James Robert and Arvid Gerstmann, who provided excellent feedback on the contents of this book during development and caught many errors in both the text and code. Any remaining errors are my own. I'd also like to thank my children Sam and Holly for inspiring me and hope that they too can achieve anything that they set their minds to. Finally, I'd like to thank Ben Moseley and Eren Kotan, both of whom introduced me to NeXT in the first place and set my career going on a twenty year journey to this book.
Read more about Alex Blewitt

Right arrow

Chapter 7. Creating Eclipse 4 Applications

Eclipse 4 – the new Eclipse platform

The last major change to Eclipse was with the 3.0 release, when it migrated to OSGi. The Eclipse 4 model provides a significant departure from the Eclipse 3.x line, with the user interface being represented as a dynamic Eclipse Modeling Framework (EMF) model. In addition, both model and views can be represented as simple Plain Old Java Objects (POJOs) with services provided by dependency injection. There is also a separate rendering mechanism that allows an E4 application to be hosted by different UIs, although we'll look at the SWT renderer specifically. In this chapter, we'll take a look at the differences and how you can evolve Eclipse plug-ins forward.

In this chapter, we shall:

  • Set up an Eclipse 4 instance for development

  • Create an E4 application with parts

  • Send and receive events

  • Create commands, handlers, and menus

  • Inject custom POJOs

Since Eclipse was first released in November 2001, its user interface has...

Time for action – installing E4 tooling


To work with Eclipse 4 application models, it is necessary to install the E4 tools to allow the application XML to be edited through an editor. These are not shipped with all the Eclipse packages, and must be installed separately.

  1. Add the following update site by going to the Preferences menu (from the Eclipse menu on macOS or the Window menu on other operating systems), followed by navigating to Install/Update | Available Software Sites, then clicking on Add..., and entering http://download.eclipse.org/e4/updates/0.17.

    Note

    Some of the E4 tools are available in the Eclipse Mars update site, but not all of them. There may be updates available or additional releases of the E4 tools site; check out http://download.eclipse.org/e4/updates/ and look at the directory contents to find a later release for later versions of Eclipse.

  2. Click on OK on the Add Site dialog and OK on the Preferences page to add it. Once added, navigate to the Help | Install New Software...

Time for action – creating an E4 application


Eclipse applications use an application ID to launch and start execution. For E4 applications, org.eclipse.e4.ui.workbench.swt.E4Application is used. A new E4 application will be created to demonstrate a standalone E4 application.

  1. Go to the File | New | Project… menu and choose Plug-in Project.

  2. Use the name com.packtpub.e4.application, and step through the wizard. Choose the default values for each field, ensuring that the activator checkbox is selected, the This plug-in will make contributions to the UI is selected, and Would you like to create a rich client application? is Yes:

  3. Click on Next and then choose the Eclipse 4 RCP application template. Click on Next again and ensure that Create sample content is selected:

  4. Click on Finish and the project will be created.

  5. Right-click on the com.packtpub.e4.application project and choose Run As | Eclipse Application. This launches a new version of the IDE, which is not intended.

    Note

    To launch the project...

Time for action – creating a part


Having created a sample application, the next step is to create a view, known as a part in E4. Parts are the generic name for views, editors, and other grouping components in an E4 application. Unlike views in Eclipse 3, the view class doesn't have to have any references to the Eclipse APIs. This makes it particularly easy to build and test in isolation.

  1. Create a new class called Hello in the com.packtpub.e4.application.parts package.

  2. Add a private field called label of type Label.

  3. Add a create method annotated with @PostConstruct that instantiates the Label and sets its text to "Hello".

  4. Optionally, add an onFocus method annotated with @Focus that sets the focus on the Label.

  5. The class will look like:

    package com.packtpub.e4.application.parts;
    import javax.annotation.PostConstruct;
    import org.eclipse.e4.ui.di.Focus;
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.widgets.Composite;
    import org.eclipse.swt.widgets.Label;
    public class Hello {
      private Label label...

Using services and contexts


An IDE is more than a collection of its component parts, and the Eclipse 4 framework allows these to coordinate and communicate with each other.

In prior releases of Eclipse, the Platform (or PlatformUI) object would act as an oracle of all the known services in the runtime infrastructure, as well as providing hooks for accessing those services, for example:

IExtensionRegistry registry = Platform.getExtensionRegistry();
IWorkbench workbench = PlatformUI.getWorkbench();

Although this provides a programmatic way of making the services available, it has two key disadvantages:

  • The provider of the interface is tightly coupled with the bundle containing the accessor, even if they are unrelated

  • Introducing new services requires a code change to a core object, and has disadvantages in being introduced to existing systems

The goal of E4 is to decouple service providers and service consumers through the use of OSGi services. These are contributed to the runtime, and can be looked...

Time for action – adding logging


The OSGi platform defines a LogService which allows messages to be logged to a central collector. In the E4 platform, an instance of LogService is available as part of the platform, routing error messages through to the console.

  1. Open the Hello class and add a private field LogService logService.

  2. Add an @Inject annotation to the LogService field.

  3. In the create method, add a call to the log service.

  4. The Hello class will look like:

    import javax.inject.Inject;
    import org.osgi.service.log.LogService;
    public class Hello {
      @Inject
      private LogService logService;
      @PostConstruct
      public void create(Composite parent) {
        label = new Label(parent, SWT.NONE);
        label.setText("Hello");
        logService.log(LogService.LOG_ERROR, "Hello");
      }
      ...
    }
  5. Run the application, and a log message will be printed out to the console of the host Eclipse:

    !ENTRY org.eclipse.e4.ui.workbench 4 0 2016-06-02 13:36:42.381
    !MESSAGE Hello
    

What just happened?

The E4 runtime infrastructure...

Time for action – getting the window


In an Eclipse 3.x application, the main window is typically accessed via a static accessor such as Display.getDisplay() or workbench.getWorkbenchWindows(). Both of these assume that there is a way of getting to this global list in the first place, often through tightly coupled code references. As well as OSGi services, E4 can also be used to inject references to GUI components. However, rather than accessing the GUI components directly, models are used instead. As a result, components in E4 tend to start with M (for Model)—such as MPart, MWindow, and MPerspective.

  1. To obtain the reference to the window, add a private field MWindow window to the Hello class, along with an @Inject annotation.

  2. Modify the create method so that the label of the text is taken from the window's title (label). The class will look like:

    import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
    public class Hello {
      @Inject
      private MWindow window;
      @PostConstruct
      public void...

Time for action – obtaining the selection


The current selection can be obtained through the selection service with a listener, similar to Eclipse 3.x. However, the ISelectionService in Eclipse 3.x has been replaced with an almost identical ESelectionService in Eclipse 4.x (other than the minor lack of JavaDoc and change of package name, the only significant difference between the two is that there are no add/removePostSelection methods).

  1. Create a class called Rainbow in the com.packtpub.e4.application.parts package. Add a private static final array of strings with colors of the rainbow.

  2. Add a create method, along with a @PostConstruct annotation, that takes a Composite parent. Inside, create a ListViewer and set the input to the array of rainbow colors. The class will look like:

    public class Rainbow {
      private static final Object[] rainbow = { "Red", "Orange",
        "Yellow", "Green", "Blue", "Indigo", "Violet" };
      @PostConstruct
      public void create(Composite parent) {
        ListViewer lv =...

Time for action – dealing with events


There's a more generic way of passing information between components in Eclipse 4, using the OSGi EventAdmin service. This is a message bus, like JMS, but operates in memory. There is also an Eclipse-specific IEventBroker, which provides a slightly simpler API to send messages.

  1. Add the following bundles as dependencies to the com.packtpub.e4.application project, by double-clicking on the project's META-INF/MANIFEST.MF file and going to the Dependencies tab:

    1. org.eclipse.osgi.services

    2. org.eclipse.e4.core.services

    3. org.eclipse.e4.core.di.extensions

  2. Open the Rainbow class and inject an instance of IEventBroker into a private field broker:

    @Inject
    private IEventBroker broker;
  3. Modify the selectionChanged method, so that instead of setting a selection, it uses the IEventBroker to post the color asynchronously to the rainbow/color topic:

    public void selectionChanged(SelectionChangedEvent event) {
      // selectionService.setSelection(event.getSelection());
      IStructuredSelection...

Time for action – calculating values on demand


The Eclipse context can supply not only services but also dynamically calculated values. These are supplied via an interface IContextFunction. By registering a service with that class name and a key name with the service.context.key, it is possible to create a value upon request.

  1. Create a class called RandomFunction, which extends ContextFunction and which returns a random value:

    package com.packtpub.e4.application;
    import org.eclipse.e4.core.contexts.ContextFunction;
    import org.eclipse.e4.core.contexts.IEclipseContext;
    public final class RandomFunction extends ContextFunction {
      @Override
      public Object compute(final IEclipseContext context) {
        return Math.random();
      }
    }
  2. To allow E4 to recognize the function, register an instance with the OSGi runtime. Although this could be done within the Activator, currently a service ordering bug prevents this from happening. Instead, register it using declarative services.

    Create a file called random...

Time for action – interacting with the UI


Sometimes it is necessary to write code to run in the UI thread, but when called back via a handler it's not always clear if the method is in the UI thread or not. In Eclipse 3.x, there is a Display.getDefault().syncExec() for running Runnable instances inside the UI thread immediately, or .asyncExec() for running them on the UI thread later. Eclipse 4 introduces the UISynchronize class, which is an abstract mechanism for executing code on the UI thread (it's like an interface for Display, except that Display doesn't implement it and it's not an interface). The syncExec and asyncExec methods can be used to schedule Runnable events. If a long calculation needs to update the UI after concluding, using UISynchronize allows the UI update to be scheduled on the right thread.

  1. Create a new Button as a field in the Hello part, and attach a selection listener such that when it is pressed, it invokes setEnabled(false) on itself. At the same time, schedule a...

Using commands, handlers, and menu items


The command and handlers in Eclipse 4 work the same way as in Eclipse 3. A command represents a generic operation, and the handler is the code that implements the operation. However, the implementation for the handler takes advantage of E4's annotations, instead of a custom subclass.

Time for action – wiring a menu to a command with a handler


As with Eclipse 3.x, a command has an identifier and an associated handler class, which can be bound to menus. Unlike Eclipse 3.x, it is not specified in the plugin.xml file; instead, it is specified in the Application.e4xmi file.

  1. Open the Application.e4xmi file in the com.packtpub.e4.application project.

  2. Navigate to the Application | Commands node in the tree, and click on Add child to add a new Command:

    1. ID: com.packtpub.e4.application.command.hello

    2. Name: helloCommand

    3. Description: Says Hello

  3. Create a class HelloHandler in the com.packtpub.e4.application.handlers package. It doesn't need to have any specific superclass or method implementation. Instead, create a method called hello which takes no arguments, and prints a message to System.out. The method needs the @Execute annotation:

    package com.packtpub.e4.application.handlers;
    import org.eclipse.e4.core.di.annotations.Execute;
    public class HelloHandler {
      @Execute
      public void...

Time for action: passing command parameters


Displaying a message to System.out shows that the command works, but what if the command needed to pick up local state? Fortunately, the @Named and @Inject annotations allow objects to be injected into the method when it is called.

  1. Modify the hello method so that instead of printing a message to System.out, it opens a dialog window, using the active shell:

    public void hello(@Named(IServiceConstants.ACTIVE_SHELL) Shell s){
      MessageDialog.openInformation(s, "Hello World",
        "Welcome to Eclipse 4 technology");
    }
  2. Other arguments can be passed in from the context, managed by the IEclipseContext interface. For example, using the math.random function from earlier, a value could be injected into the handler:

    public void hello(@Named(IServiceConstants.ACTIVE_SHELL) Shell s,
      @Named("math.random") double value) {
  3. If the same handler is being used for different functions (for example, Paste and Paste Special), they can be disambiguated by passing in a hard...

Time for action – creating a direct menu and keybindings


Although using commands and handlers provides a generic way for reusing content, it is possible to provide a shorter route to implementing menus with a Direct Menu Item. The difference between this and a Handled Menu Item is that Direct Menu Item contains a direct reference to the @Executable class, instead of indirect through a handler.

  1. To add a new direct menu item, open the Application.e4xmi file and navigate to the Application | Windows and Dialogs | Trimmed Window | Main Menu | Menu (File). Right-click on the menu and choose Add child | Direct Menu Item. In the dialog shown, fill in the following details, including the class URI link to the HelloHandler, defined previously:

    1. ID: com.packtpub.e4.application.directmenuitem.hello

    2. Label: Direct Hello

    3. Class URI: bundleclass://com.packtpub.e4.application/com.packtpub.e4.application.handlers.HelloHandler

  2. Run the application, and navigate to the File | Direct Hello menu, which shows the...

Time for action – creating a pop-up menu and a view menu


Pop-up and view menus are defined declaratively in the Application.e4xmi file. These are specific to a part, so the option is defined underneath the part declaration.

  1. Open the Application.e4xmi file.

  2. Navigate to the Application | Windows and Dialogs | Trimmed Window | Controls | Perspective Stack | Perspective | Controls | PartSashContainer | Part Stack | Part (Hello) | Menus node.

  3. Right-click on the Menus node and choose Add child | Popup Menu. Set the ID to com.packtpub.e4.application.popupmenu.hello, which will be used in code later.

  4. Right-click on the Popup Menu and choose Add child | Handled Menu Item. This is exactly the same as for other menus; fill in the details as follows:

    1. Label: Hello

    2. Command: helloCommand - com.packtpub.e4.application.command.hello

  5. Right-click on the Menus node again, and choose Add child | View Menu. Give the menu a label View Menu and right-click to choose Add child | Handled Menu Item. Use the same label...

Creating custom injectable classes


The injection framework in E4 allows custom injectable classes and services. As well as registering OSGi services, POJOs can be defined and instantiated on demand.

The rules for allowing a type to be instantiated automatically are:

  • It must be a non-abstract class

  • It must have a non-private default constructor

  • It must be annotated with @Creatable

Time for action – creating a simple service


POJOs can be instantiated and made available in the E4 context, such that they can be injected into other classes or created on demand. This allows an application to be built in a flexible manner without tight coupling between services.

  1. Create a class StringService in the com.packtpub.e4.application package with a @Creatable annotation, and a process method that takes a string and returns an uppercase version:

    import org.eclipse.e4.core.di.annotations.Creatable;
    @Creatable
    public class StringService {
      public String process(String string) {
        return string.toUpperCase();
      }
    }
  2. Add an injectable instance of StringService to the Rainbow class:

    @Inject
    private StringService stringService;
  3. Use the injected stringService to process the color choice before posting the event to the event broker:

    public void selectionChanged(SelectionChangedEvent event) {
      IStructuredSelection sel = (IStructuredSelection)
       event.getSelection();
      Object colour = sel.getFirstElement...

Time for action – injecting subtypes


Although creating a POJO can be an efficient way of creating simple classes, it can be limiting to have a concrete class definition scattered through the class definitions. It is a better design to use either an abstract class or an interface as the service type.

  1. Create a new interface in the com.packtpub.e4.application package, called IStringService. Define the process method as abstract:

    public interface IStringService {
      public abstract String process(String string);
    }
  2. Modify the existing StringService so that it implements the IStringService interface:

    public class StringService implements IStringService {
      ...
    }
  3. Modify the reference in the Rainbow class to refer to the IStringService interface instead of the StringService class:

    @Inject
    private IStringService stringService;
  4. Run the application, switch to the Rainbow tab, and a dependency injection fault will be shown in the host Eclipse instance's Console view:

    org.eclipse.e4.core.di.InjectionException...

Summary


Eclipse 4 is a new way of building Eclipse applications, and provides a number of features that make creating parts (views/editors), as well as obtaining service references and communication between parts much easier. If you are building Eclipse-based RCP applications, then there is no reason not to jump on the Eclipse 4 framework to take advantage of its features. If you are building plug-ins that will run on both Eclipse 3.x and Eclipse 4, then you have to consider backward compatibility requirements before you can make the switch. One way of supporting both is to use the workbench compatibility plug-in (which is what Eclipse 4.x uses if you download the SDK or one of the EPP packages) and continue to use the Eclipse 3.x APIs. However, this means the code cannot take advantage of the Eclipse 4.x mechanisms. Another approach is to write Eclipse 4-based plug-ins, and then wrap them in a reverse compatibility layer. Such a layer is provided in the Eclipse E4 Tools Bridge for 3.x feature...

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Eclipse Plug-in Development Beginner's Guide - Second Edition
Published in: Aug 2016Publisher: ISBN-13: 9781783980697
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at ₹800/month. Cancel anytime

Author (1)

author image
Alex Blewitt

contacted on 30 aug 16 _____________ Dr Alex Blewitt has over 20 years of experience in Objective-C and has been using Apple frameworks since NeXTstep 3.0. He upgraded his NeXTstation for a TiBook when Apple released Mac OS X in 2001 and has been developing on it ever since. Alex currently works for an investment bank in London, writes for the on-line technology news site InfoQ and has published two other books for Packt publishing. He also has a number of apps on the Apple AppStore through Bandlem Limited. When he's not working on technology, and if the weather is nice, he likes to go flying from the nearby Cranfield airport. Alex writes regularly at his blog, http://alblue.bandlem.com, as well tweeting regularly from Twitter as @alblue. Acknowledgements This book would not have been possible without the ongoing love and support of my wife Amy, who has helped me through both the highs and lows of life. She gave me the freedom to work during the many late nights and weekends that it takes to produce a book and its associated code repository. She truly is the Lem of my life. I'd also like to thank my parents, Ann and Derek, for their encouragement and support during my formative years. It was this work ethic that allowed me to start my technology career as a teenager and to incorporate my first company before I was 25. I'd also like to congratulate them on their 50th wedding anniversary in 2015, and I look forward to reaching that goal with Amy. Thanks are due especially to the reviewer of this version of the book: Antonio Bello, as well as the previous version of this book: Nate Cook, James Robert and Arvid Gerstmann, who provided excellent feedback on the contents of this book during development and caught many errors in both the text and code. Any remaining errors are my own. I'd also like to thank my children Sam and Holly for inspiring me and hope that they too can achieve anything that they set their minds to. Finally, I'd like to thank Ben Moseley and Eren Kotan, both of whom introduced me to NeXT in the first place and set my career going on a twenty year journey to this book.
Read more about Alex Blewitt