资源描述
自定义扩展点创建过程
这里要介绍的是关于Eclipse 中扩展点的问题,我们知道,Eclipse本身提供了很多的扩展点,这样的话,我们可以根据需要对Eclipse的一些功能进行扩展,使得满足我们的使用,也正是因为这一点,许多的Eclipse Fans都可以贡献自己的力量,通过不断的贡献Eclipse插件,使Eclipse的功能越来越强大,现在Eclipse已经不单单是作为一个开发工具了,而是发展成为了一个平台,我们可以基于这样的一个平台进行开发,
为了扩展现有 Eclipse 功能或在其上进行构建,插件将具体的 扩展 贡献给由其他插件暴露的 扩展点 。通常,插件专注于特定区域的责任,并通过一个或多个扩展点的方式将其他责任指派给其他插件。例如,一个插件允许您可视地并行比较两个文件的内容,但它不会关心如何读取这些文件甚至如何解释这些文件的结构;这是其他插件的工作。比较两个文件时,该插件首先检查是否有另一个插件可以解释这些文件的结构。如果找到一个,它就会向找到的插件询问有关文件结构的信息,并在比较过程中使用该信息。
那现在我们就通过一个简单的例子来示范一下怎么个扩展法 :
首先我们先新建一个 插件工程,注意这个工程作为 RCP 项目存在的,比如工程名称就叫做 TheMainMenuProject,
接下来选择一个插件模板,这里我们选择第二个 "RCP application with a view ":
点完成,这样的话我们就将这个项目建好了,看下项目的结构:
接下来,我们打开 plugin.xml或 MANIFEST.MF文件,切换到 Extension Points 标签页,然后我们就可以新增扩展点了,点 新增
点完成后,系统会自动切换到 org.vwpolo.rcp.extender.exsd 文件的编辑页面,这时我们切换到 Definition 标签页,开始扩展扩展点了:
我们先新建一个 元素(New Element)名称为 extender,
这时有两个元素了,在第一个元素上点右键,在弹出的对话框中选择"序列",
再在这个新增的对象上右键新增一个 extender 对象。
在 extender 的明细页中将 最大边界选择为 无边界就行了。
接下来我们给 extender 元素增加属性,过程就省略了
上面是添加好的属性,注意其中的className属性
好了,扩展点就这样建好了,下面我将这个扩展点文件贴出来:
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace= "TheMainMenuProject" >
<annotation>
<appInfo>
<meta.schema plugin= "TheMainMenuProject" id= "org.vwpolo.rcp.extender" name= "RCP Extension Point" />
</appInfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>
<element name= "extension" >
<complexType>
<sequence>
<element ref= "extender" minOccurs= "1" maxOccurs= "unbounded" />
</sequence>
<attribute name= "point" type= "string" use= "required" >
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name= "id" type= "string" >
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name= "name" type= "string" >
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable= "true" />
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name= "extender" >
<complexType>
<attribute name= "id" type= "string" use= "required" >
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name= "name" type= "string" use= "required" >
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name= "type" use= "required" >
<annotation>
<documentation>
</documentation>
</annotation>
<simpleType>
<restriction base= "string" >
<enumeration value= "perspective" >
</enumeration>
<enumeration value= "view" >
</enumeration>
<enumeration value= "action" >
</enumeration>
</restriction>
</simpleType>
</attribute>
<attribute name= "clientId" type= "string" use= "required" >
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name= "index" type= "string" >
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name= "desc" type= "string" >
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name= "className" type= "string" >
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind= "java" basedOn= "org.eclipse.jface.action.Action:" />
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type= "since" />
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type= "examples" />
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type= "apiInfo" />
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type= "implementation" />
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type= "copyright" />
</appInfo>
<documentation>
</documentation>
</annotation>
</schema>
接下来,我们开始实现 扩展点的一些 功能吧,新增选中的包和类:
为了方便起见,我将这些类的源代码贴出来
TheFirstAction .java:
package org.vwpolo.rcp.extension.client.actions;
import org.eclipse.jface.action.Action;
public class TheFirstAction extends Action {
public static final String ID = TheFirstAction.class.getName();
/**
* 构造函数
*/
public TheFirstAction() {
setId(ID);
setText("第一个Action");
}
public void run() {
Shell shell = Display.getCurrent().getActiveShell();
MessageDialog.openInformation(shell, "信 息", "第一个项目中的Action");
}
}
ExtensionContances .java
package org.vwpolo.rcp.extension.client.extender;
/**
* <p> 扩展点常量。</p>
*/
public class ExtensionContances {
public static final String EXTENSION_ID = "org.vwpolo.rcp.extender";
public static final String ATTR_ID = "id";
public static final String ATTR_NAME = "name";
public static final String ATTR_TYPE = "type";
public static final String ATTR_CLIENTID = "clientId";
public static final String ATTR_INDEX = "index";
public static final String ATTR_DESC = "desc";
public static final String ATTR_CLASS = "className";
public static final String TYPE_PERSPECTIVE = "perspective";
public static final String TYPE_VIEW = "view";
public static final String TYPE_ACTION = "action";
}
ExtensionHelper .java
package org.vwpolo.rcp.extension.client.extender;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.vwpolo.rcp.extension.client.Activator;
import org.vwpolo.rcp.extension.client.actions.TheFirstAction;
/**
* <p> 。</p>
*/
public class ExtensionHelper {
/** */
private String ID = ExtensionContances.EXTENSION_ID;
/** */
public static ExtensionHelper instance;
/** Action Map */
private Map<String, List<ExtensionInfoBean>> actionMap = new HashMap<String, List<ExtensionInfoBean>>();
/** 视图 Map */
private Map<String, List<ExtensionInfoBean>> viewMap = new HashMap<String, List<ExtensionInfoBean>>();
/** 透视图 Map */
private Map<String, List<ExtensionInfoBean>> perspectiveMap = new HashMap<String, List<ExtensionInfoBean>>();
/** */
private MenuManager extendMenu;
/**
* 构造函数。
*/
private ExtensionHelper() {
loadExtensions();
}
/**
* <p> 。</p>
* @return ExtensionHelper
*/
public static ExtensionHelper getInstance() {
if (instance == null)
instance = new ExtensionHelper();
return instance;
}
/**
* <p> 读取扩展点的属性,然后生成ExtensionInfoBean 对象。</p>
*/
private void loadExtensions() {
IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(Activator.EXTENSION_ID);
// IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(Activator.EXTENSION_ID); 此句在运行时报错 将Activator.EXTENSION_ID修改为"org.vwpolo.rcp.extender"即可
if (elements == null || elements.length == 0)
return;
for (int i = 0; i < elements.length; i++) {
IConfigurationElement element = elements[i];
ExtensionInfoBean bean = new ExtensionInfoBean();
bean.setId(element.getAttribute(ExtensionContances.ATTR_ID));
bean.setName(element.getAttribute(ExtensionContances.ATTR_NAME));
bean.setType(element.getAttribute(ExtensionContances.ATTR_TYPE));
bean.setClientId(element.getAttribute(ExtensionContances.ATTR_CLIENTID));
String index = element.getAttribute(ExtensionContances.ATTR_INDEX);
if (index == null || index.trim().isEmpty()) {
bean.setIndex(100);
} else {
bean.setIndex(Integer.parseInt(index));
}
bean.setDesc(element.getAttribute(ExtensionContances.ATTR_DESC));
if (ExtensionContances.TYPE_ACTION.equalsIgnoreCase(bean.getType())) {
try {
String classPath = element.getAttribute(ExtensionContances.ATTR_CLASS);
Object object = null;
if (!classPath.isEmpty()) {
object = element.createExecutableExtension(ExtensionContances.ATTR_CLASS);
} else {
object = element.createExecutableExtension(ExtensionContances.ATTR_CLIENTID);
}
if (object instanceof IAction) {
bean.setAction((IAction) object);
}
} catch (Exception e) {
e.printStackTrace();
}
}
appendGroup(bean);
}
}
private void appendGroup(ExtensionInfoBean bean) {
if (ExtensionContances.TYPE_PERSPECTIVE.equalsIgnoreCase(bean.getType()))
addToMap(perspectiveMap, bean);
else if (ExtensionContances.TYPE_VIEW.equalsIgnoreCase(bean.getType()))
addToMap(viewMap, bean);
else if (ExtensionContances.TYPE_ACTION.equalsIgnoreCase(bean.getType()))
addToMap(actionMap, bean);
}
private void addToMap(Map<String, List<ExtensionInfoBean>> map, ExtensionInfoBean bean) {
List<ExtensionInfoBean> list;
if (map.containsKey(ID)) {
list = (List<ExtensionInfoBean>) map.get(ID);
} else {
list = new ArrayList<ExtensionInfoBean>();
map.put(ID, list);
}
list.add(bean);
}
public void fillMenuBar(IMenuManager menuManager) {
extendMenu = new MenuManager("扩展菜单");
menuManager.add(extendMenu);
fillMenuBar(perspectiveMap);
fillMenuBar(viewMap);
fillMenuBar(actionMap);
}
private void fillMenuBar(Map<String, List<ExtensionInfoBean>> map) {
List<ExtensionInfoBean> list = map.get(ID);
if (list == null || list.size() == 0)
return;
Iterator<ExtensionInfoBean> iter = list.iterator();
while (iter.hasNext()) {
ExtensionInfoBean bean = iter.next();
IAction action = bean.getAction();
if (action == null) {
action = new TheFirstAction();
}
extendMenu.add(action);
}
}
}
ExtensionInfoBean .java
package org.vwpolo.rcp.extension.client.extender;
import org.eclipse.jface.action.IAction;
/**
* <p>扩展点实体 。</p>
*/
public class ExtensionInfoBean {
/** */
private String id;
/** */
private String name;
/** */
private String type;
/** */
private String clientId;
/** */
private int index;
/** */
private String desc;
/** */
private IAction action;
/**
* @return id
*/
public String getId() {
return id;
}
/**
* <p>设置id 。</p>
*/
public void setId(String id) {
this.id = id;
}
/**
* @return name
*/
public String getName() {
return name;
}
/**
* <p>设置name 。</p>
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return type
*/
public String getType() {
return type;
}
/**
* <p>设置type 。</p>
* @param type
*/
public void setType(String type) {
this.type = type;
}
/**
* @return clientId
*/
public String getClientId() {
return clientId;
}
/**
* <p>设置clientId 。</p>
* @param clientId
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
/**
* @return index
*/
public int getIndex() {
return index;
}
/**
* <p>设置index 。</p>
* @param index
*/
public void setIndex(int index) {
this.index = index;
}
/**
* @return desc
*/
public String getDesc() {
return desc;
}
/**
* <p>设置desc 。</p>
* @param desc
*/
public void setDesc(String desc) {
this.desc = desc;
}
/**
* @return action
*/
public IAction getAction() {
return action;
}
/**
* <p>设置action 。</p>
* @param action
*/
public void setAction(IAction action) {
this.action = action;
}
}
现在差不多了,我们在 ApplicationActionBarAdvisor .java 文件的 fillMenuBar 方法调用 ExtensionHelper 的方法就行了
protected void fillMenuBar(IMenuManager menuBar) {
MenuManager fileMenu = new MenuManager( "&File" ,
IWorkbenchActionConstants. M_FILE );
menuBar.add(fileMenu);
fileMenu.add( exitAction );
ExtensionHelper . getInstance ().fillMenuBar(menuBar);
}
现在我们把所有的条件都配好了,现在开始使用这个扩展点了,打开 plugin.xml 文件,切换到 Extensions 标签页,然后新增扩展点
新增完成之后,我们就添上相应的条件就行了,比如 :
运行看看效果吧:
结果就是这样了,不过这不足说明扩展点功能的强大,我打算再新增一个插件项目来扩展刚才新增的扩展点
项目的名称叫 TheSecondMenuProject
可以看到文件的结构很简单,就两个类
打开 plugin.xml 文件,切换到 Dependencies 标签页,将TheMainMenuProject工程添加成这个项目的依赖项,然后在切换到 Extensions 标签页,点击 Add...
填入相关的信息:
现在运行看看效果吧,先打开运行配置对话框
先将TheMainMenuProject 和 TheSecondMenuProject项目选中,然后点击 "添加依赖插件"
运行。。。
展开阅读全文