这篇文章是继《Eclipse RCP/Plugin 入门自学教程》专题21之“Common Navigator Framework初探”,后重新整理的CNF知识。
参考链接:http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.platform.doc.isv/guide/cnf.htm
1 CNF 简介
Common Navigator Framework ,简称 CNF 。 JFace 的 Viewer 使用内容器( Content Provider )处理它对应的模型,而 CNF 与此类似,使用了一个或者多个 Content Provider 来管理视图的模型,除了基本的 Content Provider 以外,它还提供了 Label Provider 、 Sorter 、 Filter ,这一系列的 API 可以方便用户进行基于 Eclipse 资源导航视图的扩展。
CNF 是由 org.eclipse.ui.navigator 实现的,它仅依赖于 org.eclipse.ui ,因此它即可以用于 plugin 开发中,也可以用在 RCP 开发中。
2 组成部分
下面讲一下 CNF 的主要组成部分:
- View Part:由 org.eclipse.ui.navigator.CommonNavigator 实现,这个就是 Eclipse 自带的 Navgator 的实现类了。
- Viewer:由 org.eclipse.ui.navigator.CommonViewer 实现,它的主要功能就是显示一个树形结构视图, CommonNavigator 就使用了 CommonViewer 来进行各种资源的显示。 Eclipse 允许用户扩展 CommonViewer ,当然用户也可以自己实现 Viewer 。
- Navigator Content Extensions:“ org.eclipse.ui.navigator.navigatorContent ”,导航内容器扩展点。这个是 CNF 的核心,通过它将资源模型与 Viewer 连接起来,它的功能与 JFace Viewer 的 Content Provider 类似,不过 CNF 已经将 Content Provider 封装为一个扩展点了,只需要实现这个扩展点就行,当然扩展点中会包含一个 content Provider 实现。
- Navigator Viewer:“ org.eclipse.ui.navigator.viewer ”,导航视图扩展点,与 Navigator Content Extensions 类似, CNF 也将 Viewer 进行了封装,使用中只需要实现这个扩展点就行了,当然扩展点中包含一个 Viewer Part 的实现。
- Resource Support:资源支持, CNF 还提供了许多资源操作,具体参考 org.eclipse.ui.navigator.resources 包下面的类。
2 主要功能
2.1 Navigator
Navigator 是 CNF 的直接表现形式,在 Eclipse IDE 中就有三个与 CNF 相关的 Navigator ,分别为:
- Project Explorer :默认的工程导航视图, org.eclipse.ui.navigator.resources.ProjectExplorer ,继承自org.eclipse.ui.navigator.CommonNavigator ,为所有的 Eclipse 工程提供导航功能;
- Package Explorer : Java 工程导航视图,属于 JDT ( Java Development Toolkit ),该视图与 Project Explorer 在处理Java 工程上几乎一模一样,一个很重要的原因就是 CNF 的适配性和扩展性,这里就不对 JDT 的 Package Explorer 的实现进行分析,有兴趣的可以去看看http://www.ceclipse.org/read-cec-tid-27476.html;
- Navigator :默认的导航视图,目前暂时由 org.eclipse.ui.views.navigator.ResourceNavigator 实现,不过该类已经废弃,不建议使用,它不是由 CNF 实现的,也不具备扩展性,新版本中将逐步用 “ org.eclipse.ui.navigator.CommonNavigator ”替代。
2.2 Navigator Content Extensions
如果想使用 CNF ,必须学会使用这个扩展点,它提供了 CNF 的视图需要的 Content Provider 和 Lable Provider ,以及可能的各种过滤、模型隐藏呢。
2.3 Common Filters
配置过滤器,具体效果可以看看 Project Explorer 的 Filters 。
2.4 Common Wizards
配置基于 CNF 的视图的右键新建向导,这对于自定义向导很有帮助。
2.5 Action Providers
配置基于 CNF 的视图的右键菜单,很多时候用户只需要调用一下 Eclipse 中已经实现的菜单显示即可,比如常见的复制、粘贴、剪切等。
2.6 Drag and Drop Support
提供一些拖拽操作。
2.7 Link with Editor Support
将当前选中的文件节点与对应的编辑器(可能的)关联起来,此功能的效果见 Project Explorer 的 Link with editor 。
3 示例
下面以一个示例,来讲解如何使用 CNF ,示例的结果为在自定义的视图中,给 properties 属性文件添加子节点,子节点为属性对。效果如下图:
3.1 新建 plugin 工程
新建工程“ org.salever.rcp.tech.cnf ”,选择 plugin 。
注:以下代码为在 eclipse 官网上的 navigator example 基础上修改而来的。
3.2 添加视图
打开 META-INF 下的 MANIFEST.MF 文件,转到 Extension Tab 页,添加 “ org.eclipse.ui.view ” 扩展点,具体为:
这里我们使用默认的 CommonNavigator 。
3.3 添加 Navigator Viewer
继续添加扩展点“ org.eclipse.ui.navigator.viewer ”,这个扩展点就比较重要的,用于配置 CNF 的 Viewer ,这里我们使用刚刚定义的“ org.salever.rcp.tech.cnf.navigator.view ”。
马上我们会继续修改这个扩展点。
3.4 添加 Navigator Content
添加扩展点“ org.eclipse.ui.navigator.navigatorContent ”,点击右键添加 navigatorContent ,具体为:
注意这里有几个需要说明的:
-
contentProvider :提供内容器的类,一般实现 ITreeContentProvider ,与 JFace 类似
- labelProvider :提供标签显示的类,一般继承自 LabelProvider ,与 JFace 类似
-
triggerPoints :比较重要的子元素,用于提供触发 content provider 的情况,这里为:
<span><triggerPoints> <or> <and> <instanceof value="org.eclipse.core.resources.IResource" /> <test forcePluginActivation="true" property="org.eclipse.core.resources.extension" value="properties" /> </and> <instanceof value="org.salever.rcp.tech.cnf.PropertiesTreeData" /> </or> </triggerPoints> </span>
作用为:在资源为 IResource ,而且资源后缀名为 properties ,或者资源为 PropertiesTreeData 触发此 content provider 。 - possibleChildren :子节点的配置,这里为:
作用为:仅显示类型为 PropertiesTreeData 的子节点。
3.5 添加 Common Filters
在刚刚添加的扩展点“ org.eclipse.ui.navigator.navigatorContent ”,点击右键添加 commonFilter ,这里添加一个过滤非 java 工程的过滤器:
3.6 plugin.xml
至此,我们已经配置了 Viewer 、 Navigator Content 、 Common Filter ,下面是完整的 plugin.xml :
Xml代码<span><?xml version="1.0" encoding="UTF-8"?> <?eclipse version="3.0"?> <plugin> <!-- Phase 1 --> <!-- Declare the view part to hold the default implementation --> <extension point="org.eclipse.ui.views"> <category id="org.salever.rcp.tech.cnf.navigator.category" name="Common Navigator Examples"/> <view allowMultiple="false" category="org.salever.rcp.tech.cnf.navigator.category" class="org.eclipse.ui.navigator.CommonNavigator" icon="icons/filenav_nav.gif" id="org.salever.rcp.tech.cnf.navigator.view" name="Example View"/> </extension> <!-- Declare the viewer configuration, and the default content/action bindings --> <extension point="org.eclipse.ui.navigator.viewer"> <viewer viewerId="org.salever.rcp.tech.cnf.navigator.view.view"/> <viewerContentBinding viewerId="org.salever.rcp.tech.cnf.navigator.view"> <includes> <contentExtension pattern="org.eclipse.ui.navigator.resourceContent"/> <contentExtension pattern="org.eclipse.ui.navigator.resources.filters.*"/> <contentExtension pattern="org.eclipse.ui.examples.navigator.filters.*"/> <contentExtension pattern="org.salever.rcp.tech.cnf.navigator.propertiesContent"> </contentExtension> </includes> </viewerContentBinding> <viewerActionBinding viewerId="org.salever.rcp.tech.cnf.navigator.view"> <includes> <actionExtension pattern="org.eclipse.ui.navigator.resources.*"/> </includes> </viewerActionBinding> </extension> <!-- Declare a simple filter example that uses core expressions --> <!-- Phase 2 --> <!-- Declare a content extension that renders the contents of a properties file --> <extension point="org.eclipse.ui.navigator.navigatorContent"> <navigatorContent id="org.salever.rcp.tech.cnf.navigator.propertiesContent" name="Properties File Contents" contentProvider="org.salever.rcp.tech.cnf.PropertiesContentProvider" labelProvider="org.salever.rcp.tech.cnf.PropertiesLabelProvider" activeByDefault="true" icon="icons/prop_ps.gif" priority="normal" > <triggerPoints> <or> <and> <instanceof value="org.eclipse.core.resources.IResource"/> <test forcePluginActivation="true" property="org.eclipse.core.resources.extension" value="properties"/> </and> <instanceof value="org.salever.rcp.tech.cnf.PropertiesTreeData"/> </or> </triggerPoints> <possibleChildren> <or> <instanceof value="org.salever.rcp.tech.cnf.PropertiesTreeData"/> </or> </possibleChildren> </navigatorContent> <commonFilter id="org.eclipse.ui.examples.navigator.filters.hideNonJavaProjects" name="Hide non-Java Projects"> <filterExpression> <not> <adapt type="org.eclipse.core.resources.IProject"> <test property="org.eclipse.core.resources.projectNature" value="org.eclipse.jdt.core.javanature"> </test> </adapt> </not> </filterExpression> </commonFilter> </extension> <!-- Bind the Properties content extension to the viewer --> </plugin> </span>
3.7 测试
右键运行“ Eclipse Application ”,在新打开的 IDE 中,打开视图“ Common Navigator Examples ”——“ Navigator Example ”:
新建一个一般工程“ TestProject ”,分别新建文件夹“ folder ”,文件“ test.txt ”“ test.properties ”,然后修改 test.properties 内容为:
key1=value1
key2=value2
key3=value3
点击左侧视图中,查看效果:
打开Customize View,查看filter配置:
勾选上Hide no-Java Projects,如果你刚刚新建的不是java 工程,确定以后,发现testProject不见了,被过滤掉了。
右键菜单与Project Explorer一致,因为我们在Navigator Example中引入了常见的action provider:
<span><viewerActionBinding viewerId="org.salever.rcp.tech.cnf.navigator.view">
<includes>
<actionExtension pattern="org.eclipse.ui.navigator.resources.*"/>
</includes>
</viewerActionBinding></span>
最后可能有人要问,为什么会自己的视图中也会出现工程、文件夹和文件树形结构,很简单,因为我们引入了“org.eclipse.ui.navigator.resourceContent”,这个Eclipse提供的IResource Navigator Content 。
<span><viewerContentBinding viewerId="org.salever.rcp.tech.cnf.navigator.view">
<includes>
<contentExtension pattern="org.eclipse.ui.navigator.resourceContent"/>
<contentExtension pattern="org.eclipse.ui.navigator.resources.filters.*"/>
<contentExtension pattern="org.eclipse.ui.examples.navigator.filters.*"/>
<contentExtension
pattern="org.salever.rcp.tech.cnf.navigator.propertiesContent">
</contentExtension>
</includes>
</viewerContentBinding></span>