在 Eclipse V3.3 中配置和添加菜单项

摘自: IBM developerWorks China  被阅读次数: 75


yangyi 于 2008-07-04 21:30:55 提供


级别: 中级

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.actionSetsorg.eclipse.ui.viewActionsorg.eclipse.ui.editorActionsorg.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 示例
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 扩展点并创建一个新处理程序。该处理程序的 commandIdcom.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. 添加新命令和处理程序
命令或处理程序描述属性
命令idcom.ibm.de.eclipse.menu.command.viewCmd
name视图命令
description视图命令示例
categoryIdcom.ibm.de.eclipse.menu.command.cat1
处理程序commandIdcom.ibm.de.eclipse.menu.command.viewCmd
classcom.ibm.de.eclipse.menu.handler.ViewHandler

现在添加两个菜单组件。首先,添加带有 URI menu:com.ibm.de.eclipse.menu.view.testviewmenuContribution(对于视图菜单栏)。视图的 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 元素并把变量设置为 activeMenuSelectionwith 元素将指定用于检查的变量名。如果无法解析变量,则在评估规则时将抛出 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 注册。添加值为 textControlIdequals 元素。如果光标焦点所在的活动组件拥有 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>





回页首


结束语

分享这篇文章……

digg 提交到 Digg
del.icio.us 发布到 del.icio.us
Slashdot Slashdot 一下!

新的 org.eclipse.ui.menus 提供了一种定义菜单更改和添加的一致且灵活的方法。惟一的技巧是了解如何使用 locationURI。除了普通的菜单定义,您还可以定义规则来启用菜单项的有条件可视性。但是如何处理现有的应用程序和插件?答案很简单:迁移应用程序来使用新机制。为什么迁移?因为以后的版本中可能没有您依赖的某些 Eclipse 功能。要获得关于对菜单组件的计划更改的更多信息,请参阅 参考资料






回页首


下载

描述名字大小下载方法
样例 Perl 脚本os-eclipse-3.3menuContribution.zip65KBHTTP
关于下载方法的信息


参考资料

学习

获得产品和技术

讨论
  • Eclipse Platform 新闻组 应当是您讨论关于 Eclipse 的问题的第一站(选择此链接将启动默认的 Usenet 新闻阅读器应用程序并打开 eclipse.platform)。

  • Eclipse 新闻组 中有丰富的资源,适用于对使用和扩展 Eclipse 感兴趣的人员。

  • 参与 developerWorks blog 并加入 developerWorks 社区。



关于作者

Karsten Voigt 是 IBM Global Business Services 在德国的 IT 架构师兼顾问,主要服务对象是 IBM 在汽车行业中的客户。他精通的领域是为 J2EE 和 Java 富客户机应用程序(包括 Lotus Expeditor)定义集成解决方案。闲暇时,他喜欢在 Java Swing 和 Eclipse Rich Client Platform 上设计、开发和使用应用程序。




原文链接: http://www.ibm.com/developerwork...