原文:http://space.itpub.net/13081368/viewspace-406767
Eclipse是一个功能强大的UI框架,它提供了很多可扩展的UI接口,用户可以通过这些接口扩展UI框架的功能,实现用户界面的可操作性。
回想一下Eclipse中的常用操作,当用户选择了某一个项目或文件时,Eclipse的Properties视图将会显示和资源相关的属性,当选择了某个方法或属性时,大纲视图将会定位到相关的位置,如图1所示。
图1 选择Eclipse项目节点
类似的功能是功能强大的IDE所应该具备的。然而Eclipse的视图和视图之间彼此独立,用户不太可能随时遍历每一个视图,判断某一个视图的状态,而且从效率上来说也是不可行的。
Eclipse通过选择服务(Selection Service)来解决这个问题,具体步骤如下。
(1)实现选择服务的提供者(ISelectionProvider)。
(2)获得Eclipse中的选择服务(ISelectionService)。
(3)实现选择服务的监听器(ISelectionListener)。
Eclipse平台为用户的选择和监听提供了一种服务的机制,当选择的某个节点为可提供服务的对象时,工作台会把选择对象的动作作为事件通知监听器(可以是其他插件的其他视图),监听器监听到感兴趣的事件后,将会执行相关的操作(例如属性视图显示节点信息)。选择服务的通知机制如图2所示。
图2 选择服务通知机制
选择事件提供者(Selection Provider)
在Eclipse中,被选择的对象都要实现ISelectionProvider接口,通过此接口提供选择其中子节点的能力,ISelectionProvider接口定义如例程1所示。
例程1 ISelectionProvider.java
package org.eclipse.jface.viewers;
public interface ISelectionProvider {
public void addSelectionChangedListener(ISelectionChangedListener listener);
public ISelection getSelection();
public void removeSelectionChangedListener(
ISelectionChangedListener listener);
public void setSelection(ISelection selection);
}
ISelectionProvider各方法解释如下。
l addSelectionChangedListener:添加选择节点的监听器。
l getSelection:获得当前的选择节点。
l removeSelectionChangedListener:删除选择节点的监听器。
l setSelection:设置选择节点。
JFace的Viewer中都实现了ISelectionProvider接口,也就是说,用户可以监听到Eclipse中JFace的Viewer组件的选择事件。
实现ISelectionProvider接口的对象可以提供选择监听的能力,但是用户选择的并非实现ISelectionProvider接口的对象,而是其中的节点,例如TreeViewer中的节点项。能够被选择的对象是实现了ISelection接口的对象,所有可选择的对象都实现了ISelection接口。Eclipse中一般认为有3种类型的选择对象,如图3所示。
图3 选择对象
ITextSelection、IStructuredSelection和IMarkSelection分别表示文本类型的选择对象、结构化的选择对象和标记选择对象。用户通过监听器获得选择对象的内容。
选择服务(Selection Service)
工作台提供了追踪相关Part中节点被选择的服务,通过选择服务,用户可以注册选择的监听器。工作台提供选择服务由ISelectionService对象提供。ISelectionService接口定义如例程2所示。
例程2 ISelectionService.java
package org.eclipse.ui;
import org.eclipse.jface.viewers.ISelection;
public interface ISelectionService {
public void addSelectionListener(ISelectionListener listener);
public void addSelectionListener(String partId, ISelectionListener listener);
public void addPostSelectionListener(ISelectionListener listener);
public void addPostSelectionListener(String partId,
ISelectionListener listener);
public ISelection getSelection();
public ISelection getSelection(String partId);
public void removeSelectionListener(ISelectionListener listener);
public void removeSelectionListener(String partId,
ISelectionListener listener);
public void removePostSelectionListener(ISelectionListener listener);
public void removePostSelectionListener(String partId,
ISelectionListener listener);
}
对用户来说,用户关心的只是什么节点被选择,以及如何处理节点被选择的事件,至于如何通知及什么时机通知比较适当,用户可以不用关心。Eclipse已经封装了选择的服务层,用户可以通过工作台窗口获得ISelectionService对象,例如“getSite().getWorkbenchWindow(). getSelectionService()”。ISelectionService接口方法解释如下。
l addSelectionListener:添加选择的监听器,其中如果指定partId,则表明监听指定的Part。
l addPostSelectionListener:添加Post类型的选择监听器,其中如果指定partId,则表明监听指定的Part。
l getSelection:获得当前的选择节点。
l removeSelectionListener:删除选择监听器,其中如果指定partId,则表明监听指定的Part。
l removePostSelectionListener:删除Post类型的选择监听器,其中如果指定partId,则表明监听指定的Part。
Post类型的选择监听器,在通过鼠标自动选择的场景是非常有用的,它会在一定的延时后才触发选择事件,而不会在选择某一项时触发选择事件,这样会大大提高效率。ISelectionService对象能通过addSelectionListener和addPostSelectionListener方法添加监听器,例如“getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(listener);”。
以上代码从Site中得到工作台窗口,通过工作台窗口得到SelectionService,最后添加了选择监听器。
选择事件监听器(Selection Listener)
要实现选择事件的监听,就要实现选择监听器。选择监听器是一个ISelectionListener类型的对象。ISelectionListener接口定义如例程3所示。
例程3 ISelectionListener.java
package org.eclipse.ui;
import org.eclipse.jface.viewers.ISelection;
public interface ISelectionListener {
public void selectionChanged(IWorkbenchPart part, ISelection selection);
}
如以上代码所示,ISelectionListener只有一个方法,即selectionChanged,当选择的对象改变后,将执行此过程。
选择监听器是用户比较关注的部分,通过selectionChanged方法,用户能知道哪一个Part(IWorkbenchPart)中的哪一个对象(ISelection)被选用,从而进行相应的处理。如下代码片段为当选择的对象改变后,关联的Action也随之更新。
public void selectionChanged(IWorkbenchPart part, ISelection selection)
{
updateActions(editPartActionIDs);
}
protected void updateActions(List actionIds)
{
for (Iterator ids = actionIds.iterator(); ids.hasNext();)
{
IAction action = getActionRegistry().getAction(ids.next());
if (null != action && action instanceof UpdateAction)
((UpdateAction) action).update();
}
}
实例
Eclipse中选择和监听是经常要用到的技术。下面将通过一个实例演示如何建立一个视图,然后通过视图监听Eclipse中的选择事件,以及把视图中的Viewer设置为选择提供者,代码如例程4所示。
例程4 SelectionView.java
package com.mountainminds.eclipse.selectionsample;
/**
* 为了节省篇幅,所有的import类已经被注释
* 读者可以通过ctrl+shift+o快捷键,自动引入所依赖的类
* 如果有问题可发邮件到ganshm@gmail.com
* */
public class SelectionView extends ViewPart {
//显示组件
private PageBook pagebook;
private TableViewer tableviewer;
private TextViewer textviewer;
//创建选择监听器
private ISelectionListener listener = new ISelectionListener() {
//响应选择改变事件
public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
//如果选择的Part不为当前视图,则在当前视图中显示选择的信息
if (sourcepart != SelectionView.this) {
showSelection(sourcepart, selection);
}
}
};
public void showSelection(IWorkbenchPart sourcepart, ISelection selection) {
setContentDescription(sourcepart.getTitle() + " ("
+ selection.getClass().getName() + ")");
//处理相应的选择类型
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) selection;
//显示IStructuredSelection类型的选项
showItems(ss.toArray());
}
if (selection instanceof ITextSelection) {
ITextSelection ts = (ITextSelection) selection;
//显示ITextSelection类型的选项
showText(ts.getText());
}
if (selection instanceof IMarkSelection) {
IMarkSelection ms = (IMarkSelection) selection;
try {
//显示IMarkSelection类型的选项
showText(ms.getDocument().get(ms.getOffset(), ms.getLength()));
} catch (BadLocationException ble) { }
}
}
private void showItems(Object[] items) {
tableviewer.setInput(items);
pagebook.showPage(tableviewer.getControl());
}
private void showText(String text) {
textviewer.setDocument(new Document(text));
pagebook.showPage(textviewer.getControl());
}
public void createPartControl(Composite parent) {
//创建PageBook
pagebook = new PageBook(parent, SWT.NONE);
//创建TableViewer
tableviewer = new TableViewer(pagebook, SWT.NONE);
tableviewer.setLabelProvider(new WorkbenchLabelProvider());
tableviewer.setContentProvider(new ArrayContentProvider());
//设置tableviewer为选择事件的提供者
getSite().setSelectionProvider(tableviewer);
//创建textviewer
textviewer = new TextViewer(pagebook, SWT.H_SCROLL | SWT.V_SCROLL);
textviewer.setEditable(false);
//添加选择事件监听器
getSite().getWorkbenchWindow().getSelectionService().
addSelectionListener(listener);
}
public void setFocus() {
pagebook.setFocus();
}
public void dispose() {
//删除选择事件监听器
getSite().getWorkbenchWindow().getSelectionService().
removeSelectionListener(listener);
super.dispose();
}
}
上例通过“setSelectionProvider(tableviewer)”代码把当前视图的tableviewer组件添加为选择事件的提供者,通过“addSelectionListener(listener)”代码添加了选择事件的监听器,当在Eclipse中选择了其他视图和编辑器的相关组件时,此选择监听器将会获得选择的组件信息,如图4所示。
图4 选择监听器
通过选择树中的节点,在选择监听视图中显示相关的信息。用户还可以尝试选择文本和选择标记,在监听器视图中将会显示不同的信息。