Eclipse RCP – Customize the toolbar and menus for a given Perspective: contributions using plugin extensions (xml)

I have presented in my previous post how to customize the toobar buttons of an Eclipse RCP product, when these buttons are contributed by writting java code, mainly in the ActionBarAdvisor class.
What about toolbar buttons and menus contributed as extensions in the plugin.xml file ? We will treat now about this case.

Toolbar buttons my be contributed in the plugin.xml file by using the org.eclipse.ui.menus extension point.
Here is the extension corresponding to my “new project” button on the toolbar:

  <menuContribution
            allPopups="false"
            locationURI="toolbar:org.eclipse.ui.main.toolbar?before=additions">
    <toolbar id="workfllow_studio_toolbar">
          <command
                  commandId="com.activeeon.workfloweditor.diagram.plugin.commands.newproject"
                  icon="icons/toolbar/document-new.png"
                  label="New Workflow Project"
                  style="push"
                  tooltip="Create a ProActive Workflow project in order to design a job to be executed, in a distributed environment, by the ProActive Scheduler server">
            
           
      </toolbar>
      </menuContribution>

I want to show this button on the toolbar only when my perspective com.activeeon.workflow.diagram.WorkflowDesignPerspective is active.
Here’s how I did it:

1. Implement a source provider.
A source provider is (Elcipse documentation for IsourceProvider): A provider of notifications for when a change has occurred to a particular type of source. These providers can be given to the appropriate service, and this service will then re-evaluate the appropriate pieces of its internal state in response to these change
My provider will only set a variable to a given value depending on the current perspective.
Here’s mine:

/**
 * ################################################################
 *
 * ProActive Parallel Suite(TM): The Java(TM) library for
 *    Parallel, Distributed, Multi-Core Computing for
 *    Enterprise Grids & Clouds
 *
 * Copyright (C) 1997-2011 INRIA/University of
 *                 Nice-Sophia Antipolis/ActiveEon
 * Contact: proactive@ow2.org or contact@activeeon.com
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation; version 3 of
 * the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * If needed, contact us to obtain a release under GPL Version 2 or 3
 * or a different license than the AGPL.
 *
 *  Initial developer(s):               The ProActive Team
 *                        http://proactive.inria.fr/team_members.htm
 *  Contributor(s): ActiveEon Team - http://www.activeeon.com
 *
 * ################################################################
 * $$ACTIVEEON_CONTRIBUTOR$$
 **/
package com.activeeon.workflow.diagram.custom.perspective;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.ui.AbstractSourceProvider;
import org.eclipse.ui.ISources;

/**
 * Provides a key and a value: the key is
 * org.ow2.proactive.resourcemanager.ShowActions;  the value is: showRMActions
 * (if the current perspective is RMPerspective) or hideActions (otherwise)
 * The current perspective needs to be updates via the perspectiveChanged method
 * 
 * This provider is used in the plugin.xml in order to decide to show or not 
 * specific workbench contributions (toolbar buttons, menu entries)
 * 
 * @author esalagea
 * 
 */
public class WorflowDesignPerspectiveSourceProvider extends AbstractSourceProvider {

	public final static String wsPerspectiveKey = "com.activeeon.workflow.diagram.custom.handlers.ShowActions";
	private final static String wsPerspective = "showActions";
	private final static String otherPerspective = "hideActions";

	/**
	 * true if the current perspective is the Resource Manager Perspective
	 */
	private boolean isWSPerspective = true;

	@Override
	public void dispose() {
		// TODO Auto-generated method stub

	}

	@Override
	public Map getCurrentState() {
		Map<String, String> currentState = new HashMap<String, String>(1);
		String currentState1 = isWSPerspective ? wsPerspective
				: otherPerspective;
		currentState.put(wsPerspectiveKey, currentState1);
		return currentState;
	}

	@Override
	public String[] getProvidedSourceNames() {
		return new String[] { wsPerspectiveKey };
	}

	public void perspectiveChanged(boolean _isWSPerspective) {
		if (this.isWSPerspective == _isWSPerspective)
			return; // no change

		this.isWSPerspective = _isWSPerspective;
		String currentState = isWSPerspective ? wsPerspective
				: otherPerspective;
		fireSourceChanged(ISources.WORKBENCH, wsPerspectiveKey, currentState);
	}

}

2. Add an extension, to the plugin.xml using the org.eclipse.ui.services extension point.
The service will use the provider we just defined in order to question for the value of the com.activeeon.workflow.diagram.custom.handlers.ShowActions variable.
here it is:

 <extension
         point="org.eclipse.ui.services">
      <sourceProvider
            provider="com.activeeon.workflow.diagram.custom.perspective.WorflowDesignPerspectiveSourceProvider">
         <variable
               name="com.activeeon.workflow.diagram.custom.handlers.ShowActions"
               priorityLevel="workbench">
         </variable>
      </sourceProvider>
   </extension>

3. Add visibility condition to our menu entry (toolbar button)

The command element becomes:

  <command
                  commandId="com.activeeon.workfloweditor.diagram.plugin.commands.newproject"
                  icon="icons/toolbar/document-new.png"
                  label="New Workflow Project"
                  style="push"
                  tooltip="Create a ProActive Workflow project in order to design a job to be executed, in a distributed environment, by the ProActive Scheduler server">
 <visibleWhen
                     checkEnabled="false">
                  <with
                        variable="com.activeeon.workflow.diagram.custom.handlers.ShowActions">
                     <equals
                           value="showActions">
                     </equals>
                  </with>
               </visibleWhen>

4. Implement a perspective adapter
We need to implement and add a listener to the workbench window to listen for perspective change events and update our source provider.

/**
 * ################################################################
 *
 * ProActive Parallel Suite(TM): The Java(TM) library for
 *    Parallel, Distributed, Multi-Core Computing for
 *    Enterprise Grids & Clouds
 *
 * Copyright (C) 1997-2011 INRIA/University of
 *                 Nice-Sophia Antipolis/ActiveEon
 * Contact: proactive@ow2.org or contact@activeeon.com
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation; version 3 of
 * the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * If needed, contact us to obtain a release under GPL Version 2 or 3
 * or a different license than the AGPL.
 *
 *  Initial developer(s):               The ProActive Team
 *                        http://proactive.inria.fr/team_members.htm
 *  Contributor(s): ActiveEon Team - http://www.activeeon.com
 *
 * ################################################################
 * $$ACTIVEEON_CONTRIBUTOR$$
 **/
package com.activeeon.workflow.diagram.custom.perspective;

import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PerspectiveAdapter;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.services.ISourceProviderService;

/**
 * Listens for perspective change Event and Updates the WorkflowDesignPerspectiveSourceProvider 
 * @author esalagea
 *
 */
public class WSPerspectiveAdapter extends PerspectiveAdapter {

	@Override
	public void perspectiveActivated(IWorkbenchPage page,
			IPerspectiveDescriptor perspectiveDescriptor) {
		super.perspectiveActivated(page, perspectiveDescriptor);
		boolean wsPerspective = false;
		if (perspectiveDescriptor
				.getId()
				.equals("com.activeeon.workflow.diagram.WorkflowDesignPerspective")) {
			wsPerspective = true;
		}

		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); 
		ISourceProviderService service = (ISourceProviderService) window.getService(ISourceProviderService.class); 
		WorflowDesignPerspectiveSourceProvider sourceProvider = (WorflowDesignPerspectiveSourceProvider) service.getSourceProvider(WorflowDesignPerspectiveSourceProvider.wsPerspectiveKey); 
		if (wsPerspective)
			sourceProvider.perspectiveChanged(true);
		else
			sourceProvider.perspectiveChanged(false);
	}
	
	public void perspectiveDeactivated(IWorkbenchPage page,
			IPerspectiveDescriptor perspective) {
	}

}

5. Subscribe the above adapter as a listener to the workbench window
Well, the first time I subscribed the adapter in the MyWorkbenchAdvisor#postStartup() method. Doing this will assure the workbench is fully started when subscribing the listener but it has an inconvenient. If I use my plugin within another product, or just as a stand-alone plugin for the Eclipse Workbench itself, MyrWorkbenchAdvisor class will not be used (this is specific to my product). So I decided to subscribe the listener in the Activator class of my plugin. the problem is that i have to make sure the Workbench is fully started before subscribing my listener. Here is the code, at the end of Activator#start(BundleContext context) :

			// Add a listener to the workbench to listen for perspective change and
			// perform custom actions
			// Add the listener once the workbenchh is fully started
			Display.getDefault().asyncExec(new Runnable() {
				@Override
				public void run() {
					// wait until the workbench has been initialized
					// if the workbench is still starting, reschedule the execution
					// of this runnable
					if (PlatformUI.getWorkbench().isStarting()) {
						Display.getDefault().timerExec(1000, this);
					} else { 
						// the workbench finished the initialization process 
						IWorkbenchWindow workbenchWindow = PlatformUI
								.getWorkbench().getActiveWorkbenchWindow();
						WSPerspectiveAdapter wsPerspectiveListener = new WSPerspectiveAdapter();
						workbenchWindow
								.addPerspectiveListener(wsPerspectiveListener);

						// update the PerspectiveListener with the current perspective
						// we need to perform this update by hand as no event is
						// sent by the platform at
						// platform initialization and we need to have the current
						// perspective set
						wsPerspectiveListener.perspectiveActivated(PlatformUI
								.getWorkbench().getActiveWorkbenchWindow()
								.getActivePage(), PlatformUI.getWorkbench()
								.getActiveWorkbenchWindow().getActivePage()
								.getPerspective());
					}
				}// else - isStarting()
			});
		 

Well, this is it.

Advertisements
This entry was posted in Eclipse RCP. Bookmark the permalink.

2 Responses to Eclipse RCP – Customize the toolbar and menus for a given Perspective: contributions using plugin extensions (xml)

  1. LeonVictor says:

    I have installed a lot of plugins for Eclipse. This development lets me keep my perspective clean and tidy.

  2. Marnix says:

    Is it possible to remove contribution from other plugins? I’m creating a RCP application and use some eclipse plugins, but these plugins add menuitems and toolbar items I don’t want. Can I completely control what menu items and toolbar items are shown in my RCP app?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s