在RCP程序中,实现可扩展性和可插入性的主要手段就是创建自定义扩展点,当然软件自身也要设计得当才行。本节就以给SMS项目的功能导航器增加一个结点为例,演示如何创建自定义扩展点,最终效果如图33.3所示。
图33.3 效果图
增加一个自定义扩展点
将以下语句加入到plugin.xml文件,就可以创建一个扩展点。如图33.4所示,在插件清单编辑器的“扩展点”界面会多出一项。
<extension-point id="navigators" name="Navigator Tree Entries"/>
“扩展点”界面
使用自定义扩展点
使用自定义扩展点和使用Eclipse自带的扩展点没有什么本质区别,关键是该扩展点需要设置哪些信息。回顾功能导航器的树结点,它是由NavigatorEntry类负责,该类有6个 属性:
● name:结点名称。
● image:结点的图标。
● parentEntry:父结点。
● children:子结点集合。
● editorInput:结点对应编辑器的EditorInput。
● editorId:编辑器对应于plugin.xml中的Id值。
为了简化示例,暂且只提供name和image设置信息,而这已足够让结点显示在功能导航器中了。将以下扩展点的使用语句加入到plugin.xml文件中。
<extension point="cn.com.chengang.sms.navigators">
<navigator
class="cn.com.chengang.sms.navigator.PluginNavigatorEntry"
icon="icons/project.gif"
name="扩展的结点"/>
</extension>
说明:
● 定义扩展点用“extension-point”,使用扩展点用“extension point”,两者有细微差别。
● 原来的定义扩展点的ID标识为navigators,使用时则要加上插件ID作为前缀,即cn.com.chengang.sms.navigators。
● plugin.xml本质上只是一个XML文件,class可以改为class1,icon也可以改为image。但是这样修改之后,后面的读取plugin.xml设置信息的程序代码也要相应改动,一般来说,尽量取Eclipse中约定俗成的名称。
创建扩展点定义的类PluginNavigatorEntry
代码如下:
package cn.com.chengang.sms.navigator;
public class PluginNavigatorEntry extends NavigatorEntry {
}
这个类继承了NavigatorEntry结点类,在实际开发中可以加入一些应用所需的代码。这里作为示例,没有必要再加代码了。
读取扩展点定义的信息
在plugin.xml定义好了扩展点,也创建好了相关的类,而本步的关键是读出plugin.xml中自定义扩展点的设置信息,并据此来创建树结点实例。将以下代码加入到SmsFactory类。
//取得plugin.xml中的自定义结点,加入到一个List集合中
private static List<ITreeEntry> getPluginNavigator() {
List<ITreeEntry> result = new ArrayList<ITreeEntry>();
// 从plugin.xml中取出自定义扩展点navigators的信息
IExtensionRegistry registry = Platform.
getExtensionRegistry();
IExtensionPoint extension = registry.getExtensionPoint("cn.com.chengang.sms.navigators");
if (extension == null)
return Collections.
emptyList();
// 取出plugin.xml中所有使用navigators扩展点的配置信息
IConfigurationElement[] configElements = extension.getConfigurationElements();
for (IConfigurationElement ce : configElements) {
try {
// 根据配置信息的class属性,创建所定义的类的实例
NavigatorEntry navigator=(NavigatorEntry) ce.createExecutableExtension("class");
navigator.setName((String) ce.getAttribute("name"));
String icon = (String) ce.getAttribute("icon");
navigator.setImage(Activator.getImageDescriptor(icon).createImage());
result.add(navigator);
} catch (CoreException e) {
e.printStackTrace();
}
}
return result;
}
修改SmsFactory类中创建功能导航器树结点的方法,将自定义结点加入到树结点集 合中。
public static List<ITreeEntry> createNavigatorEntryTree() {
……前面代码不变,省略。
list.addAll(getPluginNavigator());
return list;
}
如果自定义扩展点的信息较多较复杂,则可以模仿*.ui.views读取扩展点信息的方式,分成3种不同的类:
● ViewDescriptor——这是一个和自定义扩展点某一项信息相对应的数据类,它实际上为外界封闭了对IConfigurationElement类的访问。
● ViewRegistry——如果说ViewDescriptor是扩展点某一项的信息封装,那么ViewRegistry就是对自定义扩展点所有信息的封装。如果把ViewDescriptor比作某个省份,那么ViewRegistry就是整个国家。
● ViewRegistryReader——这个类负责向ViewRegistry输送数据,如果说ViewRegistry是盲人,那么ViewRegistryReader就是读报人。
总结
完成以上操作步骤,运行SMS项目就可以看到图33.3所示的效果图。
从这个实例可以看到,在Eclipse中自定义扩展点和普通的“配置文件+代码读取”编程方式没有太大差别,如果读者用过Spring或其他框架,对这一点可以更容易理解。
创建扩展点的schema文件
以前在使用扩展点时,有可能一不小心把class属性错写成了clasa,这时Eclipse就会提示有错误,但这里的这个自定义扩展点没有。以前在插件清单编辑器的“扩展”界面创建一个扩展点时,会有一个图形编辑界面,但这里的这个自定义扩展点没有。之所以这里没有这些智能化的效果,是因为少创建了一个schema文件。
自定义扩展点用的是XML,而在XML规范中有一种schema文件(过去是DTD),可以用它来约束XML的格式。schema定义了有哪些XML项和子项,各项又有哪些属性,属性的名称叫什么,属性是字符型还是数值型,属性是不是可选的等。Eclipse正是根据扩展点的schema文件来校验用户书写的扩展点语句是否有错,根据schema定义来创建扩展点的图形编辑界面。
怎么定义schema呢?可以参考Eclipse的视图扩展点org.eclipse.ui.views是如何定义的,然后模仿着做一个。*.ui.views扩展点的schema文件的所在地址是C:/eclipse/plugins /org.eclipse.rcp.source…/src/org.eclipse.ui…/schema/views.exsd,将它复制到SMS项目根目录的schema子目录(目录名可以任取),并将文件改名为navigators.exsd(文件名可任取,不过一般让它和对应的扩展点名称一样)。
为了让自定义扩展点能接受schema的规范,还要在自定义扩展点的定义语句末尾加一个属性schema="schema/navigators.exsd"。如图所示,当加了schema之后,Eclipse左边栏上立刻提示有错误。这是因为此schema文件原来是为扩展点views准备的,当然不适合这里自定义的扩展点navigators。
schema对扩展点的影响
下面根据navigators扩展点的实际情况来修改navigators.exsd文件:打开navigators.exsd文件可以显示出一个图形编辑器,将其中的“一般信息”项按图33.6所示修改。在下面的
等相当于帮助信息,可以暂时不管它们。
转到“定义”界面,在这里定义扩展点应该包含哪些项和子项,各项又有哪些属性。将原来views扩展点的定义删掉一些没有必要的属性项;将view项改为navigator;将class属性的“扩展”项(父类)改为NavigatorEntry类;将“选项”结点的原views结点删除,再新增一个navigator的引用结点。最后结果如图所示。
%提示:在列表处的右键快捷菜单可用于增删结点的操作。
navigators.exsd的“一般信息” “定义”界面中class属性的设置界面
保存navigators.exsd后,可以看到plugin.xml编辑器中原来的警告提示已经没有了,转到“扩展”界面可以看到新建的自定义扩展点也具有了图形编辑界面。
新建自定义扩展点后的图形编辑界面