Eclipse工作台:使用选取服务

Eclipse工作台:使用选取服务
摘要
Eclipse工作台提供的选取服务允许工作台窗口的各个部分有效整合。了解使用已有的选取机制可以给你的插件一个全新的设计,平滑的整合到工作台中并对将来的扩展提供开放的空间。
序论
对IDE和其它的应用程序而言,Eclipse工作台是一个强大的UI框架,它提供了许多高度综合和可扩展的用户接口。其中之一就是视图插件,它为特定的项目提供附件信息,在工作台窗口某处被选中时自动更新他们的内容。例如“属性”视图这样执行:当工作台中任何地方的一个元素被选中时,这个视图将会列出该元素的所有属性。
工作台的其它视图如全局动作协调也可能依赖当前的选取。
取代实现“硬线通讯”插件可以依靠这种被称作选取服务的机制,它减弱了从其它视图的选取发生变化来选取项目的环节。
这篇文件叙述了选取服务的功能和用法。后面一个 sample plug-in示范了工作台的选取行为并可以用来进行调试。
正题
每个工作台窗口都有自己的选取服务实例。服务保存了但前活动视图的选取并传递选择事件给所有注册的监听器。这些选择事件会在当权视图选择发生变化或者另一个视图变为活动时发生,这两者都可以通过用活的交互或者程序来触发。
拥有元素或者文本资源的视图不需要知道谁对这些东西感兴趣,因此我们可以在已有视图的选取基础上建立新的视图——不用更改那个视图的任何代码。
下节我们介绍“谁”为“谁”提供那种选取服务。
从用户的角度来看选取是一组突出的目录集合,比如一个表或是树型部件。一个选取同样也可以是编辑器里的一部分文本。工作台里的每个可视元素都是由相应的java对象来描述的。MVC模式实现了Jfce在模型对象和视图间的映射。
事实上选取是一个数据结构,它支撑着对应于工作台中被选取的图形元素的模型对象。需要指出的是这里两种基本的选取:
  • 一个对象列表
  • 一段文本
这两者都可以是空的,例如,一个空的列表或者长度为零的字符文本。其次在Eclipse 体系中这些数据结构都会由适当的接口的定义。
下面是上述接口的默认实现:
    ISelection sel = new StructuredSelection(presetElement);
treeviewer.setSelection(sel);
试一下:安装sample plug-in并看一下不同的视图里会有什么样的选取。“Workbench Selection”视图展示了ISelection实现类和它的元素或者文本的选取。
All JFace viewers are so called selection providers. A selection provider implements the interface ISelectionProvider:
所有的Jface Viewer这样调用选取提供者。选取提供者实现了ISelectionProvider接口:
不同的Jface Viewer 使用和传递不同的选取:

Viewer
Selection Type
ComboViewer
ListViewer
TreeViewer
 +- CheckboxTreeViewer
TableViewer
 +- CheckboxTableViewer
TextViewer
 +- SourceViewer
     +- ProjectionViewer

 
同样习惯上viewer可能会象象选取provider那样实现ISelectionProvider接口。
含有viewer的工作台部件要注册这个viewer作为各自视图扩展点的选取provider。
getSite().setSelectionProvider(tableviewer);
即使你发现没有必要立刻传递你的选取,但这样做会使你的插件支持你将来的扩展或者其它的扩展者。如果你的视图定义了依赖当前选取的动作,那么也要设置一个选取provider使得这些动作可以动态的执行
Use the sample plug-in to check whether your views properly register selection providers. 使用sample plug-in来检查一下你的势头是否注册了选取provider。
工作台窗口一般由数部分组成,每个至少有一个视图。工作台保存者当前选取部件和这个部件里的选取。下面开始本文有趣的部分:插件可以通过选取的改变获取这些传递的信息或者注册者。
每个工作台窗口都有一个 ISelectionService 的实现来跟踪当前的选取,一个视图部件可以通过它的扩展点来得到它的一个引用。
    getSite().getWorkbenchWindow().getSelectionService()
选取服务知道当前活动部件或者特定ID部件的选取:
    ISelection getSelection() 
    ISelection getSelection(String partId)
一般视图在工作台窗口中的选取发生变化时发生作用,因此它们最好注册一个IselectionListener来获得当前选取的改变:
    void addSelectionListener(ISelectionListener listener)
    void removeSelectionListener(ISelectionListener listener)
通过这种方式注册的监听在活动部件的选取发生变化或者不同的部件变为活动时将会被通知。只有活动部件的选取才会被传播。如果你的程序只是关注特定部件的选取(不依赖于它是否被激活)时可以通过ID将监听注册到特定的部件:
    void addSelectionListener(String partId, ISelectionListener listener) 
void removeSelectionListener(String partId, ISelectionListener listener) 
即使当前没有这个ID的部件这样做也是有效的,一旦这个部件被创建它最初的选取会被传递给注册给它的监听上。当这个部件被清除时,如果监听实现了INullSelectionListener(下面会接受)接口它会收到一个空的选取。
实现选取监听
The ISelectionListener is a simple interface with just one method. A typical implementation looks like this:
    private ISelectionListener mylistener = new ISelectionListener() {
        public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
        if (sourcepart != MyView.this &&
            selection instanceof IStructuredSelection) {
            doSomething(((IStructuredSelection) selection).toList());
            }
        }
    };
Depending on your requirements your listener implementation probably needs to deal with the following issues as shown in the code snippet above:
  • In case we also provide selections (e.g. a view or editor) we should exclude our own selection events from processing. This avoids unexpected results when the user selects elements within our part.
  • Check whether we can handle this kind of selection ( ).
  • Get the selected content from the selection and process it. ( ).
Don't mix the ISelectionListener interface up with ISelectionChangedListener used by JFace viewers to notify about selection changes.
除去选取监听
Don't forget to remove your selection listener when you can't handle events any more, e.g. when your view has been closed. The dispose() method is a good place to remove your listener:
    public void dispose() {
        ISelectionService s = getSite().getWorkbenchWindow().getSelectionService();
     s.removeSelectionListener(mylistener);
        super.dispose();
    }
其它选取问题
Up to now we focused on the core functionality of the selection service, which covers most of the use cases. There are additional issues that might come into picture in implementation projects.
传递选取
When navigating views the selection changes frequently - especially when the keyboard is used to scroll through long lists or the mouse is dragged over some text. This will lead to many unnecessary updates of the viewers registered as listeners to the selection service and may make your application less responsive.
So called post selection events will be send-out with a slight delay. All intermediate selections during the delay time are ignored; just the final selection is propagated. The ISelectionService has additional methods to register listeners for the delayed selection events:
    void addPostSelectionListener(ISelectionListener listener) 
    void removePostSelectionListener(ISelectionListener listener) 
    void addPostSelectionListener(String partId,
                                  ISelectionListener listener) 
    void removePostSelectionListener(String partId,
                                     ISelectionListener listener) 
To avoid performance issues viewers should typically register selection listeners this way.
The selection providers are responsible for sending out the delayed events and have to implement the IPostSelectionProvider interface if they support it – all JFace viewers do so.
Change the sample plug-in to listen to post selection events and check when they are sent.
The call-back method selectionChanged()ISelectionListener get the new selection as well as the originating part passed in as parameters: defined in
    public void selectionChanged(IWorkbenchPart part, ISelection selection);
  • The active part has not set a selection provider.
  • The specific part we have registered our listener for has not set a selection provider.
  • There is no active part in the workbench window, all parts are closed.
  • The specific part we have registered our listener for has been closed.
什么选取服务: 页面还是窗口?
If you study the workbench API carefully you will find out that there are two selection services: The IWorkbenchPagegetSelectionService(). Therefore e.g. registering a listener within a part implementation is possible in two ways: is a ISelectionService . On the other hand the IWorkbenchWindow has a method
    getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(l);
or
    getSite().getPage().addSelectionListener(l);
Actually this is totally equivalent because since Eclipse 2.0 a workbench window is limited to a single page only. Just don't mix both selection services when adding and removing a listener as two different implementations sit behind it.
一个部件里多个选取Providers
Be aware that the part's site accepts a single selection provider only, which should be registered within the createPartControl() method only:
    getSite().setSelectionProvider(provider);
Replacing the selection provider during the lifetime of the part is not properly supported by the workbench. If a part contains multiple viewers providing selections, like the "Java Hierarchy" view does, a intermediate ISelectionProvider implementation has to be provided that allows dynamically delegating to the currently active viewer within the part. As a starting point you may look into SelectionProviderIntermediate.java provided with this article.
使用选取对象来作甚么?
This article claims that the selection service helps to decouple views reacting on each others selection. But the view handling a selection still needs to deal with the selected objects to provide any useful functionality. Check out the adapter pattern provided by the Eclipse runtime core, which allows attaching new functionality to existing model objects or the other way round providing required functionality for newly contributed objects.
Actually our example plug-in does exactly this by using the workbench label provider which in turn relies on the IWorkbenchAdapter to retrieve icons and text labels for the listed objects. The same mechanism is utilized by the "Properties" view, see article "Take control of your properties" for details.
Plug-in 例子
This article comes with a small example plug-in that demonstrates the explained techniques. Additionally the plug-in may serve for debugging your selection providers. The example contributes a new view "Workbench Selection" which simply mirrors the current selection in the workbench. It works for element selections as well as for text selections.
获取并运行例子
Download the plug-in project com.mountainminds.eclipse.selectionsample.zip and import it into your workspace via the "Import..." wizard from the "File" menu. Select "Existing Project into Workspace" on the first wizard page. On the second page simply use the option "Select archive file" to import the downloaded archive.
The fastest way to launch the example is right-clicking the plug-in project and select "Run As" → "Eclipse Application" in the context menu. From the menu of the launched workbench activate "Window" → "Show View" → "Other..." and select our view "Workbench Selection" in the category "Other".
Now you can play around with selections in various workbench parts and see how our "Workbench Selection" view reflects these selections:
The same works for text selections:
The example is implemented in a single class SelectionView.java applying the techniques discussed in this article. When reading through this short piece of code you may note that:
  • The ISelectionListener implementation makes sure that we do not react on our own selections.
  • The title of the source part of the current selection as well as the implementation class of ISelection is shown in the view description (the optional grey bar at the top).
  • The view uses two viewers: One for object lists and one for text blocks. Switching between the viewers is implemented done with a PageBook.
  • The viewer for object lists itself registeres as a selection provider. Check it out: If you select a element listed in our "Workbench Selection" view its properties are shown in turn in the "Properties" view.
总结
The mechanisms provided by the Eclipse workbench are simple to use and powerful. Not using this mechanisms result in plug-ins that poorly integrate with the rest of the workbench and will be hard to extend. To avoid such pitfalls simply follow these rules when selections come into picture:
  • Avoid direct hard-wired inter-view communication. If one view needs to react on the selection in another view use the ISelectionService.
  • Be cooperative and open for future extensions: Always register your viewers as selection providers with the part site.
  • Use existing selection specific views like the "Properties" view when appropriate instead of creating new ones.
参考
To discuss or report problems in this article see bug 112193 .
资源
This article come with the following resources:
 
Eclipse工作台:使用选取服务
摘要
Eclipse工作台提供的选取服务允许工作台窗口的各个部分有效整合。了解使用已有的选取机制可以给你的插件一个全新的设计,平滑的整合到工作台中并对将来的扩展提供开放的空间。
序论
对IDE和其它的应用程序而言,Eclipse工作台是一个强大的UI框架,它提供了许多高度综合和可扩展的用户接口。其中之一就是视图插件,它为特定的项目提供附件信息,在工作台窗口某处被选中时自动更新他们的内容。例如“属性”视图这样执行:当工作台中任何地方的一个元素被选中时,这个视图将会列出该元素的所有属性。
工作台的其它视图如全局动作协调也可能依赖当前的选取。
取代实现“硬线通讯”插件可以依靠这种被称作选取服务的机制,它减弱了从其它视图的选取发生变化来选取项目的环节。
这篇文件叙述了选取服务的功能和用法。后面一个 sample plug-in示范了工作台的选取行为并可以用来进行调试。
正题
每个工作台窗口都有自己的选取服务实例。服务保存了但前活动视图的选取并传递选择事件给所有注册的监听器。这些选择事件会在当权视图选择发生变化或者另一个视图变为活动时发生,这两者都可以通过用活的交互或者程序来触发。
拥有元素或者文本资源的视图不需要知道谁对这些东西感兴趣,因此我们可以在已有视图的选取基础上建立新的视图——不用更改那个视图的任何代码。
下节我们介绍“谁”为“谁”提供那种选取服务。
从用户的角度来看选取是一组突出的目录集合,比如一个表或是树型部件。一个选取同样也可以是编辑器里的一部分文本。工作台里的每个可视元素都是由相应的java对象来描述的。MVC模式实现了Jfce在模型对象和视图间的映射。
事实上选取是一个数据结构,它支撑着对应于工作台中被选取的图形元素的模型对象。需要指出的是这里两种基本的选取:
  • 一个对象列表
  • 一段文本
这两者都可以是空的,例如,一个空的列表或者长度为零的字符文本。其次在Eclipse 体系中这些数据结构都会由适当的接口的定义。
下面是上述接口的默认实现:
    ISelection sel = new StructuredSelection(presetElement);
treeviewer.setSelection(sel);
试一下:安装sample plug-in并看一下不同的视图里会有什么样的选取。“Workbench Selection”视图展示了ISelection实现类和它的元素或者文本的选取。
All JFace viewers are so called selection providers. A selection provider implements the interface ISelectionProvider:
所有的Jface Viewer这样调用选取提供者。选取提供者实现了ISelectionProvider接口:
不同的Jface Viewer 使用和传递不同的选取:

Viewer
Selection Type
ComboViewer
ListViewer
TreeViewer
 +- CheckboxTreeViewer
TableViewer
 +- CheckboxTableViewer
TextViewer
 +- SourceViewer
     +- ProjectionViewer

 
同样习惯上viewer可能会象象选取provider那样实现ISelectionProvider接口。
含有viewer的工作台部件要注册这个viewer作为各自视图扩展点的选取provider。
getSite().setSelectionProvider(tableviewer);
即使你发现没有必要立刻传递你的选取,但这样做会使你的插件支持你将来的扩展或者其它的扩展者。如果你的视图定义了依赖当前选取的动作,那么也要设置一个选取provider使得这些动作可以动态的执行
Use the sample plug-in to check whether your views properly register selection providers. 使用sample plug-in来检查一下你的势头是否注册了选取provider。
工作台窗口一般由数部分组成,每个至少有一个视图。工作台保存者当前选取部件和这个部件里的选取。下面开始本文有趣的部分:插件可以通过选取的改变获取这些传递的信息或者注册者。
每个工作台窗口都有一个 ISelectionService 的实现来跟踪当前的选取,一个视图部件可以通过它的扩展点来得到它的一个引用。
    getSite().getWorkbenchWindow().getSelectionService()
选取服务知道当前活动部件或者特定ID部件的选取:
    ISelection getSelection() 
    ISelection getSelection(String partId)
一般视图在工作台窗口中的选取发生变化时发生作用,因此它们最好注册一个IselectionListener来获得当前选取的改变:
    void addSelectionListener(ISelectionListener listener)
    void removeSelectionListener(ISelectionListener listener)
通过这种方式注册的监听在活动部件的选取发生变化或者不同的部件变为活动时将会被通知。只有活动部件的选取才会被传播。如果你的程序只是关注特定部件的选取(不依赖于它是否被激活)时可以通过ID将监听注册到特定的部件:
    void addSelectionListener(String partId, ISelectionListener listener) 
void removeSelectionListener(String partId, ISelectionListener listener) 
即使当前没有这个ID的部件这样做也是有效的,一旦这个部件被创建它最初的选取会被传递给注册给它的监听上。当这个部件被清除时,如果监听实现了INullSelectionListener(下面会接受)接口它会收到一个空的选取。
实现选取监听
The ISelectionListener is a simple interface with just one method. A typical implementation looks like this:
    private ISelectionListener mylistener = new ISelectionListener() {
        public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
        if (sourcepart != MyView.this &&
            selection instanceof IStructuredSelection) {
            doSomething(((IStructuredSelection) selection).toList());
            }
        }
    };
Depending on your requirements your listener implementation probably needs to deal with the following issues as shown in the code snippet above:
  • In case we also provide selections (e.g. a view or editor) we should exclude our own selection events from processing. This avoids unexpected results when the user selects elements within our part.
  • Check whether we can handle this kind of selection ( ).
  • Get the selected content from the selection and process it. ( ).
Don't mix the ISelectionListener interface up with ISelectionChangedListener used by JFace viewers to notify about selection changes.
除去选取监听
Don't forget to remove your selection listener when you can't handle events any more, e.g. when your view has been closed. The dispose() method is a good place to remove your listener:
    public void dispose() {
        ISelectionService s = getSite().getWorkbenchWindow().getSelectionService();
     s.removeSelectionListener(mylistener);
        super.dispose();
    }
其它选取问题
Up to now we focused on the core functionality of the selection service, which covers most of the use cases. There are additional issues that might come into picture in implementation projects.
传递选取
When navigating views the selection changes frequently - especially when the keyboard is used to scroll through long lists or the mouse is dragged over some text. This will lead to many unnecessary updates of the viewers registered as listeners to the selection service and may make your application less responsive.
So called post selection events will be send-out with a slight delay. All intermediate selections during the delay time are ignored; just the final selection is propagated. The ISelectionService has additional methods to register listeners for the delayed selection events:
    void addPostSelectionListener(ISelectionListener listener) 
    void removePostSelectionListener(ISelectionListener listener) 
    void addPostSelectionListener(String partId,
                                  ISelectionListener listener) 
    void removePostSelectionListener(String partId,
                                     ISelectionListener listener) 
To avoid performance issues viewers should typically register selection listeners this way.
The selection providers are responsible for sending out the delayed events and have to implement the IPostSelectionProvider interface if they support it – all JFace viewers do so.
Change the sample plug-in to listen to post selection events and check when they are sent.
The call-back method selectionChanged()ISelectionListener get the new selection as well as the originating part passed in as parameters: defined in
    public void selectionChanged(IWorkbenchPart part, ISelection selection);
  • The active part has not set a selection provider.
  • The specific part we have registered our listener for has not set a selection provider.
  • There is no active part in the workbench window, all parts are closed.
  • The specific part we have registered our listener for has been closed.
什么选取服务: 页面还是窗口?
If you study the workbench API carefully you will find out that there are two selection services: The IWorkbenchPagegetSelectionService(). Therefore e.g. registering a listener within a part implementation is possible in two ways: is a ISelectionService . On the other hand the IWorkbenchWindow has a method
    getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(l);
or
    getSite().getPage().addSelectionListener(l);
Actually this is totally equivalent because since Eclipse 2.0 a workbench window is limited to a single page only. Just don't mix both selection services when adding and removing a listener as two different implementations sit behind it.
一个部件里多个选取Providers
Be aware that the part's site accepts a single selection provider only, which should be registered within the createPartControl() method only:
    getSite().setSelectionProvider(provider);
Replacing the selection provider during the lifetime of the part is not properly supported by the workbench. If a part contains multiple viewers providing selections, like the "Java Hierarchy" view does, a intermediate ISelectionProvider implementation has to be provided that allows dynamically delegating to the currently active viewer within the part. As a starting point you may look into SelectionProviderIntermediate.java provided with this article.
使用选取对象来作甚么?
This article claims that the selection service helps to decouple views reacting on each others selection. But the view handling a selection still needs to deal with the selected objects to provide any useful functionality. Check out the adapter pattern provided by the Eclipse runtime core, which allows attaching new functionality to existing model objects or the other way round providing required functionality for newly contributed objects.
Actually our example plug-in does exactly this by using the workbench label provider which in turn relies on the IWorkbenchAdapter to retrieve icons and text labels for the listed objects. The same mechanism is utilized by the "Properties" view, see article "Take control of your properties" for details.
Plug-in 例子
This article comes with a small example plug-in that demonstrates the explained techniques. Additionally the plug-in may serve for debugging your selection providers. The example contributes a new view "Workbench Selection" which simply mirrors the current selection in the workbench. It works for element selections as well as for text selections.
获取并运行例子
Download the plug-in project com.mountainminds.eclipse.selectionsample.zip and import it into your workspace via the "Import..." wizard from the "File" menu. Select "Existing Project into Workspace" on the first wizard page. On the second page simply use the option "Select archive file" to import the downloaded archive.
The fastest way to launch the example is right-clicking the plug-in project and select "Run As" → "Eclipse Application" in the context menu. From the menu of the launched workbench activate "Window" → "Show View" → "Other..." and select our view "Workbench Selection" in the category "Other".
Now you can play around with selections in various workbench parts and see how our "Workbench Selection" view reflects these selections:
The same works for text selections:
The example is implemented in a single class SelectionView.java applying the techniques discussed in this article. When reading through this short piece of code you may note that:
  • The ISelectionListener implementation makes sure that we do not react on our own selections.
  • The title of the source part of the current selection as well as the implementation class of ISelection is shown in the view description (the optional grey bar at the top).
  • The view uses two viewers: One for object lists and one for text blocks. Switching between the viewers is implemented done with a PageBook.
  • The viewer for object lists itself registeres as a selection provider. Check it out: If you select a element listed in our "Workbench Selection" view its properties are shown in turn in the "Properties" view.
总结
The mechanisms provided by the Eclipse workbench are simple to use and powerful. Not using this mechanisms result in plug-ins that poorly integrate with the rest of the workbench and will be hard to extend. To avoid such pitfalls simply follow these rules when selections come into picture:
  • Avoid direct hard-wired inter-view communication. If one view needs to react on the selection in another view use the ISelectionService.
  • Be cooperative and open for future extensions: Always register your viewers as selection providers with the part site.
  • Use existing selection specific views like the "Properties" view when appropriate instead of creating new ones.
参考
To discuss or report problems in this article see bug 112193 .
资源
This article come with the following resources:
 
Eclipse工作台:使用选取服务
摘要
Eclipse工作台提供的选取服务允许工作台窗口的各个部分有效整合。了解使用已有的选取机制可以给你的插件一个全新的设计,平滑的整合到工作台中并对将来的扩展提供开放的空间。
序论
对IDE和其它的应用程序而言,Eclipse工作台是一个强大的UI框架,它提供了许多高度综合和可扩展的用户接口。其中之一就是视图插件,它为特定的项目提供附件信息,在工作台窗口某处被选中时自动更新他们的内容。例如“属性”视图这样执行:当工作台中任何地方的一个元素被选中时,这个视图将会列出该元素的所有属性。
工作台的其它视图如全局动作协调也可能依赖当前的选取。
取代实现“硬线通讯”插件可以依靠这种被称作选取服务的机制,它减弱了从其它视图的选取发生变化来选取项目的环节。
这篇文件叙述了选取服务的功能和用法。后面一个 sample plug-in示范了工作台的选取行为并可以用来进行调试。
正题
每个工作台窗口都有自己的选取服务实例。服务保存了但前活动视图的选取并传递选择事件给所有注册的监听器。这些选择事件会在当权视图选择发生变化或者另一个视图变为活动时发生,这两者都可以通过用活的交互或者程序来触发。
拥有元素或者文本资源的视图不需要知道谁对这些东西感兴趣,因此我们可以在已有视图的选取基础上建立新的视图——不用更改那个视图的任何代码。
下节我们介绍“谁”为“谁”提供那种选取服务。
从用户的角度来看选取是一组突出的目录集合,比如一个表或是树型部件。一个选取同样也可以是编辑器里的一部分文本。工作台里的每个可视元素都是由相应的java对象来描述的。MVC模式实现了Jfce在模型对象和视图间的映射。
事实上选取是一个数据结构,它支撑着对应于工作台中被选取的图形元素的模型对象。需要指出的是这里两种基本的选取:
  • 一个对象列表
  • 一段文本
这两者都可以是空的,例如,一个空的列表或者长度为零的字符文本。其次在Eclipse 体系中这些数据结构都会由适当的接口的定义。
下面是上述接口的默认实现:
    ISelection sel = new StructuredSelection(presetElement);
treeviewer.setSelection(sel);
试一下:安装sample plug-in并看一下不同的视图里会有什么样的选取。“Workbench Selection”视图展示了ISelection实现类和它的元素或者文本的选取。
All JFace viewers are so called selection providers. A selection provider implements the interface ISelectionProvider:
所有的Jface Viewer这样调用选取提供者。选取提供者实现了ISelectionProvider接口:
不同的Jface Viewer 使用和传递不同的选取:

Viewer
Selection Type
ComboViewer
ListViewer
TreeViewer
 +- CheckboxTreeViewer
TableViewer
 +- CheckboxTableViewer
TextViewer
 +- SourceViewer
     +- ProjectionViewer

 
同样习惯上viewer可能会象象选取provider那样实现ISelectionProvider接口。
含有viewer的工作台部件要注册这个viewer作为各自视图扩展点的选取provider。
getSite().setSelectionProvider(tableviewer);
即使你发现没有必要立刻传递你的选取,但这样做会使你的插件支持你将来的扩展或者其它的扩展者。如果你的视图定义了依赖当前选取的动作,那么也要设置一个选取provider使得这些动作可以动态的执行
Use the sample plug-in to check whether your views properly register selection providers. 使用sample plug-in来检查一下你的势头是否注册了选取provider。
工作台窗口一般由数部分组成,每个至少有一个视图。工作台保存者当前选取部件和这个部件里的选取。下面开始本文有趣的部分:插件可以通过选取的改变获取这些传递的信息或者注册者。
每个工作台窗口都有一个 ISelectionService 的实现来跟踪当前的选取,一个视图部件可以通过它的扩展点来得到它的一个引用。
    getSite().getWorkbenchWindow().getSelectionService()
选取服务知道当前活动部件或者特定ID部件的选取:
    ISelection getSelection() 
    ISelection getSelection(String partId)
一般视图在工作台窗口中的选取发生变化时发生作用,因此它们最好注册一个IselectionListener来获得当前选取的改变:
    void addSelectionListener(ISelectionListener listener)
    void removeSelectionListener(ISelectionListener listener)
通过这种方式注册的监听在活动部件的选取发生变化或者不同的部件变为活动时将会被通知。只有活动部件的选取才会被传播。如果你的程序只是关注特定部件的选取(不依赖于它是否被激活)时可以通过ID将监听注册到特定的部件:
    void addSelectionListener(String partId, ISelectionListener listener) 
void removeSelectionListener(String partId, ISelectionListener listener) 
即使当前没有这个ID的部件这样做也是有效的,一旦这个部件被创建它最初的选取会被传递给注册给它的监听上。当这个部件被清除时,如果监听实现了INullSelectionListener(下面会接受)接口它会收到一个空的选取。
实现选取监听
The ISelectionListener is a simple interface with just one method. A typical implementation looks like this:
    private ISelectionListener mylistener = new ISelectionListener() {
        public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
        if (sourcepart != MyView.this &&
            selection instanceof IStructuredSelection) {
            doSomething(((IStructuredSelection) selection).toList());
            }
        }
    };
Depending on your requirements your listener implementation probably needs to deal with the following issues as shown in the code snippet above:
  • In case we also provide selections (e.g. a view or editor) we should exclude our own selection events from processing. This avoids unexpected results when the user selects elements within our part.
  • Check whether we can handle this kind of selection ( ).
  • Get the selected content from the selection and process it. ( ).
Don't mix the ISelectionListener interface up with ISelectionChangedListener used by JFace viewers to notify about selection changes.
除去选取监听
Don't forget to remove your selection listener when you can't handle events any more, e.g. when your view has been closed. The dispose() method is a good place to remove your listener:
    public void dispose() {
        ISelectionService s = getSite().getWorkbenchWindow().getSelectionService();
     s.removeSelectionListener(mylistener);
        super.dispose();
    }
其它选取问题
Up to now we focused on the core functionality of the selection service, which covers most of the use cases. There are additional issues that might come into picture in implementation projects.
传递选取
When navigating views the selection changes frequently - especially when the keyboard is used to scroll through long lists or the mouse is dragged over some text. This will lead to many unnecessary updates of the viewers registered as listeners to the selection service and may make your application less responsive.
So called post selection events will be send-out with a slight delay. All intermediate selections during the delay time are ignored; just the final selection is propagated. The ISelectionService has additional methods to register listeners for the delayed selection events:
    void addPostSelectionListener(ISelectionListener listener) 
    void removePostSelectionListener(ISelectionListener listener) 
    void addPostSelectionListener(String partId,
                                  ISelectionListener listener) 
    void removePostSelectionListener(String partId,
                                     ISelectionListener listener) 
To avoid performance issues viewers should typically register selection listeners this way.
The selection providers are responsible for sending out the delayed events and have to implement the IPostSelectionProvider interface if they support it – all JFace viewers do so.
Change the sample plug-in to listen to post selection events and check when they are sent.
The call-back method selectionChanged()ISelectionListener get the new selection as well as the originating part passed in as parameters: defined in
    public void selectionChanged(IWorkbenchPart part, ISelection selection);
  • The active part has not set a selection provider.
  • The specific part we have registered our listener for has not set a selection provider.
  • There is no active part in the workbench window, all parts are closed.
  • The specific part we have registered our listener for has been closed.
什么选取服务: 页面还是窗口?
If you study the workbench API carefully you will find out that there are two selection services: The IWorkbenchPagegetSelectionService(). Therefore e.g. registering a listener within a part implementation is possible in two ways: is a ISelectionService . On the other hand the IWorkbenchWindow has a method
    getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(l);
or
    getSite().getPage().addSelectionListener(l);
Actually this is totally equivalent because since Eclipse 2.0 a workbench window is limited to a single page only. Just don't mix both selection services when adding and removing a listener as two different implementations sit behind it.
一个部件里多个选取Providers
Be aware that the part's site accepts a single selection provider only, which should be registered within the createPartControl() method only:
    getSite().setSelectionProvider(provider);
Replacing the selection provider during the lifetime of the part is not properly supported by the workbench. If a part contains multiple viewers providing selections, like the "Java Hierarchy" view does, a intermediate ISelectionProvider implementation has to be provided that allows dynamically delegating to the currently active viewer within the part. As a starting point you may look into SelectionProviderIntermediate.java provided with this article.
使用选取对象来作甚么?
This article claims that the selection service helps to decouple views reacting on each others selection. But the view handling a selection still needs to deal with the selected objects to provide any useful functionality. Check out the adapter pattern provided by the Eclipse runtime core, which allows attaching new functionality to existing model objects or the other way round providing required functionality for newly contributed objects.
Actually our example plug-in does exactly this by using the workbench label provider which in turn relies on the IWorkbenchAdapter to retrieve icons and text labels for the listed objects. The same mechanism is utilized by the "Properties" view, see article "Take control of your properties" for details.
Plug-in 例子
This article comes with a small example plug-in that demonstrates the explained techniques. Additionally the plug-in may serve for debugging your selection providers. The example contributes a new view "Workbench Selection" which simply mirrors the current selection in the workbench. It works for element selections as well as for text selections.
获取并运行例子
Download the plug-in project com.mountainminds.eclipse.selectionsample.zip and import it into your workspace via the "Import..." wizard from the "File" menu. Select "Existing Project into Workspace" on the first wizard page. On the second page simply use the option "Select archive file" to import the downloaded archive.
The fastest way to launch the example is right-clicking the plug-in project and select "Run As" → "Eclipse Application" in the context menu. From the menu of the launched workbench activate "Window" → "Show View" → "Other..." and select our view "Workbench Selection" in the category "Other".
Now you can play around with selections in various workbench parts and see how our "Workbench Selection" view reflects these selections:
The same works for text selections:
The example is implemented in a single class SelectionView.java applying the techniques discussed in this article. When reading through this short piece of code you may note that:
  • The ISelectionListener implementation makes sure that we do not react on our own selections.
  • The title of the source part of the current selection as well as the implementation class of ISelection is shown in the view description (the optional grey bar at the top).
  • The view uses two viewers: One for object lists and one for text blocks. Switching between the viewers is implemented done with a PageBook.
  • The viewer for object lists itself registeres as a selection provider. Check it out: If you select a element listed in our "Workbench Selection" view its properties are shown in turn in the "Properties" view.
总结
The mechanisms provided by the Eclipse workbench are simple to use and powerful. Not using this mechanisms result in plug-ins that poorly integrate with the rest of the workbench and will be hard to extend. To avoid such pitfalls simply follow these rules when selections come into picture:
  • Avoid direct hard-wired inter-view communication. If one view needs to react on the selection in another view use the ISelectionService.
  • Be cooperative and open for future extensions: Always register your viewers as selection providers with the part site.
  • Use existing selection specific views like the "Properties" view when appropriate instead of creating new ones.
参考
To discuss or report problems in this article see bug 112193 .
资源
This article come with the following resources:
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值