RCP程序UI设计——之首页篇

来源:互联网 发布:淘宝客服和美工哪个好 编辑:程序博客网 时间:2024/05/17 05:08

在我们第一次启动eclipse时,首先呈现在我们眼前的是一个漂亮的欢迎界面,界面中提供了各种功能的快速入口,如帮助,示例程序和进入工作台等等操作,使用起来非常的直观和方便。

 

其实在我们开发的RCP程序中,一样也可以实现这样的效果,我们可以通过扩展"org.eclipse.ui.intro"这个扩展点来实现,下图是我在一个项目中所实现的界面。

RCP程序UI设计——之首页篇(一) - 严军 - 严军的博客

 

下面就谈谈它的实现的过程。

实际上,在这个欢迎界面中也是使用的html脚本,而且也有css样式表,是通过org.eclipse.ui.intro. IintroPart来呈现出来的。也就是说,要实现这样的界面,第一步就是要先考虑如何解析并显示页面的内容,其次再来设计欢迎页面,更细节的就不再说了,一切以代码来说话。

下面是整个功能的实现过程:

1,  环境配置,本例使用了Eclipse3.3.1 + WTP插件来构建。

2,  先创建一个插件项目,项目名为intro.example,注意不是rcp项目。在plugin.xml页面中的Dependencies页面中的Required Plug-ins项目中加入“org.eclipse.ui.intro”,然后保存。

3,  再创建一个RCP项目,项目名为intro.example.rcp。在plugin.xml页面中的Dependencies页面中的Required Plug-ins项目中加入“intro.example”,然后保存。

4,  在项目intro.example中新建文件夹content,再在content下建子文件夹images,在images中放入处理好的图片,然后新建以下文件:

==========================================================

root.xhtml

==========================================================

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

<title>Welcome</title>

<link href="style.css" rel="stylesheet" type="text/css" />

<script type="text/javascript">

<!--

function MM_preloadImages() { //v3.0

  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();

    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)

    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}

}

 

function MM_swapImgRestore() { //v3.0

  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;

}

 

function MM_findObj(n, d) { //v4.01

  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {

    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}

  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];

  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);

  if(!x && d.getElementById) x=d.getElementById(n); return x;

}

 

function MM_swapImage() { //v3.0

  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)

   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}

}

//-->

</script>

</head>

<body class="index" onload="MM_preloadImages('images/index_over_01.gif','images/index_over_07.gif','images/index_over_09.gif','images/index_over_14.gif','images/index_over_15.gif','images/index_over_19.gif','images/index_over_20.gif','images/index_over_22.gif','images/index_over_23.gif','images/index_over_26.gif','images/index_over_27.gif','images/index_over_28.gif','images/index_over_29.gif','images/index_over_30.gif')">

  <div id="content">

       <!-- This is where we use the Intro dynamicContent element. The class is loaded from the specified plugin. -->

       <contentProvider id="contentProviderId" class="intro.example.IntroFeatureDynamicContent" pluginId="intro.example">

       </contentProvider>

  </div>

</body>

</html>

 

==========================================================

style.css

==========================================================

html{

    overflow:auto;

}

body.index {

    background-color: #FFFFFF;

    background-image: url(welcomebg.jpg);

    background-repeat: no-repeat;

    margin: 0px;

    padding: 0px;

    background-position: left top; 

}

body.right {

    background-color: #C8E8E8;

}

#content {

    position:absolute;

    left:226px;

    top:127px;

    width: 720px;

}

.right div {

    font-family: "宋体";

    font-size: 12px;

    font-weight: bold;

    color: #999999;

}

a:link {

    color: #017781;

    text-decoration: none;

}

a:visited {

    color: #017781;

    text-decoration: none;

}

a:hover {

    color: #FF6600;

    text-decoration: underline;

}

a:active {

    color: #017781;

    text-decoration: none;

}

再增加一个welcomebg.jpg文件作为背景。

5,  在项目intro.example中新建文件夹schema,新建featureLauncher.exsd扩展点描述文件,文件内容如下:

<?xml version='1.0' encoding='UTF-8'?>

<!-- Schema file written by PDE -->

<schema targetNamespace="com.hailite.ui.intro">

<annotation>

      <appInfo>

         <meta.schema plugin="com.hailite.ui.intro" id="featureLauncher" name="featureLauncher"/>

      </appInfo>

      <documentation>

         [Enter description of this extension point.]

      </documentation>

   </annotation>

 

   <element name="extension">

      <complexType>

         <sequence>

            <element ref="introLauncher"/>

         </sequence>

         <attribute name="point" type="string" use="required">

            <annotation>

               <documentation>

                 

               </documentation>

            </annotation>

         </attribute>

         <attribute name="id" type="string">

            <annotation>

               <documentation>

                 

               </documentation>

            </annotation>

         </attribute>

         <attribute name="name" type="string">

            <annotation>

               <documentation>

                 

               </documentation>

               <appInfo>

                  <meta.attribute translatable="true"/>

               </appInfo>

            </annotation>

         </attribute>

      </complexType>

   </element>

 

   <element name="introLauncher">

      <annotation>

         <appInfo>

            <meta.element labelAttribute="title" icon="image"/>

         </appInfo>

      </annotation>

      <complexType>

         <attribute name="title" type="string">

            <annotation>

               <documentation>

                 

               </documentation>

            </annotation>

         </attribute>

         <attribute name="perspectiveId" type="string">

            <annotation>

               <documentation>

                 

               </documentation>

            </annotation>

         </attribute>

         <attribute name="image" type="string">

            <annotation>

               <documentation>

                 

               </documentation>

               <appInfo>

                  <meta.attribute kind="resource"/>

               </appInfo>

            </annotation>

         </attribute>

         <attribute name="disableImage" type="string">

            <annotation>

               <documentation>

                 

               </documentation>

               <appInfo>

                  <meta.attribute kind="resource"/>

               </appInfo>

            </annotation>

         </attribute>

         <attribute name="overImage" type="string">

            <annotation>

               <documentation>

                 

               </documentation>

               <appInfo>

                  <meta.attribute kind="resource"/>

               </appInfo>

            </annotation>

         </attribute>

         <attribute name="rule" type="string">

            <annotation>

               <documentation>

                 

               </documentation>

            </annotation>

         </attribute>

         <attribute name="shellActionId" type="string">

            <annotation>

               <documentation>

                 

               </documentation>

            </annotation>

         </attribute>

      </complexType>

   </element>

 

   <annotation>

      <appInfo>

         <meta.section type="since"/>

      </appInfo>

      <documentation>

         [Enter the first release in which this extension point appears.]

      </documentation>

   </annotation>

 

   <annotation>

      <appInfo>

         <meta.section type="examples"/>

      </appInfo>

      <documentation>

         [Enter extension point usage example here.]

      </documentation>

   </annotation>

 

   <annotation>

      <appInfo>

         <meta.section type="apiInfo"/>

      </appInfo>

      <documentation>

         [Enter API information here.]

      </documentation>

   </annotation>

 

   <annotation>

      <appInfo>

         <meta.section type="implementation"/>

      </appInfo>

      <documentation>

         [Enter information about supplied implementation of this extension point.]

      </documentation>

   </annotation>

 

   <annotation>

      <appInfo>

         <meta.section type="copyright"/>

      </appInfo>

      <documentation>

        

      </documentation>

   </annotation>

 

</schema>

 

6,  在项目intro.example根目录下创建文件introContent.xml,内容如下:

<?xml version="1.0" encoding="utf-8" ?>

<introContent>

    <page id="root" content="content/root.xhtml"/>

</introContent>

7,  在项目intro.example中增加两个类,如下:

==========================================================

IntroFeatureDynamicContent.java

==========================================================

 

package intro.example;

 

import java.io.IOException;

import java.io.PrintWriter;

import java.net.URL;

 

import org.eclipse.core.runtime.FileLocator;

import org.eclipse.core.runtime.IConfigurationElement;

import org.eclipse.core.runtime.Platform;

import org.eclipse.jface.resource.ImageDescriptor;

import org.eclipse.swt.widgets.Composite;

import org.eclipse.ui.forms.widgets.FormToolkit;

import org.eclipse.ui.intro.config.IIntroContentProviderSite;

import org.eclipse.ui.intro.config.IIntroXHTMLContentProvider;

import org.eclipse.ui.plugin.AbstractUIPlugin;

import org.osgi.framework.Bundle;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

 

 

/**

 * 创建欢迎页面的内容

 * @author 严军

 * @create 2008-5-4 下午05:26:51

 * @version v1.0

 */

public class IntroFeatureDynamicContent implements IIntroXHTMLContentProvider {

 

    public static final String EXT_INTRO_LAUNCHER = "featureLauncher";

 

    public void init(IIntroContentProviderSite site) {

    }

 

    public void createContent(String id, PrintWriter out) {

    }

 

    public void createContent(String id, Composite parent, FormToolkit toolkit) {

    }

 

    @SuppressWarnings("deprecation")

    public void createContent(String id, Element parent) {

       // 定义文档对象

       Document dom = parent.getOwnerDocument();

       // 得到所有扩展点的节点元素

       IConfigurationElement[] providerElements = Platform

              .getExtensionRegistry().getConfigurationElementsFor(

                     Activator.PLUGIN_ID, EXT_INTRO_LAUNCHER);

       int imageIndex = 0;

       for (IConfigurationElement providerElement : providerElements) {

           imageIndex++;

 

           // String title = providerElement.getAttribute("title");

           // System.out.println("系统标题:" + title);

           String rule = providerElement.getAttribute("rule");

           String perspectiveId = providerElement

                  .getAttribute("perspectiveId");

           // System.out.println("透视图ID:" + perspectiveId);

           String shellActionId = providerElement

                  .getAttribute("shellActionId");

           // System.out.println("外部程序:" + shellActionId);

           String imageFilename = providerElement.getAttribute("image");

           // System.out.println("图片:" + imageFilename);

 

           String imageDisableFilename = providerElement

                  .getAttribute("disableImage");

           // System.out.println("Disable图片:" + imageDisableFilename);

 

           String imageOverFilename = providerElement

                  .getAttribute("overImage");

           // System.out.println("Over图片:" + imageOverFilename);

 

           // 创建图片

           ImageDescriptor image = AbstractUIPlugin.imageDescriptorFromPlugin(

                  providerElement.getDeclaringExtension()

                         .getNamespaceIdentifier(), imageFilename);

           ImageDescriptor imageDisable = AbstractUIPlugin

                  .imageDescriptorFromPlugin(providerElement

                         .getDeclaringExtension().getNamespaceIdentifier(),

                         imageFilename);

 

           // 得到当前元素的目录

           Bundle bundle = Platform.getBundle(providerElement

                  .getDeclaringExtension().getNamespaceIdentifier());

 

           URL imageUrl = null;

           URL imageDisableUrl = null;

           URL imageOverUrl = null;

 

           if (imageFilename != null)

              imageUrl = bundle.getEntry(imageFilename);

           if (imageDisableFilename != null)

              imageDisableUrl = bundle.getEntry(imageDisableFilename);

           if (imageOverFilename != null)

              imageOverUrl = bundle.getEntry(imageOverFilename);

 

           try {

              if (imageUrl != null) {

                  // 得到图片

                  imageUrl = FileLocator.resolve(imageUrl);

                  // System.out.println("图片URL:" + imageUrl.toString());

              }

              if (imageDisableUrl != null) {

                  // 得到图片

                  imageDisableUrl = FileLocator.resolve(imageDisableUrl);

                  // System.out.println("Disable图片URL:"

                  // + imageDisableUrl.toString());

              }

              if (imageOverUrl != null) {

                  // 得到图片

                  imageOverUrl = FileLocator.resolve(imageOverUrl);

                  // System.out.println("Over图片URL:" +

                  // imageOverUrl.toString());

              }

           } catch (IOException e) {}

 

           // 创建xhtml元素,这里是创建一个超链接

           Element para = dom.createElement("span");

           para.setAttribute("id", providerElement.getDeclaringExtension()

                  .getNamespaceIdentifier()

                  + "ContentId");

 

           Element hrefPerspective = dom.createElement("a");

 

           // 消除单击时出现的虚线框

           hrefPerspective.setAttribute("onfocus", "this.blur();");

           // Element hrefShell = dom.createElement("a");

 

           String hrefParam = "";

 

           if (perspectiveId == "" || perspectiveId == null)

              hrefParam = "launchShell?id=" + shellActionId;

           else

              hrefParam = "launchPerspective?id=" + perspectiveId;

           // 打开透视图的ID

           hrefPerspective.setAttribute("href", "http://org.eclipse.ui.intro/"

                  + hrefParam);

 

           // 创建图片

           Element img = dom.createElement("img");

           String imageId = "Image" + imageIndex;

           img.setAttribute("id", imageId);

           img

                  .setAttribute("src", imageUrl == null ? "" : imageUrl

                         .toString());

           img.setAttribute("width", String

                  .valueOf(image.getImageData().width));

           img.setAttribute("height", String

                  .valueOf(image.getImageData().height));

           img.setAttribute("style", "border: 0px;");

           img.setAttribute("onmouseover", "MM_swapImage('" + imageId

                  + "','','" + imageOverUrl + "',1)");

           img.setAttribute("onmouseout", "MM_swapImgRestore()");

 

           Element disable = dom.createElement("img");

           disable.setAttribute("src", imageDisableUrl == null ? ""

                  : imageDisableUrl.toString());

           disable.setAttribute("width", String.valueOf(imageDisable

                  .getImageData().width));

           disable.setAttribute("height", String.valueOf(imageDisable

                  .getImageData().height));

           disable.setAttribute("style", "border: 0px;");

 

           hrefPerspective.appendChild(img);

           // 添加文本节点

           // href.appendChild(dom.createTextNode(" "+title));

 

           if (((perspectiveId == null) || ("".equals(perspectiveId)))

                  && ((shellActionId == null) || ("".equals(shellActionId)))) {

              para.appendChild(disable);

 

           } else {

              if (rule != null) {

                  para.appendChild(disable);

              } else {

                  para.appendChild(hrefPerspective);

              }

           }

           parent.appendChild(para);

 

       }

    }

 

    public void dispose() {

 

    }

 

}

==========================================================

LaunchPerspectiveAction.java

==========================================================

package intro.example;

 

import java.util.Properties;

 

import org.eclipse.jface.action.Action;

import org.eclipse.ui.IWorkbenchPage;

import org.eclipse.ui.PlatformUI;

import org.eclipse.ui.intro.IIntroSite;

import org.eclipse.ui.intro.config.IIntroAction;

import org.eclipse.ui.part.IntroPart;

 

/**

 * 执行这个Action可以打开指定的透视图

 * @author 严军

 * @create 2008-5-4 下午05:28:14

 * @version v1.0

 */

public class LaunchPerspectiveAction extends Action implements IIntroAction {

 

    public void run(IIntroSite site, Properties params) {

       String perspectiveId = params.getProperty("id");

       if (perspectiveId == null)

           return;

 

       try {

           IWorkbenchPage page = PlatformUI.getWorkbench()

                  .getActiveWorkbenchWindow().getActivePage();

           page.closeAllEditors(false);

           page.closeAllPerspectives(false, false);

           PlatformUI.getWorkbench().showPerspective(perspectiveId,

                  PlatformUI.getWorkbench().getActiveWorkbenchWindow());

           IntroPart part = (IntroPart) PlatformUI.getWorkbench()

                  .getIntroManager().getIntro();

           if (part != null)

              PlatformUI.getWorkbench().getIntroManager().closeIntro(part);

 

       } catch (Exception e) {

           // 忽略错误

       }

    }

}

 

 

 

8,  整个项目结构如下图:

9,  在项目intro.exampleExtensions页面中增加扩展点三个扩展点,分别是"org.eclipse.ui.intro""org.eclipse.ui.intro.config""org.eclipse.ui.intro.configExtension"。整个plugin.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<?eclipse version="3.2"?>

<plugin>

   <extension-point id="featureLauncher" name="featureLauncher" schema="schema/featureLauncher.exsd"/>

   <extension

         point="org.eclipse.ui.intro">

      <intro

            class="org.eclipse.ui.intro.config.CustomizableIntroPart"

            icon="icons/welcome16.gif"

            id="intro.example.intro"

            label="欢迎">

      </intro>

   </extension>

   <extension

         point="org.eclipse.ui.intro.config">

      <config

            content="introContent.xml"

            id="intro.example.config"

            introId="intro.example.config">

         <presentation

               home-page-id="root">

            <implementation

                  kind="html"

                  os="win32,linux,macosx"

                  style="content/style.css">

            </implementation>

         </presentation>

      </config>

   </extension>

   <extension

         point="org.eclipse.ui.intro.configExtension">

      <action

            name="launchPerspective"

            replaces="runAction?pluginId=intro.example&amp;class=intro.example.LaunchPerspectiveAction">

      </action>

   </extension>

 

</plugin>

 

10,  重写项目intro.example.rcp中的ApplicationWorkbenchWindowAdvisor类的openIntro方法,目的是每次启动程序之后都能够打开欢迎界面,内容如下:

@Override

    public void openIntro() {

       IWorkbenchConfigurer wbConfig = getWindowConfigurer()

              .getWorkbenchConfigurer();

       final String key = "introOpened"; //$NON-NLS-1$

       Boolean introOpened = (Boolean) wbConfig.getData(key);

       if (introOpened != null && introOpened.booleanValue()) {

           return;

       }

 

       wbConfig.setData(key, Boolean.TRUE);

 

       boolean showIntro = PrefUtil.getAPIPreferenceStore().getBoolean(

              IWorkbenchPreferenceConstants.SHOW_INTRO);

 

       if (!showIntro) {

           return;

       }

 

       if (wbConfig.getWorkbench().getIntroManager().hasIntro()) {

           wbConfig.getWorkbench().getIntroManager().showIntro(

                  getWindowConfigurer().getWindow(), false);

           // 设置下次启动程序时时否打开欢迎页面

           PrefUtil.getAPIPreferenceStore().setValue(

                  IWorkbenchPreferenceConstants.SHOW_INTRO, true);

           PrefUtil.saveAPIPrefs();

       }

}

打开项目intro.example.rcp中的plugin.xml文件,Extensions页面中增加扩展点"intro.example.featureLauncher">然后再在introLauncher属性中输入相应的值。最后把intro.exampleintro.example.rcp这两个项目进行绑定,再增加扩展点"org.eclipse.ui.intro",加入introProductBinding这个属性,如下图所示:

整个plugin.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<?eclipse version="3.2"?>

<plugin>

 

   <extension

         id="application"

         point="org.eclipse.core.runtime.applications">

      <application>

         <run

               class="intro.example.rcp.Application">

         </run>

      </application>

   </extension>

   <extension

         point="org.eclipse.ui.perspectives">

      <perspective

            name="RCP Perspective"

            class="intro.example.rcp.Perspective"

            id="intro.example.rcp.perspective">

      </perspective>

   </extension>

   <extension

         id="product"

         point="org.eclipse.core.runtime.products">

      <product

            application="intro.example.rcp.application"

            name="Hello RCP">

         <property

               name="windowImages"

               value="icons/alt_window_16.gif,icons/alt_window_32.gif">

         </property>

         <property

               name="appName"

               value="Hello RCP">

         </property>

      </product>

   </extension>

   <extension

         point="intro.example.featureLauncher">

      <introLauncher

            disableImage="icons/images/index_disable_01.gif"

            image="icons/images/index_01.gif"

            overImage="icons/images/index_over_01.gif"

            perspectiveId="intro.example.rcp.perspective"

            title="任务1"></introLauncher>

   </extension>

   <extension

         point="org.eclipse.ui.intro">

      <introProductBinding

            introId="intro.example.intro"

            productId="intro.example.rcp.product">

      </introProductBinding>

   </extension>

 

</plugin>

 

        

11,  运行项目intro.example.rcp,效果如下图:

原创粉丝点击