Skip to main content
Jump to: navigation, search

Platform UI Command Design

Revision as of 13:11, 25 August 2006 by Pwebster.ca.ibm.com (Talk | contribs) (Commands)

Starting point for menu and toolbar placement of commands in 3.3. Please contribute comments and suggestions in the discussion area.

Original RFC

Contribution RFC

Requirements

  1. Provide a single concept for contributing to the workbench. Right now, there are two distinct ontologies: actions and contribution items; and commands and handlers.
  2. Support the addition and removal of plug-ins.
  3. Separate model and behaviour from visual presentation. Adhere more closely to the Model-View-Controller pattern. Model and user interface separation.
  4. Extensibility. Every group of items in the user interface (e.g., menu, tool bar, etc.) should be extensible – both in structure and content.
  5. 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.).
  6. Separation of structure and content. The structure of the menus (e.g., groups) should be defined independently from the items.
  7. No implicit declarations of structure or content. Everything should be explicit.
  8. Fine-grained control over visibility.
  9. 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.
  10. Improved control over menu definition and item ordering. This will affect the “Search” and “Run” menus.
  11. 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.
  12. Address the difficulty in determining the keyboard shortcuts to show for context menu items.
  13. Support dynamic entries in top-level menus. For example, the recently opened files in the “File” menu should be possible using only public API.
  14. There should be an easy way to define the default behaviour in response to a user action (i.e., default handler for a command).
  15. 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.
  16. Allow the same user interface element to be placed in multiple locations. Reduce duplication in the syntax, and try to reduce memory usage.
  17. 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.
  18. 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.
  19. 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.
  20. Contributing arbitrary controls (e.g., combo boxes) to Eclipse, where appropriate.

Command Architecture Overview

http://dev.eclipse.org/viewcvs/index.cgi/~checkout~/platform-ui-home/R3_1/contributions-proposal/requestForComments_html_m41374bdb.png

Figure 1: High Level Architecture

Current Framework

Commands

Commands are managed by the org.eclipse.ui.commands extension point and the ICommandService.

An example of using the extension point to create a command:

<extension
      point="org.eclipse.ui.commands">
   <category
         description="Actions take at lunch time."
         id="z.ex.view.keybindings.category"
         name="Lunch">
   </category>
   <command
         categoryId="z.ex.view.keybindings.category"
         description="Go for the taco."
         id="z.ex.view.keybindings.eatTaco"
         name="Eat That Taco">
   </command>
</extension>

You can programmatically create commands as well. From within a view:

ICommandService cmdService = (ICommandService) getSite().getService(
    ICommandService.class);
Category lunch = cmdService
    .getCategory("z.ex.view.keybindings.category");
if (!lunch.isDefined()) {
  lunch.define("Lunch", "Actions take at lunch time.");
}
Command eatTaco = cmdService
    .getCommand("z.ex.view.keybindings.eatTaco");
if (!eatTaco.isDefined()) {
  eatTaco.define("Eat That Taco", "Go for the taco.", lunch);
}

Note, however, that a plugin that programmatically defines commands is responsible for cleaning them up if the plugin is every unloaded.

Handlers

Handlers are managed by the org.eclipse.ui.handlers extension point and the IHandlerService. Many Handlers can register for a command. At any give time, either 0 or 1 handlers will be active for the command. A handler's active state and enabled state can be controlled declaratively.

<extension
      point="org.eclipse.ui.handlers">
   <handler
         class="z.ex.view.keybindings.handlers.TacoHandler"
         commandId="z.ex.view.keybindings.eatTaco">
      <activeWhen>
         <with
               variable="activeContexts">
            <iterate
                  operator="or">
               <equals
                     value="z.ex.view.keybindings.contexts.taco"/>
            </iterate>
         </with>
      </activeWhen>
   </handler>
</extension>

Here the handler is checking the activeContexts variable (See org.eclipse.ui.ISources) and if the "taco" context is active, the handler is active.

The handler itself, TacoHandler, must implement IHandler but would usually be derived from the abstract base class org.eclipse.core.commands.AbstractHandler.

You can create and activate a handler programmatically:

IHandlerService handlerService = (IHandlerService) getSite()
    .getService(IHandlerService.class);
IHandler handler = new AbstractHandler() {
  public Object execute(ExecutionEvent event)
          throws ExecutionException {
    System.out.println("Eat that Taco");
    return null;
  }
};
handlerService
    .activateHandler("z.ex.view.keybindings.eatTaco", handler);

KeyBindings

KeyBindings are managed by the org.eclipse.ui.bindings extension point and the IBindingService. Keybindings cannot be updated programmatically.

<extension
      point="org.eclipse.ui.bindings">
   <key
         commandId="z.ex.view.keybindings.eatTaco"
         contextId="z.ex.view.keybindings.contexts.taco"
         schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
         sequence="CTRL+3">
   </key>
</extension>

A key binding is active when the context is active.

Contexts

Contexts are managed by the org.eclipse.ui.contexts extension point and the IContextService.

Most contexts are created by the extension point, and activated programmatically when appropriate. But you can create contexts programmatically as well. The active contexts usually form a tree, although in the case of keybindings this tree is narrowed down to a branch.

<extension
      point="org.eclipse.ui.contexts">
   <context
         description="To allow the consumption of Tacos"
         id="z.ex.view.keybindings.contexts.taco"
         name="Mexican Food"
         parentId="org.eclipse.ui.contexts.window">
   </context>
</extension>

For a context that was attached to a view, it would normally be activated in the view's createPartControl(*) method.

IContextService contextService = (IContextService) getSite()
  .getService(IContextService.class);
IContextActivation contextActivation = contextService.activateContext("z.ex.view.keybindings.contexts.taco");

You can only de-activate a context that you are responsible for activating.

Programmatically, you can create contexts:

Context tacos = contextService
    .getContext("z.ex.view.keybindings.contexts.taco");
if (!tacos.isDefined()) {
  tacos.define("Mexican Food", "To allow the consumption of Tacos",
      "org.eclipse.ui.contexts.window");
}

Tracing Option

There are a couple of reasons why keybindings and commands might not work.

  1. Keybindings are in a context that is not active
  2. There is a keybinding conflict
  3. No handler is currently active for the command
  4. There is a handler conflict

To help track down the problem, you can run with debug tracing options. For example:

org.eclipse.ui/debug=true
org.eclipse.ui/trace/keyBindings=true
org.eclipse.ui/trace/keyBindings.verbose=true
org.eclipse.ui/trace/sources=true
org.eclipse.ui/trace/handlers=true
org.eclipse.ui/trace/handlers.verbose=true
#org.eclipse.ui/trace/handlers.verbose.commandId=org.eclipse.ui.edit.copy
org.eclipse.ui/trace/handlers.verbose.commandId=org.eclipse.jdt.ui.navigate.open.type
org.eclipse.ui/trace/contexts=true
org.eclipse.ui/trace/contexts.verbose=true


I put these options in a debug.options file and run eclipse using:

bash$ eclipse -debug debug.options -data /opt/local/pw_workspace >debug.log 2>&1

This logs the debug output to the debug.log file. This works on windows as well:

C:\development> eclipse32\eclipse.exe -debug debug.options -data workspaces\pw_workspace >debug.log 2>&1

handlers.verbose.commandId allows you to track the information about a specific command that isn't working. org.eclipse.jdt.ui.navigate.open.type is the open type dialog (normally CTRL+SHIFT+T) and org.eclipse.ui.edit.copy (commented out) is COPY (normally CTRL+C)

Menus

Currently, menus are managed by 4 extension points:

  • org.eclipse.ui.actionSets
  • org.eclipse.ui.editorActions
  • org.eclipse.ui.viewActions
  • org.eclipse.ui.popupMenus

Programmatic contributions are managed through a number of locations: IActionBars, IViewSite, IEditorSite ... more to follow

Historical Information

The Contribution proposal started a couple of releases ago Contribution RFC

There are discussions in a number of places:

Back to the top