12.1. Defining CommandsTo assign a key binding to an action, you first have to create a command. Commands are the declarative component of an action and are independent of the implementation. They can be categorized and assigned key bindings. Tip Why is it important to separate a command from an action implementation? A good example is when you need to provide key bindings for standard actions such as copy, cut, and paste. The implementation of these operations depends on the context. So, the command must be separate from the implementation. A key binding can be defined for the command that applies regardless of the underlying implementation. To start, let's add a key binding for the Add Contact action. Open the Hyperbola plug-in editor and create a org.eclipse.ui.commands extension. You can specify all aspects of the key binding through this extension. Once you've created a commands extension, take a look at the extension point description using the Open extension point description link in the Extension Details section. This gives you a good description of what the extension point does, and in the case of commands, the meaning of the fields for commands extensions. Notice that there are several different elements for a commands extension, such as commands, categories, and key bindings. In brief, a commands extension provides one-stop shopping for all your command needs. It's good practice to group related commands together using categories. This helps users navigate the list of commands when managing key bindings, etc. Start by creating a category, as shown in Figure 12-1. Click on the "commands" extension and from the context menu, select New > category. Figure 12-1. Category element details
Once the category is defined, create a command for the Add Contact action, as shown in Figure 12-2. Again, click on the "commands" extension and select New > command. Figure 12-2. Command element details
For the id, use the value defined in AddContactAction.ID. This is the unique identifier for this command. You should always have a constant for the command id since it is needed to programmatically associate an action with a command. The name is a human-readable form that is displayed in a preference or configuration dialog. This name is not shown in menus and so it does not need a menu accelerator (e.g., "&" character). Lastly, the categoryId references the command category you just defined. The category element is deprecated and can be left empty. The next step is to add a keyBinding element and assign it to the command via the commandId attribute. Note The org.eclipse.ui.commands/keyBinding element was deprecated late in the 3.1 release in favor of a new extension point. The new extension point currently provides the same behavior and was put in place as a stepping stone for new features to come in 3.2. For now, just ignore the deprecation warnings. Click on the org.eclipse.ui.commands extension and from the context menu, select New > keyBinding. The keyBinding details are shown in Figure 12-3. The most interesting part of the keyBinding element is the keySequence; in this case, M1+A. "M1" in the sequence stands for "Meta 1." This is the platform-independent way of talking about the "Command" key on the Mac and the "Ctrl" key just about everywhere else. Similarly, "M2" is "Shift" and "M3" is "Alt." Figure 12-3. Key binding element details
The commandId defines the id for the command to which this key binding applies. The keyConfigurationId is used to identify the configuration in which this key binding lives. The org.eclipse.ui.defaultAcceleratorConfiguration is the default configuration created by the Workbench and is also the default active configuration. For now, the default configuration is fine. We discuss how to use alternate configurations in Section 12.4, "Key Configurations." Now that you have the required extension elements defined, you must link the AddContactAction to its associated command. This is done by assigning the command id to the action using the IAction method setAction DefinitionId(String). Update AddContactAction's constructor, as shown in the code snippet below. org.eclipsercp.hyperbola/AddContactAction public AddContactAction(IWorkbenchWindow window) { this.window = window; window.getSelectionService().addSelectionListener(this); setId(ID); setActionDefinitionId(ID); setText("&Add Contact..."); setToolTipText("Add a contact to your contacts list."); setImageDescriptor( AbstractUIPlugin.imageDescriptorFromPlugin( Application.PLUGIN_ID, IImageKeys.ADD_CONTACT)); } Once the action is associated with the command id, the action has to be registered with the Workbench. This tells the Workbench to call the action when the key sequence is input by the user. Hyperbola's actions are created in ApplicationActionBarAdvisor. Each action is registered by calling ActionBarAdvisor.register(IAction). You might recall that they are registered to ensure that they are properly deleted. Registering an action using ActionBarAdvisor.register(IAction) also registers the action's key binding. The following code snippet shows the register(IAction) method supplied by the Workbench. If you are already calling the method, no further effort is required. If not, either change the code to call register(IAction) or to call registerGlobalAction(IAction) directly. org.eclipse.ui.workbench/ActionBarAdvisor protected void register(IAction action) { String id = action.getId(); Assert.isNotNull(id, "Action must not have null id"); getActionBarConfigurer().registerGlobalAction(action); actions.put(id, action); } Just to be sure, go back to ApplicationActionBarAdvisor.makeActions(IWorkbenchWindow) and confirm that the actions are being registered. By setting the action definition id in the AddContactAction constructor and ensuring the action is registered with the Workbench, the action can participate in the key binding mechanism. This is a useful pattern to use for all your actions. org.eclipsercp.hyperbola/HyperbolaActionBarAdvisor protected void makeActions(IWorkbenchWindow window) { exitAction = ActionFactory.QUIT.create(window); register(exitAction); aboutAction = ActionFactory.ABOUT.create(window); register(aboutAction); addContactAction = new AddContactAction(window); register(addContactAction); chatAction = new ChatAction(window); register(chatAction); ... } |