这篇文章是继《Eclipse RCP/Plugin 入门自学教程》专题21之“Common Navigator Framework初探”,后重新整理的CNF知识。
参考链接:http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.platform.doc.isv/guide/cnf.htm
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 开发中。
下面讲一下 CNF 的主要组成部分:
Navigator 是 CNF 的直接表现形式,在 Eclipse IDE 中就有三个与 CNF 相关的 Navigator ,分别为:
如果想使用 CNF ,必须学会使用这个扩展点,它提供了 CNF 的视图需要的 Content Provider 和 Lable Provider ,以及可能的各种过滤、模型隐藏呢。
配置过滤器,具体效果可以看看 Project Explorer 的 Filters 。
配置基于 CNF 的视图的右键新建向导,这对于自定义向导很有帮助。
配置基于 CNF 的视图的右键菜单,很多时候用户只需要调用一下 Eclipse 中已经实现的菜单显示即可,比如常见的复制、粘贴、剪切等。
提供一些拖拽操作。
将当前选中的文件节点与对应的编辑器(可能的)关联起来,此功能的效果见 Project Explorer 的 Link with editor 。
下面以一个示例,来讲解如何使用 CNF ,示例的结果为在自定义的视图中,给 properties 属性文件添加子节点,子节点为属性对。效果如下图:
新建工程“ org.salever.rcp.tech.cnf ”,选择 plugin 。
注:以下代码为在 eclipse 官网上的 navigator example 基础上修改而来的。
打开 META-INF 下的 MANIFEST.MF 文件,转到 Extension Tab 页,添加 “ org.eclipse.ui.view ” 扩展点,具体为:
这里我们使用默认的 CommonNavigator 。
继续添加扩展点“ org.eclipse.ui.navigator.viewer ”,这个扩展点就比较重要的,用于配置 CNF 的 Viewer ,这里我们使用刚刚定义的“ org.salever.rcp.tech.cnf.navigator.view ”。
马上我们会继续修改这个扩展点。
添加扩展点“ org.eclipse.ui.navigator.navigatorContent ”,点击右键添加 navigatorContent ,具体为:
注意这里有几个需要说明的:
contentProvider :提供内容器的类,一般实现 ITreeContentProvider ,与 JFace 类似
triggerPoints :比较重要的子元素,用于提供触发 content provider 的情况,这里为:
<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>
作用为:在资源为 IResource ,而且资源后缀名为 properties ,或者资源为 PropertiesTreeData 触发此 content provider 。 <possibleChildren>
<or>
<instanceof value="org.salever.rcp.tech.cnf.PropertiesTreeData"/>
</or>
</possibleChildren>
<?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>
右键运行“ 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:
<viewerActionBinding viewerId="org.salever.rcp.tech.cnf.navigator.view">
<includes>
<actionExtension pattern="org.eclipse.ui.navigator.resources.*"/>
</includes>
</viewerActionBinding>
最后可能有人要问,为什么会自己的视图中也会出现工程、文件夹和文件树形结构,很简单,因为我们引入了“org.eclipse.ui.navigator.resourceContent”,这个Eclipse提供的IResource Navigator Content 。
<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>