RCP窗体生成过程(1)

来源:互联网 发布:linux 更改文件夹名字 编辑:程序博客网 时间:2024/05/08 02:25

------------------------------------------------
本文系本站原创,欢迎转载!

转载请注明出处:http://sjj0412.cublog.cn/
------------------------------------------

使用swt/jface开发过的人都知道在swt/jface中,窗体要显示必须要有shell,display,Display用于处理窗口事件等操作,相当于和系统窗体机制通信。而shell可以看成是mainwindow,是所有其他的控件的父窗体。

 一个简单的swt/jface程序如下:

 

 package swtjfacesample;

 2

 3import org.eclipse.swt.SWT;

 4import org.eclipse.swt.widgets.Display;

 5import org.eclipse.swt.widgets.Shell;

 6import org.eclipse.swt.widgets.Text;

 7

 8public class HelloSwt {

 9    /**//**

10     * Hello,world!

11     *

12     * @param args

13     */

14       public static void main(String[] args) {

15        Display display = new Display();

16        Shell shell = new Shell(display);

17       

18        Text helloText = new Text(shell, SWT.CENTER);//这个就是shell就可看成是父窗口

19        helloText.setText("Hello,World!");

20        helloText.pack();

21       

22        shell.pack();

23        shell.open();

24

25        while (!shell.isDisposed()) {

26            if (!display.readAndDispatch()) {

27                display.sleep();

28            }

29        }

30        display.dispose();

31

32    }

33}

34


 rcp程序的窗口是如何生成的呢,下面我们就来说说。

首先我们新建一个rcp程序后,新建后,我们可以看到eclipse系统自动生成的代码。

 

Activator先不管,perspective也不管,这些在plugin程序里也有,我们讲讲rcp特有的,从上面我们可以看出生成了三个文件,同时也是三个类。

既然rcp也是使用swt/jface作为界面的,刚才说了swt/jface需要shell,display,rcp也肯定有这个。

先看application.java

public class Application implements IApplication {

    public Object start(IApplicationContext context) throws Exception {

       Display display = PlatformUI.createDisplay();

       try {

           int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());

           if (returnCode == PlatformUI.RETURN_RESTART)

              return IApplication.EXIT_RESTART;

           else

              return IApplication.EXIT_OK;

       } finally {

           display.dispose();

       }

      

    }

 

}

这里的startrcp的开始。估计我们已经注意到display,在最开始就生成,那么现在已经解决一个问题了,只剩下shell了。

由于rcp是一个复杂窗体系统,所以他要以一个比较好的方式组织,一个rcp只有一个workbench,但是可以有多个workbenchwindow,然后布局又是通过perspective来实现,其他的像viewparteditpartperspective里布局,然后这些下去才是各种swt控件。看了系统为我们生成的代码,我们都有可能都注意到都有一个advisor后缀,且这些类根本不是继承上面提到类,这是为什么,其实rcp将上面提到的workbench等分成了两部分,一部分是核心部分,也就是rcpelipse系统设计者写的,这些代码是实现功能,且用户不能修改,如果用户不能定制,没有相关接口那就不好,这时于是就提出一个advisor的概念,即用户可以通过继承这些advisor类来达到添加自己程序的效果,这个就相当于windowhook技术,内核在执行到一定阶段,就会调用制定好的hook,你只要将这些Hook绑定到你的程序,那你的程序就可以在特定阶段执行。

既然workbench是头头,那肯定要创建一个啊,这个就是PlatformUI.createAndRunWorkbench的工作。

public static int createAndRunWorkbench(Display display,

            WorkbenchAdvisor advisor) {

        return Workbench.createAndRunWorkbench(display, advisor);

    }

public static final int createAndRunWorkbench(final Display display,

           final WorkbenchAdvisor advisor) {

       final int[] returnCode = new int[1];

       Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {

           public void run() {

              // create the workbench instance

              Workbench workbench = new Workbench(display, advisor);

              // run the workbench event loop

              returnCode[0] = workbench.runUI();

           }

       });

       return returnCode[0];

    }

到这为此,workbench创建了。下面就要初始化这workbench

private int runUI() {

       UIStats.start(UIStats.START_WORKBENCH, "Workbench");

       boolean avoidDeadlock = true;

 

         Thread initThread = new Thread() {

              /* (non-Javadoc)

               * @see java.lang.Thread#run()

               */

              public void run() {

                  try {

                     //declare us to be a startup thread so that our syncs will be executed

                     UISynchronizer.startupThread.set(Boolean.TRUE);

                     initOK[0] = Workbench.this.init();//这个新增一个线程运行workbench.init函数,这个就和插件机制有关了,初始化完了initok[0]=true,

                  }

                  catch (Throwable e) {

                     error[0] = e;

                  }

                  finally {

                     initDone[0] = true;

                     display.wake();

                  }

              }};

              initThread.start();

              while (true) {

                  if (!display.readAndDispatch()) {

                     if (initDone[0])

                         break;

                     display.sleep();

                  }

              }//等待init完,完了就继续。

              Throwable throwable = error[0];

              if (throwable != null) {

                  if (throwable instanceof Error)

                     throw (Error)throwable;

                  if (throwable instanceof Exception)

                     throw (Exception)throwable;

                 

                  // how very exotic - something that isn't playing by the rules.  Wrap it in an error and bail

                  throw new Error(throwable);

              }

           }

           else {

              // initialize workbench and restore or open one window

              initOK[0] = init();

 

           }

           // drop the splash screen now that a workbench window is up

           Platform.endSplash();

 

           // let the advisor run its start up code

           if (initOK[0]) {

              advisor.postStartup(); // may trigger a close/restart

           }

         //由于我们实现了advisorpoststartup,所以就执行我们的定制的程序了

           if (initOK[0] && runEventLoop) {

              // start eager plug-ins

              startPlugins();//插件相关的

              addStartupRegistryListener();//是和插件系统相关的

 

              // WWinPluginAction.refreshActionList();

 

              display.asyncExec(new Runnable() {

                  public void run() {

                     UIStats.end(UIStats.START_WORKBENCH, this, "Workbench"); //$NON-NLS-1$

                     UIStats.startupComplete();

                  }

              });

 

              getWorkbenchTestable().init(display, this);

               

              // allow ModalContext to spin the event loop

              ModalContext.setAllowReadAndDispatch(true);

              isStarting = false;

 

              if (synchronizer != null)

                  synchronizer.started();

              // the event loop

              runEventLoop(handler, display);//这个和窗体事件处理有关的}

 

       }

……………………………          ………….

       // restart or exit based on returnCode

       return returnCode;

    }

 

private void runEventLoop(Window.IExceptionHandler handler, Display display) {

       runEventLoop = true;

       while (runEventLoop) {

           try {

              if (!display.readAndDispatch()) {

                  getAdvisor().eventLoopIdle(display);

              }

           } catch (Throwable t) {

              handler.handleException(t);

              // In case Display was closed under us

              if (display.isDisposed())

                  runEventLoop = false;

           }

       }

    }//

上面这个就是执行消息处理。

刚才说了workbench的初始化是在workbenchinit函数中,下面就来看下。

private boolean init() {

       // setup debug mode if required.

      

       // create workbench window manager

       windowManager = new WindowManager();

                //workbench是管理workbenchwindow的,windowmanger就是这个结构

       IIntroRegistry introRegistry = WorkbenchPlugin.getDefault()

      

 

       initializeDefaultServices();

       initializeFonts();

       initializeColors();

       initializeApplicationColors();

//这些就是初始化字体,颜色等相关资源

           StartupThreading.runWithoutExceptions(new StartupRunnable() {

 

           public void runWithException() {

               advisor.internalBasicInitialize(getWorkbenchConfigurer());

// getWorkbenchConfigurerworkbench创建了一个configure,并付给其成员

           }

       }

final boolean bail [] = new boolean[1];

           StartupThreading.runWithoutExceptions(new StartupRunnable() {

 

              public void runWithException() throws Throwable {

                  advisor.preStartup();

                 

                  if (!advisor.openWindows()) {

                     bail[0] = true;

                  }

              }});

 

);

 

public final void internalBasicInitialize(IWorkbenchConfigurer configurer) {

       if (workbenchConfigurer != null) {

           throw new IllegalStateException();

       }

       this.workbenchConfigurer = configurer;

       initialize(configurer);//我们可以重载这个函数,加自己的

    }

这个函数给workbenchadvisorconfigure变量。

 

然后是openwindows函数,这个函数非常重要。

workbenchadvisor

public boolean openWindows() {

 

 

       final Display display = PlatformUI.getWorkbench().getDisplay();

       final boolean result [] = new boolean[1];

       public void runWithException() throws Throwable {

                         myConfigurer[0] = getWorkbenchConfigurer();

                         //这个是internalBasicInitialize赋值的

                     }});

                  if (!status.isOK()) {

                     if (status.getCode() == IWorkbenchConfigurer.RESTORE_CODE_EXIT) {

                         result[0] = false;

                         return;

                     }

                     if (status.getCode() == IWorkbenchConfigurer.RESTORE_CODE_RESET) {

                         myConfigurer[0].openFirstTimeWindow();//这个将会生成workbenchwindow东西

                     }

                  }

                  result[0] = true;

          

    }

 

public void openFirstTimeWindow() {

        ((Workbench) getWorkbench()).openFirstTimeWindow();

    }

其实就是调用workbenchopenfirsttimewindow

 

void openFirstTimeWindow() {

   

 

     

           runStartupWithProgress(expectedProgressCount, new Runnable() {

              public void run() {

                  doOpenFirstTimeWindow();

              }

           });

       }

    }

 

private void doOpenFirstTimeWindow() {

       try {

           final IAdaptable input [] = new IAdaptable[1];

           StartupThreading.runWithoutExceptions(new StartupRunnable() {

 

              public void runWithException() throws Throwable {

                  input[0] = getDefaultPageInput();

              }});

          

           busyOpenWorkbenchWindow(getPerspectiveRegistry()

                  .getDefaultPerspective(), input[0]);

       } catch (final WorkbenchException e) {

           // Don't use the window's shell as the dialog parent,

 

           // as the window is not open yet (bug 76724).

       }

    }

busyOpenWorkbenchWindow才是真正开始创建workbenchwindow

 

private IWorkbenchWindow busyOpenWorkbenchWindow (final String perspID,

           final IAdaptable input) throws WorkbenchException {

       // Create a workbench window (becomes active window)

       final WorkbenchWindow newWindowArray[] = new WorkbenchWindow[1];

       StartupThreading.runWithWorkbenchExceptions(new StartupRunnable() {

           public void runWithException() {

              newWindowArray[0] = newWorkbenchWindow();

           }

       });

 

       final WorkbenchWindow newWindow = newWindowArray[0];

      

       StartupThreading.runWithoutExceptions(new StartupRunnable() {

 

           public void runWithException() {

               newWindow.create(); // 这个创建shell即顶级窗口

           }

       });

       windowManager.add(newWindow);

 

   

       StartupThreading.runWithWorkbenchExceptions(new StartupRunnable() {

 

           public void runWithException() {

               newWindow.open();

           }

       });

 

       return newWindow;

    }

   上面的new Workbenchwindow(),newwindow.create,newwindow.open()是至关重要的,这一节到此,下一节讲分别对这三个进行解释

原创粉丝点击