Eclipse设计实现可重用的SWT构件
2007-11-19 10:44:36 来源:论坛整理 作者:翁长河 点击:
本文从创建一个简单的SWT Tree Table开始,引入可重用的用户界面构件这个开发人员普遍关心的问题,然后分析Eclipse的用户界面的一些设计模式,循序渐进的向读者展示了如何设计实现一个精巧的高度可重用的TreeTable构件,最终通过增加一些扩展的功能显示了该构件强大的可扩展能力和灵活性。
TreeTableViewer 的构造函数中需要一个 ITreeTableAdapterFactory作为参数,这是一个适配器工厂(参见《设计模式:可复用面向对象软件的基础》中的适配器工厂模式),主要根据每一行的对象获取到相应的ITreeTableAdapter作为行控制器。这个控制器主要用在了默认的TreeTableContentProvider中,详见清单6。
清单6:TreeTableContentProvider的代码
|
public class TreeTableContentProvider extends ArrayContentProvider
implements ITreeContentProvider {
private ITreeTableAdapterFactory adapterfactory;
public TreeTableContentProvider(ITreeTableAdapterFactory adapterfactory) {
this.adapterfactory = adapterfactory;
}
public Object[] getChildren(Object parentElement) {
return ((ITreeTableAdapter) adapterfactory.getAdapter(parentElement))
.getChildren(parentElement);
}
public Object getParent(Object element) {
return ((ITreeTableAdapter) adapterfactory.getAdapter(element))
.getParent(element);
}
public boolean hasChildren(Object element) {
return getChildren(element).length > 0;
}
} |
使用ITreeTableAdapter实现行控制
ITreeTableAdapter的接口很简单,它参考了IworkbenchAdapter接口的设计,实现了TreeTable中的行逻辑的控制,详见清单7。
清单7:ITreeTableAdapter的代码
public interface ITreeTableAdapter {
public Object[] getChildren(Object o);
public Object getParent(Object o);
public Color getBackgroundColor(Object element);
} |
为什么TreeTableContentProvider一定需要一个ITreeTableAdapterFactory来作为参数构造呢? 我们考虑一些复杂的情况,一个Table的行,可能会有多种类型的控制方式(还记得第二部分的IWorkbenchAdapter有三个实现吗?)因此我们会为每种类型的行数据创建一个特殊的行控制器,ITreeTableAdapterFactory可以为ContentProvider提供多个ITreeTableAdapter以实现不同类别的行数据的控制逻辑可以单独在一个类中实现,有效的隔离了代码,使得应用程序结构比较清晰。如果你的程序足够简单,你只需要实现一个ITreeTableAdapter,然后使用FixedTreeTableAdapterFactory就可以了,如清单8所示,FixedTreeTableAdapterFactory的接口非常简单,就是返回一个固定的适配器。
清单8:FixedTreeTableAdapterFactory的代码
public class FixedTreeTableAdapterFactory implements ITreeTableAdapterFactory{
private ITreeTableAdapter adapter;
public FixedTreeTableAdapterFactory(ITreeTableAdapter adapter){
this.adapter=adapter;
}
public ITreeTableAdapter getAdapter(Object treeitemdata) {
return adapter;
}
} |
通常的适配器模式,被适配的对象需要实现IAdaptable的接口,显然这里我们不能采用侵入方式的adapter模式。我们的对象模型是纯净的对象模型,因此我们需要适配器工厂模式,通过工厂取得适配器对象。根据对象获取适配器可以更为精确的控制你的程序,例如我们的示例中,