Monday, 18 November 2013

activate de-activate context on switching editor - Eclipse RCP

Developing multi-editor Eclipse based application like Eclipse plugin for HTML editor and JavaScript editor might require activating and deactivating of contexts on switching the editors. One use case is to support different shortcuts in different editors.

In Eclipse editor plugins it's common to enable some shortcuts in one editor but disable in other. For instance if you keep a shortcut for inserting HTML header then that shortcut will not make sense in JavaScript editor. To manage shortcuts you need to manage contexts.

Code for activating context:

private void activateEditorContext()
{
    IContextService contextService = (IContextService)PlatformUI.getWorkbench()
     .getService(IContextService.class);
    if(contextService != null)
        activation = contextService.activateContext("context_to_activate");
}

Code for deactivating context:

private void deactivateEditorContext()
{
    IContextService contextService = (IContextService)PlatformUI.getWorkbench()
     .getService(IContextService.class);
    if(contextService != null && activation != null)
        contextService.deactivateContext(activation);
}

Note: for deactivating context, the object returned while activating it, is required.

Activating and deactivating context is not the hard part but it is to identify where to activate and deactivate them. To understand that we need to know how Eclipse handles them internally.

Eclipse maintains a list of activated contexts. This list is modified whenever you activate or deactivate the context.

To get a Collection of activated contexts call getActiveContextIds() function defined under IContextService.

When you activate a context, it will be seen in collection returned by getActiveContextIds() and it will go away on deactivating it.  

But sometimes it just doesn't go. The possible reason could be activating it multiple times. In layman words, Eclipse internally maintains the number of times a particular context is activated, so if it's not deactivated that many times, it will still be active.

The cleanest way, I found, to manage context is on focus-listener. Activate particular context on focusgain and deactivate it on focuslost.


FocusListener focusListener = new FocusListener() {

    @Override
    public void focusLost(FocusEvent e) {
        deactivateEditorContext();
    }

    @Override
    public void focusGained(FocusEvent arg0) {
        activateEditorContext();
    }
 };
sourceViewer.getTextWidget().addFocusListener(focusListener);

But make sure not to activate it anywhere else like common practice to do so in createPartControl() when the editor window is created. Doing so will activate it twice, once in createPartcontrol() and second time on focusgain. And deactivating it in focuslost will not deactivate context because it is never deactivated twice.

0 comments:

Post a Comment