By Simon Arsenault, OTI
October 18, 2001
The image above shows the many areas where a plug-in can contribute actions:
In order for an Independent Software Vendor (ISV) to contribute actions to other views and editors, plug-ins need to make their views and editors extensible. This article shows how a plug-in can allow action contributions from other plug-ins.
This article assumes a basic understanding of writing a plug-in. For more information on how to write a plug-in for the Eclipse Platform, please read the article from Jim Amsden, "Your First Plug-in".
To follow along with the examples in this article, refer to the section running the examples.
The targetID attribute () specifies the context menu identifier for the target view or editor. The documentation of the plug-in providing the view or editor will list the identifier to use. If none is specified in the documentation, then the context menu is not registered by the plug-in for external action contribution. A view or editor may have more than one context menu.
Unfortunately, the default text editor does not follow the guidelines for plug-in developers. The context menu identifier is not part of the default text editor documentation as it should be. Also, the identifier is not fully qualified as recommended by the plug-in developer guidelines.
The action to be contributed to the context menu is described next in XML (). The first step is to assign an identifier to the action using the id attribute. The label and icon that will appear in the context menu are given next using the label and icon attributes. The optional icon attribute is specified as a path relative to the plug-in directory.
The menubarPath attribute () specifies the path, starting at the root of the context menu, where this action will be added. In this example, "additions" is the value of the constant org.eclipse.ui.IWorkbenchActionConstants.MB_ADDITIONS. Plug-ins are expected to provide this group once in their context menus indicating the default location where action contributions can be placed. Plug-ins may provide other groups in their context menus where action contributions can be added. In this case, it is recommended that plug-ins document each group. If the menubarPath attribute is not specified, the Workbench will first attempt to add the action in the group "additions". If the group "additions" does not exist, then the action is added to the end of the context menu.
The class attribute () specifies the Java™ class that will perform the action when the menu item is selected by the user. This class must implement the org.eclipse.ui.IEditorActionDelegate interface if contributing to an editor's context menu or the org.eclipse.ui.IViewActionDelegate interface if contributing to a view's context menu. One very important point to understand about the delegate class is this class is loaded by the Workbench only when the user selects the menu item for the first time because plug-ins are loaded lazily. This means that the initial enablement logic must be described in XML. Once the delegate class has been loaded by the Workbench, the delegate can control the enabled/disabled state of the action.
The interface IEditorActionDelegate allows the action delegate to retarget itself to the active editor. This is important because only one delegate is created for the action and is shared by all instances of the same editor type. The action delegate must implement the method setActiveEditor(IAction action, IEditorPart targetEditor). When the action is invoked via its run() method, it must act upon the active editor given to the delegate via the last setActiveEditor method call.
The interface IViewActionDelegate allows the action delegate, during initialization, to target itself with the view instance it should work with. The action delegate must implement the method init(IViewPart view). When the action is invoked via its run() method, it must act upon the view passed to init method.
The image above shows the result of running this example. Notice the action added at the end of the editor's context menu. This is where the additions group is located in the default text editor context menu.
Notice the attribute enablesFor in the action definition (). This attribute controls the enabled/disabled state of the action based on the current selection. The current selection is obtained from the selection provider given when the context menu was registered by the plug-in developer. The enablesFor attribute value is the selection count condition which must be met to enable the action. If the condition is not met the action is disabled. If the attribute is left out, the action is enabled for any number of items selected. The following attribute formats are supported:
Action enablement is declared in XML because plug-ins are loaded lazily. Until an action is actually invoked by the user, the plug-in is not loaded and the Workbench uses the enablement logic declared in XML. Once a plug-in is loaded, the delegate class is notified of selection changes and can update the enabled/disabled state of the action. Refer to the org.eclipse.ui.IActionDelegate.selectionChanged(IAction action, ISelection selection) method documentation for more details.
The menu element (), in this example, specifies the sub menu. The label attribute value is the text displayed in the menu. The path attribute specifies the path, starting at the root of the context menu. This attribute works like the menubarPath attribute of the action element which was discussed in the first example.
Within the menu element (), notice that a separator was defined (). A separator serves as a group name into which actions can be added. In this example, the last two actions defined use this separator name in their menubarPath attribute (). This is how the two actions are placed in the sub menu. A menu separator item is added by the Workbench menu manager above and below the group as needed.
The image above shows the result of running this example. Notice the sub menu added to the Navigator's context menu.
The order in which the actions are added to the menu and sub menu is in reverse order of how they are listed in the plugin.xml file. The current behavior is unfortunate, but this issue was discovered only after the API was frozen.
For example, if the file "f1.java" and the project "Java Project" are selected in the Navigator when the context menu is shown for that view, then the action contribution defined by the XML above would be excluded because the object "Java Project" is of type IProject not IFile, and IFile is not a super interface of IProject. However, if the objectClass attribute value in the XML above was "org.eclipse.core.resources.IResource", then the action contribution would be included because IResource is a super interface of both IFile ("f1.java") and IProject ("Java Project"), neglecting for the moment the nameFilter attribute.
The nameFilter attribute () is used to further constrain the selection to which this action will apply. In this example, only IFiles that end with the .java extension are considered. The value of this attribute is compared to the org.eclipse.ui.model.IWorkbenchAdapter.getLabel() method result for each object in the selection . If the object does not have an IWorkbenchAdapter, then the object's toString() method is used. If this attribute is not specified, then no filtering is done on the object's name.
The filter element () provides another way of controlling the enablement criteria of an action. These are name/value pairs of attributes for the objects in the selection. The attributes which apply to the selection are type-specific, so the Workbench delegates filtering at this level to the actual selection (see IActionFilter javadoc). In this example, the object attribute name, "projectNature", is defined on IResourceActionFilter and is applicable to all IResources. Therefore, the action contribution will only happen if the IProject of each object in the selection has a Java nature. Refer to the documentation on IActionFilter and its sub-interfaces for a list and description of other named attributes. For more information about project natures, refer to the documentation on org.eclipse.core.resources.IProjectNature interface.
For object contributions, the class attribute () of the action element is the name of a Java class that implements the org.eclipse.ui.IObjectActionDelegate interface. The interface IObjectActionDelegate allows the action delegate to retarget itself to the active part. This is important because only one delegate is created for the action and is shared by all instances of IWorkbenchPart. The action delegate must implement the method setActivePart(IAction action, IWorkbenchPart targetPart). When the action is invoked via its run() method, it must act upon the active part given to the delegate via the last setActivePart method call.
The image above shows the result of running this example. Notice the object action contribution is added to the Navigator's context menu because a .java file within a Java project is selected.
Each context menu should be registered with the Workbench. This is accomplished by calling either org.eclipse.ui.IWorkbenchPartSite.registerContextMenu(MenuManager menuManager, ISelectionProvider selectionProvider) or org.eclipse.ui.IWorkbenchPartSite.registerContextMenu(String menuId, MenuManager menuManager, ISelectionProvider selectionProvider). If a view or editor has more than one context menu to expose, then each one needs to be registered. Once the context menu is registered, the Workbench will automatically insert any action contributions which exist into the menu.
As part of the context menu registration, a unique identifier for each context menu is required to avoid conflicts in the Workbench global registry of context menus. For consistency across all parts, the following strategy should be adopted by all plug-ins registering a context menu:
Publishers of context menus should include the standard insertion point identifier IWorkbenchActionConstants.MB_ADDITIONS. This default reference point is used for insertion of actions contributed by ISVs. The insertion point is defined by adding a GroupMarker to the menu at an appropriate location for insertion. Other insertion points can be defined and published within the javadoc of the view or editor. This is strongly recommended to allow ISVs better control of where the action will be inserted within the context menu.
A plug-in developer of an object that can be part of a selection in a context menu can implement the org.eclipse.ui.IActionFilter interface. This is a filtering strategy which can perform type-specific filtering based on name/value pairs. This permits an ISV to use these name/value pairs within the filter element in XML to further restrict which objects the action contribution applies to. The Workbench will retrieve the filter for the selection by testing to see if it implements IActionFilter. If that fails, the Workbench will ask for a filter through the IAdaptable mechanism.
The first action element () should look familiar by now, with the same attributes covered in previous examples. The value of the menubarPath attribute () is the same as IWorkbenchActionConstants.MB_ADDITIONS constant, which is the default group that contributors add actions to. Though not shown in this example, it is possible to add a sub-menu to the view's pull down menu simply by defining a menu element. Refer to the previous example on adding sub-menu to a context menu for more details.
The second action element () is only slightly different than the first one. Instead of adding the action to the pull down menu (using the menubarPath attribute), the action is added to the view's toolbar (). The value of the toolbarPath attribute specifies the group into which the action should be added. If the group specified does not exist, then it is created at the end of the toolbar and a separator is added if required. Views may publish groups to which a plug-in can add actions inside the toolbar. In the case of the Navigator view's toolbar, it does not publish any groups. Unlike a menu which has the default IWorkbenchActionConstants.MB_ADDITIONS group, a toolbar is not required to provide one.
The selection element () can further constrain the selection to which this action applies. The class attribute specifies the selection object type that must be met for the action to be enabled. In this example, the action is only enabled if all the objects within the selection implement the IFile interface. The name attribute specifies a wildcard match against each object in the selection. The value of this attribute is compared to the org.eclipse.ui.model.IWorkbenchAdapter.getLabel() method result for each object in the selection. In this example, the action is only enabled if all the objects in the selection end with the .java extension. The selection element is ignored by the Workbench if the enablesFor attribute is not specified.
The image above shows the result of running this example. Notice the action added to the Navigator's pull down menu. The action added in the toolbar is disabled because the current selection does not contain .java files, but instead .txt files.
The toolbarPath attribute value ( and ) is different than previous examples in that the first segment of the path represents the toolbar identifier, while the second segment represents the group within the toolbar. The toolbar identifier allows the plug-in to determine which toolbar the action is added to. Currently in the Workbench, only one toolbar is supported and its identifier is "Normal". If the group does not exist, then it is not created within the specified toolbar, and the action is not added to the specified toolbar. Valid toolbar groups are listed in the documentation of the IWorkbenchActionConstants interface and the plugin providing the target editor.
The first action () is added to the default group called IWorkbenchActionConstants.MB_ADDITIONS using the toolbarPath attribute (). The second action () is being added to the group called IWorkbenchActionConstants.SAVE_EXT using the toolbarPath attribute (). Refer to the interface IWorkbenchActionConstants for a list of other groups provided by the Workbench window main toolbar.
The image above shows the result of running this example. Notice the action next to the save tool items and the action added at the end of the toolbar.
Next a sub-menu is defined in the Edit menu (). The path attribute of the menu element is made up from the IWorkbenchActionConstants.M_EDIT and IWorkbenchActionConstants.MB_ADDITIONS constants. The following two action declarations have a menubarPath attribute ( and ) which specifies the path to the group created for the sub menu ().
In the Workbench's main menu bar, there is a problem with contributing actions to a contributed sub-menu. These sub-menu items are lost by the Workbench, so the sub-menu is empty and therefore is visible but disabled. This sub-menu problem is only for editor menu contributions and action set contributions. This is why the sub-menu contribution to the Edit menu is disabled.
The last part of the XML is used to define a new top level menu to the left of the Window menu (). The path attribute of the menu element comes from the IWorkbenchActionConstants.MB_ADDITIONS constant. This is the default group plug-ins use to add top level menus to the menu bar. These new menus are always added to the left of the Window menu.
The last action element has a menubarPath attribute () which specifies the path to the group created for the top level menu (). That is the location where the action is added by the Workbench.
The image above shows the result of running this example. Notice the action below the save menu items in the File menu and the new top level menu.
When contributing to the Perspective or Project menu, the path name is not the same as the menu name. The constant IWorkbenchActionConstants.M_VIEW is used to represent the path to the Perspective menu and the constant IWorkbenchActionConstants.M_WORKBENCH is used to represent the path to the Project menu. This is for historical reasons; these menus were renamed after the constants were defined as API.
The user can choose which action sets are visible. The goal is to let users customize the Workbench environment to suit their needs and override the assumptions made by the plug-in about which actions are appropriate. Plug-in developers of views and editors are encouraged to define important actions locally within their own menu and toolbar so that they are available even when the action set is not visible.
A plug-in uses the org.eclipse.ui.actionSets extension point to define an action set. These actions appear in the Workbench window by user preference. See the customize perspective dialog by selecting the menu item Perspective->Customize... and then expanding the Other category.
The attribute visible () is optional and specifies whether this action set should be initially made visible when any perspective is open. This option will only be honoured when the user opens a new perspective which has not been customized. The user can override this setting by customizing the perspective. By default, the value of this attribute is false. Caution should be taken when enabling this attribute so as not to abuse it. If every plug-in enables this attribute, then all perspectives will be cluttered with these action sets. A better approach is for the plug-in to specify which perspective(s) should show its action sets by using the extension point org.eclipse.ui.perspectiveExtensions. Please refer to "Extending an Existing Perspective" in Dave Springgay's article "Using Perspectives in the Eclipse UI" for more details.
The definition of each action looks the same as in previous examples. However, the toolbarPath attribute ( and ) value is different in that the first segment of the path represents the toolbar identifier, while the second segment represents the group within the toolbar. The toolbar identifier allows the plug-in to determine which toolbar the action is added to. Currently in the Workbench, only one toolbar is supported and its identifier is "Normal". If the group does not exist, then it is created within the specified toolbar.
The second action definition introduces the optional pulldown attribute (). When set to true, the tool item has an optional pull down menu. The tool item has the same look as the tool item "Open The New Wizard" provided by the Workbench window. This attribute is ignored for menu item contributions.
The class attribute () specifies the Java class that is loaded to perform the action invoked by the user. This class must implement org.eclipse.ui.IWorkbenchWindowActionDelegate interface if the pulldown attribute is false, or org.eclipse.ui.IWorkbenchWindowPulldownDelegate interface if the pulldown attribute is true. This delegate class can control the enabled/disabled state of the action when the selection changes, but only once the plug-in is loaded. Until then, the enabled/disabled state of the action is controlled by other XML attributes like enablesFor and selection.
The image above shows the result of running this example. Notice the two actions added at the end of the toolbar, with one having a drop down menu option. To show this action set in the current perspective, select the menu item Perspective->Customize..., expand the Other category, and check the option "Action Set 1".
Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.