内容


为 Eclipse 组件实现 Web 用户界面

在基于 Eclipse 的组件内使用 RIA 技术

Comments

简介

最近一些年来,Web 已经成为业界最为流行的软件平台之一。Web 应用程序广为接受,一方面是因为 World Wide Web 带来的广泛可用性,另一方面是因为 Web 应用程序平台中有大量很棒的用户界面(UI)技术可用。以 Dojo、 Adobe Flex、OpenLaszlo 等技术为例,它们可提供效果迷人的交互客户机,可极大地改善用户体验。

而桌面应用程序,比如 Eclipse,主要侧重于设计一个具有良好可用性和较高用户效率的 UI;一般很难看到桌面应用程序包含交互的 UI。在 Eclipse 内,有一个灵活的工具箱 Draw2D 可用于构建 UI。不过,它有很多限制。比如,它只支持静态图像(比如 JPG 和 GIF),不支持动态图像(比如 SVG)。而且,在 Draw2D 内,效果和动画实现起来相当复杂,通常开发人员都不愿意涉足。

在本文中,我们将介绍一个面向 Eclipse 应用程序的 UI 范型:用基于 Web 的 UI 技术来构建 Eclipse UI 组件。

为何要将一个 Web UI 集成到 Eclipse?

Eclipse 是现今最为流行的开发平台。它高度可扩展的框架让它备受推崇,并且现在很多应用程序都构建于 Eclipse 之上。在 Eclipse 内实现 UI 的一种标准方式是使用 Standard Widget Toolkit (SWT)、JFace 和 Draw2D 框架。借助这些 UI 框架,您就可以轻松实现具有令用户满意且与在该环境内使用的其他应用程序相类似的观感的应用程序。在大多数情况下,这些框架可以很好地帮助您为用户构建最佳的 UI。

但是,使用 Eclipse 提供的标准 UI 框架通常很难实现最精致、最直观、用户友好性最佳的 UI。比如,实现像阴影和颜色渐变这样的效果有时会显得很重要。并且,在 Eclipse 图形视图/编辑器内放大可视对象会使这些图像(GIF 或 JPG 格式)的外观变得粗糙。要解决这些问题,就需要编写定制的呈现程序来控制 UI 的设计和制图。但是,编写过呈现程序的开发人员一定都知道这项工作不好玩。不理想的 UI 设计常常会影响应用程序的可用性。

大多数 Web UI 均提供对高端可视效果(比如动画)的内置支持和对动态图像(比如 SVG)的支持。因而,这些平台上的开发人员可以很轻松地以自己想要的方式实现 UI。

此外,使用 Web 界面技术开发的 Eclipse 组件可以很容易地被迁移到 World Wide Web,这就为部署提供了极大的灵活性。

Eclipse 内的哪些组件可以利用 Web UI?

Eclipse 内的任何 UI 都可以通过 Web UI 实现。图 1 中所示的是 Java 透视图内的一个典型的 Eclipse 工作台。

图 1. Java 透视图内的一个典型的 Eclipse 工作台
这个屏幕快照显示的 Eclipse 工作台上的每个部分都有一个标签,表明它是一个 ‘View’ 还是一个 ‘Editor’
这个屏幕快照显示的 Eclipse 工作台上的每个部分都有一个标签,表明它是一个 ‘View’ 还是一个 ‘Editor’

理论上,所有的视图和编辑器均可使用 Web UI 实现。但是,在一个基于 Eclipse 的组件内,Web UI 技术只能用来实现 UI。组件的核心逻辑应该仍由 Eclipse 环境实现。

一个 Web UI 如何在 Eclipse 内运行?

每个 Web UI 应用程序均可用一个标准的 Web 浏览器打开。比如:为了打开一个包含 HTML 文件(内有作为对象嵌入的 Shockwave 文件(.swf))的 Adobe Flex 应用程序,应该让浏览器指向此 Flex 应用程序的 HTML 文件所对应的 URL。

在 Eclipse 内,有一个 SWT 浏览器小部件(org.eclipse.swt.browser.Browser)可用来打开任何 Web UI 应用程序。这个浏览器小部件反过来可以帮助我们用 Web UI 技术实现 Eclipse 组件。我们可以使用如下步骤来通过 Web UI 实现一个 Eclipse 组件(编辑器或视图):

  1. 使用任何 Web UI 技术开发这个 Web UI。
  2. 打包这个 Web UI 应用程序以供在 Eclipse 内访问。打包的选项有很多,但通常,可以将这个 Web 应用程序放入一个 Eclipse 插件以便编辑器类可以访问它。
  3. 从编辑器代码中,实例化 SWT 浏览器小部件并用它来启动这个 Web UI 应用程序。清单 1 内的代码展示了如何在 EditorPart 控件的 createPartControl() 方法内实例化浏览器小部件并在浏览器内打开这个 Web UI。
清单 1. 在 Eclipse 编辑器内实例化一个浏览器小部件
	public void createPartControl(Composite parent) {
	 …
	 Browser browser = new Browser(parent, SWT.NONE);
	 …
	 browser.setUrl(“my.plugin.name\MyFirstWebUI.html”);
	 …
	}

以上就是这个小部件的层次结构,其中的一个浏览器小部件运行 Web UI 应用程序:Eclipse Workbench > Eclipse Editor/View > SWT Browser control > Web UI application

Web UI 应用程序如何与 Eclipse 通信?

Web UI 应用程序与 Eclipse 之间的通信渠道根据所用的 Web UI 技术而有所不同。对于最常用的 Web UI 技术,比如 Adobe Flex、Dojo 和 OpenLaszlo,JavaScript 和 HTTP 请求均可使用。接下来让我们分别来看看这两种情况。

通过 JavaScript 进行通信

使用 JavaScript,Eclipse 和 Web UI 应用程序之间的通信在方向上稍有差异。要实现从 Eclipse 到 Web UI 应用程序的通信,在 SWT 浏览器控件内有一个 API 可用(Browser.execute(String string))。借助它,可在这个运行于浏览器内的 Web UI 中执行 JavaScript。清单 2 和 3 显示了 Eclipse 是如何调用 JavaScript 的以及这个 Web UI 应用程序又是如何处理这个 JavaScript 调用的。

首先,Eclipse 进行一个 JavaScript 调用 — 在本例中,就是请求打开一个对话框。

清单 2. Eclipse 调用 JavaScript
	Browser browser = new Browser(parent, SWT.NONE);
	…
	browser.execute(“openDialog();”);

在这个 HTML 内定义的这个 JavaScript 函数将会随后执行。

清单 3. 由 Web UI 收到的 JavaScript 调用
	function openDialog() {
	…
	 alert();
	…
	}

根据实现这个 Web UI 应用程序所用的技术,在浏览器控件内执行 JavaScript 可能就已经足够了。但是,对于运行在浏览器内的另一个容器内的技术 — 比如运行在 Adobe Flash player 内的 Adobe Flex 应用程序 — Web UI 应用程序和 Eclipse 之间就需要一个代理。

让我们看看使用 Adobe Flex 的另一个例子。在从 Eclipse 浏览器调用 JavaScript 时,HTML 应用程序可以将 JavaScript 调用转换成 ActionScript,然后再在 Flex 应用程序上调用这个 ActionScript。清单 4、5 和 6 展示了 Eclipse 如何通过 JavaScript 和 ActionScript 的组合与 Flex 通信。

首先,跟以前一样,Eclipse 先生成一个 JavaScript 调用。

清单 4. Eclipse 为这个 Flex 应用程序调用 JavaScript
	Browser browser = new Browser(parent, SWT.NONE);
	…
	browser.execute(“openDialog();”);

在本例中,这个 JavaScript 函数实际创建了一个 ActionScript 调用,并执行该调用。

清单 5. JavaScript 为这个 Flex 应用程序创建 ActionScript
	var appName="MyFlexApp";
	
	function getFlexApp(appName) {
		if (navigator.appName.indexOf ("Microsoft") !=-1) {
			return window[appName];
		} else {
			return document[appName];
		}
	}
	function openDialog() {
	…
	 getFlexApp(appName).handleOpenDialog();
	…
	}

最后,ActionScript 被 Flex 应用程序接收以便执行。

清单 6. 被 Flex 应用程序接收到的 ActionScript
	…
	if (ExternalInterface.available) {
	 try {
	  ExternalInterface.addCallback("handleOpenDialog", handleOpenDialogInFlex);
	 }
	 catch (error:SecurityError) {} 
	 catch (error:Error) {}
	}
	…
	public function handleOpenDialogInFlex():void {
	 Alert.show(“hello world!”);
	}

为了方便从 Web UI 应用程序到 Eclipse 的通信,我们使用了一个稍微不同的方法,这次我们利用的是浏览器状态栏。基本而言,这个 Web UI 应用程序很有可能通过 JavaScript 更新这个浏览器的状态栏。在 Eclipse 内,有一个状态文本行侦听程序被附加到这个为 Web UI 应用程序创建的浏览器控件。因而,在浏览器的状态栏内的任何变更都将通知到所附加的这个侦听程序。不过,应该牢记的一点是这个浏览器状态栏不只由我们的 Web UI 应用程序使用。因而,在 Eclipse 内的状态栏侦听程序必须过滤出所有不相关的状态栏更新。清单 7 和 8 显示了对于这种通信渠道该如何设置此 Web UI 应用程序和 Eclipse。

在 Eclipse 内,我们打开一个浏览器并建立这个状态文本行侦听程序。请注意我们将这个侦听程序设为查找我们想要这个 Web UI 生成的特定文本。

清单 7. 在 Eclipse 内建立这个侦听程序
	Browser browser = new Browser(parent, SWT.NONE);
	Browser.addStatusTextListener(new StatusTextListener() {
	 public void changed(StatusTextEvent event) {
	  String text = event.text;
	  if ( “fromWebApp:handleButtonPressed()”.equals(text) ) {
	   handleButtonPressed();
	  }  
	 }
	});
	
	public void handleButtonPressed() {…}

在 JavaScript 内,我们定义了一个函数来更改这个浏览器的状态栏,然后我们用一个更新调用该函数。请注意此更新与我们在这个侦听程序内所等待的更新是相匹配的。

清单 8. 更新此浏览器的状态栏的 JavaScript
	function changeStatusLine(status){
	 window.status = status;
	}
	…
	changeStatusLine(“fromWebApp:handleButtonPressed()”);

同样地,如果 Web UI 应用程序在浏览器内的一个容器内运行,那么 HTML 应用程序层可充当 Web UI 应用程序和 Eclipse 间的一个代理。我们再以 Adobe Flex 作为一个例子,这个 Flex 应用程序使用 ExternalInterface 类调用 HTML 容器内的 JavaScript。接下来,该 HTML 容器更新状态栏。(参见清单 9 和 10。)

在 JavaScript 内,我们创建一个函数来更新状态栏。

清单 9. 更新状态栏的 JavaScript 函数
	function changeStatusLine(status){
	 window.status = status;
	}

在 Flex 内,我们创建一个函数来调用我们的外部 JavaScript 函数并执行它,更改状态栏。

清单 10. 更新状态栏的 Flex 应用程序
	public function changeStatusLineTo( text:String ) : void {
	 ExternalInterface.call("changeStatusLine", text);
	}
	…
	changeStatusLineTo(“fromWebApp:handleButtonPressed()”);

图 2 总结了我们在本节内设计的这个 Eclipse 与 Web UI 应用程序之间的通信渠道。

图 2. 通过 JavaScript 设计的 Eclipse 和 Web UI 应用程序间的通信渠道
此图展示了 Eclipse 应用程序如何通过 Browser.execute() 与 Web UI 的 JavaScript 接口通信
此图展示了 Eclipse 应用程序如何通过 Browser.execute() 与 Web UI 的 JavaScript 接口通信

通过 HTTP 进行通信

Web UI 应用程序和 Eclipse 之间进行通信的另一种方式是通过 HTTP 请求。在这种方式中涉及到三方:Web UI 应用程序、Eclipse 工作台和一个 HTTP servlet(运行在 Eclipse 内)。这类似于软件工程中的 Model-View-Controller (MVC) 设计模式。在这种情况下,Eclipse 工作台是 Model、 Web UI 应用程序是 View,而 HTTP servlet 则是 Controller。

每个 Eclipse 安装都嵌入了一个开源的 Jetty 引擎,用以充当一个 HTTP 服务器并运行在 Eclipse 工作台内。Eclipse 平台上的开发人员可轻松注册 servlet 以便处理来自 Eclipse 外部的 HTTP 请求。这个 HTTP servlet 还可通过扩展点 org.eclipse.equinox.http.registry.servletsorg.eclipse.equinox.http.registry.resources 轻松地注册在 Eclipse 内。

为了形成 Web UI 应用程序和 Eclipse 之间的通信渠道,必须创建一个 HTTP servlet。清单 11 和 12 展示了如何使用这些扩展点注册一个 HTTP servlet。完整的说明,请参考相关的扩展点文档。

在文件 plugin.xml 内,我们注册了这些扩展点以供 HTTP 服务器使用。

清单 11. 扩展点的 XML 注册
	<extension point="org.eclipse.equinox.http.registry.resources">
	  <resource alias="/" base-name="/webContent" />
	</extension>
	<extension point="org.eclipse.equinox.http.registry.servlets">
	  <servlet alias="/rob"
	    class="rob.MyHTTPServlet">
	  </servlet>
	  
	</extension>

我们用 Java 语言定义 servlet。

清单 12. 扩展点的 Java 注册
	public MyHTTPServlet extends HTTPServlet {
	 protected void doGet(HttpServletRequest httpServletRequest,  
	  HttpServletResponse httpServletResponse) throws ServletException,   
	  IOException {
	  …
	 }
	
	 protected void doPost(HttpServletRequest httpServletRequest, 
	  HttpServletResponse httpServletResponse) throws ServletException, 
	  IOException {
	  …
	 }
	}

HTTP servlet 被注册后,这个 servlet 将能够处理来自于 Eclipse 外部的所有 HTTP 请求。根据实施应用程序所用技术的不同,生成 HTTP 请求的方法也不同。然而,对于绝大多数可用的 Web UI 技术而言,有一个 API 可被用于生成 HTTP 请求。

大多常用浏览器,包括 Internet Explorer®、Mozilla、Safari 和 Opera,都提供了允许 JavaScript 进行 HTTP 请求的支持。例如,在 Internet Explorer 中,可以使用 ActiveXObject("Microsoft.XMLHTTP") 创建 HTTP 请求对象;在 Mozilla 和 Safari 中,则可以用 XMLHttpRequest。在 Web 上,可以很容易地找到如何用 JavaScript 创建 HTTP 请求的例子。

同样地,如果 Web UI 应用程序是在一个浏览器的容器(如 Flash 播放器)内运行的,那么运行应用程序的这个平台将能代表该应用程序进行 HTTP 请求。例如,在 Adobe Flex 中就有一个帮助程序类,HTTPService,它可以创建请求对象并发送 HTTP 请求。同样地,在 Web 上也可以很容易地找到在 Flex 内使用 HTTPService 的例子。

对比通信渠道

本文所介绍的这两种通信技术在大多数情况下均能对基于 Eclipse 的应用程序奏效。不过,如果想要在 Eclipse 工作台之外的 Web 上独立使用 Web UI 应用程序,那么 JavaScript 方式将不能正常工作。原因是 JavaScript 方式依赖于 Eclipse 浏览器内的状态文本侦听程序框架来将消息告知 Eclipse 组件。当 Web UI 应用程序从 Eclipse 之外的外部浏览器运行时,不管是在同一个计算机还是在不同的计算机上,都不可能将对状态文本的更改的事件传递回至 Eclipse 工作台。而使用 HTTP 请求的方式则让 Web UI 应用程序可以很容易地移植以运行在一个外部的浏览器内。在选择在 Web UI 应用程序内该部署哪个通信通道时,开发人员应该注意这一点。

表 1 总结了这两个通信渠道之间的主要区别。

表 1. 两个通信渠道的对比
JavaScriptHTTP
性能更轻量级HTTP 请求负荷
耦合性只有当特定浏览器控件附加了状态文本侦听程序时才奏效 可工作在内部和外部的浏览器内
软件工程可将应用程序紧密地耦合到 Eclipse 环境Eclipse 和 Web UI 应用程序间耦合较松
遵循 MVC 设计模式

在构建 Web UI 之前应该考虑的其他因素

本文到目前为止给出的信息对于用 Web UI 技术构建一个 Eclipse 组件已经足够。但是,在实际构建这样一个应用程序之前,有几个因素还应该考虑。

可访问性

如果所开发的应用程序中可访问性是个关键问题,那么在实现 Web UI 时,必须十分谨慎。需要考虑的问题有:

  • 用户使用键盘能否调用 Web UI 内的所有动作?
  • 屏幕阅读器能否识别这些 Web UI 组件?
  • 这个 Web UI 是否支持双向(BiDi)文本?
  • 这个 Web UI 是否提供一个高对比度的显示模式?

如果所用技术本身不能提供上述支持,那么可能就需要找到替代方法并将这些替代方式实现到 Web UI 应用程序内。

可用性

效果和动画有可能会让桌面应用程序用户无所适从。因而在为一个 Eclipse 组件设计 Web UI 时,必须考虑目标用户的预期。

字符串国际化

如果 Eclipse 应用程序要求字符串必须被翻译成多种语言,那么就不妨考虑选用一种本身就支持字符串国际化的技术。否则,您就需要自己想办法实现这个特性。

预期的 Eclipse 行为

Eclipse 用户常常对 UI 将如何工作有自己的预期。您必须将这一点考虑进去并避免 Web UI 和 Eclipse UI 之间的任何不一致性。比如,是在 mouse-down 还是在 mouse-up 事件发生时才算完成选择?右键单击鼠标动作的结果是选择一个组件还是显示上下文菜单?还是它只显示上下文菜单,而无需更新选择?

结束语

本文介绍了一种使用 Web UI 技术来为 Eclipse 组件构建 UI 的新范型。很多 Web UI 技术都提供了漂亮的动画和效果,而利用 Eclipse 内的工具达到同样的目的却很不容易。本文提供了利用现有的各种 Web UI 技术所需的全部基本信息。但是,在开始进行实际的实现之前,您还需要考虑您的应用程序的目标和受众,以及其他的一些因素,比如可访问性和可用性。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Open source
ArticleID=478172
ArticleTitle=为 Eclipse 组件实现 Web 用户界面
publish-date=03292010