Schlagwort-Archive: handler activation

e4: Updating UI contributions on context switch

During the implementation of a new project, I want to harness the capabilities of the Eclipse application model when it comes to changes in the Eclipse context, or more accurate the de-/activation of context specific handlers.

What does that mean? Lets have a look at the following application model:

contextswitchmodel1 is the global definition of our testCommand, 2 and 3 are perspectives in our application where for the given command a separate handler gets activated due to the context switch from perspectiveA to perspectiveB and vice-versa. 4 is the UI contribution of the command visible to the user in the top window trim.

The resulting application looks like testAppshown on the left hand side. Where the UIContribution 4 is marked with a red arrow. Now the task of the handlers is to toggle between the perspectives and update the UI contribution to either show perspectiveA or perspectiveB.

As described in stackoverflow and the Eclipse forum I did not, at first, find an obvious approach to this (remark in Eclipse 3.x this could be implemented by using an IElementUpdater). After some more analysis I found a way to do so. The source for the following example is certainly available.

Lets fix the example by having a look at HandlerA


public class HandlerA {
    
    @Execute
    public void execute(EPartService partService,
             EModelService modelService, MApplication application) {
        MPerspective perspective = (MPerspective) modelService.find(
                "perspectiveB", application);
        partService.switchPerspective(perspective);
    }

    @Inject
    public void bla(
            @Optional @Active @Named("handler::testCommand") Object value,
            EModelService modelService, MApplication application) {
        if (value == null)
            return;
        List<MHandledItem> findElements = modelService.findElements(
                application, null, MHandledItem.class, null);
        for (MHandledItem mHandledItem : findElements) {
            mHandledItem.setLabel("perspectiveA");
            mHandledItem.setTooltip("perspectiveA now active");
        }
    }
}

The @Execute method does the simple task of toggling the perspective. The updating itself happens in lines 12-23. This method does listen to property changes of handler::testCommand which is the global command (see 1 in the above app model). Each time a context switch happens we get injected the current handler through Object value. So we may act accordingly. Here we act by using the modelService to find all contribution elements subsequently setting a new Label and Tooltip.

If more commands and handlers are in your application you should do a more intelligent search and/or filter on the value to act correct.

This approach, however, is not perfect, as you have to implement this method in both handlers in order to always be able to act upon the change. There are other feasible approaches like creating an Addon where you put the @Inject part, you would have to do this for each command separately, however.

I would prefer to be able to define a class within the MCommand element to put the respective code into which would always be notified in any change that happens related to it. So imagine that a MCommand has an option Class Uri and the respective referenced class could look like this

public class TestCommand {

    @Inject
    EModelService modelService;

    @Inject
    MApplication application;

    @Inject
    public void bla(@Optional @Active MHandler activeHandler,
            @Active MCommand command) {
        if (activeHandler == null)
            return;
        List<MHandledItem> findElements =
                modelService.findElements(
                application, null, MHandledItem.class, null);
        for (MHandledItem mHandledItem : findElements) {
            mHandledItem.setLabel("perspectiveA");
            mHandledItem.setTooltip("perspectiveA now active");
        }
    }
}

Where the injection will happen on change of the activeHandler and I also get the MCommand itself injected. This way one could also efficiently store the given UiContribution elements and limit the searches ….

What do you think? Eager to hear your opinion 🙂