级别: 中级 Karsten Voigt (kvoigt@de.ibm.com), IT 架构师, IBM
2008 年 3 月 31 日 在早期的 Eclipse 版本中,向菜单、弹出式菜单或工具栏中添加命令十分复杂。这种情况将一去不复返了!Eclipse V3.3 引入了一种比以前更简单的机制。了解如何使用 org.eclipse.ui.menus 扩展点。
菜单、弹出式菜单和工具栏 —— 几乎所有 Eclipse 插件或 Eclipse Rich Client Platform (RCP) 应用程序都需要这些组件。Eclipse V3.3 引入了一项功能,该功能提供了一种更加通用的配置和添加菜单项方法。本文将演示如何使用新菜单机制加速插件和 RCP 开发。
在 Eclipse V3.2 和早期版本中,需要使用一些扩展点向菜单、弹出式菜单或工具栏添加命令。实际上,有四个不同扩展点:org.eclipse.ui.actionSets、org.eclipse.ui.viewActions、org.eclipse.ui.editorActions 和 org.eclipse.ui.popupMenus。令人遗憾的是,每类组件都要求使用各自的扩展点,而且操作的放置和可视性都不能分开。
Eclipse V3.3 引入了一种新机制:org.eclipse.ui.menus。该扩展点是放置菜单项的新方法。
本文将说明新菜单概念,并通过创建一个小型 Eclipse RCP 应用程序来演示大多数新功能。您应当具有使用 Eclipse RCP 或插件框架的一些基本技能。第一步是从 Eclipse.org 下载带有插件开发环境(Plug-in Development Environment,PDE)的 Eclipse 发行版。建议下载 Eclipse Classic 的最新版本(如果您不熟悉 Eclipse,请参阅 参考资料,了解查找 Eclipse 及其他背景信息的位置)。
平台命令框架
在开始实现一个使用新菜单机制的插件之前,需要了解命令框架。命令是组件的说明性描述,与实现细节无关。命令可以归类并且可以指定键绑定。使用这种方法,可以定义一个通用键绑定,并且根据当前上下文选择特定实现。图 1 显示了一个简化的命令类图。
图 1. 命令类图
使用扩展点 org.eclipse.ui.commands 进行命令定义。还可以通过编程的方式创建命令。要实现这个目标,可以使用 ICommandService 接口。多个处理程序都可以处理一个命令,但是只有一个处理程序可以处理命令的具体运行时实例。要在 Eclipse 工作区中进行集成,可以把图像、菜单项和绑定指定给命令。使用类别给命令分组是一种很好的方法。使用类别可以轻松地在复杂的富客户机应用程序中进行浏览。
添加菜单组件
让我们开始使用菜单组件。示例首先将实现一个拥有单个菜单项的小型 RCP 应用程序。此菜单项只打开一个消息对话框。这个小示例将演示使用命令、处理程序和菜单的核心概念。
创建一个名为 MenuContribution 的新插件项目并将 Eclipse 版本设为 3.3。当系统询问您 “Would you like to create a rich client application?” 时,请回答 Yes。使用 Hello RCP 模板。该示例基于名为 com.ibm.de.eclipse.menu 的包。所有其他设置可以保留默认值。现在将新项目作为 Eclipse Application 来运行,然后您将看到以下窗口:
图 2. Hello RCP 示例
我们将通过此应用程序来说明不同的菜单组件。打开 plugin.xml,切换到 Extensions,然后添加 org.eclipse.ui.commands extension。由于所有命令都应当分组到一个类别中,因此选择命令扩展并通过右键单击 New > category 创建一个新类别。填写类别的各个字段,如图 3 所示:
图 3. 命令类别详细信息
现在右键单击 New > command 在命令扩展中添加一条新命令。把 ID 设为 com.ibm.de.eclipse.menu.command.testCmd,将其命名为 Test Command,并把 categoryId 设为 com.ibm.de.eclipse.menu.command.cat1。对于此命令,需要使用一个处理程序来执行关联的业务逻辑。添加 org.eclipse.ui.handlers 扩展点并创建一个新处理程序。该处理程序的 commandId 是 com.ibm.de.eclipse.menu.command.testCmd。要创建处理程序类,单击图 4 中所示的类链接。图 5 显示了填写完必填参数的向导。
提示:如果要在多个扩展中使用类链接,请创建一个包含所选扩展点的必备接口的新类。
图 4. 新处理程序类链接
图 5. 向导
处理程序必须实现 execute 方法。添加清单 1 中的代码行显示消息对话框。
清单 1. 处理程序的 execute 方法
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window =
HandlerUtil.getActiveWorkbenchWindowChecked(event);
MessageDialog.openInformation(
window.getShell(), "MenuEclipseArticle Plug-in",
"Hello, Eclipse world");
return null;
}
|
保存类,返回到 plugin.xml 并保存该文件。现在为新命令和处理程序创建菜单组件。添加 org.eclipse.ui.menus 扩展并创建一个新 menuContribution。该菜单组件只有一个名为 locationURI 的属性。此属性将定义一个插入点,包含的新增组件将添加到这里。使用 menu:org.eclipse.ui.main.menu 作为 locationURI。此 URI 定义一个菜单,该菜单将被放到标准的 Eclipse 菜单中。
到目前为止,我们只定义了插入点。要添加具体菜单,请选择菜单组件并创建新菜单。把标签设置为 TestMenu 并使用 ID com.ibm.de.eclipse.menu.test。
最后一步是定义菜单项与预定义命令之间的链接。单击 TestMenu 并添加新命令。把 commandId 设置为 com.ibm.de.eclipse.menu.command.testCmd 并把标签设置为 Do something。plugin.xml 的扩展应当类似图 6 所示的内容。在运行 Eclipse 应用程序之前,请打开 ApplicationWorkbenchWindowAdvisor 类,转到 preWindowOpen 方法,并添加 configurer.setShowMenuBar(true); 代码行。运行 Eclipse 应用程序并测试新菜单项。
图 6. 所有扩展概览
菜单位置 URI
在上面的示例中,我们为菜单定义了一个 locationURI,用于直接把菜单项添加到应用程序菜单栏中,但是 locationURI 也支持其他菜单组件。以下模式定义了菜单插入点的特征:<scheme>:<menu-id>[?<placement-modifier>]。
-
<scheme> menu
- 把组件添加到主菜单或视图的菜单中。
<menu-id> 必须指向现有视图 ID 或者标准的 Eclipse 菜单 org.eclipse.ui.main.menu。<placement-modifier> 支持使用 <placement>=<id> 模式定位菜单组件。对于布局,前面或后面的标记都可以使用,并且 <id> 可以是现有的分隔符名称、菜单 ID 或项 ID。
提示:
MenuUtil 类包含菜单 URI 的一些公共常量值。
-
<scheme> toolbar
- 向任意工具栏添加组件。对于这个
<scheme>,<menu-id> 可以指向任意视图 ID(对于视图工具栏)、org.eclipse.ui.main.toolbar,也可以指向主工具栏中包含的任意工具栏 ID。您还可以使用 <placement-modifier>。
-
<scheme> pop-up
- 添加用于已注册上下文 ID 的菜单和用于所有已注册上下文菜单的
org.eclipse.ui.popup.any。也可以使用 <placement-modifier>。
现在让我们扩展简短示例并将各种类型用于菜单组件。
添加视图和视图组件
接下来,我们将扩展小型应用程序,使其包含工具栏中一项操作的视图。把现有主菜单操作更改为打开视图。
首先,添加视图扩展点(org.eclipse.ui.views)并使用图 7 所示的属性创建新视图。接下来,打开 TestHandler 并将执行方法更改为打开视图。
清单 2. 把执行方法更改为打开视图
public Object execute(ExecutionEvent event) throws ExecutionException {
try {
HandlerUtil.getActiveWorkbenchWindow(event)
.getActivePage()
.showView("com.ibm.de.eclipse.menu.view.testview");
} catch (PartInitException e) {
throw new ExecutionException("Error while opening view", e);
}
return null;
}
|
图 7. 创建视图元素详细信息
对于该视图,需要使用一个新命令和处理程序来添加被提及的组件。创建新命令和新处理程序。使用以下属性;处理程序必须扩展 org.eclipse.core.commands.AbstractHandler。使用清单 1 实现处理程序执行方法的内容。
表 1. 添加新命令和处理程序
| 命令或处理程序 | 描述 | 属性 |
|---|
| 命令 | id | com.ibm.de.eclipse.menu.command.viewCmd |
|---|
| name | 视图命令 | | description | 视图命令示例 | | categoryId | com.ibm.de.eclipse.menu.command.cat1 | | 处理程序 | commandId | com.ibm.de.eclipse.menu.command.viewCmd |
|---|
| class | com.ibm.de.eclipse.menu.handler.ViewHandler |
现在添加两个菜单组件。首先,添加带有 URI menu:com.ibm.de.eclipse.menu.view.testview 的 menuContribution(对于视图菜单栏)。视图的 ID 是 <menu-id>。用 commandId: com.ibm.de.eclipse.menu.command.viewCmd 和标签 Do
something 直接把命令添加到菜单中。由于不需要子菜单结构,因此菜单组件的菜单不是必需的。另外,给工具栏添加 menuContribution 并使用 URI toolbar:com.ibm.de.eclipse.menu.view.testview。对于工具栏,命令将被再次引用,但是需要选择图标。使用任意默认插件图标(例如,icons/alt_window_16.gif)。运行应用程序,执行主菜单命令,然后查看打开的视图。该视图应当包含工具栏和带有被提及命令的菜单。
图 8. 带有工具栏和菜单组件的示例视图
添加有条件弹出式组件
最后,需要向样例应用程序中添加一个有条件弹出式组件。首先,把视图扩展为包含一个元素列表。系统将显示这些元素的上下文菜单。打开 TestView 类并更改 createPartControl 方法。
清单 3. 向 TestView 中添加列表和上下文菜单
public void createPartControl(Composite parent) {
ListViewer lViewer = new ListViewer(new List(parent, SWT.MULTI));
lViewer.setContentProvider(new ArrayContentProvider());
lViewer.setInput(new String[] { "1", "2", "3", "4" });
MenuManager menuMgr = new MenuManager();
menuMgr.add(
new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
getSite().registerContextMenu(menuMgr, lViewer);
Control control = lViewer.getControl();
Menu menu = menuMgr.createContextMenu(control);
control.setMenu(menu);
}
|
标准的 ArrayContentProvider 创建 ListViewer 并仅显示一个字符串数组。对于该列表,创建一个 MenuManager 并使用新的 GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS) 添加 plugin.xml 中定义的所有内容。上下文菜单被注册到站点中并附加到 ListViewer 的控件中。
向 plugin.xml 中添加弹出和条件语句。只有当我们在列表中选择两个元素后,才应当会显示上下文菜单。由于这个条件可能会对插件中的几个位置有用,因此使用 org.eclipse.core.expressions.definitions 扩展定义一个通用规则。此扩展是 org.eclipse.core.expression 插件的一部分,并在需要时添加到插件中。转到 plugin.xml 的依赖性部分并添加该插件。返回到扩展部分并添加 org.eclipse.core.expressions.definitions。把新建定义的 id 设为 twoSelectedCheck。如果在添加扩展时没有创建任何定义,请创建一个定义。对于此定义,添加一个 with 元素并把变量设置为 activeMenuSelection。with 元素将指定用于检查的变量名。如果无法解析变量,则在评估规则时将抛出 ExpressionException。
Eclipse 中定义了几个标准变量。要获得完整的可用变量列表,请查看 Command Core Expression 的 Wikipedia 定义(请参阅 参考资料)。我们将在示例中使用 activeMenuSelection。在显示上下文菜单时,此变量是选择变量。现在向元素中添加计数并把值设置为 2。把规则定义为计算当前选中的元素,并在两个元素被选中时返回 true。定义的 plugin.xml 应当类似清单 4。
清单 4. plugin.xml 中的定义扩展
<extension point="org.eclipse.core.expressions.definitions">
<definition id="twoSelectedCheck">
<with variable="activeMenuSelection">
<count value="2"></count>
</with>
</definition>
</extension>
|
创建定义之后,将添加一个新菜单组件。转到 org.eclipse.ui.menus 扩展点,并用 locationURI 弹出命令 org.eclipse.ui.popup.any 添加菜单。用 commandId
com.ibm.de.eclipse.menu.command.viewCmd 为此菜单添加一个命令。到目前为止,我们始终都能看到上下文菜单。要切换此行为,请向命令中添加 visibleWhen 元素。接下来,用 definitionId twoSelectedCheck 把引用元素添加到 visibleWhen 元素中。最后,测试应用程序。TestView 现在包含一个元素列表。如果选中了两个元素,则可以看到上下文菜单。
在插件配置文件中使用 visibleWhen 元素是在设计或运行时限定菜单组件的可视性的好方法。我们将在一个示例中展示这个元素的功效,在这个示例中使用另一个规则定义扩展该元素的用途。TestView 得到一个附加文本字段,并且只有当光标位于文本字段上时工具栏命令才可用。首先,用清单 5 中的代码扩展 TestView。使用 IFocusService 注册文本字段以便应用程序可以处理文本字段的焦点更改。
清单 5. 带有注册到 IFocusService 中的文本字段的 TestView
public void createPartControl(Composite parent) {
parent.setLayout(new FillLayout(SWT.VERTICAL));
Text text = new Text(parent, SWT.BORDER);
IFocusService focusService =
(IFocusService) PlatformUI.getWorkbench()
.getService(IFocusService.class);
focusService.addFocusTracker(text, "textControlId");
ListViewer lViewer = new ListViewer(new List(parent, SWT.MULTI));
...
}
|
下一步是创建新定义。转到 org.eclipse.core.expressions.definitions,使用 activeFocusControlId 变量添加一个带有 with 元素的定义 focusDefinition。此变量包含拥有光标焦点的控件的 ID,该控件使用 IFocusService 注册。添加值为 textControlId 的 equals 元素。如果光标焦点所在的活动组件拥有 ID textControlId,则此规则将返回 true。清单 6 显示了 plugin.xml 中的这个定义。结合使用 visibleWhen 与清单 7 中的引用元素向工具栏菜单中添加此定义。运行并测试示例。
清单 6. 焦点控制规则定义
<definition id="focusDefinition">
<with variable="activeFocusControlId">
<equals value="textControlId"></equals>
</with>
</definition>
|
清单 7. 带有 visibleWhen 的工具栏菜单组件
<menuContribution
locationURI="toolbar:com.ibm.de.eclipse.menu.view.testview">
<command
commandId="com.ibm.de.eclipse.menu.command.viewCmd"
icon="icons/alt_window_16.gif" label="Do something"
tooltip="Do something">
<visibleWhen>
<reference definitionId="focusDefinition"></reference>
</visibleWhen>
</command>
</menuContribution>
|
结束语
新的 org.eclipse.ui.menus 提供了一种定义菜单更改和添加的一致且灵活的方法。惟一的技巧是了解如何使用 locationURI。除了普通的菜单定义,您还可以定义规则来启用菜单项的有条件可视性。但是如何处理现有的应用程序和插件?答案很简单:迁移应用程序来使用新机制。为什么迁移?因为以后的版本中可能没有您依赖的某些 Eclipse 功能。要获得关于对菜单组件的计划更改的更多信息,请参阅 参考资料。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| 样例 Perl 脚本 | os-eclipse-3.3menuContribution.zip | 65KB | HTTP |
|---|
参考资料 学习
获得产品和技术
讨论
关于作者  | |  | Karsten Voigt 是 IBM Global Business Services 在德国的 IT 架构师兼顾问,主要服务对象是 IBM 在汽车行业中的客户。他精通的领域是为 J2EE 和 Java 富客户机应用程序(包括 Lotus Expeditor)定义集成解决方案。闲暇时,他喜欢在 Java Swing 和 Eclipse Rich Client Platform 上设计、开发和使用应用程序。 |
原文链接: http://www.ibm.com/developerwork...
|