eclipshine

Eclipse主题站

RCP中视图间的交互机制探讨

有时候一个视图(View)希望得到另外一个视图显示的内容,或者选择的内容。在Eclipse中,比较标准的做法是通过ISelectionProviderISelectionListener来完成的。不过因为视图往往是独立的,他们之间并不太方便进行直接的事件监听,而且往往一个视图需要对诸多试图进行选择事件的监听,因此在这种情况下对每一个视图的事件进行注册,比较繁琐,有时候也不可能(比如在需要被监听的试图尚未激活的情况下)。

比较典型的例子就是Eclipse本身所提供的PropertySheetOutline这两个视图,他们都是对其它试图或者Editor中的选择进行监听,并更具选择的内容作相应的处理,显示其Outline或者属性页。

 Eclipse为了解决这个问题,提供了所谓的Site,以及ISelectionService机制,来处理试图之间的简单的交互。简单的说,ViewSite提供了一个交互的中心点,其它ViewViewSite提供选择事件,或者向其注册监听器,而事件的触发与转发则由ViewSite()来完成。

这应该也是一个设计模式,不过我还没想到比较接近的设计模式的名字。如果勉强要使用一个的话,我认为“Mediator”(调停者模式)可能比较适合(欢迎发表见解) 

调停者模式
Blabla...

为了在这个机制中扮演角色,视图通常需要实现两类接口,或者Adapter。首先是作为被监听方的视图,需要实现ISelectionProvider接口。ISelectionProviderJface中引入的接口。

       public interface ISelectionProvider {

           public void addSelectionChangedListener(ISelectionChangedListener listener);

           public ISelection getSelection();

           public void removeSelectionChangedListener(

                   ISelectionChangedListener listener);

           public void setSelection(ISelection selection);

       }

方法都比较简单,不做一一阐述。具体实现时,可能需要进行所谓的hookControl,也就是将View中具体控件的事件,关联到这个View所提供的ISelectionProvider上,简单的一个例子,如果View中控件是一个TableViewer的话,那么可以做如下的操作:

       protected void hookControl(Control control) {

       tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){

              public void selectionChanged(SelectionChangedEvent event) {

                     ISelection selection2 = event.getSelection();

                     setSelection(selection2);

              }

       });

       }

 

然后再setSelection()中对事件进行扩散(propagate

       public void setSelection(ISelection selection) {

              this.selection = selection;

              SelectionChangedEvent event2 = new SelectionChangedEvent(

                            OntIndividualEditor.this, selection);

              for (Iterator i = selectionChangeListeners.iterator(); i.hasNext();) {

                     ISelectionChangedListener object = (ISelectionChangedListener) i

                                   .next();

                     object.selectionChanged(event2);

              }

       }

 

一个ISelectionProvider如果希望被别的View进行监听的话,则应该向其Site()进行注册:

       this.getSite().setSelectionProvider(this);

如果事件比较简单,比如上面的例子,只是对TableViewer的选择进行监听,因为TableViewer本身就是一个ISelectionProvider,因此可以直接这样做:

       this.getSite().setSelectionProvider(tableViewer);

这样View本身就不必实现ISelectionProvider接口了,但是实现的效果同上面的方式实现的是一样的。

 作为事件监听的另一端,则更为简单一些。只需要实现ISelectionListener接口,并注册在Site中:

       site.getPage().addSelectionListener(this);

然后实现public void selectionChanged(IWorkbenchPart part, ISelection selection) {}方法即可。这样,当SelectionProvider中的选择发生改变时,这个视图中的selectionChanged()方法就会被调用。

 注意SelectionProviderSelectionListener并不直接对应。这个地方有一点容易混淆,就是Eclipse实际上提供有两套与Selection相关的事件与接口:

ISelectionChangedListener <--> ISelectionProvider

这个是JFace中的选择监听机制,对试图或者控件而言,它提供对原始的选择事件的通知与响应。ISelectionProvider需要注册在Site上,以供ISelectionSerivce使用,将选择事件扩散到其他的ISelectionListener中。

ISelectionListener <--> ISelectionService

这个是在Site中使用的,ISelectionService不需要自己实现,已经实现好了,ISelectionListener则需要注册到ISelectionService上,以对其它SelectionProvider的事件响应进行监听。

 Eclipse本身的实现中,PropertySheetOutline都使用了这种机制。不过需要注意的是,缺省的PropertyShee需要接受一个IStructuredSelection,而不仅仅是一个ISelection。因此,如果ISeletionProvider需要提供一个能够让PropertySheet进行显示的对象的话,除了除了要实现ISelection接口外,还需要对其进行封装成一个IStructuredSelection。这个比较简单,直接调用StructuredSelection构造函数即可。

posted on 2005-09-19 22:42 Living Not Striving 阅读(4985) 评论(6)  编辑  收藏 所属分类: RCPECLIPSE

评论

# re: RCP中视图间的交互机制探讨 2005-09-19 22:43 eclipshine

得八进制勉励,新发一篇:)  回复  更多评论   

# re: RCP中视图间的交互机制探讨 2005-09-20 16:20 Dart

好文章!一直以来,我都是传递View本身对象来实现事件监听,原来利用SelectionService中转可以实现啊。
谢谢楼主的文章!  回复  更多评论   

# re: RCP中视图间的交互机制探讨 2005-09-20 16:46 eclipshine

传递View本身会有一些问题,需要有特定的视图激活的顺序才行。
不过那样做也有好处,因为事件转发更为特定,因此可以提高系统性能。

而本文中所描述的方法,则当任何视图上的任何选择事件发生时,任何监听者都会得到通知,系统性能会有一定的影响。  回复  更多评论   

# re: RCP中视图间的交互机制探讨 2005-09-20 22:28 gady

呵呵 我也是传view的 看了这篇文章,我忽然发现eclipse中的action是不是也是这样做的 对于右键菜单中的action一般要实现一个checkEnable方法?  回复  更多评论   

# re: RCP中视图间的交互机制探讨 2005-11-08 10:41 witty_wang

selectionChangeListeners是所有监听器列表吗?如何获得这个对象阿?  回复  更多评论   

# re: RCP中视图间的交互机制探讨[未登录] 2008-10-28 21:19 fish

Mediator和Observer模式。  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: