• Eclipse 4


    Eclipse 4简介

    Eclipse SDK 4.x基于E4孵化器项目,是新一代构建基于Eclipse的工具和富客户端桌面应用的平台。它使得开发和组装基于Eclipse平台的应用和工具要更加容易。第一个版本(4.0)发布于2010年7月28日,4.1发布于2011年6月22日,2012年将发布Eclipse 4.2。Eclipse 3.8将和4.2同时发布,同时3.x也将停止更新。

    Eclipse 4包含:

    • 基于模型的用户界面和用于程序样式的基于CSS的声明机制。这使得设计和自定义应用程序界面变得更加容易,也给UI布局带来更大的灵活性,可以使UI看起来与IDE完全不同。
    • 新的面向服务的编程模型,可以更容易地使用Eclipse平台提供的应用程序服务。
    • 支持依赖注入。
    • 提供了一个兼容层,已有的Eclipse 3.x程序也可以利用Eclipse 4应用程序平台的新功能。

    架构概述

    Eclipse 4应用程序平台与Eclipse 3.x应用程序平台非常类似。如全部JDT和PDE、大部分Platform都和Eclipse 3.x完全相同。E4AP与Eclipse 3.x平台的不同之处在于Workbench的实现(如org.eclipse.ui.workbench.plugin),以及这个新实现所依赖的技术。在发布之前,这些技术(模型化的UI、依赖注入、基于服务的编程模型、基于CSS的样式)称为“e4”,而现在,我们叫它Eclipse 4应用程序平台(E4AP)。在E4AP上端,4.0 Workbench提供了一个3.x Workbench APIs的实现,称为兼容层,为已有的Eclipse 3.x应用提供向后兼容。

    E4AP架构

    模型化UI

    Eclipse 4应用程序的布局现在完全支持模型。它与Web页的DOM类似,描述用户界面的布局和结构,尽管还包含其他对用户不可见的元素(如命令和handler)。

    模型化UI为自定义应用程序外观提供非常灵活的方式。应用程序的结构比3.x的透视图工厂和扩展更容易理解,因为每个元素的容器模型都设计得更好。

    模型本身使用EMF创建和维护的,并使用EMF风格的模式来创建和添加元素。对模型的改变将立即反应在运行的应用程序中。

    模型元素

    Eclipse 4中的模型是一组接口,都以M作为前置,并公开了很多getter、setter方法。Eclipse 4的模型继承了上一代Eclipse应用程序平台的最佳实践。模型化的UI描述了窗体、透视图、stacks or tiles和part,也吸收了Eclipse 3.4中的命令/处理程序/绑定这个模型。

    E4AP提供了MApplicationElementMUILable等抽象元素,以及MWindowMPerspectiveMPartMMenu等具体元素。详细内容可以参考这里

    CSS样式

    E4AP的一个主要改进就是重新思考如何处理应用程序的主题和样式。它可以对控件、窗体、对话框应用样式。这一开始可能会感到很陌生。不过UI的层次结构与HTML类似。如SWT窗体或对话框包含一个根容器Shell,它又包含一些CompositeGroup元素,每个元素又可以包含CTabFolderTextTreeTable等。

    CSS映射

    使用CSS选择器可以通过type#id.class这样的方式来指定元素。从E4AP到SWT的映射如下:

    • type对应Java组件类(如ButtonComposite等)。
    • 元素可以包含很多类。E4AP公开了模型化UI元素的接口类型(如MPartMTrimmedWindow)及其标签(通过类的特性(attribute))。类的特性也可以访问SWT组件的数据值。
    • id对应模型化元素的elementId。

    这里有CSS属性与SWT控件方法的映射表。

    应用样式

    在CSS文件中,我们使用相关SWT控件的标示符,如下面的CSS文件:

    Label{
        font:Verdana8px;
        color: black;}CompositeLabel{
        color: black;}Text{
        font:Verdana8px;}CompositeText{
        background-color: white;
        color: black;}SashForm{
        background-color:#c1d5ef;}.MTrimBar{
        background-color:#e3efff #c1d5ef;
        color: white;
        font:Verdana8px;}Shell{
        background-color:#e3efff #c1d5ef 60}

    要让你的程序使用CSS文件,可以有两种方式:

    • 对产品指定applicationCSS文件。
    • 使用主题管理器

    如果程序样式固定,就使用第一种方式。打开RCP项目的plugin.xml文件,选择extensioni选项卡,向org.eclipse.core.runtime.products扩展点添加applicationCSS属性。该属性的值是指向CSS文件的URI,格式约定为platform:/plugin/BundleSymbolicName/path/file这种格式。例如:

    platform:/plugin/com.example.e4.rcp.todo/css/default.css

    设置applicationCSS

    这样,我们的程序在一开始就将应用该样式。

    第二种方法要更灵活一些。我们定义一个对于org.eclipse.e4.ui.css.swt.theme扩展点(定义ID和对CSS文件的指针)的扩展。然后为产品定义cssTheme属性。主题管理器允许我们在运行时选择样式,和注册新主题。

    我们创建org.eclipse.e4.ui.css.swt.theme扩展点的两个扩展,如下图

    创建一个css/red.css文件:

    CTabItem,ToolBar,Button,CBanner,CoolBar{
        font-size:9;
        background-color: red;}

    对项目添加cssTemplate参数:

    创建下面这个handler将选择红色样式:

    import javax.inject.Named;import org.eclipse.e4.core.di.annotations.Execute;import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;import org.eclipse.e4.ui.workbench.IWorkbench;publicclassThemeSwitchHandler{@Executepublicvoid switchTheme(IThemeEngine engine){
            engine.setTheme("de.vogella.e4.todo.redtheme",true);}}

    在应用程序中添加一个调用上面handler的菜单。运行程序,就可以通过菜单选择红色主题:

    此外,我们还可以指定某个控件的标签,并在CSS文件中定义这些标签。我们可以用下面的代码来设置标签:

    Label label =newLabel(parenet, SWT.NONE);
    label.setData("org.eclipse.e4.ui.css.id","MyCSSTagForLabel");

    CSS文件可以这样定义该标签的样式:

    #MyCSSTagForLabel{
        color:#blue;}

    依赖注入

    Eclipse平台经过10年的发展,仍然存在以下问题:

    1. 代码需要频繁使用全局单例访问器(如PlatformPlatformUI)或请求较深的依赖链(如获取IStatusLineManager)。单例服务对RAP和Riena这种应用服务器来说,问题多多。
    2. 单例与提供程序的消费者紧密耦合,并且禁止重用。
    3. 不够动态。
    4. ……

    E4AP使用依赖注入来解决这些问题。客户端代码不需要知道如何访问服务,只需要描述所需的服务,而由平台负责配置适当的服务。它提供了与JSR 330兼容的基于注解的依赖注入框架,与Spring类似。注入器定义在多个插件中:org.eclipse.e4.core.diorg.eclipse.e4.core.di.extensionsorg.eclipse.e4.ui.di

    在Eclipse 3.x中,视图需要通过PlatformUI单例和part site的状态行管理器来访问Eclipse帮助系统:

    classMyViewextendsViewPart{publicvoid createPartControl(Composite parent){Button button =...;PlatformUI.getWorkbench().getHelpSystem().setHelp(button,"com.example.button.help.id");
    
            getViewSite().getActionBars().getStatusLineManager().setMessage("Configuring system...");}}

    而在E4AP中,part是POJO,应用程序服务是直接注入进来的:

    classMyView{@Injectpublicvoid create(Composite parent,IWorkbenchHelpSystem help){Button button =...;
            help.setHelp(button,"com.example.button.help.id");
    
            slm.setMessage("Configuring system...");}}

    DI的好处有:

    • 客户端可以编写POJO和所需的服务列表。
    • 更利于测试。

    而DI也有一些缺点:

    • 服务发现:无法使用代码自动完成功能来找到可用的服务。
    • 调试加载失败的注入项时会很困难。

    与依赖注入相关的注释,详见这里

    上下文

    E4AP使用上下文IEclipseContext接口)向应用程序提供公共服务。普通代码不需要使用或了解上下文。应该在Java类中使用@Inject注解来接收必要的服务,不应该直接使用IEclipseContext

    Eclipse 3.x存在以下问题,可以由IEclipseContext和依赖注入来解决:

    1. 频繁使用全局单例访问器(如PlatformPlatformUI等等)
    2. 生产者与消费者之间的耦合过于紧密,同时很难重用
    3. 对上下文变化的动态响应不是增量的
    4. IEvaluationContext包含全局状态(可根据上下文的改变而变化)
    5. 当前解决方案不是多线程的(计算发生在UI线程)
    6. 尺寸变化
      • 当前解决方案不会因为服务的生命周期短而减小尺寸
      • 当前解决方案会因为服务多而增大尺寸
    7. 包含太多相似的并行树(控件树、服务位置树等)
    8. 不跟踪服务的消费者
    9. 客户端代码需要了解Eclipse代码库的内部
    10. 不支持由运行时的其他服务组成的服务查找

    E4AP的上下文存储了可用的服务,并提供了OSGi服务查找。由于不太可能向Eclipse上下文请求可用的服务,并且不建议直接调用上下文中的方法,所以了解能够注入哪些内容是十分重要的。

    模型为例,它们都是MContext的实例,包含在自身的上下文中。例如,MWindowMPart都是MContext,所以可以这样查询模型对象的上下文:

    // window == mwindowMWindow window =(MWindow) mwindow.getContext().get(MWindow.class.getName());// part == mpartMWindow part =(MPart) mpart.getContext().get(MPart.class.getName());

    这些模型对象都存在于上下文中,所以可以直接将它们注入到客户端代码中:

    publicclassAccountsPart{@InjectprivateMPart part;@InjectprivateMWindow window;void setDirty(boolean dirty){
            part.setDirty(dirty);}}

    为了鼓励重用,你应该注入所需的最小公分母。例如,如果只关注让part变dirty,只需要:

    publicclassAccountsPart{@InjectprivateMDirtyable dirtyable;void setDirty(boolean dirty){
            dirtyable.setDirty(dirty);}}

    这样其他非MPartMDirtyable实现也可以复用你的代码。这导致了一个非常有趣的现象,即一个模型接口的上层接口也会添加到上下文中。例如:

    publicclassAccountsPart{@InjectprivateMDirtyable dirtyable;@InjectprivateMUILabel label;@InjectprivateMContext context;@InjectprivateMPart part;}

    所有的字段都是相同的MPart实例。

    关于上下文的详细内容,请参考这里

    事件模型

    Eclipse 4使用了一个发布/订阅事件模型的全局事件总线(global event bus)。《E4中的事件处理》描述了其原理。全局事件总线实现在OSGi事件引起之上,可使用org.eclipse.e4.core.services.events.IEventBroker访问。

    IEventBroker提供了一些方法,可以订阅、取消订阅总线上的事件,以及向总线发布事件。

    获取IEventBroker

    可以通过EclipseContext来获取IEventBroker的一个实例:

    privateIEclipseContext eclipseContext;IEventBroker eventBroker = eclipseContext.get(IEventBroker.class);

    或通过依赖注入:

    @InjectIEventBroker eventBroker;

    发布事件

    向全局事件总线发布事件十分简单,只需调用一下两个方法之一:

    IEventBroker.post(String topic,Object data)// synchronous deliveryIEventBroker.send(String topic,Object data)// asynchronous delivery

    例如:

    ...
    foo.Bar payload = getPayload();boolean wasDispatchedSuccessfully = eventBroker.send(TOPIC_STRING, payload);

    如果sendpost命令的payload是普通Java对象,将把它作为包含IEventBroker.DATA键的属性附加到OSGi事件上。如果payloadDictionaryMap,所有的值都将作为包含相应键的属性进行添加。

    响应事件

    声明和相应事件包含两种方法:依赖注入和通过IEventBroker订阅。

    Eclipse推荐在任何时候都使用依赖注入来注册和相应事件。它的代码更少,更容易阅读和维护,包含较少的匿名内部类。(但实际上E4代码库并没有使用这种方法来订阅事件。)

    @Inject@Optionalvoid closeHandler(@UIEventTopic(''TOPIC_STRING'') foo.Bar payload){// Useful work that has access to payload.  The instance of foo.Bar that the event poster placed on the global event bus with the topic ''TOPIC_STRING''}

    应该将事件处理方法定义为私有的,这样可以更清晰,也能避免直接调用。依赖注入机制可以注入私有字段和方法。(目前定义成私有方法会有bug,可以定义为包级私有。)

    如果你的类没有使用依赖注入,则只能用IEventBroker来订阅:

    IEventBroker eventBroker;void addSubscribers(){
    
        eventBroker.subscribe(TOPIC_STRING, closeHandler);}void removeSubscribers(){
        eventBroker.unsubscribe(closeHandler);}private org.osgi.service.event.EventHandler closeHandler =newEventHandler(){publicvoid handleEvent(Eventevent){// Useful work that has access
        foo.Bar payload =(foo.Bar)event.getProperty(IEventBroker.DATA);}

    参考资料

     
    标签: Eclipse

    当前标签: Eclipse

     
    麒麟.NET 2012-05-11 12:38 阅读:721 评论:1
     
    麒麟.NET 2011-12-23 13:33 阅读:130 评论:2
     
    麒麟.NET 2010-03-25 13:28 阅读:1886 评论:2
     
    麒麟.NET 2010-03-23 12:39 阅读:655 评论:3
     
    麒麟.NET 2009-06-22 16:57 阅读:854 评论:1
  • 相关阅读:
    六:页面优化
    五:title,keywords,description标签
    专题之一:开篇有益
    通过JavaScript以及ActiveX控件获得客户端的机器名[Z]
    [1]Web Service简介
    (转载)虚拟环境中的隐蔽信道(续)
    虚拟机VMware如何能将屏幕调大
    VMware下Ubuntu上网设置
    基于CPU负载的隐蔽信道 ——> ——>基于网络负载的隐蔽信道
    Ubuntu 12.04终端Terminal快捷方式调用
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2496199.html
Copyright © 2020-2023  润新知