hechengjin 发表于 2016-4-25 12:07:17

品味kettle--(二)XUL框架内幕

http://blog.csdn.net/renminzdb/article/details/42422083
[-]
[*]21 XUL文件
[*]
[*]XUL的运行


前话
      看了上篇文章,用源码从eclipse启动起来的kettle。相信你已经可以执行成功了,并且看到了软件的登录界面。没有设置什么密码啊,为什么要我输入用户名和密码呢?因为kettle的元数据是可以入库的,如果你选择的是文件的资源库,那么就不用输入密码了,这下你知道为什么了吧。当你看到kettle的操作界面,你是否特别想知道,这是怎么做到的,本文重点讲述下kettle你看到的界面所运用的技术。      

正文
XUL Framework是一个试图为不同UI技术提供统一样式的项目(pentaho-xul)。它的目标是使得多种UI技术(如:Swing、SWT、GWT)能够提交出一个统一的用户接口而不必每次重写描述层。在2010年7月与Shandor XUL分支版本合并。目前可以到https://bitbucket.org/codeoncoffee/shandor-xul/项目下下载到源码。但是找到跟此项目配套的源码,还比较困难。有知道的朋友请告知下。

XUL的常见案例有:普通对话框、可定制的菜单和工具栏、新的工具应用。
   相关jar包:pentaho-xul-core-5.0.1-stable.jar    核心业务类与接口
pentaho-xul-swing-5.0.1-stable.jar   针对swing的具体实现
pentaho-xul-swt-5.0.1-stable.jar   针对swt的具体实现
jface.jar/swt.jar   等             swt等实现的第三方包
   XUL技术,在技术整合的时候,给我们上了很好的一课。善于把问题抽象出来,再具体扩展。从设计模式上来看,这种适配器、外观模式的设计思路,是比较普遍的。后面我们提到Kettle提供的数据库插件,也基本上基于此思路的,后面再详述。下面我们来具体看下core的代码结构。http://dl2.iteye.com/upload/attachment/0099/2404/bebdb105-d506-34cd-9930-29865333b480.jpg
11.2.1 XUL文件
XUL是英文“XML User Interface Language”的首字母缩写。它是为了支持Mozilla系列的应用程序(如Mozilla Firefox和Mozilla Thunderbird)而开发的使用者界面标示语言。顾名思义,它是一种应用XML来描述使用者界面的标示语言。PDI的界面就使用了XUL,节省了开发的时间。以文件kettle平台登录选择资源库的对话框来做示例。 view plain copy
https://code.csdn.net/assets/CODE_ico.pnghttps://code.csdn.net/assets/ico_fork.svg


[*]<?xml version="1.0"?>
[*]<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
[*] <!-- ############################################################################### -->
[*] <!--   REPOSITORY LOGIN DIALOG: Dialog to login to the repository                     -->
[*] <!--############################################################################### -->      
[*]    <dialog id="repository-login-dialog"   
[*]buttonlabelaccept="${Dialog.Ok}" buttonlabelcancel="${Dialog.Cancel}"
[*]      ondialogaccept="repositoryLoginController.login()"
[*]      ondialogcancel="repositoryLoginController.closeRepositoryLoginDialog()"   
[*]      buttons="accept, cancel" buttonalign="right" title="${RepositoryLoginDialog.Title}"   
[*]      height="475" width="400"
[*]      resizable="true"
[*]      appicon="ui/images/spoon.ico"
[*]      xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
[*]      xmlns:pen="http://www.pentaho.org/2008/xul"   
[*]      onload="repositoryLoginController.init()" padding="10" spacing="3">
[*]      <hbox>
[*]            <label value="${RepositoryLoginDialog.RepositoryLabel}"/>
[*]            <label id="spacer-label" flex="1" />
[*]            <button id="repository-edit" image="images/Edit.png"   
[*]pen:disabledimage="images/dEdit.png"   
[*]onclick="repositoryLoginController.editRepository()" disabled="true"/>
[*]            <button id="repository-add" image="images/Add.png"   
[*]pen:disabledimage="images/dAdd.png"   
[*]onclick="repositoryLoginController.newRepository()"/>
[*]            <button id="repository-remove" image="images/Remove.png"   
[*]pen:disabledimage="images/dRemove.png"   
[*]onclick="repositoryLoginController.deleteRepository()" disabled="true"/>
[*]      </hbox>
[*]      <listbox id="available-repository-list"   
[*]pen:binding="description" disabled="false" flex="1"   
[*]command="repositoryLoginController.login()"/>
[*]      <label value="${RepositoryLoginDialog.UserName}" />
[*]      <textbox id="user-name" multiline="false"   
[*]command="repositoryLoginController.login()"/>
[*]      <label value="${RepositoryLoginDialog.Password}"/>
[*]      <textbox id="user-password"   
[*]type="password" multiline="false" command="repositoryLoginController.login()"/>
[*]      <label id="spacer-label"/>
[*]      <checkbox id="show-login-dialog-at-startup"   
[*]command="repositoryLoginController.updateShowDialogAtStartup()"
[*]label="${RepositoryLoginDialog.ShowDialogAtStartup}" checked="false"/>            
[*]</dialog>


资源变量:以${}包裹的参数,都是资源参数。在加载XUL文件时,可以通过传递资源参数         ResourceBundle,在解析的时候,可以把参数传进去。

XUL的运行


(1)指定XulLoader加载XUL文件,解析出一个XulDomContainer
view plain copy
https://code.csdn.net/assets/CODE_ico.pnghttps://code.csdn.net/assets/ico_fork.svg


[*]KettleXulLoader xulLoader = new KettleXulLoader();
[*]      xulLoader.setOuterContext( shell );
[*]      xulLoader.setSettingsManager( XulSpoonSettingsManager.getInstance() );
[*]      container = xulLoader.loadXul( "org/pentaho/di/ui/repository/xul/repositories.xul", resourceBundle );



(2)为XulDomContainer指定一个XulRunner
view plain copy
https://code.csdn.net/assets/CODE_ico.pnghttps://code.csdn.net/assets/ico_fork.svg


[*]final XulRunner runner = new SwtXulRunner();
[*]   runner.addContainer( container );



(3)为XulDomContainer添加Event Handlers
view plain copy
https://code.csdn.net/assets/CODE_ico.pnghttps://code.csdn.net/assets/ico_fork.svg


[*]BindingFactory bf = new DefaultBindingFactory();
[*]    bf.setDocument( container.getDocumentRoot() );
[*]    // repositoriesController是继承AbstractXulEventHandler
[*]    repositoriesController.setBindingFactory( bf );   
[*]    repositoriesController.setPreferredRepositoryName( preferredRepositoryName );
[*]    repositoriesController.setMessages( resourceBundle );
[*]    repositoriesController.setCallback( callback );
[*]    repositoriesController.setShell( getShell() );
[*]    container.addEventHandler( repositoriesController );


注意:
Event Handlers可以用script标签,在xul文件中直接指定。通过代码addEventHandler 添加的事件处理器,在调用的时候,默认是用该事件类的getName() 来指代该事件处理器的。如该例子中repositoriesController的getName() 返回的就是repositoryLoginController。所以在xul文件上的动作是repositoryLoginController.editRepository()。这跟我们的mvc是不是有异曲同工之妙。

view plain copy
https://code.csdn.net/assets/CODE_ico.pnghttps://code.csdn.net/assets/ico_fork.svg


[*]<script id="handler" src="org.my.Handler.java"/>
[*]<script id="handler2" src="anotherHandler.groovy"/>



(4)让XulRunner启动起来
view plain copy
https://code.csdn.net/assets/CODE_ico.pnghttps://code.csdn.net/assets/ico_fork.svg


[*]try {
[*]       runner.initialize();   
[*]   } catch ( XulException e ) {
[*]       SpoonFactory.getInstance().messageBox(
[*]         e.getLocalizedMessage(), "Service Initialization Failed", false, Const.ERROR );
[*]       log.error( resourceBundle.getString( "RepositoryLoginDialog.ErrorStartingXulApplication" ), e );
[*]    }



Initialize()方法是调用xul文件中 <window> 和 <dialog> 标签中定义的onload事件的。如果要显示你的window或者dialog,需要调用 XulRunner的start()方法。


(5)从XulDomContainer获取组件对象
view plain copy
https://code.csdn.net/assets/CODE_ico.pnghttps://code.csdn.net/assets/ico_fork.svg


[*]XulDialog dialog = (XulDialog) container.getDocumentRoot().getElementById( "repository-login-dialog" );
[*]SwtDialog swtDialog = (SwtDialog)dialog.getManagedObject();

参考https://bitbucket.org/codeoncoffee/shandor-xul/wiki/Home
http://wiki.pentaho.com/display/ServerDoc2x/The+Pentaho+XUL+Framework+Developer%27s+Guide


[*]http://dl2.iteye.com/upload/attachment/0099/2404/bebdb105-d506-34cd-9930-29865333b480-thumb.jpg
[*]大小: 162.9 KB

[*]查看图片附件





页: [1]
查看完整版本: 品味kettle--(二)XUL框架内幕