2007-06-15

Working with the menus extension point

I'm in the process of updating my training materials for the new org.eclipse.ui.menus extension point in Eclipse 3.3. To do that I first have to get acquainted with the new functionality.

The new extension point is basically a replacement of the following extension points from Eclipse 3.2:
org.eclipse.ui.popupMenus/viewerContribution
Used to add an action to a specific popup menu (usually a context menu or a ruler) of a view or editor
org.eclipse.ui.popupMenus/objectContribution
Used to add an action to all popup menus when a specific object type is selected
org.eclipse.ui.actionSets/actionSets
Used to add an action to the top-level menu bar and top-level tool bar
org.eclipse.ui.editorActions/editorContribution
Used to add an action to a specific editor top-level menu and tool bar
org.eclipse.ui.viewActions/viewContribution
Used to add an action to a specific view local menu
The new menus extension point not only replaces these extension points, but also adds the ability to add stuff to the trim areas and to the status line. Adding to the trim areas was difficult in Eclipse 3.2, whereas adding to the status line could only easily be done in the ActionBarAdvisor - which made to difficult to use in applications with multiple plug-ins.

To add stuff to any menu or tool bar in Eclipse 3.3, you basically needs two things:
  • The ID of the menu or tool bar.
  • A command defined with the commands extension point.
The ID of the top-level menus and tool bars are:
  • menu:org.eclipse.ui.main.menu – the top-level menu
  • popup:org.eclipse.ui.any.popup – all pop-up menus
  • toolbar:org.eclipse.ui.main.toolbar – the top-level tool bar
  • toolbar:org.eclipse.ui.trim.command1 – the top left trim area
  • toolbar:org.eclipse.ui.trim.command2 – the top right trim area
  • toolbar:org.eclipse.ui.trim.vertical1 – the left vertical trim area
  • toolbar:org.eclipse.ui.trim.vertical2 – the right vertical trim area
  • toolbar:org.eclipse.ui.trim.status – the status line trim area
See MenuUtil for constants.
So... to add a new top-level menu along with a single sample action you get:
<extension
point="org.eclipse.ui.menus">
<menuContribution
  locationURI="menu:org.eclipse.ui.main.menu?after=additions">
<menu
    id="com.rcpcompany.demo.menus33.menus.sampleMenu"
    label="Sample Menu"
    mnemonic="M">
  <command
      commandId="com.rcpcompany.demo.menus33.commands.sampleCommand"
      id="com.rcpcompany.demo.menus33.menus.sampleCommand"
      mnemonic="S">
  </command>
</menu>
</menuContribution>
</extension>
Notice the locationURI above. This specification contains three parts, as described in the extension point documentation:

[Scheme]:[ID]?[ArgList]
  • Scheme - The 'type' of the UI component into which the contributions will be added. It may be either "menu", "popup" or "toolbar". While 'popup' is indeed a form of menu it is provided to allow a distinction between a view's 'chevron' menu (for which we use the "menu" scheme) and its default context menu which, by convention, should be registered using the "popup" scheme.
  • ID - This is the id of menu or toolbar into which the contributions should be added. By convention views should use their view id as the id of the root of their chevron and default popup menu. Note that there is no explicit distinction between contributions supporting editors and 'normal' contributions into the Menu Menu or Toolbar; both global contributions and editor contributions would use the "org.eclipse.ui.main.menu" id or "org.eclipse.ui.main.toolbar". A special id used with popup:, "org.eclipse.ui.any.popup", is reserved to handle contributions which are candidates to appear on any (top level) context menu. Note that these contributions are expected to implement a 'visibleWhen' expression sufficient to limit their visibility to appropriate menus
  • Query - This field allows fine-grained definition of the specific location within a given menu. It has the form "[placement]=[id]" where placement is one of "before" or "after" and the id is expected to be the id of some IContributionItem in the menu.

Nearly all the needed information about the menu item is picked up from the command definition (and optionally from the commandImages extension point) except for the tool tip which for some reason cannot be specified in the command declaration.

If you add anything to any of the top-level tool bars (those with the toolbar scheme), you must remember that these really are cool bars and you must therefore first add a tool bar before you add the command itself:
<extension
point="org.eclipse.ui.menus">
<menuContribution
  locationURI="toolbar:org.eclipse.ui.trim.status?after=BEGIN_GROUP">
<toolbar
    id="com.rcpcompany.demo.menus33.toolbars.sampleToolbar">
  <command
      commandId="com.rcpcompany.demo.menus33.commands.sampleCommand">
  </command>
</toolbar>
</menuContribution>
</extension>


One last thing: Previously it was quite clear that you had to have certain specific stuff in the ActionBarAdvisor: if you wanted to use any of the actions from the ActionFactory, then this must be hard-coded, which for practical reasons meant the menu structure would also be hard-coded.

Not so in Eclipse 3.3: here you can just register the needed actions from the ActionFactory in ActionBarAdvisor.makeActions(IWorkbenchWindow) and then declare the rest in the menus extension point using the proper command IDs. Look in the org.eclipse.ui plug-in for a list of all the defined IDs.

9 comments:

Mr. Campbell’s Soup said...

Thank you for sharing this news from Eclipse RCP 3.3. :)

Ovais said...

Nice article. One thing that is still not clear to me is after we have created the menus (declaratively or programmatically), how can we get a reference to the action/command/menuItem/toolbarItem etc. that are added to the main menu or main toolbar. MenuManager has find methods, but how do we get to reference to the MenuManager/ToolBarManager/StatusLineManager.

Anonymous said...

Hi "Ovais",

Could you please tell me why you want to get a reference to the item?

Using the MenuManager you can get access to a IContributionItem - which does not get you to the IHandler itself.

If you have specific needs to get to a handler the easiest way is to save a reference in the constructor in a static variable or something similar.

Radoslaw Urbas said...

How toolbars in locations such as toolbar:org.eclipse.ui.trim.vertical2 can be locked - so user cannot drag them to another place?

Anonymous said...

Hi Radoslaw,

As a matter of fact, I don't know! I'm at Eclipse Summit Europe right now, so there should be a number of people to ask. If I find a solution I'll let you know.

Regards,
Tonny

Radoslaw Urbas said...

There is solution for locking all trim toolbar by setting org.eclipse.ui/LOCK_TRIM=true in *.ini.

Unfortunately I do not know if it is possible to lock just one toolbar.

Have fun on Eclipse Summit!

Anubhav Manak said...

How can I show/hide menu items in menucontribution based upon my object state?

Radoslaw Urbas said...

Take a look on visibleWhen parameter

Anonymous said...

Yes look at visibleWhen and especially the checkEnabled attribute of this element.