我的实验环境如下:WindowsXP SP2,Eclipse 3.3+VE+GEF+EMF+GMF+UML2。在没有特殊声明的情况下,全部的代码都将在这个环境中实现。
1.1. 缺省启动Logo与进度条
通常情况下,当你用Eclipse的RCP向导生成一个应用程序时,PDE总是会在你的工程根目录下为你生成一个名为splash.bmp的图片作为启动Logo,其大小为500*330像素且名字是不可变的。在生成product配置文件之后,我们可以看到:
<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 453pt; HEIGHT: 150pt" type="#_x0000_t75"><imagedata src="file:///C:%5CDOCUME~1%5Czl%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png" o:title=""></imagedata></shape>
如果我们想要把splash.bmp放到本产品(product)中的其他插件的根目录下,就需要在Plug-in中进行指定。如果想要集成一个类似于Eclipse平台启动时显示的那个进度条的话,只需向上面那样简单定制进度条的位置、消息以及文本颜色即可。要显示的消息数据就是定义在org.eclipse.core.runtime.products扩展里面的属性。
但是我们发现即便是按照上面的方法定制了之后,程序之启动时还是不显示进度条的,要显示进度条我们需要做一些额外的工作,完整地定制过程如下:
1. 在 .product文件的“Splash”页签中点选“Add Progress Bar”,并指定进度条尺寸
2. 在.product文件同一目录里创建myconfig.ini文件,文件中要包含以下内容:org.eclipse.ui/SHOW_PROGRESS_ON_STARTUP=true
3. 在plugin.xml里的org.eclipse.core.runtime.products扩展点下的对应product下添加属性preferenceCustomization,值为myconfig.ini;这个扩展点一般是在编辑.product文件后导出RCP时自动生成的。
4. 在“Open Run Dialog->Main”页签中点选“clear workspace data before launching”,以-clean方式启动你的RCP程序。
完成以上步骤之后,我们就可以在导出的应用程序启动时看到那可爱的进度条了。但是,从上述步骤我们也可以看到,这个缺省的进度条是很简陋的,除了固定的文字及其位置和尺寸之外我们没办法对它进行其它配置。如果我们想让它在不同的进度显示不同的文字,想控制进度条的最大值/最小值,抑或想让它支持多语言,缺省的进度条就无能为力了。
注意:在Eclipse3.3RC2之后,我们可以通过在WorkbenchAdvisor的initialize()方法中写入如下语句:
PlatformUI.getPreferenceStore().setDefault(IWorkbenchPreferenceConstants.SHOW_PROGRESS_ON_STARTUP, true); 就可以显示缺省的进度条和文字信息而无需配置.ini文件。
当然,如果想让我们的Splash产生点与众不同的区别的话,我们可以点击Extension页面中的“Add”按钮,Eclipse向导给我们提供了3个比较复杂的Splash Screen的实现,分别是:交互式登陆框、内嵌式Web浏览器以及动态显示图标。通过研究其源码,我们就可以很轻松地定制自己的Splash Screen了。不过值得注意的是由于Eclipse Workbench本身具有多线程特性,所以在我们自己实现的Splash Screen中一定要注意有关线程同步方面的问题,否则就会出现一些莫名其妙的错误。
1.2. Nightlabs的Splash插件
所以要想实现丰富的功能还是要靠我们自己来实现。不过网上JFire工程下有个插件(我们权且称之为NightlabsSplash插件)实现了比较完整的Splash相关功能。它是作为一个独立的RCP应用程序插件来构建的,可以显示和Eclipse类似的启动画面。缺省情况下,它将显示workbench已经载入的插件名称。
1.2.1. 启动过程概览
在其他插件被载入之前,它将显示一个Swing JFrame,里面包含了一个可配置的图片及图片下面的一个用于显示信息的MessageBar,其缺省的动作是现实所有载入的插件名称。所以要想显示这个Splash,我们就必须保证这个插件在应用程序启动过程中被尽可能早的载入进来。为了达到这一目标,我们需要让自己的插件(不妨称之为MySplashTestApp插件,它可以是一个PDE向导按照HelloWorld模版生成出来的一个最简单的RCP应用程序)中的WorkbenchWindowAdvisor(不妨命名为ApplicationWorkbenchWindowAdvisor,简称AWWA类)类继承SplashHandlingWorkbenchWindowAdvisor(简称为SHWWA)即可。在Workbench启动之后,该插件还会自动关闭先前生成的JFrame,实在是很人性化。成功运行后的结果如下图所示:
<shape id="_x0000_i1026" style="WIDTH: 221.25pt; HEIGHT: 123pt" type="#_x0000_t75"><imagedata src="file:///C:%5CDOCUME~1%5Czl%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image003.png" o:title=""></imagedata></shape>
那么,NightlabsSplash插件是如何保证自己会先于其他插件和Workbench被加载进来呢?原因在于,在我们的Appliction类(实现IApplication接口的类)的start方法中,一般情况下我们代码都与下图所示代码很类似:
<shape id="_x0000_i1027" style="WIDTH: 435pt; HEIGHT: 151.5pt" type="#_x0000_t75" o:bordertopcolor="this" o:borderleftcolor="this" o:borderbottomcolor="this" o:borderrightcolor="this"><font size="3"><imagedata src="file:///C:%5CDOCUME~1%5Czl%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image005.png" o:title=""></imagedata><bordertop type="single" width="4"></bordertop><borderleft type="single" width="4"></borderleft><borderbottom type="single" width="4"></borderbottom><borderright type="single" width="4"></borderright></font></shape>
注意到第21行我们首先要生成一个ApplicationWorkbenchAdvisor,而该类的createWorkbenchWindowAdvisor方法要返回一个AWWA类的实例,而AWWA类又继承自SHWWA,由于类装载器是按照继承顺序自顶向下地进行加载动作的,所以NightlabsSplash插件就在此时被加载进来。同样在这个时刻,其他插件和Workbench都尚未被加载进来,这就保证了NightlabsSplash插件的首先加载。
1.2.2. 使用方法
1. 消息的显示方式
通过如下的方式,我们可以显示自定义的消息:
<shape id="_x0000_i1028" style="WIDTH: 399pt; HEIGHT: 27.75pt" type="#_x0000_t75"><imagedata src="file:///C:%5CDOCUME~1%5Czl%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image007.png" o:title=""><font size="3"></font></imagedata></shape>
2. 可定制属性
而在插件根目录下,可以找到一个名为splashscreen.properties文件,利用这个文件我们可以进行更为细致的配置。具体内容如下:
l splashscreen.location:指向你所要显示的图像文件的相对路径。从版本<chsdate w:st="on" year="1899" month="12" day="30" islunardate="False" isrocdate="False"><span lang="EN-US"><font face="Times New Roman">1.0.2</font></span></chsdate>开始,该插件支持{$nl}通配符作为属性值。通过查看源码我们知道,SplashScreen类的run()方法将在运行期用当前的locale(如en_US,de_DE)来替换这个通配符,并用以作为splash的路径。如果以当前的locale找不到任何文件的话,插件将会试图使用“default” 替换{$nl}的方式进行查找。所以你的应用程序应该提供一个可靠的图象文件作为缺省之用。
l splashscreen.title:该属性所表示的字符串用于设置frame的标题,将被显示在taskbar中。
l splashscreen.messagebar.height:定义了信息条的高度(以像素记)。
l splashscreen.messages.showloadedplugins:这个布尔值定义了是否每当一个插件被载入时都要显示一个消息。
3. 进度条值域的设置
SplashScreen提供了下面的静态函数来控制进度条的最大/最小值:
<shape id="_x0000_i1029" style="WIDTH: 319.5pt; HEIGHT: 56.25pt" type="#_x0000_t75" o:bordertopcolor="this" o:borderleftcolor="this" o:borderbottomcolor="this" o:borderrightcolor="this"><font size="3"><imagedata src="file:///C:%5CDOCUME~1%5Czl%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image009.png" o:title="" cropright="20667f"></imagedata><bordertop type="single" width="4"></bordertop><borderleft type="single" width="4"></borderleft><borderbottom type="single" width="4"></borderbottom><borderright type="single" width="4"></borderright></font></shape>
4. 自定义显示面板
为了让显示的内容更丰富,该插键允许我们提供一个位于进度条之上的自定义JPanel。如此一来,实现下面的功能也就易如反掌了:
<shape id="_x0000_i1030" style="WIDTH: 300pt; HEIGHT: 189pt" type="#_x0000_t75"><imagedata src="file:///C:%5CDOCUME~1%5Czl%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image011.png" o:title=""><font size="3"></font></imagedata></shape>
我们所需要做的只是简单的调用SplashScreen提供的静态功能方法,如下所示:
<shape id="_x0000_i1031" style="WIDTH: 303.75pt; HEIGHT: 63.75pt" type="#_x0000_t75" o:bordertopcolor="this" o:borderleftcolor="this" o:borderbottomcolor="this" o:borderrightcolor="this"><font size="3"><imagedata src="file:///C:%5CDOCUME~1%5Czl%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image013.png" o:title="" cropright="22876f"></imagedata><bordertop type="single" width="4"></bordertop><borderleft type="single" width="4"></borderleft><borderbottom type="single" width="4"></borderbottom><borderright type="single" width="4"></borderright></font></shape>
5. 显示信息的截断(word cut)策略
由于采用了自定义的JProgressPanel,该插件可以将显示信息按照左、右和居中的方式将显示信息进行对齐,同时还提供了信息截断的能力。即当显示的信息不满足进度面板的预设值的时候,多余的信息将被截断:
l right (缺省):消息将会在面板的结尾处被阶段,所以信息的开始部分总是可见的。
l left:消息将会在开始处截断,所以只有结尾部分是可见的。
l center:消息将会在中间截断,所以只有两头的信息是可见的。
l slide:信息截断的位置将会随着时间的推移而自左向右移动。
注意:由于在构建RCP工程时PDE缺省为我们在工程根目录下产生了一个名为splash.bmp的图片,在使用nightlabs提供的Splash插件时一定要将它删除,否则会影响插件的运行。
小结:虽然这个插件没有采用SWT/JFace,让人感到有些遗憾,因为这使得在添减自定义面板中添加的组件的观感(Look And Feel)和Swing是一致的,这与RCP应用程序的本地观感不太搭调L;但这样做的优势是可以支持更多格式的图片,此外在核心类SplashScreen中还提供了Debug的功能,所以整体来说瑕不掩瑜。如果您不想费时自己动手写Splash的话,这个插件也算是个不错的选择J。