Starting point for menu and toolbar placement of commands in 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].

+

{{Platform UI}}

−

+

Starting point for menu and toolbar placement of commands in 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]. Here is a page with concrete example cases: [[Menu Item Placement Examples]]

Line 55:

Line 55:

.getVariable(ISources.ACTIVE_WORKBENCH_WINDOW_NAME);

.getVariable(ISources.ACTIVE_WORKBENCH_WINDOW_NAME);

selection = (ISelection) appContext

selection = (ISelection) appContext

−

.getVariable(ISources.ACTIVE_CONTEXT_NAME);

+

.getVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME);

}

}

if (window != null) {

if (window != null) {

Line 61:

Line 61:

"Hello, Eclipse world");

"Hello, Eclipse world");

}

}

−

if (selection instanceof IStructuredSelection) {

+

return null;

−

if (((IStructuredSelection) selection).size() > 1) {

+

}

−

setEnabled(false);

+

−

} else {

+

}

−

setEnabled(true);

+

−

}

+

+

At the moment, a wrapper for an existing <b>I*ActionDelegate</b> is the ActionDelegateHandlerProxy.

+

+

Similarly, an IEditorActionDelegate equivalent (same applies to IViewActionDelegate, except it would use the active part) can access the active editor:

Also note that IHandlers are not handed an IAction, but the IHandler can return its own <b>isEnabled()</b> state directly. For Handlers that want to programmatically report their enablement change, they must remember to fire an event.

+

+

public class SampleEnabledHandler extends AbstractHandler {

private boolean enabled = true;

private boolean enabled = true;

Line 89:

Line 108:

return enabled;

return enabled;

}

}

−

}

+

−

+

−

Also note that IHandlers are not handed an IAction, but the IHandler can return its own <b>isEnabled()</b> state directly.

+

−

+

−

At the moment, a wrapper for an existing <b>I*ActionDelegate</b> is the ActionDelegateHandlerProxy.

+

−

+

−

Similarly, an IEditorActionDelegate equivalent (same applies to IViewActionDelegate, except it would use the active part) can access the active editor:

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.

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 expression makes the activation correct and the service locator disposes of them correctly.

−

−

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.

=== PluginActionBuilder subclasses ===

=== PluginActionBuilder subclasses ===

Line 371:

Line 374:

We need a relatively straight forward model to represent our menu and toolbar structures. But JFace already provides decent coverage for that using MenuManager, ToolBarManager, and IContributionItems. As part of providing our rendering, we would be changing from ActionContributionItems that are currently used to some kind of CommandContributionItem.

We need a relatively straight forward model to represent our menu and toolbar structures. But JFace already provides decent coverage for that using MenuManager, ToolBarManager, and IContributionItems. As part of providing our rendering, we would be changing from ActionContributionItems that are currently used to some kind of CommandContributionItem.

−

IActions would still be used (mostly), but really our IAction would be the focal point of the rendering data model.

+

IActions would still be used (mostly), but really our IAction would be the focal point of the rendering data model. For example, we'll provide a <code>CommandBridgeAction</code>. Knowledge of the command will allow the <code>CommandBridgeAction</code> to provide label, description, icons (from the ICommandImageService). Its <code>runWithEvent(*)</code> method will simply be <code>handlerService.executeCommand("commandId", event)</code>.

+

+

As an alternative option, we could skip IActions and just use the CommandContributionItem. Why build an IAction as the intermediary when the CommandContributionItem can fetch things like the label, icon, etc for us.

+

We would still have to deal with [[#Issue 104 - Dynamic menus need a good story|Issue 104]] and improve dynamic menu creation.

We would still have to deal with [[#Issue 104 - Dynamic menus need a good story|Issue 104]] and improve dynamic menu creation.

Line 491:

Line 497:

#Overrides

#Overrides

#Visibility expression like <visibleWhen/> or the Expression used in IMenuService#contribute(*)

#Visibility expression like <visibleWhen/> or the Expression used in IMenuService#contribute(*)

−

#Programmatic visibility property*

+

#Programmatic visibility property <sup>1</sup>

If the check at a level returns false, the item won't be visible. If it returns true the next level of visibility is evaluated.

If the check at a level returns false, the item won't be visible. If it returns true the next level of visibility is evaluated.

−

<nowiki>*</nowiki> - I'm not sure if a programmatic level of visibility is warranted. The counter example is enablement, which can be changed through Overrides, the <enabledWhen/> expression on the handler, or programmatically from the handler isEnabled() method.

+

:<sup>[1]</sup> I'm not sure if a programmatic level of visibility is warranted. The counter example is enablement, which can be changed through Overrides, the <enabledWhen/> expression on the handler, or programmatically from the handler isEnabled() method.

−

==== Action Set 01 ====

+

==== Menu Placement Locations ====

−

Provide a basic action set. 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.

+

We'll support 7 <b>root</b> types to start with:

+

#SBar.MENU

+

#: The main menu.

+

#SBar.TOOLBAR

+

#: The main toolbar.

+

#SBar.VIEW_MENU

+

#: A view menu. The first path segment will be the view id.

+

#SBar.VIEW_TOOLBAR

+

#: A view toolbar. The first path segment will be the view id.

+

#SBar.CONTEXT_MENU

+

#: A context menu. The first path segment will be the context menu id, or <code>org.eclipse.ui.menus.context.any</code> to apply to all context menus

+

#SBar.TRIM

+

#: Contribute a piece of trim. This is already implemented

+

#SBar.STATUS

+

#: Contribute information to the status line manager ... I'm not sure about this one, is it no longer necessary since they can contribute trim?

−

Define the action set:

+

For describing menu locations as strings, we have a couple of options.

−

+

−

<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>

+

−

<menu id="org.eclipse.search.menu">

+

−

<group id="dialogGroup"/>

+

−

</menu>

+

−

</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>

+

−

<menu id="org.eclipse.search.menu">

+

−

<group id="dialogGroup"/>

+

−

</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.

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>

+

−

<menu id="#EditorContext">

+

−

<group id="z.ex.editor.contextGroup"/>

+

−

</menu>

+

−

</location>

+

−

<visibleWhen>

+

−

<with variable="selection">

+

−

<adapt type="org.eclipse.ui.handlers.IHandlerActivation"/>

+

−

</with>

+

−

</visibleWhen>

+

−

</item>

+

−

</extension>

+

−

+

−

+

−

It's probably that the default variable for core expression evaluations would be <b>selection</b>, so you wouldn't need the <with/> clause. There would probably also be a short-hand to tie the visibility to an active handler. Maybe <visibleWhen handler="true"/>

+

−

+

−

Hmmmm, so to programmatically do this, you would have to go through the IMenuService.

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.

−

If it returns <code>null</code> the next level of visibility is evaluated. The <code>null</code> case is to keep it consistent with other overrides.

+

The usecases are being moved to [[Menu Item Placement Examples]]

== Menu Proposal 3 ==

== Menu Proposal 3 ==

Line 794:

Line 602:

Aside from these main points, there are handful of other significant problems we hope to address – either directly or indirectly. These include dynamic menus, ordering of contribution items, performance problems, and better macro and instrumentation support.

Aside from these main points, there are handful of other significant problems we hope to address – either directly or indirectly. These include dynamic menus, ordering of contribution items, performance problems, and better macro and instrumentation support.

Current Framework

Menus and ToolBars

Menu and toolbar placement is managed by 4 extension points, and through programmatic contributions at a number of locations: IActionBars, IViewSite, IEditorSite, EditorActionBarContributor ... more to follow

I'm not sure of an appropriate way to wrap org.eclipse.ui.IActionDelegate. It is the base class and provides 2 methods to all of the I*ActionDelegates.

run(*) is the execution method, so that is pretty straight forward. The selectionChanged(*) method is called as the workbench selection changes, often times it updates the IAction enablement ... but moving forward there is no IAction enablement. However, an IHandler can be a selection listener and update its own enablement state directly.

The current action delegate proxy, ActionDelegateHandlerProxy, creates a bogus IAction. It allows the action delegates to continue working, but it is disconnected from any state.

Programmatic Contributions and Delegates

I*ActionDelegate

Each of the IActionDelegates has a slightly different initialization interface. With each execution the IHandler is provided an
ExecutionEvent that contains the application context, which will allow the handler to retrieve the information of interest.

Creating an equivalent IHandler for IWorkbenchWindowActionDelegate that has access to the window is straightforward. ex:

Also note that IHandlers are not handed an IAction, but the IHandler can return its own isEnabled() state directly. For Handlers that want to programmatically report their enablement change, they must remember to fire an event.

IObjectActionDelegate

For the behaviour part of an IObjectActionDelegate, it can simply get the active part on execution similar to the
IEditorActionDelegate with appContext.getVariable(ISources.ACTIVE_PART_NAME).

Handlers are the implementation of behaviour, and so there is no one to one equivalent of IObjectActionDelegate#setActivePart(IAction
action, IWorkbenchPart targetPart). The menu item as displayed in the popup menu can declare visibleWhen in its XML to help control
its visibility, but will not be notified just before it is about to show.

EditorActionBars

These are the editor specific IActionBars. They add some functionality, but most specifically the ability to add two IEditorActionBarContributors. The editor action bar contributor and the extension action bar contributor (which is an ExternalContributor provided by the EditorActionBuilder).

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.

PluginActionBuilder subclasses

PluginActionBuilder is the base class for reading the 4 current action extension points. The subclasses are:

PluginActionSetBuilder - for org.eclipse.ui.actionSets, it creates an ActionSetContribution and the ActionDescriptors with ActionDescriptor.T_WORKBENCH or ActionDescriptor.T_WORKBENCH_PULLDOWN. It fills in each PluginActionSet provided by the ActionSetRegistry. Each PluginActionSet provides the IActionBars.

EditorActionBuilder - for org.eclipse.ui.editorActions, it creates an EditorContribution and ActionDescriptors with ActionDescriptor.T_EDITOR. The EditorContributions are added to an ExternalContributor. These are added to the EditorActionBars.

ViewActionBuilder - for org.eclipse.ui.viewActions, it creates a BasicContribution and the ActionDescriptors with ActionDescriptor.T_VIEW. The BasicContributions are added to the IViewSite IActionBars.

ViewerActionBuilder - this is part of the org.eclipse.ui.popupMenus extension point. This is used after IPartSite#registerContextMenu(*) creates a PopupMenuExtender. It creates a ViewerContribution and stores ActionDescriptors with ActionDescriptor.T_EDITOR or ActionDescriptor.T_VIEW. It's contributed to the popup menu by PopupMenuExtender#menuAboutToShow(*) - viewerContributions are called "static" contributions.

ObjectActionContributor - also for org.eclipse.ui.popupMenus, it stores the ActionDescriptions of type ActionDescriptor.T_POPUP in an ObjectContribution. This goes back to the ObjectActionContributorManager, which is called into from PopupMenuExtender#menuAboutToShow(*).

org.eclipse.ui.actionSets

Action Sets are visible in the main menu and coolbar. Their visibility can be updated by the user using Customize Perspective. Here is a sample actionSet distributed with Eclipse SDK.

The <actionSet/> element defines the group of elements that can be shown or hidden. The <menu/> elements create menus and groups. The <action/> elements define individual "actions" ... they contain rendering information (label, icon), menu placement (menubarPath, toolbarPath) and behaviour (the class attribute, in this case an IWorkbenchWindowActionDelegate).

org.eclipse.ui.editorActions

Editor Actions appear in the main menu and coolbar as long as an editor of that type is the active editor. Using the org.eclipse.ui.actionSetPartAssociation extension with an org.eclipse.ui.actionSet works similarly, except all editor actions are IEditorActionDelegates instead of IWorkbenchWindowActionDelegates.

Here, the Sample Menu will show up in the view menu, the dropdown from the top of the view's CTabFolder.

org.eclipse.ui.popupMenus

Popup menu contributions are actions contributed to the various popup menus in eclipse. They take 2 forms. A <viewerContribution/>
contributes actions to a popup in a view or an editor. An <objectContribution/> contributes actions to any popup, as long as the
selected object matches its enablement criteria.

Issue 102 - Commands implementation of label changing

Commands are an abstraction of behaviour, an have a lot in common with RetargetableActions. Certain kinds of RetargetableActions provide the ability to switch the labels, like switching Undo to Redo. This can be accomodated by adding text state to the command:

The NAME state can be updated, and also supports state change notification. Our menu and/or toolbar rendering would have to listen for changes to properties and states associated with commands?

States are also the proposed way to handle information like toggled state (for check boxes or toggle buttons) and radio state (for a group of radio buttons).

Issue 103 - Menu items map to ParameterizedCommands

Just like a keybinding, each menu item or toolbar button would map to a ParameterizedCommand. If there was no parameters involved, then just containing the command id would be acceptable. For example, if you were creating menu items for Show Console View and Show Problems View each menu item would map to the ParameterizedCommand.

IHandlerService#executeCommand(String commandId, Event event) can execute a normal command with a selection event, and IHandlerSerivce#executeCommand(ParameterizedCommand command, Event event) does the same with a parameterized command.

Issue 104 - Dynamic menus need a good story

Dynamic menus need to work correctly for menus and menu items. They also need to create the drop-downs for toolbar items.

If the top part of a dynamic menu is declarative, then it can be provided without loading the plugin. Then a callback could be specified.

It seems right now that dynamic menus are mostly used to populate pull-down actions.

The appropriate IAction returns an IMenuCreator. This means that it must be instanitated inside the IAction.

Menu Proposal 1

Replace the entire thing with something really simple (haha). This should most closely resemble the design described in the original RFC in Historical Information Section.

Menu placements would be controlled by a tree of data.

File (menu)

New (menu)

(group: new.wizard)

New Wizard (item)

Open File... (item)

(group: file.close)

Close (item)

Close All (item)

Edit (menu)

Undo (item)

Redo (item)

All nodes in the tree would have visibility and enablement state. Enablement for the menu node would be tied to its Command.

The each menu item would be able to specify some order constraints.

Dynamic menus would have a simpler form. They would also be included in the declarative extension point (as much as possible) See Issue 104.

There would be a product level visibility (similar to the way Customize Perspective works for ActionSets). Would we also provide product level ability to customize other prospective menu item attributes? For example, a product level way to override menu order?

This would mean an out-and-out replacement of most of the internal classes to do with PluginActions and the ActionSetRegistry. For RCP support, we would continue to allow MenuManager and contribution items to be added, but those structures would need to be used to populate the tree structures. This is hard :-)

The new system would have to manage the interaction between 4 properties: Enabled, Active, Visible, Showing. Enabled is the state of the command (from the active handler), Active is the state of the handler, Visible is the state of the menu item, and Showing (and internal state) describes if the menu item can currently be seen by the user. Showing is a new concept designed to help with lazy loading and lazy creation of sub-menus. It's not in the current menu behaviour.

We would have to provide a visibility engine of somekind that would update the menu item structure visibility as state changed.

From an menu visibility/enablement point of view, Enabled is the state that matters. If no handler is active, Enabled will be false. If a handler is active, the Enabled will be the handler Enabled state.

Menu Proposal 2

We need a relatively straight forward model to represent our menu and toolbar structures. But JFace already provides decent coverage for that using MenuManager, ToolBarManager, and IContributionItems. As part of providing our rendering, we would be changing from ActionContributionItems that are currently used to some kind of CommandContributionItem.

IActions would still be used (mostly), but really our IAction would be the focal point of the rendering data model. For example, we'll provide a CommandBridgeAction. Knowledge of the command will allow the CommandBridgeAction to provide label, description, icons (from the ICommandImageService). Its runWithEvent(*) method will simply be handlerService.executeCommand("commandId", event).

As an alternative option, we could skip IActions and just use the CommandContributionItem. Why build an IAction as the intermediary when the CommandContributionItem can fetch things like the label, icon, etc for us.

We would still have to deal with Issue 104 and improve dynamic menu creation.

Perhaps IContributionManagerOverrides could be enhanced and used as the product override mechanism. There would have to be some API to update and list the product level list of overrides.

We would get rid of the PluginAction and ActionSet code.

We would need to provide a "visibility" engine to update the visibility of contribution items or IActions as the sources changed.

This still needs a good story for replacing EditorActionBarContributor and the IActionBar stuff ... providing the same functionality in an alternate place. I don't think providing the functionality is too much of a problem, but finding the correct place for it will require more thought.

Proposal "A" (Eric's World...;-):

The basic idea is to provide a single menu/action/command(+binding)/handler 'best practices' path. We can do this by re-using the existing extension points; tweaking as necessary to provide complete functionality and deprecating EP's that are no longer necessary.

Move the current 'ActionSet.action' and 'ActionSet.menu' out from under the ActionSet extension point and make them their own EPs. This allows the definition of actions and menu structure independent of any particular action set and/or each other.

Standardize on core expressions for vis and enablement states. It turns out that this mechanism is already capable of emulating many behaviours that can currently be accessed through the use of specialized EPs.

Allow for the definition of the IWorkbenchWindowPulldownDelegate2 for any sub-menu to handle the dynamic menus case.

Extend the 'menuBarPath' & 'tooBarPath' to allow for new conventions specific to siting an action anywhere within the workbench. This should allow us to deprecate View/Editor Actions -and- ObjectContributions.

EditorContributions:

"editor: <editorId>[/groupPath]"

ViewContributions:

"view-context:<viewId>[/groupPath]" - Site it in the given view's context menu

"view-chevron:<viewId>[/groupPath]" - Site it in the given view's chevron menu [in the given group]

"any context menu" - Replacement for the current ObjectContribution mechanism. The 'visibleWhen' core expression can determine whether the selection context is appropriate...

Proposal "A" - item 3 - Dynamic Menu interface

The menu extension can declaratively specify that the menu item is a dynamic menu, and provide a dynamic menu callback class that implements IDynamicMenu. When the menu item is about to show, the callback class will be handed an IMenuCollection, which contains a modifiable list of menu elements. As an example:

public interface IDynamicMenu {
/**
* Called just before the given menu is about to show. This allows the
* implementor of this interface to modify the list of menu elements before
* the menu is actually shown.
*
* @param menu
* The menu that is about to show. This value is never
* null.
*/
public void aboutToShow(IMenuCollection menu);
}

And the IMenuCollection allows the modification of the menu that's about to show. Assume that MenuElement is the new flavour of IContributionItem/IContributionManager

public interface IMenuCollection {
/**
* Appends a menu element to the end of the collection.
*
* @param element
* The element to append. Must not be null, and
* must be of the appropriate type for the type of collection.
*/
public void add(MenuElement element);
/**
* Adds a menu element at the given index.
*
* @param index
* The index at which to insert.
* @param element
* The element to append. Must not be null, and
* must be of the appropriate type for the type of collection.
*/
public void add(int index, MenuElement element);
/**
* Removes all elements from the collection.
*/
public void clear();
/**
* Gets the element at a given index.
*
* @param index
* The index at which to retrieve the element.
* @return The element at the index.
*/
public MenuElement get(int index);
/**
* Removes the element at a given index.
*
* @param index
* The index at which to remove the element.
* @return The element that has been removed.
*/
public MenuElement remove(int index);
/**
* Removes the given menu element, if it exists.
*
* @param element
* The element to remove.
* @return true if the object was removed; false if it could not be found.
*/
public boolean remove(MenuElement element);
/**
* Returns the number of elements in the collection.
*
* @return The size of the collection.
*/
public int size();
}

This is a change from the IMenuCreator interface, which directly references an SWT Control or SWT Menu.

Menu Proposal 2 UseCases

Visibility controls if the user can see the menu item in the menubar or toolbar or context menu. There are 3 levels of visibility that are checked in order:

Overrides

Visibility expression like <visibleWhen/> or the Expression used in IMenuService#contribute(*)

Programmatic visibility property 1

If the check at a level returns false, the item won't be visible. If it returns true the next level of visibility is evaluated.

[1] I'm not sure if a programmatic level of visibility is warranted. The counter example is enablement, which can be changed through Overrides, the <enabledWhen/> expression on the handler, or programmatically from the handler isEnabled() method.

Menu Placement Locations

We'll support 7 root types to start with:

SBar.MENU

The main menu.

SBar.TOOLBAR

The main toolbar.

SBar.VIEW_MENU

A view menu. The first path segment will be the view id.

SBar.VIEW_TOOLBAR

A view toolbar. The first path segment will be the view id.

SBar.CONTEXT_MENU

A context menu. The first path segment will be the context menu id, or org.eclipse.ui.menus.context.any to apply to all context menus

SBar.TRIM

Contribute a piece of trim. This is already implemented

SBar.STATUS

Contribute information to the status line manager ... I'm not sure about this one, is it no longer necessary since they can contribute trim?

For describing menu locations as strings, we have a couple of options.

Option 1: URI

All of our paths can be generalized to a URI that looks like type://id/path.

The main File menu extention group marker: menu://org.eclipse.ui.menu.main/file/file.ext

Menu Proposal 3

In this proposal we don't seek to address most of what the RFC is talking about. Leave dynamic menus alone. The current extension points are fine, they just need to be backed by a single implementation.

It would involve cleaning up some of the workbench code, and wiring up the underlying framework like in Issue 101.

We would also go through all of the programmatic code in the workbench and make sure we're creating IActions backed by commands.

Historical Information

The Contribution proposal started a couple of releases ago with the original RFC
Contribution RFC

Original Requirements

Provide a single concept for contributing to the workbench. Right now, there are two distinct ontologies: actions and contribution items; and commands and handlers.

Support the addition and removal of plug-ins.

Separate model and behaviour from visual presentation. Adhere more closely to the Model-View-Controller pattern. Model and user interface separation.

Extensibility. Every group of items in the user interface (e.g., menu, tool bar, etc.) should be extensible – both in structure and content.

Universal keyboard shortcuts. A user should be able to add a keyboard shortcut to any item that appears in the user interface (e.g., menu item, tool item, menu, etc.).

Separation of structure and content. The structure of the menus (e.g., groups) should be defined independently from the items.

No implicit declarations of structure or content. Everything should be explicit.

Fine-grained control over visibility.

More intelligent updating of elements within the user interface. Support for lazy updating for elements that are not showing within the user interface. This lazy updating should be handled automatically – without the elements needing to understand whether they are showing.

Improved control over menu definition and item ordering. This will affect the “Search” and “Run” menus.

The selection should be capable of overriding the behaviour of a user action. For example, if a Java element is selected in the Resource Navigator, a rename should be a refactoring rename.

Address the difficulty in determining the keyboard shortcuts to show for context menu items.

Support dynamic entries in top-level menus. For example, the recently opened files in the “File” menu should be possible using only public API.

There should be an easy way to define the default behaviour in response to a user action (i.e., default handler for a command).

Provide localized control of the model, view and controller elements talked about in this proposal. This includes such concepts as automatic addition/removal as parts are become active/inactive, and automatic removal as parts are destroyed.

Allow the same user interface element to be placed in multiple locations. Reduce duplication in the syntax, and try to reduce memory usage.

Provide facilities for finding and triggering elements within the user interface. This is intended to provide better support for the welcome facilities, cheat sheets, macros and scripting.

JFace must not lose functionality. Everything that can be accomplished with JFace must still be possible in JFace, even if the API changes radically. Similarly, everything that can be accomplished with the workbench must still be possible in the workbench.

Contribute all of the workbench and IDE model, view and controller elements using the API from this proposal. Everything that the workbench and IDE can do should be possible for third-party plug-ins as well.

Rational

The Eclipse Platform has always provided a mechanism for contributing items to the menus and tool bars in Eclipse. This mechanism has – up until now – been based on instances of IAction.

Actions suffered from a few key deficiencies. First of all, the interaction with the application model (e.g., the handling of the run method) was tightly coupled with its presentation elements (e.g., icon, label, etc.). Also, there was no easy way to provide user-configurable keyboard shortcuts. Actions were not initially designed with a way to identify two actions as sharing the same semantic behaviour. To further confuse matters, there were action delegates. Action delegates were not actions, but could handle action behaviour in some circumstances.

Actions were defined in XML using several extension points. This XML syntax had several problems. First of all, there were too many extension points, which made the syntax hard to learn and caused maintenance problems. Features added to one extension point, would have to be copied into other extension points. Ultimately, what ended up happening is that for any given feature, it was possible that only a subset of the extension points would actually support it (e.g., dynamic menus). Partly due to this and partly due to the tight coupling mentioned above, this lead to an overly verbose syntax containing duplicate XML elements. If an action was required in a view menu and in a context menu, then the XML would need to be copied and contributed to two different extension points. This also led to multiple instances of the action in memory.

Aside from these main points, there are handful of other significant problems we hope to address – either directly or indirectly. These include dynamic menus, ordering of contribution items, performance problems, and better macro and instrumentation support.