RCP窗体生成过程(1)

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

转载请注明出处: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();

       }

      

    }

 

}

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

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

           }

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

           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 的初始化是在 workbench init 函数中,下面就来看下。

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());

// getWorkbenchConfigurer workbench 创建了一个 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);// 我们可以重载这个函数,加自己的

    }

这个函数给 workbenchadvisor configure 变量。

 

然后是 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();

    }

其实就是调用 workbench openfirsttimewindow

 

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()是至关重要的,这一节到此,下一节讲分别对这三个进行解释

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xcl119xxcl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值