org.eclipse.ui.menus

Commands can be implemented using org.eclipse.ui.handlers and bound to keys using org.eclipse.ui.bindings. With the org.eclipse.ui.menus extension point they can be placed in the main menu, view dropdown menus, context menus. They can also be added to the main toolbar, view toolbars, and various trim locations.

Contribution location

The older action contribution points use the concept of menu and toolbar paths to place menu items and tool items. The org.eclipse.ui.menus extension point requires the id of a menu, toolbar, or trim area and an insertion point. This is the locationURI of a <menuContribution/> element. Some examples of locationURIs:

A word about popup: locationURIs. In popup:id, the id refers to the id that comes from registering the context menu when the registerContextMenu(*) method is called. If an no id is specified in the call, it defaults to the id of the view or editor registering the context menu.

The workbench defines all of its group slot names in the classes IWorkbenchActionConstants and IIDEActionConstants. These ids, like the file example above, are available to menu contributions.

After the locationURI specifies the insertion point, the <menuContribution/> elements are turned into IContributionItems and inserted in order. Another difference between menu contributions and action contributions is that the menu contributions can be defined in the XML in the same kind of containing relationship that would would see in a menu or toolbar.

Let's start with a simple example from our Info example, adding some commands to the InfoView.

   <extension
         point="org.eclipse.ui.menus">
      <menuContribution
            locationURI="menu:org.eclipse.ui.examples.contributions.view?after=additions">
         <command
               commandId="org.eclipse.ui.examples.contributions.view.count"
               mnemonic="%contributions.view.count.mnemonic">
         </command>
         <command
               commandId="org.eclipse.ui.examples.contributions.view.edit"
               mnemonic="%contributions.view.edit.mnemonic">
         </command>
         <command
               commandId="org.eclipse.ui.file.refresh"
               mnemonic="%contributions.view.refresh.mnemonic">
         </command>
      </menuContribution>
      ...

Our locationURI marks this contribution for the org.eclipse.ui.examples.contributions.view view. Here we are adding 3 commands to the InfoView dropdown menu: Count Entries, Edit, and Refresh.

Although you can specify a label in the menu contribution <command/> element, if you don't we will use the name attribute from the org.eclipse.ui.commands command definition. Now clicking on the menu element will execute that command.

We've also placed a command in the InfoView toolbar:

      <menuContribution
            locationURI="toolbar:org.eclipse.ui.examples.contributions.view?after=additions">
         <command
               commandId="org.eclipse.ui.examples.contributions.view.swap"
               label="%contributions.view.swap.name"
               tooltip="%contributions.view.swap.tooltip">
         </command>
      </menuContribution>

The "Swap Entries" button on the toolbar will be disabled until 2 Person entries are selected in the info view because we defined an <enabledWhen> expression in the handler definition:

         <enabledWhen>
            <count
                  value="2">
            </count>
         </enabledWhen>

Contribution visibility

A command's enabled state is controlled by a combination of the command is handled and if so, the handler's enabled state. Menu contributions can use core expressions to control the command's visibility in menus and toolbars.

As an example, menu contributions can still be tied to an existing action set while being contributed to the main menu or main toolbar, as action sets are converted into contexts. In this example we place our command in the main menu and main toolbar.

   <extension
         point="org.eclipse.ui.actionSets">
      <actionSet
            id="org.eclipse.ui.examples.contributions.globalActionSet"
            label="%contributions.globalActionSet.label"
            visible="false">
      </actionSet>
   </extension>
   <extension
         point="org.eclipse.core.expressions.definitions">
      <definition
            id="org.eclipse.ui.examples.contributions.inGlobalActionSet">
         <with
               variable="activeContexts">
            <iterate
                  operator="or">
               <equals
                     value="org.eclipse.ui.examples.contributions.globalActionSet">
               </equals>
            </iterate>
         </with>
      </definition>
      ...

The above XML defines the action set to use, and a definition for a core expression that checks contexts to see if the action set is active. See the org.eclipse.ui.handlers section for other examples of core expressions.

Now we can add our command to the main menu:

      <menuContribution
            locationURI="menu:org.eclipse.ui.main.menu?after=additions">
         <menu
               label="%contributions.menus.globalMenu.label"
               mnemonic="%contributions.menus.globalMenu.label"
               id="org.eclipse.ui.examples.contributions.menus.globalMenu">
            <command
                  commandId="org.eclipse.ui.examples.contributions.commands.globalCommand"
                  mnemonic="%contributions.menus.globalCommand.mnemonic"
                  id="org.eclipse.ui.examples.contributions.menus.globalCommand">
               <visibleWhen>
                  <reference
                        definitionId="org.eclipse.ui.examples.contributions.inGlobalActionSet">
                  </reference>
               </visibleWhen>
            </command>
            <separator
                  name="additions"
                  visible="false">
            </separator>
         </menu>
      </menuContribution>
      <menuContribution
            locationURI="toolbar:org.eclipse.ui.main.toolbar?after=additions">
         <toolbar
               id="org.eclipse.ui.examples.contributions.toolbars.sampleToolbar">
            <command
                  commandId="org.eclipse.ui.examples.contributions.commands.globalCommand"
                  icon="icons/sample.gif"
                  tooltip="%contributions.toolbars.globalCommand.tooltip"
                  id="org.eclipse.ui.examples.contributions.toolbars.globalCommand">
               <visibleWhen>
                  <reference
                        definitionId="org.eclipse.ui.examples.contributions.inGlobalActionSet">
                  </reference>
               </visibleWhen>
            </command>
            <separator
                  name="additions"
                  visible="false">
            </separator>
         </toolbar>
      </menuContribution>
      ...

In the above XML, we are adding the menu "Global Menu" to the main menu, and then placing the "Global Command" in it. The <visibleWhen/> element will evaluate the body of the previously defined inGlobalActionSet core expression. The <separator/> element adds and additions group that can be used by other contributions. We are also creating a toolbar in the main coolbar (org.eclipse.ui.main.toolbar) and placing a our command in it with the sample.gif icon.

Other contributions can now contribute to the "Global Menu" menu by specifying its id as a contribution locationURI: menu:org.eclipse.ui.examples.contributions.menus.globalMenu?after=additions.

Currently, commands contributed to action sets don't show up in the Window > Customize Perspective... dialog.

You can add menu contributions that work similar to org.eclipse.ui.editorActions. First you define your editor command and handler, like Reset. Then you can add them in an editor menu like "Info" to the main menu:

      ... org.eclipse.core.expressions.definitions
      <definition
            id="org.eclipse.ui.examples.contributions.view.activeEditor">
         <with
               variable="activeEditorId">
            <equals
                  value="org.eclipse.ui.examples.contributions.editor">
            </equals>
         </with>
      </definition>
      ... org.eclipse.ui.menus
      <menuContribution
            locationURI="menu:org.eclipse.ui.main.menu?after=additions">
         <menu
               id="org.eclipse.ui.examples.contributions.editor.menu"
               label="%contributions.editor.menu.label"
               mnemonic="%contributions.editor.menu.mnemonic">
            <command
                  commandId="org.eclipse.ui.examples.contributions.editor.reset"
                  mnemonic="%contributions.editor.reset.mnemonic">
               <visibleWhen>
                  <reference
                        definitionId="org.eclipse.ui.examples.contributions.view.activeEditor">
                  </reference>
               </visibleWhen>
            </command>
         </menu>
      </menuContribution>

This is similar to adding to the main menu with our global action example. Here our core expression will make this element visible as long as the active editor id variable matches our editor. You can check out org.eclipse.ui.ISources for a list of supported variables names.

Note: updating the main menu and especially the main toolbar are expensive operations. You generally want to confine them to actionSet equivalent contexts and active editor type. Although you can update the main toolbar on each selection change using the default variable or a <with variable="selection"/> expression, it's not a good idea. The common practice is to leave your command visibility at the action set or active editor level, and have your handler enabled state track the current selection.

Contributing to popup menus

As in org.eclipse.ui.popupMenus, commands can be contributed to a specific context menu by the context menu's id, or to any context menu where it can satisfy its <visibleWhen> clause. For example, we can add our Refresh command to the Info View popup as a convenience. Because we didn't call registerContextMenu(*) with a specific id it defaults to the view id.

      <menuContribution
            locationURI="popup:org.eclipse.ui.examples.contributions.view?after=additions">
         <command
               commandId="org.eclipse.ui.file.refresh"
               mnemonic="%contributions.view.refresh.mnemonic">
         </command>
      </menuContribution>

To contribute a command to a popup if its selection matches a particular object type you can use the default variable, or for behaviour closest to org.eclipse.ui.popupMenus target a specific popup selection variable. Here's an example using the context menu selection provider. This just effects the popup menu visibility, not the command enabled state.

      <menuContribution
            locationURI="popup:org.eclipse.ui.popup.any?after=additions">
         <command
               commandId="org.eclipse.ui.examples.contributions.view.edit"
               mnemonic="%contributions.view.edit.mnemonic">
            <visibleWhen>
               <with
                     variable="activeMenuSelection">
                  <iterate>
                     <adapt
                           type="org.eclipse.ui.examples.contributions.model.Person">
                     </adapt>
                  </iterate>
               </with>
            </visibleWhen>
         </command>
      </menuContribution>

Using <iterate><adapt type="Person"/></iterate> is the core expression equivalent of the old objectClass attribute.

Adding toolbars to trim areas

A 'trim' widget is a control that gets sited into a location (called a 'Trim Area') on the outer boundary of the Workbench Window. The most common example is the generic 'status line' which almost all GUI's place along the bottom of the window. The extension point org.eclipse.ui.menus allows plug-ins to add views to the workbench. Plug-ins that contribute trim must register the trim in their plugin.xml file and provide  configuration information about the trim, such as its implementation class, the trim group (trim bar) that it resides in and layout information sucha s whether the trim wishes to use available 'extra' space during its layout within the trim area.

The interface for contributed trim is defined in IWorkbenchWidget, but plug-ins can (are in fact encouraged) to choose to extend the AbstractWorkbenchTrimWidget class rather than implement the interface from scratch.

For the readmetool example we've contributed a fairly naive trim widget that simply displays a string and an indication of which side the trim is currently docked on.

Let's take a look at the extension point definition used to contribute this piece of trim:

      <menuContribution
            locationURI="toolbar:org.eclipse.ui.trim.status">
         <toolbar
               id="org.eclipse.ui.examples.contributions.verticalTrim">
            <command
                  commandId="org.eclipse.ui.examples.contributions.item2"
                  icon="icons/editor.gif"
                  id="contributions.trimItem"
                  label="%Trim.item"
                  tooltip="%TrimItem.toolTip">
            </command>
            <control
                  class="org.eclipse.ui.examples.contributions.ExampleControlContribution"
                  id="contributions.controlContrib1">
            </control>
            <command
                  commandId="org.eclipse.ui.examples.contributions.item2"
                  icon="icons/editor.gif"
                  id="contributions.trimItem2"
                  label="%Trim2.item"
                  tooltip="%TrimItem2.toolTip">
            </command>
         </toolbar>
      </menuContribution>

The first section of the extension (the 'group' definition) simply defines the id of the group and defines a 'location' for the group as being at the start of the 'status' group (i.e. at the beginning of the bottom trim area). The second section (the 'widget' definition) specifies the implementation 'class' of the widget and defines the 'location' of the widget as being placed within the previously defined group.

Note that in both cases the bar's 'type' is defined as trim (which is the only type currently supported).

Once you have the actual readmetool example installed, take a look at the implementation of the ReadmeTrimWidget's fill method. This is different from the other fill methods used when adding widgets into toolbars or menus in that, because trim can be dragged from one area to another, it also passes the 'side' that the trim is being placed into, allowing the implementor to tailor the widget's display based on its location by changing orientation etc. The current implementation simply changes the displayed text to reflect the current location. Also note how the 'dispose'/'fill' life-cycle is handled; there will be repeated calls to dispose and fill generated by workbench changes (i.e. changing perspectives or dragging the trim to a new side).

One thing that is not reflected in this sample's code is the reliance of the trim layout manager on the trim's proper implementation of the widget control's computeSize method. The widget must be capable of calculating and returning its 'preferred' size since this is used throughout the layout management implementation to determine, for example, how much space is needed for a particular trim area. See the SWT documentation for notes on how to correctly implement 'computeSize correctly.