菜单,弹出菜单和工具栏-几乎每个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下载包含插件开发环境(PDE)的Eclipse发行版。 我建议下载最新版本的Eclipse Classic。 (请参阅相关主题 ,了解在哪里可以找到Eclipse和其他背景信息,如果你是新来的Eclipse)。
平台命令框架
在开始实现使用新菜单机制的插件之前,我们需要了解命令框架。 命令是组件的声明性描述,并且与实现细节无关。 可以对命令进行分类并可以分配键绑定。 通过这种方法,可以定义通用键绑定,并且根据当前上下文,我们可以选择特定的实现。 图1显示了简化的命令类图。
图1.命令类图
将扩展点org.eclipse.ui.commands
用于命令定义。 命令也可以以编程方式创建。 为了实现这个目标,我们可以使用ICommandService
接口。 多个处理程序可以处理命令,但是只有一个处理程序可以处理命令的具体运行时实例。 为了集成到Eclipse工作区中,可以将图像,菜单项和绑定分配给命令。 这是使用类别对命令进行分组的好方法。 类别简化了复杂的富客户端应用程序中的导航。
添加菜单内容
让我们开始使用菜单功能。 该示例从实现一个具有单个菜单项的小型RCP应用程序开始。 该菜单项仅打开一个消息对话框。 这个小例子说明了使用命令,处理程序和菜单的核心概念。
创建一个名为MenuContribution
的新插件项目,并将Eclipse版本设置为3.3
。 对于“您要创建富客户端应用程序吗?”的问题回答“ 是 ”。 使用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);
preWindowOpen
。 运行Eclipse应用程序并测试我们的新菜单项。
图6.所有扩展概述
菜单位置URI
在前面的示例中,我们为菜单定义了locationURI
,将菜单项直接添加到应用程序菜单栏,但是locationURI
还支持其他菜单内容。 以下模式描述菜单插入点: <scheme>:<menu-id>[?<placement-modifier>]
。
-
向主菜单或视图菜单添加内容。
<menu-id>
必须指向现有的视图ID或标准Eclipse菜单org.eclipse.ui.main.menu
。<placement-modifier>
可以使用模式<placement>=<id>
来定位菜单内容。 对于放置,可以使用之前或之后的标签,<id>
可以是现有的分隔符名称,菜单ID或项目ID。
提示:MenuUtil
类包含菜单URI的一些公共常量值。
<scheme> menu
-
将贡献添加到任何工具栏。
对于此
<scheme>
,<menu-id>
可以指向任何视图ID(用于视图工具栏),org.eclipse.ui.main.toolbar
或主工具栏中包含的任何工具栏ID。 您也可以使用<placement-modifier>
。
<scheme> toolbar
-
为所有注册的上下文菜单添加一个用于注册的上下文ID的菜单和
org.eclipse.ui.popup.any
。 也可以使用<placement-modifier>
。
<scheme> pop-up
现在,让我们扩展简短的示例,并使用不同类型的菜单。
添加视图和视图贡献
接下来,我们扩展该小型应用程序以在工具栏中包含一个带有动作的视图。 我们更改现有的主菜单操作以打开视图。
首先,添加视图扩展点( org.eclipse.ui.views
),并使用图7所示的属性创建一个新视图。接下来,打开TestHandler
并更改执行方法以打开视图。
清单2.更改execute方法以打开视图
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 |
名称 | 查看命令 | |
描述 | 视图命令示例 | |
categoryId | com.ibm.de.eclipse.menu.command.cat1 | |
处理程序 | commandId | com.ibm.de.eclipse.menu.command.viewCmd |
类 | 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
和标签“ 执行某些操作” 。 由于我们不需要子菜单结构,因此不需要用于菜单添加的菜单。 另外,为工具栏添加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中定义了几个标准变量。 有关可用变量的完整列表,请查看Wikipedia的Command Core Expressions定义(请参阅参考资料 )。 在示例中,我们使用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
添加一个名为focusDefinition
带有with
元素的定义。 此变量包含具有焦点并已使用IFocusService
注册的控件的ID。 添加一个值为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的某些功能可能在以后的版本中不可用。 请参阅相关的主题为关于菜单的捐款计划更改的更多信息。
翻译自: https://www.ibm.com/developerworks/opensource/library/os-eclipse-3.3menu/index.html