这两天学习了一下commands架构,自己感觉和之前的action set架构相比,有一点比较方便。即:针对同一个command,可以存在多个handler与之绑定,在运行时则自动选择command指定的默认 handler或者由core expression条件过滤出的handler来执行。 这个亮点也是之所以action set架构进化到commands架构的原因。
最近给自己规划了一个插件任务:把选中的调试堆栈存储起来,并且可以选取若干个堆栈进行比较,采用直观的方式显示两个堆栈中的不同。有了这个插件,以后再调程序时就可以省去很多力气了,尤其是对我这样撂爪儿就忘的人更是帮助很大,我以前都是把堆栈拷贝到文本编辑器中比较的。而且,为了保持断点窗口的清洁,很多有价值的堆栈信息都删了,如果加上标注存起来,以后查找起来也会方便很多。
动手开始做的第一件事,就是解决如何向Debug View中添加一个右键菜单,就像拷贝堆栈时用的那个“copy stack”按钮一样,这个按钮为我们提供了一个拷贝堆栈的参考方法,但这不属于本文讨论的范围了。
有的文章在描述一个问题时,采用的方法只是把操作步骤列一下,然后配合几张图就ok了,这种方式很像家用电器的操作手册,可以对于我们经常面对的复杂问题,只有这些显然不够,只有理解了为什么这样做,才会真正领会其要义,务必求其宗而非其法。
在这里我将操作步骤只是简要列一下,最主要的,还是要把解决问题过程中遇到的难点和解决办法整理出来。
操作步骤:
1.
添加org.eclipse.ui.commands扩展,创建一个command
2.
添加org.eclipse.ui.menus扩展,创建一个menuContribution
3.
添加org.eclipse.ui.handlers扩展,创建一个handler,command id指向步骤1中创建的command,并为其编写实现类
4.
为步骤3中创建的handler指定激活状态的表达式
要点:
1.
Q:新建command时,是否需要为其指定catagory属性?
A:看情况。我个人感觉catagory就是用来进行菜单分组的。例如,一般一个插件会把自己提供的菜单指定一个统一的catagory,这样在显示或处理时能放在一起
2.
Q:新建command时,是否需要为其指定name属性?
A:name属性是必填项,当然要指定了
:-) 当对应的menu没有指定label时,菜单中显示的就是这个name了。
3.
Q:menu的locationURI如何指定?
A:这是我碰到的第一个难题,因为uri需要用一个描述脚本编写,那么如何编写脚本?编写脚本的规则是什么?
答案就在eclipse的帮助文档中:
http://help.eclipse.org/stable/index.jsp?topic=/org.eclipse.platform.doc.isv/guide/workbench_cmd_menus.htm
举例:popup:org.eclipse.debug.ui.DebugView?after=additions
可以把这个示例uri看成3部分,第一部分是“popup”,代表样式是右键弹出菜单;第二部分是 “org.eclipse.debug.ui.DebugView”,含义是显示在哪个view的弹出菜单中;第三部分是 “after=additions”,含义是显示在弹出菜单的什么位置(弹出菜单中还有其他的菜单项)。
这个只是uri众多写法的其中之一,还有向主菜单添加项目的,向工具栏添加项目的,具体情况请参考上面的帮助文档链接。
进行到这里,菜单应该已经可以在debug窗口中显示出来了,但是这又引发了一个问题:每当点击这个菜单的时候,总是报告:The chosen operation is not enabled。这是因为handler的实现类直接实现了IHandler接口,其isHandled,isEnabled方法由eclipse自动生成的情况下全部是返回false的,除非必要,否则一般情况下应采用继承org.eclipse.core.commands.AbstractHandler的方式来编写handler的实现类,可以省去不少麻烦。
其中要注意的是:在plugin编辑器中,点击handler的属性面板中的“class”链接,会自动创建实现类,这个自动创建的实现类不是继承AbstractHandler的,而是直接实现IHandler,我就是这样被带到沟里去的。
报错的问题解决了,但是发现新增的菜单在有选中堆栈和没有选中堆栈的情况下都可以显示,这个有些不大合适,因为如果要复制堆栈信息,至少应该有一条被选中才可以。所以应该采取措施让这个菜单在没有选中任何堆栈信息时灰显,这也就引出了另一个很难理解的框架:command core expression。
command core expression是一个脚本规则,eclipse定义了许多变量、属性,通过core expression可以对这些变量、属性进行诸如instanceof, equals等判定,从而得到一个boolean值用来参与程序的逻辑。针对这个问题,我们只需要为handler指定enabledWhen的表达式(core expression),让handler只在选中已条堆栈信息时才被激活即可。
core expression的文档在:http://wiki.eclipse.org/Command_Core_Expressions 在 org.eclipse.ui.handlers 扩展的声明文档中也有很多可以参考的信息。
在本例中我们通过对selection变量的计数来判断是否有堆栈信息被选定。详细内容请参考本文后面的plugin.xml文件的内容。
至此,添加菜单的过程就结束了,看似简单,其实牵涉了许多其他的应用技术,例如core expression, locationURI等。其他的问题其实也是一样,不断地遇到问题,不断地踩平它,不断地积累,慢慢地,一条路就会出现在脚下。
附件:
plugin.xml文件的内容:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
<extension
point="org.eclipse.ui.commands">
<command
id="xxx.rick.stacker.cmd.copy"
name="testcopy">
</command>
</extension>
<extension
point="org.eclipse.ui.menus">
<menuContribution
locationURI="popup:org.eclipse.debug.ui.DebugView?after=additions">
<command
commandId="xxx.rick.stacker.cmd.copy"
style="push">
</command>
</menuContribution>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="xxx.rick.stacker.handler.CopyStack"
commandId="xxx.rick.stacker.cmd.copy">
<enabledWhen>
<with
variable="selection">
<count
value="+">
</count>
</with>
</enabledWhen>
</handler>
</extension>
</plugin>
posted on 2009-04-08 23:17
Rick Murphy 阅读(557)
评论(0) 编辑 收藏 所属分类:
eclipse插件开发