首页 > 开发 > 综合 > 正文

自己动手编写Eclipse扩展点

2020-02-05 14:04:41
字体:
来源:转载
供稿:网友
  • 网站运营seo文章大全
  • 提供全面的站长运营经验及seo技术!
  • 扩展(extension)是eclipse中一个关键的机制,plug-in利用扩展向eclipse平台添加新功能。但是扩展不能随意地创建,必须按照扩展点(extension point)定义的规范进行明确的声明,eclipse才能认出这些扩展。我们不仅可以使用eclipse提供的众多现成的扩展点,而且还可以定义新的扩展点,并在该扩展点上进行扩展。
    当然,扩展点的定义比较复杂。不过eclipse为用户提供了图形化的编辑界面,我们只要输入一些信息,eclipse就会自动生成代码,使扩展点的定义变得非常简单。
    下面我们就来看看如何在eclipse中创建一个新的扩展点,并在这个扩展点上进行扩展。
    我们需要做以下的工作:
    1.设计该扩展点
    2.定义扩展点,即编写扩展点的清单文件
    3.编写代码来载入该扩展点的扩展
    我们以创建worklist扩展点为例,进行详细介绍。
    worklist完成的功能是:创建一个view,在其中以树状显示系统中可用的功能模块,通过双击某个模块节点,执行该扩展定义的方法(method)。其实相当于一个控制台,通过控制台来运行不同的功能。
    由于eclipse是由一个运行时核心(runtime core)和众多插件组成的,我们也将worklist扩展点定义在一个插件中,有关worklist的代码文件也放在这个插件中,这样便于查找和修改,也不影响eclipse本身的代码。

    1. 定义扩展点
    首先我们要创建一个存放新扩展点信息的插件net.softapp.worklist,这个插件对org.eclipse.ui.views进行扩展,以下是插件的plugin.xml文件在views扩展点的信息:
    <extension
    point="org.eclipse.ui.views">
    <category
    name="worklistcategory"
    id="worklistcategory"/>
    <view
    icon="icons/sample.gif"
    class="net.softapp.internal.worklist.worklistview"
    category="worklistcategory"
    name="worklist视图"
    id="net.softapp.internal.worklist.worklistview"/>
    </extension>
    这样就可以通过“window->show view->other”,在弹出的“show view”对话框中选择“worklist视图”,打开视图,我们用这个视图显示worklist扩展点的所有扩展信息。“show view”对话框显示了eclipse中定义所有视图,即所有org.eclipse.views扩展点的扩展。了解这一点很重要,因为我们在编写worklist扩展点代码时,就可以模仿甚至拷贝views扩展点的代码。
    下面,我们要在net.softapp.worklist插件中定义worklist扩展点。
    扩展点的定义文件按照eclipse的存放方式,一般存放在schema目录下,我们把文件命名为worklist.exsd。内容如下,此内容由pde生成:
    <?xml version='1.0' encoding='utf-8'?>
    <!-- schema file written by pde -->
    <schema targetnamespace="mtn.esip.worklist">
    <annotation>
    <appinfo>
    <meta.schema plugin="net.softapp.worklist" id="worklist" name="worklist"/>
    <!--通过这个定义,我们可以看出,定义的扩展点的id是 net.softapp.worklist.worklist,以后引用时要注意,同时注意大小写-->
    </appinfo>
    <documentation>
    [enter description of this extension point.]
    </documentation>
    </annotation>

    <element name="extension">
    <complextype>
    <choice minoccurs="0" maxoccurs="unbounded">
    <element ref="category" minoccurs="0" maxoccurs="1"/>
    <element ref="worklist" minoccurs="0" maxoccurs="1"/>
    </choice>
    <attribute name="point" type="string" use="required"><!--定义point-->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    <attribute name="id" type="string"><!--定义id-->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    <attribute name="name" type="string"><!--定义name-->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    </complextype>
    </element>

    <!--定义category-->
    <element name="category">
    <complextype>
    <attribute name="name" type="string"><!--定义category/name-->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    <attribute name="id" type="string"><!--定义category/id。引用category时,必须指出应用的id,而name给出了一个可供显示的直观的名字-->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    <attribute name="parentcategory" type="string"><!--定义父category,也就是说我们的category可以嵌套形成树状结构-->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    </complextype>
    </element>

    <!--定义worklist,注意大小写-->
    <element name="worklist">
    <complextype>
    <attribute name="name" type="string"><!--定义worklist/name,可供显示的直观的名字-->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    <attribute name="icon" type="string"><!--定义worklist/icon,可供显示的直观的图标-->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    <attribute name="category" type="string">!--定义worklist/category,存放的category位置。如果引用嵌套形式的category,则采用 parent_id/child_id的形式 -->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    <attribute name="class" type="string"><!--定义worklist/class,实现功能的类名称-->
    <annotation>
    <documentation>
    </documentation>
    <appinfo>
    <meta.attribute kind="java"/>
    </appinfo>
    </annotation>
    </attribute>
    <attribute name="id" type="string" use="required"><!--定义worklist/id,唯一标志-->
    <annotation>
    <documentation>
    </documentation>
    </annotation>
    </attribute>
    </complextype>
    </element>
    <!--以下内容为pde自动生成,与我们的编程无关-->
    <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>
    这样我们就定义好了扩展的属性。
    然后在plugin.xml加入:
    <extension-point id="worklist" name="worklist" schema="schema/worklist.exsd"/>
    就定义好了!

    2. 实现扩展
    定义完扩展之后,接下来要编写解析此扩展的相关代码。可喜的是,eclipse为我们提供了大量的api可以调用,省下了若干代码的编写。另外我们还可以借鉴eclipse实现的其他代码,通过模仿来编写我们自己的解析代码。本例参考了view的解析部分。同view,我们定义了worklistdescriptor,worklistregistry,worklistregistryreader.其中worklistdescriptor完成对上述定义的解析,worklistregistry存放了其他插件对worklist扩展的相关信息,worklistregistryreader则从worklistregistry读取信息供我们使用。
    此处代码从略,具体请参考view实现部分的viewdescriptor,viewregistry,viewregistryreader相关代码。

    3. 编写界面部分
    根据1对view的扩展,我们需要编写界面部分。此处请参考view插件的编写。我们在此对worklistplugin添加了一个方法用以从注册表中读取扩展信息:
    public iworklistregistry getworklistregistry() {
    if (worklistregistry == null) {
    worklistregistry = new worklistregistry();
    try {
    worklistregistryreader reader = new worklistregistryreader();
    reader.readworklist(platform.getextensionregistry(), worklistregistry);
    } catch (coreexception e) {
    // cannot safely show a dialog so log it
    workbenchplugin.log("unable to read worklist registry.", e.getstatus()); //$non-nls-1$
    }
    }
    return worklistregistry;
    }
    其中worklistregistryreader.readworklist定义如下:
    /**
    * read the worklist extensions within a registry.
    */
    public void readworklist(iextensionregistry in, worklistregistry out)
    throws coreexception {
    // this does not seem to really ever be throwing an the exception
    worklistregistry = out;
    readregistry(in, worklistplugin.getdefault().getpluginid(), "worklist");
    out.mapworklisttocategories();
    }
    可见,我们不需要编写复杂的代码就可以读取注册表中存放的扩展信息!
    我们对worklist扩展的显示是采用了treeview,代码如下(worklistview):
    protected treeviewer createviewer(composite parent) {
    treeviewer viewer =
    new treeviewer(parent, swt.multi | swt.h_scroll | swt.v_scroll);
    viewer.setusehashlookup(true);
    viewer.setcontentprovider(new worklistcontentprovider());
    viewer.setlabelprovider(new worklistlabelprovider());
    worklistreg = worklistplugin.getdefault().getworklistregistry();
    viewer.setinput(worklistreg);
    initlisteners(viewer);
    return viewer;
    }
    这样,就可以实现显示了。
    那么,怎样实现选择某个扩展后,通过双击执行其功能呢?我们对treeviewer添加了鼠标双击事件支持,关键代码如下:
    protected void handledoubleclick(doubleclickevent event) {
    istructuredselection selection = (istructuredselection) event.getselection();
    object element = selection.getfirstelement();

    treeviewer viewer = getworklistviewer();
    if (viewer.isexpandable(element)) {
    viewer.setexpandedstate(element, !viewer.getexpandedstate(element));
    }else {
    worklistdescriptor worklist = (worklistdescriptor)element;
    try {
    iworklistpart worklistpart = (iworklistpart) worklist.createworklist();
    worklistpart.run();
    } catch (coreexception e) {
    // should add something to handle the exception
    }
    }

    }
    其中iworklistpart很简单,使所有实现worklist扩展必须实现的接口:
    public interface iworklistpart {

    public void run();

    }
    只有一个run方法(可以自行添加其他的支持)。
    其中worklistdescriptor.createworklist方法实现根据class的字符串创建一个对象,也是超级简单,因为eclipse已经为我们编好了:
    public object createworklist() throws coreexception {
    object obj = workbenchplugin.createextension(configelement, "class");
    return obj;
    }
    这样就可以执行扩展的功能了。
    但是别忘了,还要编写pluin.xml,否则eclipse可不认吆:
    <extension
    point="net.softapp.worklist.worklist">
    <category
    name="hellotest"
    id="hellotest"/>
    <worklist
    icon="icons/example.ico"
    class="net.softapp.internal.worklist.hello"
    category="hellotest"
    name="hello"
    id="net.softapp.internal.worklist.hello"/>
    </extension>

    4.测试新扩展点

    ok,开始运行eclipse的plugin调试环境,打开worklist视图,看看在树状列表里是不是有一个hellotest目录,下面有hello。双击它,你编写的代码出来了吧!

    发表评论 共有条评论
    用户名: 密码:
    验证码: 匿名发表