一个通用的页签式视图框架

 

一个通用的页签式视图框架

简介: 本文设计并实现了一个通用页签式视图框架,它提供了一种纵向页签视图的快速开发能力。开发者可以利用它快捷地开发出页签样式的视图。这个框架是在 Tabbed Properties View 的基础上设计的。同时本文给出了该框架的一个使用示例。

属性视图是 Eclipse 最重要的一个扩展,用来查看或编辑项目的属性。自从 Eclipse 3.2 版本,开发者通过扩展点为属性视图定制用户界面,可以创建页签属性视图 (Tabbed Properties View)。它是纵向页签 ( 以下简称页签 ) 式的 Properties 视图,有着更加美观的效果。但是当需要在多个场合同时使用页签这种表现式时,开发者无法基于 Tabbed Properties View 创建更多的视图。

本文在 Tabbed Properties View 的基础上设计了一个通用的页签式视图框架,通过扩展框架提供的扩展点,开发者可以将特定的信息以页签的形式在视图中表现。

Tabbed Properties View 介绍

属性视图是 Eclipse 平台的默认视图,用做属性编辑器。通过页签属性视图 (Tabbed Properties View) ,开发者可以为属性视图提供页签式用户界面的扩展。

页签属性视图由 IBM 开发,最早用在 IBM 的一些基于 Eclipse 平台的产品之上,比如 IBM Rational Software Architect 和 IBM WebSphere Integration Developer 等等。随后,页签属性视图被贡献到 Eclipse open source,成为 Eclipse Web 工具平台项目的一部分。从 Eclipse 3.2 M5 开始,它成为 Eclipse 核心平台的组成部分。页签属性视图由插件 org.eclipse.ui.views.properties.tabbed 实现。

下面通过三个方面简单介绍一下 Tabbed Properties View:

  1. Tabbed Properties View 的外观
  2. Tabbed Properties View 的扩展点
  3. Tabbed Properties View 的局限

Tabbed Properties View 的外观

Tabbed Properties View 中页签式的表现形式最突出的好处就是纵向排列的页签十分直观,能很好地和视图页签区别开来。下面介绍两个例子:

IBM Rational Software Architect 中的 Properties 视图,如图 1 所示。


图 1. IBM Rational Software Architect 中的 Tabbed Properties View (tabbed_properties_view_in_RSA.jpg)
图 1. IBM Rational Software Architect 中的 Tabbed Properties View (tabbed_properties_view_in_RSA.jpg) 

在 WebSphere Business Modeler 7.03 版本中也使用了这样页签式的界面,如图 2 所示。


图 2. WebSphere Business Modeler 7.03 中的 Tabbed Properties View (tabbed_properties_view_in_WBM_7.03.jpg)
图 2. WebSphere Business Modeler 7.03 中的 Tabbed Properties View (tabbed_properties_view_in_WBM_7.03.jpg) 

Tabbed Properties View 的扩展点

Tabbed Properties view 扩展点有主要有 3 个:

  1. org.eclipse.ui.views.properties.tabbed.propertyContributor:用于设置 Property Contributor 信息,其 id 会在接下来介绍的两个扩展点中使用。信息包括 id,typeMapper,标题,需要注册的 Action,以及 Group;
  2. org.eclipse.ui.views.properties.tabbed.propertyTabs:用于描述页签信息,包括 id,名称,所属 Group,相对位置等;
  3. org.eclipse.ui.views.properties.tabbed.propertySections:设置 Section 的信息,包括对应的 Property Contributor 的 id,以及每个 Section 所在的页签,id,对应的 UI 类,相对位置,过滤方案等。

具体的使用可以参考 Eclipse Corner Article 中的 The Eclipse Tabbed Properties View 一文。

Tabbed Properties View 的局限

在属性视图中,Tabbed Properties View 可以很好地用于扩展用户界面。但是在属性视图之外,Tabbed Properties View 就无能为力了,开发者如果还想以纵向页签这种表现方式在新的视图中展示用户界面的话,需要重新设计开发类似的功能。

由于上述的局限,本文实现了一个通用页签式视图框架,用于快捷地创建这种页签式视图。接下来,本文将通过以下几个方面对这个框架进行介绍:

  1. 通用页签式视图框架基本介绍
  2. 通用页签式视图框架的类结构图
  3. 通用页签式视图框架的扩展点
  4. 示例

通用页签式视图框架基本介绍

通用页签式视图框架是在 Tabbed Properties View 的基础上设计的,保持了原来的界面风格。通过这套框架,开发者可以摒弃页签实现的底层细节,迅速地开发出一个纵向页签式视图。

通用页签式视图框架通过 org.eclipse.ui.views 扩展点来定义一个 ViewPart,然后再通过框架中的 com.ibm.crl.scpm.ui.views.tabbed.tabsProvider 扩展点,把视图配置成页签式视图。

通用页签式视图框架主要有以下两部分:

  1. View:由 com.ibm.crl.scpm.ui.views.tabbedview.TabbedView 提供;
  2. TabsProvider 扩展点:com.ibm.crl.scpm.ui.views.tabbed.tabsProvider 扩展点可以用于配置 TabbedView 的界面和功能。

本框架基于 Eclipse 平台 3.5.1 版本。

通用页签式视图框架的类结构图

通用页签式视图框架根据 com.ibm.crl.scpm.ui.views.tabbed.tabsProvider 中的配置实例化一些类对象,TabbedView 通过调用这些对象完成界面信息的展示。图 3 展现了这个框架中一些主要的类之间的调用关系。


图 3. 通用页签式视图框架中一些主要类间的关系 (tabbed_view_framework_classes.jpg)
图 3. 通用页签式视图框架中一些主要类间的关系 (tabbed_view_framework_classes.jpg) 

TabbedView 类作为 ViewPart 的子类,为我们的视图提供基础功能。

TabsProviderRegistry 用来注册视图实现类 TabbedView 和 com.ibm.crl.scpm.ui.views.tabbed.tabsProvider 扩展点的对应关系。

ITabsProvider 有以下四个用途,

  1. 判断是否支持当前编辑器 (Editor) ;
  2. 根据编辑器 (Editor) 中选中的对象 (Selection 中的元素 ),为 TabbedView 提供合适的 ITabDescriptor;
  3. 为 TabbedView 和 Title 提供名称;
  4. 为 TabbedView 注册 Action。

TabDescriptor 与页签一一对应,它的作用是在页签中,为编辑器 (Editor) 中选中的对象 (Selection 中的元素 ) 选择合适的 ISection。

ISection 用于页签中用户界面的显示,包括界面布局和数据输入。

通用页签式视图的框架扩展点

com.ibm.crl.scpm.ui.views.tabbed.tabsProvider 用于配置页签式视图的界面,包括页签列表以及页签中 Section。下面是这个扩展点的文档类型定义 (Document Type Definition)。


清单 1. com.ibm.crl.scpm.ui.views.tabbed.tabsProvider 扩展点信息
				
 <!ELEMENT extension ((tabsProvider , (tabDescriptor)+)+)> 
 <!ATTLIST extension 
 point CDATA #REQUIRED 
 id    CDATA #IMPLIED 
 name  CDATA #IMPLIED 
 > 

point - 目标扩展点的全称

id – 扩展实例的 id( 可选 )

name – 扩展实例的名称 ( 可选 )


清单 2. 节点 tabsProvider 信息
				
 <!ELEMENT tabsProvider (tabDescriptors+)> 
 <!ATTLIST tabsProvider 
 id  CDATA #REQUIRED 
 editorContributorId  CDATA #REQUIRED 
 viewContributorId  IDREF #REQUIRED 
 titleLabelProvider  CDATA #IMPLIED 
 partNameLabelProvider  CDATA #IMPLIED 
 actionProvider   CDATA #IMPLIED 
 > 

id – tabsProvider 唯一 id

editorContributorId – 编辑器的唯一 id,决定这个 tabsProvider 将支持哪些编辑器,如有多个,中间用逗号隔开

viewContributorId – 要服务的 Tabbed View 的唯一 id

titleLabelProvider – 提供 Tabbed View 的标题 ( 可选 ),实现 org.eclipse.jface.viewers.ILabelProvider 接口

partNameLabelProvider - 提供 Tabbed View 的名称 ( 可选 ),实现 org.eclipse.jface.viewers.ILabelProvider 接口

actionProvider - 提供 Tabbed View 的标题 ( 可选 ),实现 com.ibm.crl.scpm.ui.views.tabbedview.IActionProvider


清单 3. 节点 tabDescriptors 信息
				
 <!ELEMENT tabDescriptors (enablement , (tabDescriptorId)+)> 
 <!ATTLIST tabDescriptors 
 id CDATA #REQUIRED 
 > 

id – 页签列表唯一 id,可用 enablemet 来确定是否支持


清单 4. 节点 tabDescriptor 信息
				
 <!ELEMENT tabDescriptor (section)+> 
 <!ATTLIST tabDescriptor 
 id    CDATA #REQUIRED 
 name   CDATA #REQUIRED 
 image  CDATA #IMPLIED 
 > 

id – 页签的唯一 id

name – 页签的名称

image – 页签的图片 ( 可选 )


清单 5. 节点 section 信息
				
 <!ELEMENT section (enablement)> 
 <!ATTLIST section 
 id   CDATA #REQUIRED 
 class   CDATA #REQUIRED 
 > 

id – Section 的唯一 id

class – 为一个页签提供 Section,需要实现 com.ibm.crl.scpm.ui.views.tabbedview.ISection 接口


清单 6. 节点 tabDescriptorId 信息
				
 <!ELEMENT tabDescriptorId EMPTY> 
 <!ATTLIST tabDescriptorId 
 tabDescriptor  IDREF #REQUIRED 
 > 

tabDescriptor – Tab 的唯一 id


清单 7. 节点 enablement 信息
				
 <!ELEMENT enablement (not , and , or , instanceof , test , systemTest , 
 equals , count , with , resolve , adapt , iterate , reference)*> 

为所选中的元素提供表达式判断。关于 enablement 的使用,详见参考资源 org.eclipse.core.expressions

示例

下面将以一个基于 GEF Logic Example 的示例来具体地演示这个通用页签式框架的使用 (GEF Logic Example 可通过 GEF Update Sites 更新得到 )。GEF 是 Eclipse 平台下的图形编辑框架,其中,EditPart 维护着图形 (figure) 与模型 (model) 的对应关系。


图 4. GEF Logic Example (GEF_Logic_Example.jpg)
图 4. GEF Logic Example (GEF_Logic_Example.jpg) 

示例将会为 LED 组件 ( 对应 org.eclipse.gef.examples.logicdesigner.edit.LEDEditPart) 和逻辑门组件 ( 对应 org.eclipse.gef.examples.logicdesigner.edit.OutputEditPart) 仅显示一个 Basic 页签,为容器组件 (org.eclipse.gef.examples.logicdesigner.edit.LogicContainerEditPart) 显示 Basic 和 Advanced 页签。前两者的 Basic 页签中采用的 Section 将只显示选中元素的名称,后者则采用另一个 Section,除了显示选中元素之外,还显示所找开的文件名称。

首先,使用 org.eclipse.ui.views 扩展点来设置所要创建的 View,将其 class 属性设为 com.ibm.crl.scpm.ui.views.tabbedview.TabbedView,设置 id 和 name,id 在之后的配置中将会使用到。如清单 8 所示。


清单 8. 注册视图
				
 <extension 
      point="org.eclipse.ui.views"> 
   <view 
         class="com.ibm.crl.scpm.ui.views.tabbedview.TabbedView"
         id="TabbedViewExample.view"
         name="TabbedViewExample"
         restorable="true"> 
   </view> 
 </extension> 

直接将 com.ibm.crl.scpm.ui.views.tabbedview.TabbedView 注册成新视图。如果有需要,开发者可以基于 TabbedView 扩展自己的视图,并在此注册。TabbedViewExample 为新视图对应的名称。

然后,扩展 com.ibm.crl.scpm.ui.views.tabbed.tabsProvider 用来配置 TabbedViewExample。这里我们使用 GEF Logic Example 中的 Logic 编辑器来进行演示,它的 Editor id 是 Logic Graphic Editor。


清单 9. 配置 tabsProvider
				
 <extension 
      point="com.ibm.crl.scpm.ui.views.tabbed.tabsProvider"> 
   <tabsProvider 
         editorContributorId="Logic Graphical Editor"
         id="TabbedViewExample.tabsProvider"
         viewContributorId="TabbedViewExample.view"> 
         ……

接下来,我们开始为 org.eclipse.gef.examples.logicdesigner.edit.LEDEditPart,org.eclipse.gef.examples.logicdesigner.edit.OutputEditPart 和 org.eclipse.gef.examples.logicdesigner.edit.LogicContainerEditPart 创建对应的页签列表,如清单 10 所示。


清单 10. 配置 tabsDescriptors
				
 <tabDescriptors 
      id="TabbedViewExample.tabDescriptors1"> 
    <enablement> 
        <instanceof 
              value="org.eclipse.gef.examples.logicdesigner.edit.LogicContainerEditPart"> 
        </instanceof></enablement> 
    <tabDescriptorId 
           tabDescriptor="TabbedViewExample.tabDescriptorId.Basic"> 
    </tabDescriptorId> 
    <tabDescriptorId 
           tabDescriptor="TabbedViewExample.tabDescriptor.Advanced"> 
    </tabDescriptorId> 
 </tabDescriptors> 
 <tabDescriptors 
      id="TabbedViewExample.tabDescriptors2"> 
    <enablement> 
        <or> 
            <instanceof 
                  value="org.eclipse.gef.examples.logicdesigner.edit.LEDEditPart"> 
            </instanceof> 
            <instanceof 
                  value="org.eclipse.gef.examples.logicdesigner.edit.OutputEditPart"> 
            </instanceof> 
        </or> 
    </enablement> 
    <tabDescriptorId 
           tabDescriptor="TabbedViewExample.tabDescriptorId.Basic"> 
    </tabDescriptorId> 
 </tabDescriptors> 

这里为 LogicContainerEditPart 定义了两个页签 Basic 和 Advanced 页签, id 分别为 TabbedViewExample.tabDescriptorId.Basic 和 TabbedViewExample.tabDescriptor.Advanced,而为 LEDEditPart 和 OutputEditPart 定义了一个 Basic 页签, id 为 TabbedViewExample.tabDescriptorId.Basic。对 Logic Example 来说,enablement 中的表达式针对选中图形所对应的 EditPart,用于判断这个 tabDescriptors 是否响应在 Editor 中选中 EditPart。

Basic 与 Advanced 页签各自可以拥有一些不同的 Section,用于显示所选择的图形对应的用户界面,这种对应关系 (Section 与 EditPart) 也应用 enablement 表达式来进行判断。


清单 11. 配置 tabsDescriptor
				
 <tabDescriptor 
       id="TabbedViewExample.tabDescriptorId.Basic"
       name="Basic"> 
    <section 
          class="tabbedviewexample.sections.BasicSection"
          id="TabbedViewExample.BasicSection"> 
       <enablement> 
            <or> 
               <instanceof 
                     value="org.eclipse.gef.examples.logicdesigner.edit.OutputEditPart"> 
               </instanceof> 
               <instanceof 
                     value="org.eclipse.gef.examples.logicdesigner.edit.LEDEditPart"> 
               </instanceof> 
            </or></enablement> 
    </section> 
    <section 
          class="tabbedviewexample.sections.BasicSection"
          id="TabbedViewExample.BasicLogicContainerSection"> 
        <enablement> 
        <instanceof 
           value="org.eclipse.gef.examples.logicdesigner.edit.LogicContainerEditPart"> 
        </instanceof></enablement> 
 </section> 
 </tabDescriptor> 
 <tabDescriptor 
      id="TabbedViewExample.tabDescriptor.Advanced"
      name="Advanced"> 
 <section 
         class="tabbedviewexample.sections.AdvancedSection"
         id="TabbedViewExample.Advanced"> 
       <enablement> 
       <instanceof 
             value="org.eclipse.gef.examples.logicdesigner.edit.LogicContainerEditPart"> 
       </instanceof></enablement> 
   </section> 
 </tabDescriptor> 

tabbedviewexample.sections.BasicSection、TabbedViewExample.BasicLogicContainerSection 及 tabbedviewexample.sections.AdvancedSection 几个类为页签提供不同的界面,它们都实现了 com.ibm.crl.scpm.ui.views.tabbedview.ISection 这个接口。ISection 继承自 org.eclipse.core.runtime.IAdaptable 接口,它是开发者必须实现的接口,一共有四个方法:

  1. void createControls(Composite composite): 这个方法用于创建页签的界面;
  2. void setInput(IEditorPart part, Object object) :根据当前的 Editor 及在 Editor 中选中的元素,为用户界面提供输入数据;开发者根据输入决定用户界面的行为;
  3. void refresh(): 用于刷新界面的内容,开发者可通过代码的方式进行调用,比如当开发者改变了当前选中元素的数据,需要刷新界面时,调用视图对象的刷新 TabbedView.refresh(),它会调用当前显示的 Section 的该方法;
  4. Object getAdapter(Class adapter):获得匹配的适配对象。

清单 12 是 tabbedviewexample.sections.AdvancedSection 的实现,在这个示例中 refresh 与 getAdapter 方法并没有被使用到,开发者可根据自身的需求进行覆写。BasicSection 和 LogiclContainerBasicSection 与其类似,读者可以详见示例代码。


清单 12. AdvancedSection 类
				
 public class AdvancedSection extends Section 
 { 
    private TreeViewer viewer = null; 

    @Override 
    public void createControls(Composite composite) 
    { 
        Composite com = new Composite(composite, SWT.NONE); 
        com.setLayoutData(new GridData(GridData.FILL_BOTH)); 
        com.setLayout(new GridLayout()); 
        viewer = new TreeViewer(com); 
        viewer.getTree().setLayoutData(new GridData(GridData.FILL_BOTH)); 
        viewer.setContentProvider(new ITreeContentProvider() 
        { 
	   ……
            @Override 
            public Object[] getElements(Object inputElement) 
            { 
                return ((EditPart) inputElement).getChildren().toArray(); 
            } 

            @Override 
            public boolean hasChildren(Object element) 
            { 
                return getChildren(element).length > 0; 
            } 

            @Override 
            public Object getParent(Object element) 
            { 
                return null; 
            } 

            @Override 
            public Object[] getChildren(Object parentElement) 
            { 
                return getElements(parentElement); 
            } 
        }); 

        viewer.setLabelProvider(new LabelProvider() 
        { 
            @Override 
            public String getText(Object element) 
            { 
                return ((EditPart) element).getModel().toString(); 
            } 
        }); 
    } 

    @Override 
    public void setInput(IEditorPart part, Object object) 
    { 
        viewer.setInput(object); 
    } 
 } 

另外,开发者可以根据需要定制针对 TabbedView 的 TitleProvider,PartNameProvider 及 ActionProvider,前两个 Provider 要实现 org.eclipse.jface.viewers.ILabelProvider,后者要实现 com.ibm.crl.scpm.ui.views.tabbedview.IActionProvider。

TitleProvider 根据选中的 EditPart 来决定 TabbedView 的 Title,这里我们给出了一个简单的实现,如清单 13。同时我们将 tabsProvider 节点中的 titleProvider 也设为 tabbedviewexample.providers.TitleProvider。


清单 13. TitleProvider 类
				
 public class TitleProvider extends LabelProvider 
 { 
    @Override 
    public String getText(Object element) 
    { 
        return ((EditPart) element).getModel().toString(); 
    } 
 } 

PartNameProvider 根据当前编辑器 (Editor) 确定 TabbedView 的 Name,使用方法与设置 Title 类似,只需将 partNameProvider 的属性值设置为对应的类即可。

ActionProvider 用来为 TabbedView 的 ActionBar 注册 Action。开发者可以在 Section 中通过 PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(String id) 这个方法得到对应的 TabbedView 后,再得到 TabbedView 的 ActionBar,这样进行注册 Action 或是获得注册的 Action。开发者还可以利用 Eclipse 中的 org.eclipse.ui.menus,org.eclipse.ui.ActionSet 或是 org.eclipse.ui.ViewActions 等扩展点向当前的 TabbedView 注册 Action。

下面来看看定制后的 TabbedViewExample 的界面,比较简单,但足以反映出这个扩展点的特性。

当 LED 被选中时,TabbedViewExample 只显示 Basic 一个页签。图 5 中 Basic 使用 Section 展示 LED 对应的数据模型信息。


图 5. 选中 LED 时 TabbedViewExample 界面 (basic_led.jpg)
图 5. 选中 LED 时 TabbedViewExample 界面 (basic_led.jpg) 

当 Logic Diagram (Editor 中空白处,对应最顶层的 Logic Container) 被选中时,TabbedViewExample 显示 Basic 与 Advanced 两个页签,需要注意的是,Basic 页签使用了另一个 Section,这个 Section 与上图中使用的不同,它会显示编辑器中输入的模型文件的名字。


图 6. 选中 Logic Diagram 时 Basic 页签 (basic_logiccontainer.jpg)
图 6. 选中 Logic Diagram 时 Basic 页签 (basic_logiccontainer.jpg) 

Advanced 页签为 Logic Diagram 显示被它所包含的图形的信息。


图 7. 选中 Logic Diagram 时 Advanced 页签 (advanced_logiccontainer.jpg)
图 7. 选中 Logic Diagram 时 Advanced 页签 (advanced_logiccontainer.jpg) 

结束语

本文介绍了一个通用的页签式视图框架。该框架参照 Tabbed Properties View 的界面风格,实现了一套页签式视图快速开发的框架。最后本文给出了一个应用示例,来帮助开发者更好地熟悉这个框架。我们希望这个框架能够帮助 Eclipse RCP 开发人员开发出更好的用户界面。您如果对本文有什么意见或者建议,可以通过电子邮件和我们交流,对本文的内容进行指证。

转载于:http://www.ibm.com/developerworks/cn/opensource/os-cn-eclipse-tabview/index.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值