Skip to main content
Jump to: navigation, search

Difference between revisions of "Menu Contributions"

(Product removes the Project menu)
m (Fixed a typo)
 
(208 intermediate revisions by 14 users not shown)
Line 1: Line 1:
Placement examples that try to describe the old to new way.  Please contribute comments and suggestions in the discussion area or on [https://bugs.eclipse.org/bugs/show_bug.cgi?id=154130 Bug 154130 -KeyBindings- Finish re-work of commands and key bindings].  
+
Placement examples that describe the proposed new way of placing menu items for '''3.3'''.  Please contribute comments and suggestions in the discussion area or on [https://bugs.eclipse.org/bugs/show_bug.cgi?id=154130 Bug 154130 -KeyBindings- Finish re-work of commands and key bindings].  
  
 +
= Placement and visibility =
  
= Add ProblemView menus =
+
The 4 extension points that deal with menus now org.eclipse.ui.actionSets, org.eclipse.ui.viewActions, org.eclipse.ui.editorActions, and org.eclipse.ui.popupMenus specify both menu placement and their visibility criteria.  In the new menu mechanism they are separate concepts, placement and visibility.
  
Add the Problems view menus.  The problems view has one toolbar action and in the view menu, 3 actions and 2 dynamic submenus.  It also has a dynamic menu and another bunch of actions in its context menu.
+
= Example Matrix =
  
== Commands ==
+
A (hopefully) growing list of menu contribution examples.
  
First define commands that are specific to the view.  Since these are view commands, we can specify a default handler ... we're unlikely to replace it.
+
{| class="wikitable" border="1"
 +
|-
 +
! Example !! comments
 +
|-
 +
| [[Menu Contributions/Dropdown Command]] || Dropdown tool items can have their menus filled in using menu contributions
 +
|-
 +
| [[Menu Contributions/Problems View Example]] || An example showing how the Problems View might be converted
 +
|-
 +
| [[Menu Contributions/Populating a dynamic submenu]] || A menu contribution to populate a Problems View dynamic submenu
 +
|-
 +
| [[Menu Contributions/Toggle Mark Occurrences]] || Placing the toggle mark occurrences button
 +
|-
 +
| [[Menu Contributions/Toggle Button Command]] || Contribute a toggle state menu item thru commands
 +
|-
 +
| [[Menu Contributions/Radio Button Command]] || Similar to updating toggle state, you can create radio buttons using menu contributions
 +
|-
 +
| [[Menu Contributions/Update checked state]] || The active handler can update the checked state (and other attributes) of its button
 +
|-
 +
| [[Menu Contributions/Search Menu]] || Adding the Java Search options to the Search menu
 +
|-
 +
| [[Menu Contributions/IFile objectContribution]] || A menu contribution for context menus when the selection is an IFile
 +
|-
 +
| [[Menu Contributions/TextEditor viewerContribution]] || A menu contribution for the text editor context menu
 +
|-
 +
| [[Menu Contributions/Widget in a toolbar]] || A menu contribution adding a control into the main toolbar
 +
|-
 +
| [[Menu Contributions/RCP removes the Project menu]] || An RCP application removes the Project menu. Note: this will probably not be in 3.3
 +
|-
 +
| [[Menu Contributions/Workbench wizard contribution]] || Contributing workbench wizards to Menu
 +
|-
 +
|}
  
<extension
+
= Menu XML =
    point="org.eclipse.ui.commands">
+
  <category
+
      id="org.eclipse.ui.views.problems"
+
      name="Problems View">
+
  </category>
+
  <command
+
      categoryId="org.eclipse.ui.views.problems"
+
      defaultHandler="org.eclipse.ui.views.markers.internal.TableSortHandler"
+
      description="Change the problem sort order"
+
      id="org.eclipse.ui.views.problems.sorting"
+
      name="Sorting...">
+
  </command>
+
  &lt;-- the view preference command would probably be defined once
+
      with the other preference contributions --&gt;
+
  <command
+
      categoryId="org.eclipse.ui.views.problems"
+
      defaultHandler="org.eclipse.ui.preferences.ViewPreferencesHandler"
+
      description="Open the view preferences"
+
      id="org.eclipse.ui.preferences.viewPreferences"
+
      name="Preferences">
+
    <commandParameter
+
        id="org.eclipse.ui.preferences.viewPreferences.markerEnablementName"
+
        name="Marker Enablement Preference"
+
        optional="false"/>
+
    <commandParameter
+
        id="org.eclipse.ui.preferences.viewPreferences.markerLimitName"
+
        name="Marker Limit Preference"
+
        optional="false"/>
+
  </command>
+
  <command
+
      categoryId="org.eclipse.ui.views.problems"
+
      defaultHandler="org.eclipse.ui.views.markers.internal.FiltersHandler"
+
      description="Open the filters dialog"
+
      id="org.eclipse.ui.views.problems.configureFilters"
+
      name="Configure Filters...">
+
  </command>
+
  <command
+
      categoryId="org.eclipse.ui.views.problems"
+
      defaultHandler="org.eclipse.ui.views.markers.internal.OpenMarkerHandler"
+
      description="Go to the current marker"
+
      id="org.eclipse.ui.views.problems.goTo"
+
      name="Go To"/>
+
</extension>
+
  
== Handlers ==
+
Declarative information ... this needs to be cleaned up.
  
We can also use a number of global commands, like copy, paste, delete, quick fix, and properties.  For these, we just need to define our handlers.  We need to add them with <activeWhen/> clauses to restrict them to being active when the view is active.
+
=== Declarative menus - some constraints ===
 
+
<extension
+
    point="org.eclipse.ui.handlers">
+
  <handler
+
      commandId="org.eclipse.ui.edit.copy"
+
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler">
+
    <enabledWhen>
+
      <not>
+
        <count value="0"/>
+
      </not>
+
    </enabledWhen>
+
    <activeWhen>
+
      <with variable="activePartId">
+
        <equals value="org.eclipse.ui.views.ProblemView"/>
+
      </with>
+
    </activeWhen>
+
  </handler>
+
  <handler
+
      commandId="org.eclipse.ui.edit.paste"
+
      class="org.eclipse.ui.views.markers.internal.PasteMarkerHandler">
+
    <enabledWhen>
+
      <not>
+
        <count value="0"/>
+
      </not>
+
    </enabledWhen>
+
    <activeWhen>
+
      <with variable="activePartId">
+
        <equals value="org.eclipse.ui.views.ProblemView"/>
+
      </with>
+
    </activeWhen>
+
  </handler>     
+
  <handler
+
      commandId="org.eclipse.ui.edit.delete"
+
      class="org.eclipse.ui.views.markers.internal.RemoveMarkerHandler">
+
    <enabledWhen>
+
      <not>
+
        <count value="0"/>
+
      </not>
+
    </enabledWhen>
+
    <activeWhen>
+
      <with variable="activePartId">
+
        <equals value="org.eclipse.ui.views.ProblemView"/>
+
      </with>
+
    </activeWhen>
+
  </handler>     
+
  <handler
+
      commandId="org.eclipse.ui.edit.selectAll"
+
      class="org.eclipse.ui.views.markers.internal.SelectAllMarkersHandler">
+
    <enabledWhen>
+
      <not>
+
        <count value="0"/>
+
      </not>
+
    </enabledWhen>
+
    <activeWhen>
+
      <with variable="activePartId">
+
        <equals value="org.eclipse.ui.views.ProblemView"/>
+
      </with>
+
    </activeWhen>
+
  </handler>
+
  <handler
+
      commandId="org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals"
+
      class="org.eclipse.ui.views.markers.internal.ResolveMarkerHandler">
+
    <enabledWhen>
+
      <not>
+
        <count value="0"/>
+
      </not>
+
    </enabledWhen>
+
    <activeWhen>
+
      <with variable="activePartId">
+
        <equals value="org.eclipse.ui.views.ProblemView"/>
+
      </with>
+
    </activeWhen>
+
  </handler>     
+
  <handler
+
      commandId="org.eclipse.ui.file.properties"
+
      class="org.eclipse.ui.views.markers.internal.ProblemPropertiesHandler">
+
    <enabledWhen>
+
      <not>
+
        <count value="0"/>
+
      </not>
+
    </enabledWhen>
+
    <activeWhen>
+
      <with variable="activePartId">
+
        <equals value="org.eclipse.ui.views.ProblemView"/>
+
      </with>
+
    </activeWhen>
+
  </handler>
+
</extension>
+
 
+
Or we can programmatically activate them through the IHandlerService which we would retrieve from the ProblemView site.
+
 
+
IHandlerService handlerServ = (IHandlerService)getSite().getService(IHandlerService.class);
+
copy = new CopyMarkerHandler();
+
handlerServ.activateHandler("org.eclipse.ui.edit.copy", copy);
+
 
+
Using the ProblemView site to access the IHandlerService handles the <activeWhen/> clause for us, and our programmatic handler would manage its own enablement state.
+
 
+
=== Expression Sidebar ===
+
 
+
You can see that the <activeWhen/>, <enabledWhen/>, and probably the <visibleWhen/> are likely to be replicated over and over again.  A possible option is some kind of expression template markup ... either in its own extension or supported by our UI extensions that can use core expressions.
+
 
+
Here's an example of using expression templates in its own extension point.
+
 
+
<extension
+
    point="org.eclipse.core.expression.templates">
+
  <expression id="isPartActive">
+
    <parameter id="partId"/>
+
    <with variable="activePartId">
+
      <equals value="$partId"/>
+
    </with>
+
  </expression>
+
  <expression id="isActionSetActive">
+
    <parameter id="actionSetId"/>
+
    <with variable="activeContexts">
+
      <iterator operator="or">
+
        <equals value="$actionSetId"/>
+
      </iterator>
+
    </with>
+
  </expression>
+
  <expression id="isContextActive">
+
    <parameter id="contextId"/>
+
    <with variable="activeContexts">
+
      <iterator operator="or">
+
        <equals value="$contextId"/>
+
      </iterator>
+
    </with>
+
  </expression>
+
  <expression id="isSelectionAvailable">
+
    <not>
+
      <count value="0"/>
+
    </not>
+
  </expression>
+
</extension>
+
 
+
This could be used to simplify the handler definitions:
+
 
+
<extension
+
    point="org.eclipse.ui.handlers">
+
  <handler
+
      commandId="org.eclipse.ui.edit.copy"
+
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler">
+
    <enabledWhen>
+
      <evaluate ref="isSelectionAvailable"/>
+
    </enabledWhen>
+
    <activeWhen>
+
      <evaluate ref="isPartActive">
+
        <parameter id="partId" value="org.eclipse.ui.views.ProblemView"/>
+
      </evaluate>
+
    </activeWhen>
+
  </handler>
+
</extension>
+
 
+
If we allow recursive template definitions, that would allow you to specify the concrete expression once and then reference it throughout your view.
+
 
+
<extension
+
    point="org.eclipse.core.expression.templates">
+
  <expression id="isProblemViewActive">
+
      <evaluate ref="isPartActive">
+
        <parameter id="partId" value="org.eclipse.ui.views.ProblemView"/>
+
      </evaluate>
+
  </expression>
+
</extension>
+
<extension
+
    point="org.eclipse.ui.handlers">
+
  <handler
+
      commandId="org.eclipse.ui.edit.copy"
+
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler">
+
    <enabledWhen>
+
      <evaluate ref="isSelectionAvailable"/>
+
    </enabledWhen>
+
    <activeWhen>
+
      <evaluate ref="isProblemViewActive"/>
+
    </activeWhen>
+
  </handler>
+
</extension>
+
 
+
This reduces the handler definition even more.
+
 
+
== Menus ==
+
 
+
Then we would define the ProblemView menu structures.  We are using 3 <b>roots</b>:  the view menu, the view toolbar, and the view context menu.  This is an example of an "in-place" menu definition.  The XML hierarchy mirrors the menu hierarchy.
+
 
+
 
+
<extension point="org.eclipse.ui.menus">
+
  <menuRoot location="menu://org.eclipse.ui.views.ProblemView">
+
    <item id="org.eclipse.ui.views.problems.sorting.item"
+
          commandId="org.eclipse.ui.views.problems.sorting"
+
          mnemonic="S"
+
          tooltip="Change the Sort order"/>
+
    <menu id="org.eclipse.ui.views.problems.groupBy.menu"
+
          label="Group By"
+
          mnemonic="G">
+
      <dynamic class="org.eclipse.ui.views.markers.internal.GroupByMenu"/>
+
    </menu>
+
    <separator id="group.filter" visible="true"/>
+
    <menu id="org.eclipse.ui.views.problems.filters.menu"
+
          label="Filters"
+
          mnemonic="F">
+
      <dynamic class="org.eclipse.ui.views.markers.internal.FilterMenu"/>
+
    </menu>
+
    <item id="org.eclipse.ui.views.problems.configureFilters.item"
+
          commandId="org.eclipse.ui.views.problems.configureFilters"
+
          mnemonic="C"
+
          icon="$nl$/elcl16/filter_ps.gif"
+
          tooltip="Configure the filters to be applied to this view"/>
+
    <item id="org.eclipse.ui.preferences.viewPreferences.item"
+
          commandId="org.eclipse.ui.preferences.viewPreferences"
+
          mnemonic="P"
+
          tooltip="">
+
      <parameter id="org.eclipse.ui.preferences.viewPreferences.markerEnablementName"
+
                  value="LIMIT_PROBLEMS"/>
+
      <parameter id="org.eclipse.ui.preferences.viewPreferences.markerLimitName"
+
                  value="PROBLEMS_LIMIT"/>
+
    </item>
+
  </menuRoot>
+
  <menuRoot location="toolbar://org.eclipse.ui.views.ProblemView">
+
    <item id="org.eclipse.ui.views.problems.configureFilters.toolitem"
+
          commandId="org.eclipse.ui.views.problems.configureFilters"
+
          icon="$nl$/elcl16/filter_ps.gif"
+
          tooltip="Configure the filters to be applied to this view"/>
+
  </menuRoot>
+
  <menuRoot location="popup://org.eclipse.ui.views.ProblemView">
+
    <item id="org.eclipse.ui.views.problems.goTo.item"
+
          commandId="org.eclipse.ui.views.problems.goTo"
+
          mnemonic="G"
+
          icon="$nl$/elcl16/gotoobj_tsk.gif"
+
          disabledIcon="$nl$/dlcl16/gotoobj_tsk.gif"
+
          tooltip="Go to the marker location"/>
+
    <separator id="group.showIn" visible="true"/>
+
    <menu id="org.eclipse.ui.views.problems.showIn.menu"
+
          label="Show In"
+
          mnemonic="w">
+
      <dynamic class="org.eclipse.ui.actions.ShowInContributions"/>
+
    </menu>
+
    <separator id="group.edit" visible="true"/>
+
    <item id="org.eclipse.ui.views.problems.copy.item"
+
          mnemonic="C"
+
          commandId="org.eclipse.ui.edit.copy"
+
          icon="$nl$/icons/full/etool16/copy_edit.gif"
+
          disabledIcon="$nl$/icons/full/dtool16/copy_edit.gif"/>
+
    <item id="org.eclipse.ui.views.problems.paste.item"
+
          commandId="org.eclipse.ui.edit.paste"
+
          mnemonic="P"
+
          icon="$nl$/icons/full/etool16/paste_edit.gif"
+
          disabledIcon="$nl$/icons/full/dtool16/paste_edit.gif"/>
+
    <item id="org.eclipse.ui.views.problems.delete.item"
+
          commandId="org.eclipse.ui.edit.delete"
+
          mnemonic="D"
+
          icon="$nl$/icons/full/etool16/delete_edit.gif"
+
          disabledIcon="$nl$/icons/full/dtool16/delete_edit.gif">
+
      <visibleWhen>
+
        <not>
+
          <with variable="activePartId">
+
            <equals value="org.eclipse.ui.views.ProblemView"/>
+
          </with>
+
        </not>
+
      </visibleWhen>
+
    </item>
+
    <item id="org.eclipse.ui.views.problems.selectAll.item"
+
          commandId="org.eclipse.ui.edit.selectAll"
+
          mnemonic="A"/>
+
    <separator id="group.resolve" visible="true"/>
+
    <item id="org.eclipse.ui.views.problems.resolveMarker.item"
+
          commandId="org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals"
+
          mnemonic="Q"
+
          icon="$nl$/icons/full/elcl16/smartmode_co.gif"
+
          disabledIcon="$nl$/icons/full/dlcl16/smartmode_co.gif"/>
+
    <separator id="additions" visible="true"/>
+
    <separator id="group.properties" visible="true"/>
+
    <item id="org.eclipse.ui.views.problems.properties.item"
+
          commandId="org.eclipse.ui.file.properties"
+
          mnemonic="r"/>
+
  </menuRoot>
+
</extension>
+
  
 
Some constraints on the system:
 
Some constraints on the system:
  
# Identifiers (id) for <menu/> and <item/> elements must be globally unique.
+
# Identifiers (id) for <menu/> elements must be globally unique.
# <separator/> ids only have to be unique within that menu level.
+
# Identifiers (id) for <command/> elements must be globally unique if they are specified.
# You can provide an <item/> label attribute.  If none is provided, it will take the command name.
+
# You can reference a <menu/> by id.
 +
# If you are just creating menu items for your commands, you can leave them with only a command id.  You don't have to specify an item id.
 +
# You can reference a <command/> for placement options (after, before, etc.) by id.
 +
# <separator/> ids only have to be unique within that menu level.  This is changed to name instead of id in '''3.3M5'''.
 +
# You can provide a <command/> label attribute.  If none is provided, it will take the command name.
 
# In this design the item contains most of the same rendering information that <action/> did.
 
# In this design the item contains most of the same rendering information that <action/> did.
# <menu/> and <item/> can have <visibleWhen/> clauses.  If a menu's <visibleWhen/> evaluates to false, we will never ask the items contained in that menu.
+
# <menu/> and <command/> can have <visibleWhen/> clauses.  If a menu's <visibleWhen/> evaluates to false, we will never ask the items contained in that menu.
# All of the display-able attributes are translatable
+
# All of the displayable attributes are translatable.
 +
# The mnemonic is specified as you place your <command/> elements in their respective menus, since it is possible that the same command might need a different mnemonic depending on which menu it is placed.  Also, when defaulting to command names, they don't contain any mnemonic information.
  
 +
Menus cannot be re-used, and so they have an intrinsic id value.  Separators are unique within one menu level, so they also contain their name.
  
=== Menu - JSR198 ===
+
=== Menu URIs ===
  
There is a JSR describing how IDEs can contribute menusBelow is a sample for 2 items:
+
For location placement we need a path and placement modifier, and to specify how the paths are built.  First pass we are going to look at URIs.   
  
* org.eclipse.ui.views.problems.sorting.item from menu://org.eclipse.ui.views.ProblemView
+
* <scheme>:<menu-id>[?<placement-modifier>]
* org.eclipse.ui.views.problems.resolveMarker.item from popup://org.eclipse.ui.views.ProblemView
+
  
<menu-hook>
+
scheme is about how to interpret the URI path. For example, <code>menu</code>, <code>toolbar</code>, <code>popup</code>, <code>status</code> (although status may be deprecated).
  <actions>
+
    <action id="org.eclipse.ui.views.problems.sorting.item">
+
      <label>Sorting...</label>
+
      <mnemonic>S</mnemonic>
+
      <tooltip>Change the Sort order</tooltip>
+
      <invoke-class>org.eclipse.ui.views.problems.sorting</invoke-class>
+
    </action>
+
    <action id="org.eclipse.ui.views.problems.resolveMarker.item">
+
      <label>Quick Fix</label>
+
      <mnemonic>Q</mnemonic>
+
      <iconpath>$nl$/icons/full/elcl16/smartmode_co.gif</iconpath>
+
      <invoke-class>org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals</invoke-class>
+
      <update-class>org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals</update-class>
+
    </action>
+
  </actions>
+
  <menus>
+
    <menubar id="org.eclipse.ui.views.ProblemView">
+
      <menu id="org.eclipse.ui.views.ProblemView">
+
        <section id="problem.view.section">
+
          <item action-ref="org.eclipse.ui.views.problems.sorting.item" />
+
          <menu id="org.eclipse.ui.views.problems.groupBy.menu">
+
            <label>Group By</label>
+
            <mnemonic>G</mnemonic>
+
          </menu>
+
        </section>
+
      </menu>
+
    </menubar>
+
    <popup id="org.eclipse.ui.views.ProblemView">
+
      <section id="group.resolve">
+
        <item action-ref="org.eclipse.ui.views.problems.resolveMarker.item" />
+
      </section>
+
    </popup>
+
  </menus>
+
</menu-hook>
+
  
Some thoughts:
+
==== menu: ====
  
* the actions can only specify one icon
+
For <code>menu:</code> valid root ids will be any viewId for that view's menu, and <b>org.eclipse.ui.main.menu</b> for the main menu.  Then specify the id of the menu this contribution applies to.  The placement modifier helps position the menu contribution.  ex: after=<id>, where <id> can be a separator name, menu id, or item id.  An example of a path: <code>menu:org.eclipse.search.menu?after=contextMenuActionsGroup</code>
* the actions can't *quite* link to our commands
+
* the menus can't specify dynamic submenus
+
  
=== Menu - XUL ===
+
Since menu ids must be unique, you can specify your menu location relative to an existing id: <code>menu:org.eclipse.search.menu?after=contextMenuActionsGroup</code>
  
With Mozilla everywhere, there is the probability eclipse will include xulrunner.  Menu definitions that are consistent with XUL look like:
+
==== toolbar: ====
  
  <keyset>
+
For <code>toolbar:</code> valid root ids will be any viewId for that view's toolbar, <b>org.eclipse.ui.main.toolbar</b> for the main toolbar, and any toolbar id that is contained in the main toolbar. Toolbars can support <b>invisible</b> separators. Toolbars in the main toolbar (technically a coolbar) can have ids as well as separators, but only one level. For example: <code>toolbar:org.eclipse.ui.edit.text.actionSet.presentation?after=Presentation</code>
    <key id="paste-key" modifiers="accel" key="V" />
+
  </keyset>
+
  <menubar id="org.eclipse.ui.views.ProblemView">
+
    <menupopup id="org.eclipse.ui.views.ProblemView">
+
      <menuitem id="org.eclipse.ui.views.problems.sorting.item"
+
                accesskey="S"
+
                key="paste-key"
+
                label="Sorting..."
+
                oncommand="invokeCommand('org.eclipse.ui.views.problems.sorting')" />
+
      <menu id="org.eclipse.ui.views.problems.groupBy.menu"
+
            label="Group By"
+
            accesskey="G">
+
        <menupopup id="groupby.popup">
+
          <!-- this is where submenu items would go -->
+
        </menupopup>
+
      </menu>
+
    </menupopup>
+
  </menubar>
+
  
XUL supports everything as a flavour of a DOM, and javascripting can drive your buttons to perform commands.  I suspect the scripting would allow you to dynamically update menus (dynamic menus) on popup, depending on what events the DOM would report to you.
+
In this example, <b>Presentation</b> is an invisible separator in the <b>org.eclipse.ui.edit.text.actionSet.presentation</b> toolbar.
  
== Menus API ==
+
The use of <b>org.eclipse.ui.main.toolbar</b> might change if all "main" toolbars have ids anyway, so the only options for interpretting the toolbar root is 1) the view toolbar or 2) an IDed main toolbar.
  
We can contribute menu definitions through the IMenuService API.
+
==== popup: ====
  
The above example can be done for the view menus:
+
For <code>popup:</code> valid root ids are any registered context id (which defaults to the part id if no context menu id was given at registration time) and <b>org.eclipse.ui.popup.any</b> for all registered context menus.  For example, to add to the default Text Editor context menu: <code>popup:#TextEditorContext?after=additions</code>
  
    public void createProblemsViewMenu() {
+
Popup submenus are treated like menu submenus, except the form continues to be <code>popup:submenuId</code>.
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
+
                .getActiveWorkbenchWindow().getService(IMenuService.class);
+
        IMenuCollection menuRoot = menuServ.getMenuRoot(
+
                "menu://org.eclipse.ui.views.ProblemView", //$NON-NLS-1$
+
                null);
+
+
        // add a menu item
+
        Item sort = new Item(SORTING_CMD);
+
        sort.setMnemonic("S"); //$NON-NLS-1$
+
        sort.setTooltip("Change the Sort order"); //$NON-NLS-1$
+
        menuRoot.add(SORTING_ITEM, sort, null);
+
+
        // add a dynamic submenu
+
        Menu groupByMenu = new Menu(GROUPBY_MENU, "Group By"); //$NON-NLS-1$
+
        groupByMenu.setMnemonic("B"); //$NON-NLS-1$
+
        groupByMenu.setDynamicMenu(new GroupByDynamicMenu());
+
        menuRoot.add(groupByMenu, null);
+
+
        menuRoot.add(new Separator("group.filter", true)); //$NON-NLS-1$
+
+
        // add a sub menu
+
        Menu filtersMenu = new Menu(FILTERS_MENU, "Filters"); //$NON-NLS-1$
+
        filtersMenu.setMnemonic("F"); //$NON-NLS-1$
+
        filtersMenu.setDynamicMenu(new FiltersDynamicMenu());
+
        menuRoot.add(filtersMenu, null);
+
+
        // add items to the sub menu
+
        Item fitem = new Item(CONFIGURE_FILTER_CMD);
+
        fitem.setTooltip("Configure the filters to be applied to this view"); //$NON-NLS-1$
+
        fitem.setMnemonic("C"); //$NON-NLS-1$
+
        fitem.setImage(getSharedImage("elcl16/filter_ps.gif")); //$NON-NLS-1$
+
        menuRoot.add(CONFIGURE_FILTER_ITEM, fitem, null);
+
+
        fitem = new Item(getProblemPreferencesCommand());
+
        fitem.setTooltip("Open the preferences"); //$NON-NLS-1$
+
        fitem.setMnemonic("P"); //$NON-NLS-1$
+
        menuRoot.add(PREFERENCES_ITEM, fitem, null);
+
+
        // place the contribution back into the menu service.
+
        IMenuContribution viewMenu = menuServ.contribute(menuRoot);
+
+
        // and possibly much later
+
        menuServ.remove(viewMenu);
+
    }
+
  
You ask for a menu root, specifying a root item (like <code>menu://org.eclipse.ui.views.ProblemView</code>) and potentially a location modifier (after some id).
+
There will be constants defined for the ids that the eclipse workbench provides, probably in <code>org.eclipse.ui.menus.MenuUtil</code>.
  
You can add Menus, Separators, Items, and Widgets to an IMenuCollection (and a Menu is an IMenuCollection).  Once you've update your collection, contribute it back to the menu service.
+
=== Using Expressions in &lt;visibleWhen/&gt; ===
  
When you add Items (and possibly Widgets) you must specify an id. This would allow you to re-use an Item's rendering information.
+
In '''3.3M6''' an org.eclipse.core.expressions.definitions extension point was added. Used to define a [[Platform Expression Framework|core expression]], the definition can then be referenced from other locations.
  
Menus cannot be re-used in this manner, and so they have an intrinsic id value. Separators are unique within one menu level, so they also contain their id value.
+
<source lang="xml">
 +
<extension point="org.eclipse.core.expressions.definitions">
 +
  <definition id="com.example.context">
 +
    <with variable="activeContexts">
 +
      <iterate operator="or">
 +
        <equals value="org.eclipse.ui.contexts.actionSet"/>
 +
      </iterate>
 +
    </with>
 +
  </definition>
 +
</extension>
 +
</source>
  
== Menus API Option 2 ==
+
This can be called in a core expression like activeWhen, enabledWhen, visibleWhen, etc using the reference element:
  
In option 1, the IMenuCollection manages a set of menu updates and works on the menu hierarchy, but is a distinct object. In option 2, you are returned your menu and just add items to it.
+
<source lang="xml">
 +
<reference definitionId="com.example.context"/>
 +
</source>
  
    public void createProblemsViewMenuOption2() {
+
=== Ideas that were considered but not implemented ===
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
+
                .getActiveWorkbenchWindow().getService(IMenuService.class);
+
        Menu viewMenu = menuServ.getMenu("menu://org.eclipse.ui.views.ProblemView", //$NON-NLS-1$
+
                null);
+
+
        // add a menu item
+
        Item sort = new Item(SORTING_CMD);
+
        sort.setMnemonic("S"); //$NON-NLS-1$
+
        sort.setTooltip("Change the Sort order"); //$NON-NLS-1$
+
        viewMenu.add(SORTING_ITEM, sort, null);
+
+
        // add a dynamic submenu
+
        Menu groupByMenu = new Menu(GROUPBY_MENU, "Group By"); //$NON-NLS-1$
+
        groupByMenu.setMnemonic("B"); //$NON-NLS-1$
+
        groupByMenu.setDynamicMenu(new GroupByDynamicMenu());
+
        viewMenu.add(groupByMenu, null);
+
+
        viewMenu.add(new Separator("group.filter", true)); //$NON-NLS-1$
+
+
        // add a sub menu
+
        Menu filtersMenu = new Menu(FILTERS_MENU, "Filters"); //$NON-NLS-1$
+
        filtersMenu.setMnemonic("F"); //$NON-NLS-1$
+
        filtersMenu.setDynamicMenu(new FiltersDynamicMenu());
+
        viewMenu.add(filtersMenu, null);
+
+
        // add items to the sub menu
+
        Item fitem = new Item(CONFIGURE_FILTER_CMD);
+
        fitem.setTooltip("Configure the filters to be applied to this view"); //$NON-NLS-1$
+
        fitem.setMnemonic("C"); //$NON-NLS-1$
+
        fitem.setImage(getSharedImage("elcl16/filter_ps.gif")); //$NON-NLS-1$
+
        viewMenu.add(CONFIGURE_FILTER_ITEM, fitem, null);
+
+
        fitem = new Item(getProblemPreferencesCommand());
+
        fitem.setTooltip("Open the preferences"); //$NON-NLS-1$
+
        fitem.setMnemonic("P"); //$NON-NLS-1$
+
        viewMenu.add(PREFERENCES_ITEM, fitem, null);
+
+
        // update the menu changes
+
        viewMenu.update();
+
    }
+
  
The <code>update()</code> at the end tells the menu service to contribute your changes to the menu rendering items (<code>IContributionItems</code>).
+
These ideas were considered but not implemented.
  
= Add Toggle Mark Occurrences to main toolbar =
+
==== Menu - JSR198 ====
  
 +
'''Note:''' for novelty purposes only.
  
We can provide the Toggle Mark Occurrences toolbar buttonIt's normally contributed through an actionSet as a retargettable action, and the Java and Class File editors *EditorActionBarContributors provide the implementation ToggleMarkOccurrencesAction through IActionBars#setGlobalActionHandler(*).
+
For comparison, there is a JSR describing how IDEs can contribute menusBelow is a sample for 2 items:
  
== Commands ==
+
* org.eclipse.ui.views.problems.sorting.item from menu:org.eclipse.ui.views.ProblemView
 +
* org.eclipse.ui.views.problems.resolveMarker.item from popup:org.eclipse.ui.views.ProblemView
  
First define the toggle mark occurrences command.  Pretty straight forward,
+
<source lang="xml">
although it needs a "STYLE" state since it can be toggled.  To allow handlers to
+
<menu-hook>
update the label for the menu/toolbar items, we also add the "NAME" state.
+
   <actions>
 
+
     <action id="org.eclipse.ui.views.problems.sorting.item">
  <extension point="org.eclipse.ui.commands">
+
       <label>Sorting...</label>
    <command categoryId="org.eclipse.jdt.ui.category.source"
+
      <mnemonic>S</mnemonic>
            description="Toggles mark occurrences in Java editors"
+
       <tooltip>Change the Sort order</tooltip>
            id="org.eclipse.jdt.ui.edit.text.java.toggleMarkOccurrences"
+
      <invoke-class>org.eclipse.ui.views.problems.sorting</invoke-class>
            name="Toggle Mark Occurrences">
+
    </action>
      <state id="NAME" class="org.eclipse.jface.menus.TextState" />
+
     <action id="org.eclipse.ui.views.problems.resolveMarker.item">
      <state id="STYLE" class="org.eclipse.jface.commands.ToggleState:true" />
+
      <label>Quick Fix</label>
    </command>
+
      <mnemonic>Q</mnemonic>
   </extension>
+
       <iconpath>$nl$/icons/full/elcl16/smartmode_co.gif</iconpath>
 
+
       <invoke-class>org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals</invoke-class>
== Handlers ==
+
       <update-class>org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals</update-class>
 
+
     </action>
This command doesn't have a default handler, as it only applies to specific
+
  </actions>
editors that are provided.  So we would provide the handler for the java editor.
+
  <menus>
 
+
     <menubar id="org.eclipse.ui.views.ProblemView">
  <extension point="org.eclipse.ui.handlers">
+
       <menu id="org.eclipse.ui.views.ProblemView">
     <handler commandId="org.eclipse.jdt.ui.edit.text.java.toggleMarkOccurrences"
+
        <section id="problem.view.section">
            class="org.eclipse.jdt.internal.ui.javaeditor.ToggleMarkOccurrencesHandler">
+
          <command action-ref="org.eclipse.ui.views.problems.sorting.item" />
       <activeWhen>
+
          <menu id="org.eclipse.ui.views.problems.groupBy.menu">
        <with variable="activePartId">
+
            <label>Group By</label>
          <or>
+
            <mnemonic>G</mnemonic>
            <equals value="org.eclipse.jdt.ui.CompilationUnitEditor" />
+
          </menu>
            <equals value="org.eclipse.jdt.ui.ClassFileEditor" />
+
         </section>
          </or>
+
        </with>
+
       </activeWhen>
+
    </handler>
+
  </extension>
+
 
+
We're active for both the Java editor and the Class File editor.  There is also the option to programmatically install the handler.
+
 
+
AndExpression expr = new AndExperssion();
+
expr.add(new ActivePartIdExpression("org.eclipse.jdt.ui.CompilationUnitEditor"));
+
expr.add(new ActivePartIdExpression("org.eclipse.jdt.ui.ClassFileEditor"));
+
IHandlerService handlerServ = (IHandlerService)getSite().getWorkbenchWindow().getService(IHandlerService.class);
+
toggleOccurrencesHandler = new ToggleMarkOccurrencesHandler();
+
handlerServ.activateHandler("org.eclipse.jdt.ui.edit.text.java.toggleMarkOccurrences", toggleOccurrencesHandler, expr);
+
 
+
Since the same handler is valid for both editors, we install it with a specific expression and <b>don't</b> tie the activation to the part site.  But as written, the  <code>toggleOccurrencesHandler</code> will exist as long as the workbench window exists.
+
 
+
== Menus ==
+
 
+
  <extension point="org.eclipse.ui.menus">
+
     <menuRoot location="toolbar:org.eclipse.ui.edit.text.actionSet.presentation"
+
              after="Presentation">
+
      <item id="org.eclipse.jdt.ui.edit.text.java.toggleMarkOccurrences.item"
+
            commandId="org.eclipse.jdt.ui.edit.text.java.toggleMarkOccurrences"
+
            icon="$nl$/icons/full/etool16/mark_occurrences.gif"
+
            disabledIcon="$nl$/icons/full/dtool16/mark_occurrences.gif"
+
            helpContextId="toggle_mark_occurrences_action_context">
+
        <visibleWhen>
+
          <with variable="activeContexts">
+
            <iterator operator="or">
+
              <equals value="org.eclipse.jdt.ui.text.java.actionSet.presentation" />
+
            </iterator>
+
          </with>
+
        </visibleWhen>
+
       </item>
+
    </menuRoot>
+
  </extension>
+
 
+
Here we are adding ourselves to the workbench text presentation toolbar, which
+
has already been contributed.  This item is also tied to an actionSet.
+
 
+
== Menus API ==
+
 
+
The above XML can be done using the menus API:
+
 
+
    public void createToggleMarkOccurrences() {
+
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
+
                .getActiveWorkbenchWindow().getService(IMenuService.class);
+
        IMenuCollection menuRoot = menuServ.getMenuRoot(
+
                "toolbar:org.eclipse.ui.edit.text.actionSet.presentation", //$NON-NLS-1$
+
                "Presentation"); //$NON-NLS-1$
+
+
        Item toggleItem = new Item(TOGGLE_MARK_OCCURRENCES_CMD);
+
        toggleItem.setHelpContextId("toggle_mark_occurrences_action_context"); //$NON-NLS-1$
+
        menuRoot.add(TOGGLE_MARK_OCCURRENCES_ITEM, toggleItem,
+
                new ActiveContextExpression(JAVA_PRESENTATION_ACTIONSET_ID));
+
+
        menuServ.contribute(menuRoot);
+
    }
+
 
+
This asks for a menu root in the org.eclipse.ui.edit.text.actionSet.presentation toolbar after the Presentation id.
+
 
+
It's contributed with a visibleWhen clause <code>ActiveContextExpression(JAVA_PRESENTATION_ACTIONSET_ID)</code>, so it will be visible when the actionSet is active.
+
 
+
== Menus API Option 2 ==
+
 
+
You can add your item directly to the toolbar, and update it when you are done.
+
 
+
    public void createToggleMarkOccurrencesOption2() {
+
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
+
                .getActiveWorkbenchWindow().getService(IMenuService.class);
+
        Menu menu = menuServ.getMenu(
+
                "toolbar:org.eclipse.ui.edit.text.actionSet.presentation", //$NON-NLS-1$
+
                "Presentation"); //$NON-NLS-1$
+
+
        Item toggleItem = new Item(TOGGLE_MARK_OCCURRENCES_CMD);
+
        toggleItem.setHelpContextId("toggle_mark_occurrences_action_context"); //$NON-NLS-1$
+
        IMenuContribution toggleContribution = menu.add(
+
                TOGGLE_MARK_OCCURRENCES_ITEM, toggleItem,
+
                new ActiveContextExpression(JAVA_PRESENTATION_ACTIONSET_ID));
+
+
        menu.update();
+
+
        // at some later point
+
        menu.remove(toggleContribution);
+
    }
+
 
+
Each <code>add(*)</code> returns an IMenuContribution, which you can use to remove that item.  You cannot remove items that you didn't add yourself.  An application can hide any item at the product level using the override mechanism.
+
 
+
I wonder about using IMenuCollection and Menu when working with toolbars.  Toolbars can't recursively add toolbars inside them.  It's strictly toolbars contain items, widgets, and invisible separators.  Maybe specifying the IMenuService#getToolBar(location, afterId) for the option 2 API makes more sense.  That will also prevent mistakes with the Menu#add(Menu, Expression) use in the toolbar case.
+
 
+
= Possible Java Search Menu Example =
+
 
+
The java search menu items are added through a Java Search action set.  They have code that enables/disables the action set depending on the active editor.
+
 
+
== ActionSet context ==
+
 
+
If this is still to go in an actionSet, then we would define the actionSet context.
+
 
+
  <extension point="org.eclipse.ui.contexts">
+
    <context description="%JavaSearchActionSet.description"
+
            id="org.eclipse.jdt.ui.SearchActionSet"
+
            name="%JavaSearchActionSet.label"
+
            parentId="org.eclipse.ui.contexts.actionSet">
+
    </context>
+
  </extension>
+
 
+
== Commands ==
+
 
+
Also, a number of the items were retargetable actions that allow label updates.  The current pattern would mean adding the NAME state to a lot of the commands.
+
 
+
  <extension point="org.eclipse.ui.commands">
+
    <command name="%ActionDefinition.readAccessInworkspace.name"
+
            description="%ActionDefinition.readAccessInWorkspace.description"
+
            categoryId="org.eclipse.search.ui.category.search"
+
            id="org.eclipse.jdt.ui.edit.text.java.search.read.access.in.workspace">
+
       <state id="NAME" class="org.eclipse.jface.menus.TextState" />
+
    </command>
+
    <command name="%ActionDefinition.readAccessInProject.name"
+
            description="%ActionDefinition.readAccessInProject.description"
+
            categoryId="org.eclipse.search.ui.category.search"
+
            id="org.eclipse.jdt.ui.edit.text.java.search.read.access.in.project">
+
      <state id="NAME" class="org.eclipse.jface.menus.TextState" />
+
    </command>
+
    <command name="%ActionDefinition.readAccessInHierarchy.name"
+
            description="%ActionDefinition.readAccessInHierarchy.description"
+
            categoryId="org.eclipse.search.ui.category.search"
+
            id="org.eclipse.jdt.ui.edit.text.java.search.read.access.in.hierarchy">
+
       <state id="NAME" class="org.eclipse.jface.menus.TextState" />
+
    </command>
+
    <command name="%ActionDefinition.readAccessInWorkingSet.name"
+
            description="%ActionDefinition.readAccessInWorkingSet.description"
+
            categoryId="org.eclipse.search.ui.category.search"
+
            id="org.eclipse.jdt.ui.edit.text.java.search.read.access.in.working.set">
+
      <state id="NAME" class="org.eclipse.jface.menus.TextState" />
+
     </command>
+
    <command name="%ActionDefinition.writeAccessInWorkspace.name"
+
            description="%ActionDefinition.writeAccessInWorkspace.description"
+
            categoryId="org.eclipse.search.ui.category.search"
+
            id="org.eclipse.jdt.ui.edit.text.java.search.write.access.in.workspace">
+
      <state id="NAME" class="org.eclipse.jface.menus.TextState" />
+
     </command>
+
    <command name="%ActionDefinition.writeAccessInProject.name"
+
            description="%ActionDefinition.writeAccessInProject.description"
+
            categoryId="org.eclipse.search.ui.category.search"
+
            id="org.eclipse.jdt.ui.edit.text.java.search.write.access.in.project">
+
       <state id="NAME" class="org.eclipse.jface.menus.TextState" />
+
    </command>
+
    <command name="%ActionDefinition.writeAccessInHierarchy.name"
+
            description="%ActionDefinition.writeAccessInHierarchy.description"
+
            categoryId="org.eclipse.search.ui.category.search"
+
            id="org.eclipse.jdt.ui.edit.text.java.search.write.access.in.hierarchy">
+
      <state id="NAME" class="org.eclipse.jface.menus.TextState" />
+
    </command>
+
    <command name="%ActionDefinition.writeAccessInWorkingSet.name"
+
            description="%ActionDefinition.writeAccessInWorkingSet.description"
+
            categoryId="org.eclipse.search.ui.category.search"
+
            id="org.eclipse.jdt.ui.edit.text.java.search.write.access.in.working.set">
+
      <state id="NAME" class="org.eclipse.jface.menus.TextState" />
+
    </command>
+
  </extension>
+
 
+
== Menus ==
+
 
+
We'll assume that the Search menu is globally defined elsewhere by the org.eclipse.search plugin.
+
 
+
  <extension point="org.eclipse.ui.menus">
+
    <menuRoot location="menu://org.eclipse.ui.main.menu" after="navigate">
+
      <menu label="%searchMenu.label" mnemonic="a" id="org.eclipse.search.menu">
+
        <!-- not to be used by clients  -->
+
        <separator name="internalDialogGroup" visible="false" />
+
        <!-- to be used by clients -->
+
        <separator name="dialogGroup" visible="false" />
+
        <!-- to be used by clients      -->
+
        <separator name="fileSearchContextMenuActionsGroup" visible="true" />
+
         <!-- to be used by clients      -->
+
        <separator name="contextMenuActionsGroup" visible="true" />
+
        <!-- to be used by clients -->
+
        <separator name="occurencesActionsGroup" visible="true" />
+
        <!-- to be used by clients -->
+
        <separator name="extraSearchGroup" visible="true" />
+
 
       </menu>
 
       </menu>
     </menuRoot>
+
     </menubar>
   </extension>
+
    <popup id="org.eclipse.ui.views.ProblemView">
 +
      <section id="group.resolve">
 +
        <command action-ref="org.eclipse.ui.views.problems.resolveMarker.item" />
 +
      </section>
 +
    </popup>
 +
   </menus>
 +
</menu-hook>
 +
</source>
  
Then the JDT plugin would contribute the menu items to search, where the menuRoot location specifies the starting point for adding the menus.  For groups of actions like the Write Access or Read Access shown here, they can just be specified in order.  The <visibleWhen/> clauses must be specified on the items contributed if they want to belong to the actionSet, but if the contribute items are contain in a contributed menu, it can just be specified on the <menu/> element.  We also use the relative URI notation, since the menu id org.eclipse.search.menu must be unique.
+
Some thoughts:
  
  <extension point="org.eclipse.ui.menus">
+
* the actions can only specify one icon
    <menuRoot location="menu:org.eclipse.search.menu" after="dialogGroup">
+
* the actions can't *quite* link to our commands
      <item id="org.eclipse.jdt.ui.actions.OpenJavaSearchPageAction"
+
* the menus can't specify dynamic submenus
            commandId="org.eclipse.jdt.internal.ui.search.openJavaSearchPage"
+
            label="%openJavaSearchPageAction.label"
+
            mnemonic="J"
+
            icon="$nl$/icons/full/obj16/jsearch_obj.gif"
+
            helpContextId="java_search_action_context">
+
        <visibleWhen>
+
          <with variable="activeContexts">
+
            <iterator operator="or">
+
              <equals value="org.eclipse.jdt.ui.SearchActionSet" />
+
            </iterator>
+
          </with>
+
        </visibleWhen>
+
      </item>
+
    </menuRoot>
+
    <menuRoot location="menu:org.eclipse.search.menu"
+
              after="contextMenuActionsGroup">
+
      <menu id="readAccessSubMenu"
+
            label="%readAccessSubMenu.label"
+
            mnemonic="R">
+
        <separator name="group1" visible="false" />
+
        <item id="org.eclipse.jdt.ui.actions.ReadAccessInWorkspace"
+
              commandId="org.eclipse.jdt.ui.edit.text.java.search.read.access.in.workspace"
+
              label="%InWorkspace.label"
+
              mnemonic="W">
+
        </item>
+
        <item id="org.eclipse.jdt.ui.actions.ReadAccessInProject"
+
              commandId="org.eclipse.jdt.ui.edit.text.java.search.read.access.in.project"
+
              label="%InProject.label"
+
              mnemonic="P">
+
        </item>
+
        <item id="org.eclipse.jdt.ui.actions.ReadAccessInHierarchy"
+
              commandId="org.eclipse.jdt.ui.edit.text.java.search.read.access.in.hierarchy"
+
              label="%InHierarchy.label"
+
              mnemonic="H">
+
        </item>
+
        <item id="org.eclipse.jdt.ui.actions.ReadAccessInWorkingSet"
+
              commandId="org.eclipse.jdt.ui.edit.text.java.search.read.access.in.working.set"
+
              label="%InWorkingSet.label"
+
              mnemonic="S">
+
        </item>
+
        <visibleWhen>
+
          <with variable="activeContexts">
+
            <iterator operator="or">
+
              <equals value="org.eclipse.jdt.ui.SearchActionSet" />
+
            </iterator>
+
          </with>
+
        </visibleWhen>
+
      </menu>
+
      <menu id="writeAccessSubMenu"
+
            label="%writeAccessSubMenu.label"
+
            mnemonic="W">
+
        <separator name="group1" visible="false" />
+
        <item id="org.eclipse.jdt.ui.actions.WriteAccessInWorkspace"
+
              commandId="org.eclipse.jdt.ui.edit.text.java.search.write.access.in.workspace"
+
              label="%InWorkspace.label"
+
              mnemonic="W">
+
        </item>
+
        <item id="org.eclipse.jdt.ui.actions.WriteAccessInProject"
+
              commandId="org.eclipse.jdt.ui.edit.text.java.search.write.access.in.project"
+
              label="%InProject.label"
+
              mnemonic="P">
+
        </item>
+
        <item id="org.eclipse.jdt.ui.actions.WriteAccessInHierarchy"
+
              commandId="org.eclipse.jdt.ui.edit.text.java.search.write.access.in.hierarchy"
+
              label="%InHierarchy.label"
+
              mnemonic="H">
+
        </item>
+
        <item id="org.eclipse.jdt.ui.actions.WriteAccessInWorkingSet"
+
              commandId="org.eclipse.jdt.ui.edit.text.java.search.write.access.in.working.set"
+
              label="%InWorkingSet.label"
+
              mnemonic="S">
+
        </item>
+
        <visibleWhen>
+
          <with variable="activeContexts">
+
            <iterator operator="or">
+
              <equals value="org.eclipse.jdt.ui.SearchActionSet" />
+
            </iterator>
+
          </with>
+
        </visibleWhen>
+
      </menu>
+
    </menuRoot>
+
    <menuRoot location="menu:org.eclipse.search.menu"
+
              after="occurencesActionsGroup">
+
      <item id="org.eclipse.jdt.internal.ui.actions.OccurrencesSearchMenuAction"
+
            commandId="org.eclipse.jdt.ui.edit.text.java.search.occurrences.in.file.quickMenu"
+
            label="%occurrencesSubMenu.label">
+
        <dynamic class="org.eclipse.jdt.internal.ui.actions.OccurrencesSearchMenuAction" />
+
        <visibleWhen>
+
          <with variable="activeContexts">
+
            <iterator operator="or">
+
              <equals value="org.eclipse.jdt.ui.SearchActionSet" />
+
            </iterator>
+
          </with>
+
        </visibleWhen>
+
      </item>
+
    </menuRoot>
+
  </extension>
+
  
Currently, the java search menus are in the Java Search actionSet, that is dynamically enabled/disabled.  This could also be done by specifying a visibleWhen like:
+
==== Menu - XUL ====
  
<visibleWhen>
+
'''Note:''' for novelty purposes only.
  <with variable="activeEditorId">
+
    <or>
+
      <equals value="org.eclipse.jdt.ui.CompilationUnitEditor" />
+
      <equals value="org.eclipse.jdt.ui.ClassFileEditor" />
+
    </or>
+
  </with>
+
</visibleWhen>
+
  
This would make the visible if either the Java or Class File editor was the active editor, and they would disappear otherwise.
 
  
 +
For comparison, with Mozilla everywhere there is the probability eclipse will include xulrunner.  Menu definitions that are consistent with XUL look like:
  
== Menus API ==
+
<source lang="xml">
 +
<keyset>
 +
  <key id="paste-key" modifiers="accel" key="V" />
 +
</keyset>
 +
<menubar id="org.eclipse.ui.views.ProblemView">
 +
  <menupopup id="org.eclipse.ui.views.ProblemView">
 +
    <menuitem id="org.eclipse.ui.views.problems.sorting.item"
 +
        accesskey="S"
 +
        key="paste-key"
 +
        label="Sorting..."
 +
        oncommand="invokeCommand('org.eclipse.ui.views.problems.sorting')" />
 +
    <menu id="org.eclipse.ui.views.problems.groupBy.menu"
 +
        label="Group By"
 +
        accesskey="G">
 +
      <menupopup id="groupby.popup">
 +
        <!-- this is where submenu items would go -->
 +
      </menupopup>
 +
    </menu>
 +
  </menupopup>
 +
</menubar>
 +
</source>
  
The API can be used to contribute to the main menu bar:
+
XUL supports everything as a flavour of a DOM, and javascripting can drive your buttons to perform commands.  I suspect the scripting would allow you to dynamically update menus (dynamic menus) on popup, depending on what events the DOM would report to you.
  
    public void addSearchMenu() {
 
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
 
                .getActiveWorkbenchWindow().getService(IMenuService.class);
 
        IMenuCollection menuRoot = menuServ.getMenuRoot(
 
                "menu://org.eclipse.ui.main.menu", "navigate"); //$NON-NLS-1$ //$NON-NLS-2$
 
        Menu searchMenu = new Menu("org.eclipse.search.menu", "Search"); //$NON-NLS-1$ //$NON-NLS-2$
 
        menuRoot.add(searchMenu, null);
 
 
        searchMenu.add(new Separator("internalDialogGroup", false)); //$NON-NLS-1$
 
        searchMenu.add(new Separator("dialogGroup", false)); //$NON-NLS-1$
 
        searchMenu
 
                .add(new Separator("fileSearchContextMenuActionsGroup", true)); //$NON-NLS-1$
 
        searchMenu.add(new Separator("contextMenuActionsGroup", true)); //$NON-NLS-1$
 
        searchMenu.add(new Separator("occurencesActionsGroup", true)); //$NON-NLS-1$
 
        searchMenu.add(new Separator("extraSearchGroup", true)); //$NON-NLS-1$
 
 
        menuServ.contribute(menuRoot);
 
    }
 
  
It's just a menu inserted at the menu root location.
+
==== Expression Templates original suggestion  ====
  
  
Then another plugin can contribute to that menu:
+
You can see that the <activeWhen/>, <enabledWhen/>, and probably the <visibleWhen/> are likely to be replicated over and over againA possible option is some kind of expression template markup ... either in its own extension or supported by our UI extensions that can use core expressions.
    public void addToSearchMenu() {
+
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
+
                .getActiveWorkbenchWindow().getService(IMenuService.class);
+
        IMenuCollection menuRoot = menuServ.getMenuRoot(
+
                "menu://org.eclipse.search.menu", "dialogGroup"); //$NON-NLS-1$ //$NON-NLS-2$
+
        Item searchItem = new Item(
+
                "org.eclipse.jdt.internal.ui.search.openJavaSearchPage"); //$NON-NLS-1$
+
        searchItem.setMnemonic("J"); //$NON-NLS-1$
+
        searchItem.setImage(getSharedImage("icons/full/obj16/jsearch_obj.gif")); //$NON-NLS-1$
+
        searchItem.setHelpContextId("java_search_action_context"); //$NON-NLS-1$
+
        ActiveContextExpression activeSearchActionSet = new ActiveContextExpression(
+
                "org.eclipse.jdt.ui.SearchActionSet"); //$NON-NLS-1$
+
        menuRoot.add("org.eclipse.jdt.ui.actions.OpenJavaSearchPageAction", //$NON-NLS-1$
+
                searchItem, activeSearchActionSet);
+
+
        menuServ.contribute(menuRoot);
+
   
+
        menuRoot = menuServ.getMenuRoot(
+
                "menu://org.eclipse.search.menu", "contextMenuActionsGroup"); //$NON-NLS-1$ //$NON-NLS-2$
+
+
        Menu readMenu = new Menu("readAccessSubMenu", "Read Access"); //$NON-NLS-1$ //$NON-NLS-2$
+
        readMenu.setMnemonic("R"); //$NON-NLS-1$
+
        menuRoot.add(readMenu, activeSearchActionSet);
+
+
        readMenu.add(new Separator("group1", false)); //$NON-NLS-1$
+
+
        Item item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.workspace"); //$NON-NLS-1$
+
        item.setMnemonic("W"); //$NON-NLS-1$
+
        readMenu.add("org.eclipse.jdt.ui.actions.ReadAccessInWorkspace", item, //$NON-NLS-1$
+
                null);
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.project"); //$NON-NLS-1$
+
        item.setMnemonic("P"); //$NON-NLS-1$
+
        readMenu.add("org.eclipse.jdt.ui.actions.ReadAccessInProject", item, //$NON-NLS-1$
+
                null);
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.hierarchy"); //$NON-NLS-1$
+
        item.setMnemonic("H"); //$NON-NLS-1$
+
        readMenu.add("org.eclipse.jdt.ui.actions.ReadAccessInHierarchy", item, //$NON-NLS-1$
+
                null);
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.working.set"); //$NON-NLS-1$
+
        item.setMnemonic("S"); //$NON-NLS-1$
+
        readMenu.add("org.eclipse.jdt.ui.actions.ReadAccessInWorkingSet", item, //$NON-NLS-1$
+
                null);
+
+
        Menu writeMenu = new Menu("readAccessSubMenu", "Read Access"); //$NON-NLS-1$ //$NON-NLS-2$
+
        writeMenu.setMnemonic("R"); //$NON-NLS-1$
+
        menuRoot.add(writeMenu, activeSearchActionSet);
+
+
        writeMenu.add(new Separator("group1", false)); //$NON-NLS-1$
+
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.workspace"); //$NON-NLS-1$
+
        item.setMnemonic("W"); //$NON-NLS-1$
+
        writeMenu.add(
+
                "org.eclipse.jdt.ui.actions.WriteAccessInWorkspace", item, //$NON-NLS-1$
+
                null);
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.project"); //$NON-NLS-1$
+
        item.setMnemonic("P"); //$NON-NLS-1$
+
        writeMenu.add("org.eclipse.jdt.ui.actions.WriteAccessInProject", item, //$NON-NLS-1$
+
                null);
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.hierarchy"); //$NON-NLS-1$
+
        item.setMnemonic("H"); //$NON-NLS-1$
+
        writeMenu.add(
+
                "org.eclipse.jdt.ui.actions.WriteAccessInHierarchy", item, //$NON-NLS-1$
+
                null);
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.write.access.in.working.set"); //$NON-NLS-1$
+
        item.setMnemonic("S"); //$NON-NLS-1$
+
        writeMenu.add(
+
                "org.eclipse.jdt.ui.actions.WriteAccessInWorkingSet", item, //$NON-NLS-1$
+
                null);
+
+
        menuServ.contribute(menuRoot);
+
    }
+
  
When done, contribute the built menu back to the menu service.
+
Here's an example of using expression templates in its own extension point.
  
== Menus API Option 2 ==
+
<source lang="xml">
 +
<extension point="org.eclipse.core.expression.templates">
 +
  <expression id="isPartActive">
 +
    <parameter id="partId" />
 +
    <with variable="activePartId">
 +
      <equals value="$partId" />
 +
    </with>
 +
  </expression>
 +
  <expression id="isActionSetActive">
 +
    <parameter id="actionSetId" />
 +
    <with variable="activeContexts">
 +
      <iterator operator="or">
 +
        <equals value="$actionSetId" />
 +
      </iterator>
 +
    </with>
 +
  </expression>
 +
  <expression id="isContextActive">
 +
    <parameter id="contextId" />
 +
    <with variable="activeContexts">
 +
      <iterator operator="or">
 +
        <equals value="$contextId" />
 +
      </iterator>
 +
    </with>
 +
  </expression>
 +
  <expression id="isSelectionAvailable">
 +
    <not>
 +
      <count value="0" />
 +
    </not>
 +
  </expression>
 +
</extension>
 +
</source>
  
When contributing  to the main menu you will still get a <code>Menu</code> object returned, it just represents the main menu bar:
+
This could be used to simplify the handler definitions:
  
    public void addSearchMenuOption2() {
+
<source lang="xml">
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
+
<extension point="org.eclipse.ui.handlers">
                .getActiveWorkbenchWindow().getService(IMenuService.class);
+
  <handler commandId="org.eclipse.ui.edit.copy"
        Menu mainMenuBar = menuServ.getMenu(
+
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler">
                "menu://org.eclipse.ui.main.menu", "navigate"); //$NON-NLS-1$ //$NON-NLS-2$
+
    <enabledWhen>
        Menu searchMenu = new Menu("org.eclipse.search.menu", "Search"); //$NON-NLS-1$ //$NON-NLS-2$
+
      <evaluate ref="isSelectionAvailable" />
        mainMenuBar.add(searchMenu, null);
+
    </enabledWhen>
+
    <activeWhen>
        searchMenu.add(new Separator("internalDialogGroup", false)); //$NON-NLS-1$
+
      <evaluate ref="isPartActive">
        searchMenu.add(new Separator("dialogGroup", false)); //$NON-NLS-1$
+
         <parameter id="partId" value="org.eclipse.ui.views.ProblemView" />
        searchMenu
+
      </evaluate>
                .add(new Separator("fileSearchContextMenuActionsGroup", true)); //$NON-NLS-1$
+
    </activeWhen>
         searchMenu.add(new Separator("contextMenuActionsGroup", true)); //$NON-NLS-1$
+
  </handler>
        searchMenu.add(new Separator("occurencesActionsGroup", true)); //$NON-NLS-1$
+
</extension>
        searchMenu.add(new Separator("extraSearchGroup", true)); //$NON-NLS-1$
+
</source>
+
        mainMenuBar.update();
+
    }
+
  
Once within a menu we could allow you to continue to add to it without going back to the menu service:
+
If we allow recursive template definitions, that would allow you to specify the concrete expression once and then reference it throughout your view.
  
    public void addToSearchMenuOption2() {
+
<source lang="xml">
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
+
<extension point="org.eclipse.core.expression.templates">
                .getActiveWorkbenchWindow().getService(IMenuService.class);
+
  <expression id="isProblemViewActive">
        Menu searchMenu = menuServ.getMenu(
+
    <evaluate ref="isPartActive">
                "menu://org.eclipse.search.menu", "dialogGroup"); //$NON-NLS-1$ //$NON-NLS-2$
+
      <parameter id="partId" value="org.eclipse.ui.views.ProblemView" />
        Item searchItem = new Item(
+
    </evaluate>
                "org.eclipse.jdt.internal.ui.search.openJavaSearchPage"); //$NON-NLS-1$
+
  </expression>
        searchItem.setMnemonic("J"); //$NON-NLS-1$
+
</extension>
        searchItem.setImage(getSharedImage("icons/full/obj16/jsearch_obj.gif")); //$NON-NLS-1$
+
<extension point="org.eclipse.ui.handlers">
        searchItem.setHelpContextId("java_search_action_context"); //$NON-NLS-1$
+
  <handler commandId="org.eclipse.ui.edit.copy"
        ActiveContextExpression activeSearchActionSet = new ActiveContextExpression(
+
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler">
                "org.eclipse.jdt.ui.SearchActionSet"); //$NON-NLS-1$
+
    <enabledWhen>
        searchMenu.add("org.eclipse.jdt.ui.actions.OpenJavaSearchPageAction", //$NON-NLS-1$
+
      <evaluate ref="isSelectionAvailable" />
                searchItem, activeSearchActionSet);
+
    </enabledWhen>
+
    <activeWhen>
        searchMenu.after("contextMenuActionsGroup"); //$NON-NLS-1$
+
      <evaluate ref="isProblemViewActive" />
+
    </activeWhen>
        Menu readMenu = new Menu("readAccessSubMenu", "Read Access"); //$NON-NLS-1$ //$NON-NLS-2$
+
  </handler>
        readMenu.setMnemonic("R"); //$NON-NLS-1$
+
</extension>
        searchMenu.add(readMenu, activeSearchActionSet);
+
</source>
+
        readMenu.add(new Separator("group1", false)); //$NON-NLS-1$
+
+
        Item item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.workspace"); //$NON-NLS-1$
+
        item.setMnemonic("W"); //$NON-NLS-1$
+
        readMenu.add("org.eclipse.jdt.ui.actions.ReadAccessInWorkspace", item, //$NON-NLS-1$
+
                null);
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.project"); //$NON-NLS-1$
+
        item.setMnemonic("P"); //$NON-NLS-1$
+
        readMenu.add("org.eclipse.jdt.ui.actions.ReadAccessInProject", item, //$NON-NLS-1$
+
                null);
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.hierarchy"); //$NON-NLS-1$
+
        item.setMnemonic("H"); //$NON-NLS-1$
+
        readMenu.add("org.eclipse.jdt.ui.actions.ReadAccessInHierarchy", item, //$NON-NLS-1$
+
                null);
+
        item = new Item(
+
                "org.eclipse.jdt.ui.edit.text.java.search.read.access.in.working.set"); //$NON-NLS-1$
+
        item.setMnemonic("S"); //$NON-NLS-1$
+
        readMenu.add("org.eclipse.jdt.ui.actions.ReadAccessInWorkingSet", item, //$NON-NLS-1$
+
                null);
+
+
        // add write menu ...
+
+
        searchMenu.update();
+
    }
+
  
Once you have a <code>Menu</code> you can add structure to it, and propogate it into the system using <code>update()</code>.
+
This reduces the handler definition even more.
  
Of course, updates are not re-entrant and all updates are confined to the UI thread.
 
  
 +
A similar option to reuse expressions as much as possible without turning them into their own procedural language would be to allow global definitions and then reuse them.  No parameters and no expression composition:
  
= IFile object contribution =
+
<source lang="xml">
 +
<extension point="org.eclipse.core.expression.templates">
 +
  <expression id="isProblemViewActive">
 +
    <with variable="activePartId">
 +
      <equals value="org.eclipse.ui.views.ProblemView" />
 +
    </with>
 +
  </expression>
 +
  <expression id="isSelectionAvailable">
 +
    <not>
 +
      <count value="0" />
 +
    </not>
 +
  </expression>
 +
</extension>
 +
<extension point="org.eclipse.ui.handlers">
 +
  <handler commandId="org.eclipse.ui.edit.copy"
 +
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler">
 +
    <enabledWhen ref="isSelectionAvailable" />
 +
    <activeWhen ref="isProblemViewActive" />
 +
  </handler>
 +
</extension>
 +
</source>
  
We also have to provide object contributions (which in the past were scoped by objectClass).
+
==== Another Expression Alternative: Specify Context at Extension Level ====
  
== Menus ==
 
  
There will be a reserved popup ID, "org.eclipse.ui.menus.popup.any" that will allow contributions to any popup menu.
+
Since <code>enabledWhen</code> and <code>activeWhen</code> specify context and the simple way to specify context in XML is enclosure, how about scoping context to the extension point rather than the handler:
  
  <extension point="org.eclipse.ui.menus">
+
<source lang="xml">
     <menuRoot location="popup://org.eclipse.ui.menus.popup.any"
+
<extension point="org.eclipse.ui.handlers">
              after="additions">
+
  <enabledWhen>  <!-- context of all  handlers in this extension -->
       <item id="org.eclipse.ui.examples.wiki.post.item"
+
     <not>
            commandId="org.eclipse.ui.examples.wiki.post"
+
      <count value="0" />
            mnemonic="P"
+
    </not>
            icon="$nl$/icons/full/elcl16/post_wiki.gif">
+
  </enabledWhen>
        <visibleWhen>
+
  <activeWhen>
          <with variable="selection">
+
    <with variable="activePartId">
            <adapt type="org.eclipse.core.resources.IFile" />
+
      <equals value="org.eclipse.ui.views.ProblemView" />
          </with>
+
    </with>
        </visibleWhen>
+
  </activeWhen>
      </item>
+
  <handler commandId="org.eclipse.ui.edit.copy"
      <item id="org.eclipse.ui.examples.wiki.load.item"
+
       class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler" />
            commandId="org.eclipse.ui.examples.wiki.load"
+
  <handler commandId="org.eclipse.ui.edit.paste"
            mnemonic="L"
+
      class="org.eclipse.ui.views.markers.internal.PasteMarkerHandler" />
            icon="$nl$/icons/full/elcl16/load_wiki.gif">
+
  <handler commandId="org.eclipse.ui.edit.delete"
        <visibleWhen>
+
      class="org.eclipse.ui.views.markers.internal.RemoveMarkerHandler" />
          <adapt type="org.eclipse.core.resources.IFile" />
+
  <handler commandId="org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals"
        </visibleWhen>
+
      class="org.eclipse.ui.views.markers.internal.ResolveMarkerHandler" />
       </item>
+
  <handler commandId="org.eclipse.ui.edit.selectAll"
    </menuRoot>
+
      class="org.eclipse.ui.views.markers.internal.SelectAllMarkersHandler" />
  </extension>
+
  <handler commandId="org.eclipse.ui.file.properties"
 +
       class="org.eclipse.ui.views.markers.internal.ProblemPropertiesHandler" />
 +
</extension>
 +
</source>
  
It's probably that the default variable for core expression evaluations would be <b>selection</b>, so you wouldn't need the <with/> clause like in the second item aboveThere would probably also be a short-hand to tie the visibility to an active handler. Maybe <visibleWhen handler="true"/>
+
This gives compact markup without inventing a new languageElements nested in the handler element could override the extension-wide settings.
  
== Menus API ==
+
= Updating the menu and toolbar appearance =
  
So programmatically it is similar to all other menu contributions.
 
  
    public void addIFileContribution() {
+
It was suggested in 3.2 that state on the command could be used to implement the old contribution story behaviours:
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
+
#changing label text and tooltips
                .getActiveWorkbenchWindow().getService(IMenuService.class);
+
#changing icons
        IMenuCollection menuRoot = menuServ.getMenuRoot(
+
#changing enablement
                "popup://org.eclipse.ui.menus.popup.any", "additions"); //$NON-NLS-1$ //$NON-NLS-2$
+
#setting the item state (like checked state)
+
        Expression ifileExpression = new AdaptSelectionExpression(
+
                "org.eclipse.core.resources.IFile"); //$NON-NLS-1$
+
+
        Item wikiItem = new Item("org.eclipse.ui.examples.wiki.post"); //$NON-NLS-1$
+
        wikiItem.setMnemonic("P"); //$NON-NLS-1$
+
        wikiItem.setImage(getSharedImage("icons/full/elcl16/post_wiki.gif")); //$NON-NLS-1$
+
        menuRoot.add("org.eclipse.ui.examples.wiki.post.item", wikiItem, //$NON-NLS-1$
+
                ifileExpression);
+
        wikiItem = new Item("org.eclipse.ui.examples.wiki.load"); //$NON-NLS-1$
+
        wikiItem.setMnemonic("L"); //$NON-NLS-1$
+
        wikiItem.setImage(getSharedImage("icons/full/elcl16/load_wiki.gif")); //$NON-NLS-1$
+
        menuRoot.add("org.eclipse.ui.examples.wiki.load.item", wikiItem, //$NON-NLS-1$
+
                ifileExpression);
+
+
        menuServ.contribute(menuRoot);
+
    }
+
  
The location of org.eclipse.ui.menus.popup.any specifies any context menu, and the expression ties it to a specific objectClass.  Using the new expression syntax you can make your conditions more complex.
+
In 3.3 the enablement is tied to the command, and for the other behaviours we've decided to go with UIElements approach.
  
= Product removes the Project menu =
+
== UIElements represent each UI visible instance of a command ==
  
An RCP product wishes to remove the Project menuIt should be possible to override the visibility of menu contributions.
+
The command service keeps a list of registered UI elements, which can be updated by the active handlerThe checked state can be updated through <tt>UIElement#setChecked(boolean);</tt> (note that <tt>updateElement</tt> below is from <tt>IElementUpdater</tt>):
  
    public void addOverride() {
+
<source lang="java">
        // the RCP app would already have its product key
+
private boolean isChecked() {
        Object productKey = null;
+
    return getStore().getBoolean(
 +
            PreferenceConstants.EDITOR_MARK_OCCURRENCES);
 +
}
 
   
 
   
        IMenuService menuServ = (IMenuService) PlatformUI.getWorkbench()
+
public void updateElement(UIElement element, Map parameters) {
                .getActiveWorkbenchWindow().getService(IMenuService.class);
+
    element.setChecked(isChecked());
        menuServ.addOverride(productKey, "menu:project", new OverrideAdapter() { //$NON-NLS-1$
+
}
                    public Boolean getVisible() {
+
</source>
                        return Boolean.FALSE;
+
                    }
+
                });
+
    }
+
  
 +
When the toggle handler runs, it can request that any UI elements have their appearance updated from its <tt>execute(*)</tt> method:
  
The idea is to provide this ability at the product level. For example, an RCP app should be able to hide any menu items that it doesn't want but picked up through the inclusion of a plugin.
+
<source lang="java">
 +
ICommandService service = (ICommandService) serviceLocator
 +
        .getService(ICommandService.class);
 +
service.refreshElements(IJavaEditorActionDefinitionIds.TOGGLE_MARK_OCCURRENCES, null);
 +
</source>
  
That implies that it might not be part of the general IMenuService interface.  Or (taking a page from the IExtensionRegistry) it might use a token that's available from the WorkbenchWindowAdvisor so that products can use the interface, or even expose the ability to their users.
+
== State associated with the command is propogated to UI visible elements ==
  
If it returns <code>null</code> the next level of visibility is evaluatedThe <code>null</code> case is to keep it consistent with other overrides.
+
First define the toggle mark occurrences commandPretty straight forward,
 +
although it needs a "STYLE" state since it can be toggled.  To allow handlers to
 +
update the label for the menu/toolbar items, we also add the "NAME" state.
  
= File-&gt;Exit =
+
<source lang="xml">
 +
<extension point="org.eclipse.ui.commands">
 +
  <command categoryId="org.eclipse.jdt.ui.category.source"
 +
      description="%jdt.ui.ToggleMarkOccurrences.description"
 +
      id="org.eclipse.jdt.ui.edit.text.java.toggleMarkOccurrences"
 +
      name="%jdt.ui.ToggleMarkOccurrences.name">
 +
    <state id="NAME" class="org.eclipse.jface.menus.TextState" />
 +
    <state id="STYLE" class="org.eclipse.jface.commands.ToggleState:true" />
 +
  </command>
 +
</extension>
 +
</source>
  
== Current RCP using ActionBarAdvisor ==
+
= Work =
  
The ApplicationActionBarAdvisor should add the exit menu. The QuitAction is already coded and the exit command is already defined.
+
Progress in 3.3.
  
// create the file menu
+
== Available in 3.3 ==
MenuManager menu = new MenuManager(IDEWorkbenchMessages.Workbench_file, IWorkbenchActionConstants.M_FILE);
+
// ...
+
quitAction = ActionFactory.QUIT.create(window);
+
register(quitAction);
+
ActionContributionItem quitItem = new ActionContributionItem(quitAction);
+
quitItem.setVisible(!"carbon".equals(SWT.getPlatform())); //$NON-NLS-1$
+
menu.add(quitItem);
+
  
== Current RCP or Eclipse plugin using an actionSet ==
+
* [[Image:Ok_green.gif]] the editor action bar contributor solution.  EditorActionBarContributor will not be deprecated, but is not used in the commands/handler story.  Menu Contributions have visibility tied to an active editor id, and editor specific handlers can be created in the editor init(*) or createPartControl(*) method using the handler service from getPartSite().getService(IHandlerService.class).
 +
* [[Image:Ok_green.gif]] Attributes for <command/>: '''helpContextId''', '''style''' to support radio buttons and check boxes
 +
* [[Image:Ok_green.gif]] action sets as contexts - action sets are still defined using org.eclipse.ui.actionSets, and each actionSet generates an equivalent context.  showing/hiding actionSets activates/deactivates the equivalent context.
 +
* [[Image:Ok_green.gif]] How do we give Trim widgets/toolbar widgets "focus" for command and handlers?  There was an IFocusService added in 3.3 that allows a trim control to register itself.  When that control has focus, the control and the ID it registered with are provided in the global application context to core expressions and handlers.  This is available, but might not be the optimal solution if you just want cut, copy, and paste to work.
 +
* [[Image:Ok_green.gif]] Shortcuts to define reusable core expressions for <activeWhen/>, <enabledWhen/>, and <visibleWhen/>. This has been added as the org.eclipse.core.expressions.definitions extension point and the core expression <reference/> element.
 +
* [[Image:Ok_green.gif]] the mnemonic field for <command/> elements (decorating)
 +
* [[Image:Ok_green.gif]] display any keybinding for <command/> elements (decorating)
 +
* [[Image:Ok_green.gif]] toolbar <visibleWhen/> expressions
  
Using an actionSet, you can also place the action in the main menu.
+
== Available in 3.3M5 ==
  
<extension
+
There is an example of the RCP Mail application template updated for 3.3M5 and converted to use the org.eclipse.ui.menus extension point as much as possible at [http://dev.eclipse.org/viewcvs/index.cgi/platform-ui-home/R3_3/contributions-proposal/ Contribution Example].
      point="org.eclipse.ui.actionSets">
+
    <actionSet
+
          id="org.eclipse.ui.file.exitActions"
+
          label="Exit Actions"
+
          visible="true">
+
      <action
+
            class="org.eclipse.ui.internal.QuitAction"
+
            id="quit"
+
            definitionId="org.eclipse.ui.file.exit"
+
            label="E&amp;amp;xit"
+
            menubarPath="file/fileEnd"
+
            tooltip="Exit Eclipse">
+
      </action>
+
    </actionSet>
+
</extension>
+
  
== Proposed new menu support ==
+
* [[Image:Ok_green.gif]]  changing the menu item or tool item state from a handler, like updating the label or tooltip or checked state.  Commands can contain <state/> elements, but that is not appropriate to use for providing feedback to the user.  This will be done by adapting a callback provided by the UI element.
 +
* [[Image:Ok_green.gif]] the <separator/> element should have a '''name''' not an '''id'''
 +
* [[Image:Ok_green.gif]] support creating radio button or checked menu items
 +
* [[Image:Ok_green.gif]] creating new toolbars in the main coolbar/trim declaratively
 +
* [[Image:Ok_green.gif]] creating new toolbars in the main coolbar/trim programmatically
 +
* [[Image:Ok_green.gif]] org.eclipse.ui.popup.any as a context menu contribution
 +
* [[Image:Ok_green.gif]] Drop down toolbar items
  
With the new structure, you would have to turn the action into a handler.
+
We also have action sets activating and de-activating contexts in '''3.3M5''', but we'll need to decide the proper action set story for '''3.3M6'''
  
 +
We are still working on the EditorActionBarContributor story.  It seems like we might be able to deprecate it.  Editor instances can instantiate handlers upon creation for each command they support.
  
<extension
+
== Available in 3.3M4 ==
      point="org.eclipse.ui.handlers">
+
    <handler commandId="org.eclipse.ui.file.exit"
+
          class="org.eclipse.ui.internal.QuitHandler"/>
+
</extension>
+
  
Then you can place it in the menu:
+
The basic menu API will be available in 3.3M4.  It includes both declarative '''org.eclipse.ui.menus''' extension point with core expression support for visibility, and a programmatic interface accessed through the <code>IMenuService</code>.
  
<extension
 
      point="org.eclipse.ui.menus">
 
    <item
 
          commandId="org.eclipse.ui.file.exit"
 
          mnemonic="x"
 
          id="org.eclipse.ui.file.exit.menu">
 
      <location type="menu">
 
          <menu id="file"/>
 
          <order after="fileEnd"/>
 
      </location>
 
    </item>
 
</extension>
 
  
You can globally place your exit menu in the file menu, or tie it to an actionSet using the <visibleWhen/> clause.
+
We support contributing to the main menu, and the view menu, view toolbar, and any IDed context menu.  We support contributing to existing toolbars in the main coolbar, and contributing trim widgets.
  
= Edit-&gt;Copy =
+
Programmatically we support the following types of contributions:
 +
*MenuManager
 +
*CommandContributionItem
 +
*CompoundContributionItem
 +
*ControlContribution (in 3.3M5)
 +
*Separator
 +
*GroupMarker
  
Some Copy Stuff.
+
There are some specific mappings of elements and attributes on [[Menus Extension Mapping]].
  
= Global toolbar-&gt;Save =
 
  
save
+
== Work still to be done ==
  
= Global toolbar-&gt;Open Type =
 
  
open type
+
A list of behaviours not supported or shipped with '''3.3'''.
  
 +
* validate and possibly optimize the context menu population story and lifecycle.  Many context menus set remove all when shown.
 +
* migrate Marker views
 +
* migrate standard workbench actions - a few were done
 +
* Check enabled visibleWhen support
 +
* Shortcuts placed on submenu items (like CTRL+N) (decorating)
 +
* ensure full visibleWhen support in the MenuManagers - i.e. should empty menus display '''(empty)'''
 +
* do we want to manage trim with a TrimContributionManager?  This removes the coolbar, but has RCP implications.
 +
* the menu override capability - does this tie into the Customize Perspective dialog and action sets
 +
* A set of default programmatic core expressions.  For example, ActionContextExpression or ActivePartExpression
 +
* deprecate the 4 extension: actionSets, viewActions, editorActions, popupMenus
 +
* read old extensions in terms of new extension
 +
* convert platform UI extensions to new extension
 +
* migration guide - what are the most common migration paths for Action and IActionDelegate to Command/IHandler.
 +
* Attributes for <command/>:  '''state''' for checkboxes and radio buttons
 +
* possibly provide an plugin.xml converter for actionSets to menus
 +
* possibly provide an Action -> Handler converter
 +
* [[Image:Error.gif]] status manager contributions
  
  
= Search-&gt;Registry Search =
+
Legend:
 +
* nothing - TBD
 +
* [[Image:Glass.gif]] - investigating
 +
* [[Image:Progress.gif]] - in progress
 +
* [[Image:Ok_green.gif]] - completed
 +
* [[Image:Error.gif]] - dropped
  
Provide a basic action set.  You have 2 actions, Registry Find and Registry Replace, and you want to add them to the "dialog" section of the Search menu.
+
[[Category:Eclipse Project]]
 
+
 
+
== Proposed new menu support ==
+
 
+
Assume you have 2 commands defined, <code>com.example.registry.search.find</code> (Registry Find) and <code>com.example.registry.search.replace</code> (Registry Replace), and you want to add them to the main Search menu at <code>org.eclipse.search.menu/dialogGroup</code>.  Your commands already have their images defined in the <code>org.eclipse.ui.commandImages</code> extension point.
+
 
+
Define the action set:
+
 
+
<context
+
      description="The collection of registry search actions"
+
      id="com.example.registry.search.actionSet"
+
      name="Registry Search Action Set"
+
      parentId="org.eclipse.ui.contexts.actionSet">
+
</context>
+
 
+
And here is a possible view of the menus extension point:
+
 
+
<extension
+
      point="org.eclipse.ui.menus">
+
    <item
+
          commandId="com.example.registry.search.find"
+
          mnemonic="d"
+
          id="com.example.registry.search.find.menu">
+
      <location type="menu">
+
          <menu id="org.eclipse.search.menu"/>
+
          <order after="dialogGroup"/>
+
      </location>
+
      <visibleWhen>
+
          <with variable="activeContexts">
+
            <iterator operator="or">
+
                <equals value="com.example.registry.search.actionSet"/>
+
            </iterator>
+
          </with>
+
      </visibleWhen>
+
    </item>
+
    <item
+
          commandId="com.example.registry.search.replace"
+
          mnemonic="p"
+
          id="com.example.registry.search.replace.menu">
+
      <location type="menu">
+
          <menu id="org.eclipse.search.menu"/>
+
          <order after="com.example.registry.search.find.menu"/>
+
      </location>
+
      <visibleWhen>
+
          <with variable="activeContexts">
+
            <iterator operator="or">
+
                <equals value="com.example.registry.search.actionSet"/>
+
            </iterator>
+
          </with>
+
      </visibleWhen>
+
    </item>
+
</extension>
+
 
+
Hmmmm, so to programmatically do this, you would have to go through the IMenuService.
+
 
+
 
+
ICommandService commandServ = (ICommandService) getSite().getWindow().getService(ICommandService.class);
+
IMenuService menuServ = (IMenuService) getSite().getWindow().getService(IMenuService.class);
+
 
+
Command findCmd = commandServ.getCommand("com.example.registry.search.find");
+
SLocation findLocation = new SLocation(SBar.MENU, "org.eclipse.search.menu");
+
findLocation.setOrder(new SOrder(SOrder.AFTER, "dialogGroup"));
+
+
SItem findItem = menuServ.getItem(new SLocation(SBar.MENU, "org.eclipse.search.menu/com.example.registry.search.find.menu"));
+
findItem.define(findCmd, findLocation, "d");
+
menuServ.contribute(findItem, new ActionSetExpression("com.example.registry.search.actionSet"));
+
+
Command replaceCmd = commandServ.getCommand("com.example.registry.search.replace");
+
SLocation replaceLocation = new SLocation(SBar.MENU, "org.eclipse.search.menu");
+
replaceLocation.setOrder(new SOrder(SOrder.AFTER, "com.example.registry.search.find.menu"));
+
+
SItem replaceItem = menuServ.getItem(new SLocation(SBar.MENU, "org.eclipse.search.menu/com.example.registry.search.replace.menu"));
+
replaceItem.define(replaceCmd, replaceLocation, "p");
+
menuServ.contribute(replaceItem, new ActionSetExpression("com.example.registry.search.actionSet"));
+
 
+
= Widget in the main toolbar =
+
 
+
You can use the extension point to contribute a control to the toolbar.  You use the <widget/> element instead of the <item/> element.
+
 
+
<extension
+
      point="org.eclipse.ui.menus">
+
    <widget
+
          class="com.example.registry.search.SearchBar"
+
          id="com.example.registry.search.find.searchbar">
+
      <location type="toolbar">
+
          <menu id="org.eclipse.search.toolbar"/>
+
      </location>
+
      <visibleWhen>
+
          <with variable="activeContexts">
+
            <iterator operator="or">
+
                <equals value="com.example.registry.search.actionSet"/>
+
            </iterator>
+
          </with>
+
      </visibleWhen>
+
    </widget>
+
</extension>
+
 
+
The widget class must implement [http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/menus/IWorkbenchWidget.html org.eclipse.ui.menus.IWorkbenchWidget], and provide <code>fill(Composite parent)</code> for a toolbar.
+
 
+
I'm not sure how far to go with IWorkbenchWidget.  We already use this interface for adding controls to the trim, and there are open bug requests about adding arbitrary controls to the toolbars.
+
 
+
Will menus take arbitrary controls?
+
 
+
= Edit-&gt;Undo relabel action =
+
 
+
Like the Undo action, sometimes menu items would want to allow their label to be updated.  This is currently handled through the Command objects and the handlers.  IMenuStateIds and INamedHandleStateIds define some states that we currently support.
+
 
+
This can be used to update the menu item label:
+
 
+
<extension
+
      point="org.eclipse.ui.commands">
+
    <command
+
          description="Targetted Undo Command"
+
          id="org.eclipse.ui.commands.targettedUndo"
+
          name="Undo">
+
      <state
+
            class="org.eclipse.jface.menus.TextState"
+
            id="NAME"/>
+
    </command>
+
</extension>
+
 
+
It's placed in the menus just like any other command:
+
 
+
<extension
+
      point="org.eclipse.ui.menus">
+
    <item
+
          commandId="org.eclipse.ui.commands.targettedUndo"
+
          mnemonic="u"
+
          id="org.eclipse.ui.commands.undo">
+
      <location type="menu">
+
          <menu id="edit"/>
+
          <order after="edit.ext"/>
+
      </location>
+
    </item>
+
</extension>
+
 
+
As a handler becomes active and implement IObjectWithState (for example, derives from AbstractHandlerWithState) it is notified about any states that the handler's command contains.  The states can be updated at that time.
+
 
+
class FileDeleteUndoHandler extends AbstractHandlerWithState {
+
    public final void handleStateChange(final State state, final Object oldValue) {
+
        if (INamedHandleStateIds.NAME.equals(state.getId()) && oldValue==null) {
+
            state.setValue("Undo File Delete");
+
        }
+
    }
+
    public final Object execute(final ExecutionEvent event) {
+
        // undo a file delete using EFS ... very cool
+
        return null;
+
    }
+
}
+
 
+
= Search-&gt;Registry Search editor action =
+
 
+
This should basically be the same as [[#Search-&gt;Registry Search|Search-&gt;Registry Search]] with a different visible when clause.
+
 
+
      <visibleWhen>
+
          <with variable="activeEditorId">
+
            <equals value="com.example.registry.RegistryEditor"/>
+
          </with>
+
      </visibleWhen>
+
 
+
So programmatically, that just translates into a different visible when expression:
+
 
+
menuServ.contribute(editorFindItem, new ActiveEditorIdExpression("com.example.registry.RegistryEditor"));
+
 
+
The menu items must be uniquely identified by their id.  Since they only have one location, they can only have one activation in the service at a time.
+
 
+
= Search-&gt;Registry Search programmatic editor action =
+
 
+
Programmatically we have to take the editor action handlers into account.
+
 
+
One of the advantages of EditorActionBars is the lifecycle of the actions that are added.  They're created when the first editor of that type is loaded and exist until the last editor of that type is closed.
+
 
+
Our service hierarchy has 2 levels, IWorkbenchWindow and IPartSite.  Handlers registered with IWorkbenchWindow are active as long as the window is active, and are disposed when the window is disposed.  Handlers registered with IPartSite are active and available as long as that specific part is active and available.  When the part is closed, the handlers are disposed.
+
 
+
Two possibilities are:
+
 
+
1. Provide a service locator for the in-between case.  Tied to a part type.  The service locator expression makes the activation correct and the service locator disposes of them correctly.  Basically, we would make IActionBars returned from each IPartSite a service locator as well.
+
 
+
2. Move these actions up to the IWorkbenchWindow level.  With the correct expression the handler activation would be correct.  But once created they would live as long as the workbench.
+
 
+
= Add View submenu and item =
+
 
+
View actions have to specify their menus as they are self contained.
+
 
+
<command id="z.ex.editor.commands.SampleViewAction"
+
    name="Sample View Action"
+
    description="Sample View Action command"/>
+
 
+
<extension
+
      point="org.eclipse.ui.commandImages">
+
    <image commandId="z.ex.editor.commands.SampleViewAction"
+
          icon="icons/sample.gif"/>
+
</extension>
+
 
+
Placing the action (which is specifically a menu or button linked to a command) can be accomplished with the org.eclipse.ui.menus
+
extension point.
+
 
+
<extension
+
      point="org.eclipse.ui.menus">
+
    <menu
+
          id="z.ex.view.SampleViewMenu"
+
          mnemonic="M"
+
          label="Sample Menu">
+
      <location type="viewMenu">
+
          <part partId="z.ex.view.keybindings.views.SampleView"/>
+
      </location>
+
    </menu>
+
    <group
+
          groupId="z.ex.view.SampleViewGroup"
+
          separatorsVisible="false">
+
      <location type="viewMenu">
+
          <part partId="z.ex.view.keybindings.views.SampleView">
+
            <menu id="z.ex.view.SampleViewMenu"/>
+
          </part>
+
      </location>
+
    </group>
+
    <item
+
          commandId="z.ex.editor.commands.SampleViewAction"
+
          mnemonic="V"
+
          id="z.ex.view.SampleViewAction">
+
      <location type="viewMenu">
+
          <part partId="z.ex.view.keybindings.views.SampleView">
+
            <menu id="z.ex.view.SampleViewMenu"/>
+
          </part>
+
          <order after="z.ex.view.SampleViewGroup"/>
+
      </location>
+
    </item>
+
</extension>
+
 
+
 
+
 
+
Hmmmm, so to programmatically do this, you would have to go through the IMenuService.
+
 
+
 
+
ICommandService commandServ = (ICommandService) getSite().getWindow().getService(ICommandService.class);
+
IMenuService menuServ = (IMenuService) getSite().getWindow().getService(IMenuService.class);
+
+
SMenu viewMenu = menuServ.getMenu(new SLocation(SBar.VIEW_MENU,
+
        "z.ex.view.keybindings.views.SampleView/z.ex.view.SampleViewMenu"));
+
viewMenu.define("Sample Menu", new SLocation(SBar.VIEW_MENU,
+
        "z.ex.view.keybindings.views.SampleView"), "M");
+
SGroup viewGroup = menuServ.getGroup(new SLocation(SBar.VIEW_MENU,
+
        "z.ex.view.keybindings.views.SampleView/z.ex.view.SampleViewMenu/z.ex.view.SampleViewGroup"));
+
viewGroup.define(new SLocation(SBar.VIEW_MENU,
+
        "z.ex.view.keybindings.views.SampleView/z.ex.view.SampleViewMenu", false);
+
+
Command viewCmd = commandServ.getCommand("z.ex.editor.commands.SampleViewAction");
+
SLocation viewLocation = new SLocation(SBar.VIEW_MENU,
+
        "z.ex.view.keybindings.views.SampleView/z.ex.view.SampleViewMenu")
+
viewLocation.setOrder(new SOrder(SOrder.AFTER, "z.ex.view.SampleViewGroup"));
+
SItem viewItem = menuServ.getItem(new SLocation(SBar.VIEW_MENU,
+
        "z.ex.view.keybindings.views.SampleView/z.ex.view.SampleViewMenu/z.ex.view.SampleViewAction.menu"));
+
viewItem.define(viewCmd, viewLocation, "V");
+
menuServ.contribute(viewItem);
+
 
+
= Text editor popup action =
+
 
+
Popups can be targetted at any registered context menu, or at all of them
+
 
+
<command id="z.ex.view.commands.SampleContributionAction"
+
    name="Sample Context Action"
+
    description="Sample Context Action command"/>
+
 
+
<extension
+
      point="org.eclipse.ui.commandImages">
+
    <image commandId="z.ex.view.commands.SampleContributionAction"
+
          icon="icons/sample.gif"/>
+
</extension>
+
 
+
Placing the action (which is specifically a menu or button linked to a command) can be accomplished with the org.eclipse.ui.menus
+
extension point.
+
 
+
<extension
+
      point="org.eclipse.ui.menus">
+
    <item
+
          commandId="z.ex.view.commands.SampleContributionAction"
+
          mnemonic="C"
+
          id="z.ex.objectContribution.menu">
+
      <location type="contextMenu">
+
          <menu id="#EditorContext"/>
+
          <order after="z.ex.editor.contextGroup"/>
+
      </location>
+
    </item>
+
</extension>
+
 
+
 
+
Hmmmm, so to programmatically do this, you would have to go through the IMenuService.
+
 
+
 
+
Command contextCmd = commandServ.getCommand("z.ex.view.commands.SampleContributionAction");
+
SLocation contextLocation = new SLocation(SBar.CONTEXT_MENU, "#EditorContext");
+
contextLocation.setOrder(new SOrder(SOrder.AFTER, "z.ex.editor.contextGroup"));
+
SItem contextItem = menuServ.getItem(new SLocation(SBar.CONTEXT_MENU, "#EditorContext/z.ex.objectContribution.menu"));
+
contextItem.define(contextCmd, contextLocation, "C");
+
menuServ.contribute(contextItem);
+
 
+
 
+
 
+
 
+
 
+
= Dynamic Previous Searches submenu =
+
 
+
You want to add a dynamic "Previous Searches" submenu to the main Search menu.
+
 
+
<extension
+
      point="org.eclipse.ui.menus">
+
    <menu
+
          label="Previous Searches"
+
          mnemonic="c"
+
          id="com.example.registry.search.recent.menu">
+
      <dynamic class="com.example.registry.search.RecentMenu"/>
+
      <location type="menu">
+
          <menu id="org.eclipse.search.menu"/>
+
          <order after="additions"/>
+
      </location>
+
    </item>
+
</extension>
+
 
+
You can programmatically accomplish the same thing:
+
 
+
ICommandService commandServ = (ICommandService) getSite().getWindow().getService(ICommandService.class);
+
IMenuService menuServ = (IMenuService) getSite().getWindow().getService(IMenuService.class);
+
+
SMenu recentMenu = menuServ.getMenu(new SLocation(SBar.MENU,
+
        "org.eclipse.search.menu/com.example.registry.search.recent.menu"));
+
SLocation menuLocation = new SLocation(SBar.MENU,
+
        "org.eclipse.search.menu");
+
menuLocation.setOrder(new SOrder(SOrder.AFTER, "additions"));
+
recentMenu.define("Previous Searches", menuLocation, "c", new RecentMenu());
+
 
+
When your menu is about to show, you should get the callback:
+
 
+
public class RecentMenu implements IDynamicMenu {
+
    public void aboutToShow(IMenuCollection menu) {
+
        menu.clear();
+
        String[] searchIds = getSearchVew().getPreviousSearches();
+
        Command findCmd = commandServ.getCommand("com.example.registry.search.find");
+
        SLocation findLocation = new SLocation(SBar.MENU, "org.eclipse.search.menu/com.example.registry.search.recent.menu");
+
        for (int i=0; i<searchIds.length && i<4; i++) {
+
            SItem item = menuServ.getItem(new SLocation(SBar.MENU,
+
                "org.eclipse.search.menu/com.example.registry.search.recent.menu/recentItem" + i));
+
            item.undefine();
+
            ParameterizedCommand parmFindCmd = ....; // findCmd + the searchId parameter
+
            item.define(parmFindCmd, findLocation);
+
            menu.add(item);
+
        }
+
    }
+
    public SearchViewPart getSearchView() {
+
        return ....;
+
    }
+
}
+
 
+
= Dynamic Previous Searches editors group =
+
 
+
You can have a group dynamically insert elements as a menu is shown.
+
 
+
<extension
+
      point="org.eclipse.ui.menus">
+
    <group
+
          groupId="com.example.registry.search.editors.menu"
+
          separatorsVisible="true">
+
      <dynamic class="com.example.registry.search.RecentSearchEditors"/>
+
      <location type="menu">
+
          <menu id="file"/>
+
          <order after="mru"/>
+
      </location>
+
    </group>
+
  </extension>
+
 
+
When the File menu is about to show, you will be called with your group IMenuCollection (not the entire File menu).  But basically, it looks the same as the dynamic menu case.
+
 
+
public class RecentSearchEditors implements IDynamicMenu {
+
    public void aboutToShow(IMenuCollection menu) {
+
        menu.clear();
+
        String[] editorIds = getSearchVew().getPreviousOpenEditors();
+
        Command openCmd = commandServ.getCommand("com.example.registry.search.openEditor");
+
        SLocation fileLocation = new SLocation(SBar.MENU, "file");
+
        for (int i=0; i<editorIds.length && i<4; i++) {
+
            SItem item = menuServ.getItem(new SLocation(SBar.MENU,
+
                "file/searchOpenEditor" + i));
+
            item.undefine();
+
            ParameterizedCommand parmOpenCmd = ....; // openCmd + the editorsId parameter
+
            item.define(parmOpenCmd, fileLocation);
+
            menu.add(item);
+
        }
+
    }
+
    public SearchViewPart getSearchView() {
+
        return ....;
+
    }
+
}
+
=Added For Paul=
+
<menu name="Window" id="window">
+
    <itemRef id="newWindow">
+
    <itemRef id="newEditor">
+
    <seperator id="seperator1">
+
    <menu name="Open Perspective" id="openPerspective"  class="generatePerspectivesMenu"/>
+
    <menu name="Show View" id="showView"/>
+
    <seperator id="seperator1">
+
    <itemRef id="customizePerspective">
+
    <itemRef id="savePerspective">
+
    <itemRef id="closePerspective">
+
    <itemRef id="closeAllPerspectives">
+
    <seperator id="seperator3">
+
    <menu name="Navigation" id="navigation">
+
    <seperator id="seperator4">
+
    </menu>
+
</menu>
+
<menu name="Working Sets" id="workingSets" after="window/navigation">
+
    <dynamic class="windowworkingsets"/>
+
    <itemRef id="editWorkingSets"/>
+
</menu>
+
<toolbar id="workingSet">
+
    <itemRef id="editWorkingSets"/>
+
</toolbar>
+
<itemRef id="hideToolbars" before="window/seperator1">
+
 
+
 
+
= Example Matrix =
+
 
+
{| class="wikitable" border="1"
+
|-
+
! Example !! Location !! visible when !! enabled when !! defined by !! placed by !! handled by !! comments
+
|-
+
| [[#Add ProblemView menus|Add ProblemView menus]] || view menu || always || always || ViewPart & IActionBars || ViewPart & IActionBars || SampleViewAction
+
|-
+
| [[#Add Toggle Mark Occurrences to main toolbar|Add Toggle Mark Occurrences to main toolbar]] || main menu || always || retarget action supplied || org.eclipse.ui.actionSet & IActionBars || org.eclipse.ui.actionSet & IActionBars || ToggleMarkOccurrencesAction
+
|-
+
| [[#File-&gt;Exit|File-&gt;Exit]] || global menu || always || always || ActionFactory || WorkbenchActionBuilder || QuitAction
+
|-
+
| [[#Edit-&gt;Copy|Edit-&gt;Copy]] || global menu || always || there is an enabled handler || Workbench || IDEApplication || active part (what about Trim??) || enablement determined by handler
+
|-
+
| [[#Global toolbar-&gt;Save|Global toolbar-&gt;Save]] || global toolbar || always || the active part needs saving || Workbench || IDEApplication || Workbench
+
|-
+
| [[#Global toolbar-&gt;Open Type|Global toolbar-&gt;Open Type]] || global toolbar || Java Navigation action set is enabled || Java Navigation action set is enabled || JDT UI || JDT UI || JDT UI
+
|-
+
| [[#Global toolbar-&gt;Toggle Mark Occurrences|Global toolbar-&gt;Toggle Mark Occurrences]] || global (editor) toolbar || any Java editor is active || any Java editor is active || all Java Editors || all Java Editors || active Java Editor || push button state is updated based on active editor
+
|-
+
| [[#Search-&gt;Registry Search|Search-&gt;Registry Search]] || global menu || Registry Search action set is enabled || Registry Search action set is enabled || plugin || actionSet || RegistrySearchAction
+
|-
+
| [[#Widget in the main toolbar|Widget in the main toolbar]] || global toolbar || Registry Search action set is enabled || Registry Search action set is enabled || plugin || actionSet || RegistrySearchAction
+
|-
+
| [[#Edit-&gt;Undo relabel action|Edit-&gt;Undo relabel action]] || global menu || always || always || ActionFactory || WorkbenchActionBuilder || LabelRetargetAction
+
|-
+
| [[#Search-&gt;Registry Search editor action|Search-&gt;Registry Search editor action]] || global (editor) menu || any registry editor is active || any registry editor is active || org.eclipse.ui.editorActions || org.eclipse.ui.editorActions || RegistrySearchAction
+
|-
+
| [[#Search-&gt;Registry Search programmatic editor action|Search-&gt;Registry Search programmatic editor action]] || global (editor) menu || any registry editor is active || any registry editor is active || registry editor action bar contributor || registry editor action bar contributor || RegistrySearchAction
+
|-
+
| [[#Add View submenu and item|Add View submenu and item]] || view menu || always || always || org.eclipse.ui.viewActions || org.eclipse.ui.viewActions || SampleViewAction
+
|-
+
| [[#Text editor popup action|Text editor popup action]] || text editor context menu || always || always || org.eclipse.ui.popupMenus || org.eclipse.ui.popupMenus || SampleContributionAction
+
|-
+
| [[#IFile object contribution|IFile object contribution]] || all context menus || selection is an IFile || always || org.eclipse.ui.popupMenus || org.eclipse.ui.popupMenus || SampleContributionAction
+
|-
+
| [[#Product removes Search Registry|Product removes Search Registry]] || global menu || never || always || ApplicationWorkbenchWindowAdvisor || N/A || menu service || this cannot easily be done
+
|-
+
| [[#Dynamic Previous Searches submenu|Dynamic Previous Searches submenu]] || global menu || always || always || org.eclipse.ui.actionSets || org.eclipse.ui.actionSets || IMenuCreator
+
|-
+
| [[#Dynamic Previous Searches editors group|Dynamic Previous Searches editors group]] || global menu || always || always || N/A || N/A || IDynamicMenu
+
|}
+

Latest revision as of 15:48, 24 December 2012

Placement examples that describe the proposed new way of placing menu items for 3.3. Please contribute comments and suggestions in the discussion area or on Bug 154130 -KeyBindings- Finish re-work of commands and key bindings.

Placement and visibility

The 4 extension points that deal with menus now org.eclipse.ui.actionSets, org.eclipse.ui.viewActions, org.eclipse.ui.editorActions, and org.eclipse.ui.popupMenus specify both menu placement and their visibility criteria. In the new menu mechanism they are separate concepts, placement and visibility.

Example Matrix

A (hopefully) growing list of menu contribution examples.

Example comments
Menu Contributions/Dropdown Command Dropdown tool items can have their menus filled in using menu contributions
Menu Contributions/Problems View Example An example showing how the Problems View might be converted
Menu Contributions/Populating a dynamic submenu A menu contribution to populate a Problems View dynamic submenu
Menu Contributions/Toggle Mark Occurrences Placing the toggle mark occurrences button
Menu Contributions/Toggle Button Command Contribute a toggle state menu item thru commands
Menu Contributions/Radio Button Command Similar to updating toggle state, you can create radio buttons using menu contributions
Menu Contributions/Update checked state The active handler can update the checked state (and other attributes) of its button
Menu Contributions/Search Menu Adding the Java Search options to the Search menu
Menu Contributions/IFile objectContribution A menu contribution for context menus when the selection is an IFile
Menu Contributions/TextEditor viewerContribution A menu contribution for the text editor context menu
Menu Contributions/Widget in a toolbar A menu contribution adding a control into the main toolbar
Menu Contributions/RCP removes the Project menu An RCP application removes the Project menu. Note: this will probably not be in 3.3
Menu Contributions/Workbench wizard contribution Contributing workbench wizards to Menu

Menu XML

Declarative information ... this needs to be cleaned up.

Declarative menus - some constraints

Some constraints on the system:

  1. Identifiers (id) for <menu/> elements must be globally unique.
  2. Identifiers (id) for <command/> elements must be globally unique if they are specified.
  3. You can reference a <menu/> by id.
  4. If you are just creating menu items for your commands, you can leave them with only a command id. You don't have to specify an item id.
  5. You can reference a <command/> for placement options (after, before, etc.) by id.
  6. <separator/> ids only have to be unique within that menu level. This is changed to name instead of id in 3.3M5.
  7. You can provide a <command/> label attribute. If none is provided, it will take the command name.
  8. In this design the item contains most of the same rendering information that <action/> did.
  9. <menu/> and <command/> can have <visibleWhen/> clauses. If a menu's <visibleWhen/> evaluates to false, we will never ask the items contained in that menu.
  10. All of the displayable attributes are translatable.
  11. The mnemonic is specified as you place your <command/> elements in their respective menus, since it is possible that the same command might need a different mnemonic depending on which menu it is placed. Also, when defaulting to command names, they don't contain any mnemonic information.

Menus cannot be re-used, and so they have an intrinsic id value. Separators are unique within one menu level, so they also contain their name.

Menu URIs

For location placement we need a path and placement modifier, and to specify how the paths are built. First pass we are going to look at URIs.

  • <scheme>:<menu-id>[?<placement-modifier>]

scheme is about how to interpret the URI path. For example, menu, toolbar, popup, status (although status may be deprecated).

menu:

For menu: valid root ids will be any viewId for that view's menu, and org.eclipse.ui.main.menu for the main menu. Then specify the id of the menu this contribution applies to. The placement modifier helps position the menu contribution. ex: after=<id>, where <id> can be a separator name, menu id, or item id. An example of a path: menu:org.eclipse.search.menu?after=contextMenuActionsGroup

Since menu ids must be unique, you can specify your menu location relative to an existing id: menu:org.eclipse.search.menu?after=contextMenuActionsGroup

toolbar:

For toolbar: valid root ids will be any viewId for that view's toolbar, org.eclipse.ui.main.toolbar for the main toolbar, and any toolbar id that is contained in the main toolbar. Toolbars can support invisible separators. Toolbars in the main toolbar (technically a coolbar) can have ids as well as separators, but only one level. For example: toolbar:org.eclipse.ui.edit.text.actionSet.presentation?after=Presentation

In this example, Presentation is an invisible separator in the org.eclipse.ui.edit.text.actionSet.presentation toolbar.

The use of org.eclipse.ui.main.toolbar might change if all "main" toolbars have ids anyway, so the only options for interpretting the toolbar root is 1) the view toolbar or 2) an IDed main toolbar.

popup:

For popup: valid root ids are any registered context id (which defaults to the part id if no context menu id was given at registration time) and org.eclipse.ui.popup.any for all registered context menus. For example, to add to the default Text Editor context menu: popup:#TextEditorContext?after=additions

Popup submenus are treated like menu submenus, except the form continues to be popup:submenuId.

There will be constants defined for the ids that the eclipse workbench provides, probably in org.eclipse.ui.menus.MenuUtil.

Using Expressions in <visibleWhen/>

In 3.3M6 an org.eclipse.core.expressions.definitions extension point was added. Used to define a core expression, the definition can then be referenced from other locations.

<extension point="org.eclipse.core.expressions.definitions">
  <definition id="com.example.context">
    <with variable="activeContexts">
       <iterate operator="or">
         <equals value="org.eclipse.ui.contexts.actionSet"/>
       </iterate>
    </with>
  </definition>
</extension>

This can be called in a core expression like activeWhen, enabledWhen, visibleWhen, etc using the reference element:

<reference definitionId="com.example.context"/>

Ideas that were considered but not implemented

These ideas were considered but not implemented.

Menu - JSR198

Note: for novelty purposes only.

For comparison, there is a JSR describing how IDEs can contribute menus. Below is a sample for 2 items:

  • org.eclipse.ui.views.problems.sorting.item from menu:org.eclipse.ui.views.ProblemView
  • org.eclipse.ui.views.problems.resolveMarker.item from popup:org.eclipse.ui.views.ProblemView
<menu-hook>
  <actions>
    <action id="org.eclipse.ui.views.problems.sorting.item">
      <label>Sorting...</label>
      <mnemonic>S</mnemonic>
      <tooltip>Change the Sort order</tooltip>
      <invoke-class>org.eclipse.ui.views.problems.sorting</invoke-class>
    </action>
    <action id="org.eclipse.ui.views.problems.resolveMarker.item">
      <label>Quick Fix</label>
      <mnemonic>Q</mnemonic>
      <iconpath>$nl$/icons/full/elcl16/smartmode_co.gif</iconpath>
      <invoke-class>org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals</invoke-class>
      <update-class>org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals</update-class>
    </action>
  </actions>
  <menus>
    <menubar id="org.eclipse.ui.views.ProblemView">
      <menu id="org.eclipse.ui.views.ProblemView">
        <section id="problem.view.section">
          <command action-ref="org.eclipse.ui.views.problems.sorting.item" />
          <menu id="org.eclipse.ui.views.problems.groupBy.menu">
            <label>Group By</label>
            <mnemonic>G</mnemonic>
          </menu>
        </section>
      </menu>
    </menubar>
    <popup id="org.eclipse.ui.views.ProblemView">
      <section id="group.resolve">
        <command action-ref="org.eclipse.ui.views.problems.resolveMarker.item" />
      </section>
    </popup>
  </menus>
</menu-hook>

Some thoughts:

  • the actions can only specify one icon
  • the actions can't *quite* link to our commands
  • the menus can't specify dynamic submenus

Menu - XUL

Note: for novelty purposes only.


For comparison, with Mozilla everywhere there is the probability eclipse will include xulrunner. Menu definitions that are consistent with XUL look like:

<keyset>
  <key id="paste-key" modifiers="accel" key="V" />
</keyset>
<menubar id="org.eclipse.ui.views.ProblemView">
  <menupopup id="org.eclipse.ui.views.ProblemView">
    <menuitem id="org.eclipse.ui.views.problems.sorting.item"
        accesskey="S"
        key="paste-key"
        label="Sorting..."
        oncommand="invokeCommand('org.eclipse.ui.views.problems.sorting')" />
    <menu id="org.eclipse.ui.views.problems.groupBy.menu"
        label="Group By"
        accesskey="G">
      <menupopup id="groupby.popup">
        <!-- this is where submenu items would go -->
      </menupopup>
    </menu>
  </menupopup>
</menubar>

XUL supports everything as a flavour of a DOM, and javascripting can drive your buttons to perform commands. I suspect the scripting would allow you to dynamically update menus (dynamic menus) on popup, depending on what events the DOM would report to you.


Expression Templates original suggestion

You can see that the <activeWhen/>, <enabledWhen/>, and probably the <visibleWhen/> are likely to be replicated over and over again. A possible option is some kind of expression template markup ... either in its own extension or supported by our UI extensions that can use core expressions.

Here's an example of using expression templates in its own extension point.

<extension point="org.eclipse.core.expression.templates">
  <expression id="isPartActive">
    <parameter id="partId" />
    <with variable="activePartId">
      <equals value="$partId" />
    </with>
  </expression>
  <expression id="isActionSetActive">
    <parameter id="actionSetId" />
    <with variable="activeContexts">
      <iterator operator="or">
        <equals value="$actionSetId" />
      </iterator>
    </with>
  </expression>
  <expression id="isContextActive">
    <parameter id="contextId" />
    <with variable="activeContexts">
      <iterator operator="or">
        <equals value="$contextId" />
      </iterator>
    </with>
  </expression>
  <expression id="isSelectionAvailable">
    <not>
      <count value="0" />
    </not>
  </expression>
</extension>

This could be used to simplify the handler definitions:

<extension point="org.eclipse.ui.handlers">
  <handler commandId="org.eclipse.ui.edit.copy"
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler">
    <enabledWhen>
      <evaluate ref="isSelectionAvailable" />
    </enabledWhen>
    <activeWhen>
      <evaluate ref="isPartActive">
        <parameter id="partId" value="org.eclipse.ui.views.ProblemView" />
      </evaluate>
    </activeWhen>
  </handler>
</extension>

If we allow recursive template definitions, that would allow you to specify the concrete expression once and then reference it throughout your view.

<extension point="org.eclipse.core.expression.templates">
  <expression id="isProblemViewActive">
    <evaluate ref="isPartActive">
      <parameter id="partId" value="org.eclipse.ui.views.ProblemView" />
    </evaluate>
  </expression>
</extension>
<extension point="org.eclipse.ui.handlers">
  <handler commandId="org.eclipse.ui.edit.copy"
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler">
    <enabledWhen>
      <evaluate ref="isSelectionAvailable" />
    </enabledWhen>
    <activeWhen>
      <evaluate ref="isProblemViewActive" />
    </activeWhen>
  </handler>
</extension>

This reduces the handler definition even more.


A similar option to reuse expressions as much as possible without turning them into their own procedural language would be to allow global definitions and then reuse them. No parameters and no expression composition:

<extension point="org.eclipse.core.expression.templates">
  <expression id="isProblemViewActive">
    <with variable="activePartId">
      <equals value="org.eclipse.ui.views.ProblemView" />
    </with>
  </expression>
  <expression id="isSelectionAvailable">
    <not>
      <count value="0" />
    </not>
  </expression>
</extension>
<extension point="org.eclipse.ui.handlers">
  <handler commandId="org.eclipse.ui.edit.copy"
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler">
    <enabledWhen ref="isSelectionAvailable" />
    <activeWhen ref="isProblemViewActive" />
  </handler>
</extension>

Another Expression Alternative: Specify Context at Extension Level

Since enabledWhen and activeWhen specify context and the simple way to specify context in XML is enclosure, how about scoping context to the extension point rather than the handler:

<extension point="org.eclipse.ui.handlers">
  <enabledWhen>  <!-- context of all  handlers in this extension -->
    <not>
      <count value="0" />
    </not>
  </enabledWhen>
  <activeWhen>
    <with variable="activePartId">
      <equals value="org.eclipse.ui.views.ProblemView" />
    </with>
  </activeWhen>
  <handler commandId="org.eclipse.ui.edit.copy"
      class="org.eclipse.ui.views.markers.internal.CopyMarkerHandler" />
  <handler commandId="org.eclipse.ui.edit.paste"
      class="org.eclipse.ui.views.markers.internal.PasteMarkerHandler" />
  <handler commandId="org.eclipse.ui.edit.delete"
      class="org.eclipse.ui.views.markers.internal.RemoveMarkerHandler" />
  <handler commandId="org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals"
      class="org.eclipse.ui.views.markers.internal.ResolveMarkerHandler" />
  <handler commandId="org.eclipse.ui.edit.selectAll"
      class="org.eclipse.ui.views.markers.internal.SelectAllMarkersHandler" />
  <handler commandId="org.eclipse.ui.file.properties"
      class="org.eclipse.ui.views.markers.internal.ProblemPropertiesHandler" />
</extension>

This gives compact markup without inventing a new language. Elements nested in the handler element could override the extension-wide settings.

Updating the menu and toolbar appearance

It was suggested in 3.2 that state on the command could be used to implement the old contribution story behaviours:

  1. changing label text and tooltips
  2. changing icons
  3. changing enablement
  4. setting the item state (like checked state)

In 3.3 the enablement is tied to the command, and for the other behaviours we've decided to go with UIElements approach.

UIElements represent each UI visible instance of a command

The command service keeps a list of registered UI elements, which can be updated by the active handler. The checked state can be updated through UIElement#setChecked(boolean); (note that updateElement below is from IElementUpdater):

private boolean isChecked() {
    return getStore().getBoolean(
            PreferenceConstants.EDITOR_MARK_OCCURRENCES);
}
 
public void updateElement(UIElement element, Map parameters) {
    element.setChecked(isChecked());
}

When the toggle handler runs, it can request that any UI elements have their appearance updated from its execute(*) method:

ICommandService service = (ICommandService) serviceLocator
        .getService(ICommandService.class);
service.refreshElements(IJavaEditorActionDefinitionIds.TOGGLE_MARK_OCCURRENCES, null);

State associated with the command is propogated to UI visible elements

First define the toggle mark occurrences command. Pretty straight forward, although it needs a "STYLE" state since it can be toggled. To allow handlers to update the label for the menu/toolbar items, we also add the "NAME" state.

<extension point="org.eclipse.ui.commands">
  <command categoryId="org.eclipse.jdt.ui.category.source"
      description="%jdt.ui.ToggleMarkOccurrences.description"
      id="org.eclipse.jdt.ui.edit.text.java.toggleMarkOccurrences"
      name="%jdt.ui.ToggleMarkOccurrences.name">
    <state id="NAME" class="org.eclipse.jface.menus.TextState" />
    <state id="STYLE" class="org.eclipse.jface.commands.ToggleState:true" />
  </command>
</extension>

Work

Progress in 3.3.

Available in 3.3

  • Ok green.gif the editor action bar contributor solution. EditorActionBarContributor will not be deprecated, but is not used in the commands/handler story. Menu Contributions have visibility tied to an active editor id, and editor specific handlers can be created in the editor init(*) or createPartControl(*) method using the handler service from getPartSite().getService(IHandlerService.class).
  • Ok green.gif Attributes for <command/>: helpContextId, style to support radio buttons and check boxes
  • Ok green.gif action sets as contexts - action sets are still defined using org.eclipse.ui.actionSets, and each actionSet generates an equivalent context. showing/hiding actionSets activates/deactivates the equivalent context.
  • Ok green.gif How do we give Trim widgets/toolbar widgets "focus" for command and handlers? There was an IFocusService added in 3.3 that allows a trim control to register itself. When that control has focus, the control and the ID it registered with are provided in the global application context to core expressions and handlers. This is available, but might not be the optimal solution if you just want cut, copy, and paste to work.
  • Ok green.gif Shortcuts to define reusable core expressions for <activeWhen/>, <enabledWhen/>, and <visibleWhen/>. This has been added as the org.eclipse.core.expressions.definitions extension point and the core expression <reference/> element.
  • Ok green.gif the mnemonic field for <command/> elements (decorating)
  • Ok green.gif display any keybinding for <command/> elements (decorating)
  • Ok green.gif toolbar <visibleWhen/> expressions

Available in 3.3M5

There is an example of the RCP Mail application template updated for 3.3M5 and converted to use the org.eclipse.ui.menus extension point as much as possible at Contribution Example.

  • Ok green.gif changing the menu item or tool item state from a handler, like updating the label or tooltip or checked state. Commands can contain <state/> elements, but that is not appropriate to use for providing feedback to the user. This will be done by adapting a callback provided by the UI element.
  • Ok green.gif the <separator/> element should have a name not an id
  • Ok green.gif support creating radio button or checked menu items
  • Ok green.gif creating new toolbars in the main coolbar/trim declaratively
  • Ok green.gif creating new toolbars in the main coolbar/trim programmatically
  • Ok green.gif org.eclipse.ui.popup.any as a context menu contribution
  • Ok green.gif Drop down toolbar items

We also have action sets activating and de-activating contexts in 3.3M5, but we'll need to decide the proper action set story for 3.3M6

We are still working on the EditorActionBarContributor story. It seems like we might be able to deprecate it. Editor instances can instantiate handlers upon creation for each command they support.

Available in 3.3M4

The basic menu API will be available in 3.3M4. It includes both declarative org.eclipse.ui.menus extension point with core expression support for visibility, and a programmatic interface accessed through the IMenuService.


We support contributing to the main menu, and the view menu, view toolbar, and any IDed context menu. We support contributing to existing toolbars in the main coolbar, and contributing trim widgets.

Programmatically we support the following types of contributions:

  • MenuManager
  • CommandContributionItem
  • CompoundContributionItem
  • ControlContribution (in 3.3M5)
  • Separator
  • GroupMarker

There are some specific mappings of elements and attributes on Menus Extension Mapping.


Work still to be done

A list of behaviours not supported or shipped with 3.3.

  • validate and possibly optimize the context menu population story and lifecycle. Many context menus set remove all when shown.
  • migrate Marker views
  • migrate standard workbench actions - a few were done
  • Check enabled visibleWhen support
  • Shortcuts placed on submenu items (like CTRL+N) (decorating)
  • ensure full visibleWhen support in the MenuManagers - i.e. should empty menus display (empty)
  • do we want to manage trim with a TrimContributionManager? This removes the coolbar, but has RCP implications.
  • the menu override capability - does this tie into the Customize Perspective dialog and action sets
  • A set of default programmatic core expressions. For example, ActionContextExpression or ActivePartExpression
  • deprecate the 4 extension: actionSets, viewActions, editorActions, popupMenus
  • read old extensions in terms of new extension
  • convert platform UI extensions to new extension
  • migration guide - what are the most common migration paths for Action and IActionDelegate to Command/IHandler.
  • Attributes for <command/>: state for checkboxes and radio buttons
  • possibly provide an plugin.xml converter for actionSets to menus
  • possibly provide an Action -> Handler converter
  • Error.gif status manager contributions


Legend:

  • nothing - TBD
  • Glass.gif - investigating
  • Progress.gif - in progress
  • Ok green.gif - completed
  • Error.gif - dropped

Back to the top