Sunday, May 20, 2007

RCP Keybinding Issues

Currently I'm developing some RCP application (using Eclipse 3.2 and 3.3M6) and I noticed, that some keyboard shortcuts aren't working well.

By the way - sometimes it seems to me, that there must exists one secret URL containing complete and actual RCP documentation, which every developer - except me - knows.

Back to the problem - we were using older way (deprecated, but still functional) to specify key bindings in plugin.xml

<keyBinding
commandId="yournamespace.command.newempty"
keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration"
keySequence="Ctrl+N" />


It works fine, but not for keys, that are normaly used by RCP (common shortcuts like Ctrl+N, Ctrl+S, etc.). This combinations needs to override (of course, you can implement the corresponding actions, but sometimes you may don't want to do that) the default RCP setting, but how?

The way I found is as follows:
1. Create some context for your app in plugin.xml:

<extension point="org.eclipse.ui.contexts">
<context id="yournamespace.context" name="Default Context"
parentid="org.eclipse.ui.contexts.window"
description="..."></extension>


2. Move problematic keybindings into this context (by specifying contextId in the keyBinding element):

<keyBinding
commandId="yournamespace.command.newempty"
keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration"
contextId="yournamespace.context"
keySequence="Ctrl+N" />


3. Active this context at run-time somewhere in the app init:

PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
public void run() {
((IContextService) PlatformUI.getWorkbench()
.getService(IContextService.class))
.activateContext("yournamespace.context");
}
});


That's all folks. I suppose the command you have specified in commandId already exists (if not, create it). The same stands for action binded to this command.

Actually, not all actions are always specified in plugin.xml, but are created at runtime. Wiring this action (to command and its keybinding) through following methods worked for me.

undoAction.setId("yournamespace.action.undo");
undoAction.setActionDefinitionId("yournamespace.command.undo");
this.getActionBarConfigurer().registerGlobalAction(undoAction);

Hope this post might have helped someone. The presented solution isn't very clean, but functional for me. If you have something better, please feel free to post it here.

6 comments:

Anonymous said...

Hey!
Thank you for your post. I spent a lot of time trying to find a way to overwrite the default shortcuts. :-)
It worked perfectly.
Regards,
Diego

Anonymous said...

Wow, congratulations for comming up with such a, hum..., gentle solution.

Oh, and have you found the saint "one secret URL containing complete and actual RCP documentation" that every RCP knight is looking for ?

SorryForMyEnglish said...

I'm happy this post has been useful to someone.

And for the secret url, still nothing new, maybe for christmas :)

Anonymous said...

Man ! I owe you a beer ! I've also spent a lot of hours looking a simple an detailed solution for an apparently simple problem... Very nice post !

Just a comment... It only worked for me once I put the PlatformUI.getWorkbench().getDisplay().asyncExec... code in the createInitialLayout() method of the initial perspective (class implementing the IPerspectiveFactory interface)...

Regards !

Christian said...

Thanks, I had already found out that a specific context inheriting the predefined ones is necessary but I was looking for information about how to activate the new one. Works, thanks a lot!

Mikhail Barg said...

Thanks! It also works when extending the original Eclipse with a plugin.