2007-06-17

Translating objectContributions into menuContributions

Maybe it is trivial... but never the less I have just used the better part of a day understanding just why my initial proposal didn't work :-(

Consider the following action definition used in Eclipse 3.2.
<extension
    point="org.eclipse.ui.popupMenus">
  <objectContribution
      adaptable="false"
      id="com.rcpcompany.demo.providers.ui.objectContributions.ires.general"
      objectClass="com.rcpcompany.training.demo.core.IRes">
    <action
        class="com.rcpcompany.training.demo.providers.ui.actions.ShowName"
        icon="icons/ShowName.gif"
        id="com.rcpcompany.demo.providers.ui.actions.showname"
        label="Show Name">
    </action>
    <filter
        name="folder"
        value="true">
    </filter>
  </objectContribution>
</extension>
This definition will add a new action with the text "Show Name" to all popup menus if the current selection contains at least one object of the IRes interface and this object returns true for the folder (using an IActionFilter). It is a rather tense description.

For Eclipse 3.3, this description is spread over a number of extension.

First a commands extension is used to declare the command itself:
<extension
    point="org.eclipse.ui.commands">
  <command
      description="Shows the name of the current resource"
      id="com.rcpcompany.training.demo33.providers.ui.commands.showName"
      name="&Show Name">
  </command>
</extension>

Then the image of the command must be added:
<extension
    point="org.eclipse.ui.commandImages">
  <image
      commandId="com.rcpcompany.training.demo33.providers.ui.commands.showName"
      icon="icons/ShowName.gif">
  </image>
</extension>

The next thing is to add a handler for the command:
<extension
    point="org.eclipse.ui.handlers">
  <handler
      class="com.rcpcompany.training.demo33.providers.ui.handlers.ShowName"
      commandId="com.rcpcompany.training.demo33.providers.ui.commands.showName">
    <enabledWhen>
      <with
          variable="selection">
        <iterate
            ifEmpty="false"
            operator="and">
          <and>
            <instanceof
                value="com.rcpcompany.training.demo33.core.IRes">
            </instanceof>
            <test
                property="com.rcpcompany.isFolder">
            </test>
          </and>
        </iterate>
      </with>
    </enabledWhen>
  </handler>
</extension>

This is where most of the complexity is in the new implementation: the tense declaration from 3.2 is now rather verbose. Having said that, the new notation also allows for much more complicated stuff than what was possible before. Note that the IActionFilter has been replaced with a IPropertyTester - which is very good, as all properties now need not be in a single test object, but can be distributed over any number of o objects.

Last the popup menus must be added to all popup menus:
<extension
    point="org.eclipse.ui.menus">
  <menuContribution
      locationURI="popup:org.eclipse.ui.popup.any">
    <command
 commandId="com.rcpcompany.training.demo33.providers.ui.commands.showName">
    </command>
  </menuContribution>
</extension>

Depending on the small details, there can be some changes to this - e.g. if the command should only be shown when the selection includes the right objects.

So what didn't work? I hadn't added the iterate test declaration! And since my selection actually was a StructedSelection, then the implicit iteration from 3.2 had to be handled explicitly.

Having worked with the new notation for a number of days now, I think the new notation is better than the old notation. If you just use a command in a single place, then the new notation will take longer to use, but if the same command is used in at least a few places, then the new notation is faster. With other words: the basic overhead of the new notation is larger than for the old notation...
Post a Comment