由于Eclipse的易扩展性,理论上可以有无数个Action运行在一个RCP 程序中,但是快捷键是有限的,尤其是一些常用的,像Ctrl+C,Ctrl+S之类的普通用户能记得住的就那么几个,万一你自定义的Action的快捷键和Eclipse默认的发生了冲突怎么办?比如Eclipse默认Ctrl+S是Save的快捷键,但是你又自定义了一个SaveAction,希望用户按下Ctrl+S之后执行的是自己的SaveAction的run方法.
一般给Action绑定快捷键的方法是自定义binding和command,然后在action中指定definition id为command的id.如下:
<extension
point="org.eclipse.ui.bindings">
<key
commandId="myplugin.actions.save"
contextId="org.eclipse.ui.contexts.window"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
sequence="CTRL+S">
</key>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
id="myplugin.actions.save"
name="Save">
</command>
</extension>
这样的方法一般是不会有冲突的,但是像我们上面提到的情况,如果你自定义一个binding,它的key sequence是Ctrl+S,那就会有问题.由于org.eclipse.ui插件已经提供了一个Ctrl+S的快捷键,所以系统中会有两个Ctrl+S,这样Eclipse会在右下角pop up一个assist dialog,让你从两个Action中选择一个,这样可能会造成一些用户使用上的不习惯.
解决办法:
1.直接改快捷键.
这个最简单了,比如把你自己的save定义成Alt+S.但是这个方法也是最不好的方法,因为很多用户并不知道Alt+S在你的程序里面就是save.
2.修改自定义action的definition id
我们刚才说过,action的definition id绑定着一个command,而command又对应着一个binding,Eclipse通过这样的方式实现action和快捷键的绑定.我们再来看看Eclipse定义的command和key binding(摘自org.eclipse.ui的plugin.xml):
<command
name="%command.save.name"
description="%command.save.description"
categoryId="org.eclipse.ui.category.file"
id="org.eclipse.ui.file.save" />
<key
commandId="org.eclipse.ui.file.save"
sequence="M1+S"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" />
<key
Eclipse的Save Action把definition id指定为org.eclipse.ui.file.save,然后它就和上面的command进行了绑定,而这个command对应的key就是"M1+S"(Ctrl + S),这样就实现了快捷键绑定.如果我们也把自定义的Save Action的definition id指定为org.eclipse.ui.file.save,是不是就可以达到目的呢?答案是肯定的.
Eclipse中的Action存在着一个类似"优先级"的概念(具体实现是通过action handler).越"具体"的action,优先级越高.Eclipse的Save Action明显是一个global的action,(同样的global action还有copy, cut,undo,redo等等).而我们自定义的action一般是实现了IWorkbenchWindowActionDelegate接口的,就是说,它是contribute to workbench window的,它是一个workbench action,它的优先级就高于任何global action.同理,如果你定义一个editor action或者view action,由于它比workbench还"具体"(workbench可以包含多个editor或view,workbench action对这些editor或view都是有效的;而editor action只对某个具体的editor有效),所以editor action的优先级就高于workbench action.这样,如果自定义的action和eclipse缺省的action都绑定到同一个command,那么eclipse runtim最后会选择自定义的action来执行.
3.终极解决大法:自定义schema
Eclipse 有一个default的快捷键schema文件:org.eclipse.ui.defaultAcceleratorConfiguration.它存储着Eclipse所有的快捷键.如果你自定义一个自己的schema文件,并把它设成当前使用的schema文件,那么Eclipse就会调用自定义的schema文件.(新的schema文件可以在org.eclipse.ui.bindings扩展点中定义,请注意,在定义新schema的时候由一个parentID属性,如果你定义了它,新的schema会像类继承一样把parent schema里面的key binding全继承下来.如果不定义,则是一个全新的schema)
假定我们已经有了一个新的schema文件,id是myplugin.schema.然后我们在org.eclipse.ui.bindings下定义一个key:
<key
commandId="myplugin.actions.save"
contextId="org.eclipse.ui.contexts.window"
schemaId="myplugin.schema"
sequence="CTRL+S">
</key>
我们已经把schemaId换成了myplugin.schema,表示我们把CTRL+S加到了myplugin.schema中,然后把新建的schema文件在product配置文件plugin_customization.ini中设置成当前的key schema文件:
org.eclipse.ui/KEY_CONFIGURATION_ID=myplugin.schema
这种方法虽然麻烦了一点,但却可以治标又治本.而且由于可以指定parent schema,我们完全可以把org.eclipse.ui.defaultAcceleratorConfiguration作为parent schema,继承它全部的快捷键配置,只定制几个会产生冲突的快捷键即可