Sunday 8 December 2013

Eclispe menu contribution based on active context


There are lot of good blogs explaining how to add a menu item in one of the menus of Eclipse. What I will focus on is how to enable/disable them according to specific editors. I explained in my previous blog, how to enable/disable context on editor switching. On that understanding if we enable/disable menu items on active contexts then our work is done.

This is how a typical menu item is coded in plugin.xml
Use enableWhen tag to enable it on a particular condition. Use with tag to specify the variable on which it should be dependent. For our case variable will be 'activeContexts'. We will iterate all the activeContexts and specify what context to match.

Take a look at complete exmaple below:


We also have to define command like this:

And a handler for our command


      

Read More...

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.
Read More...