ISelection
中的多个ISelectionProvider
处理ISelectionListener
s而不破坏松耦合,没有猜测(类型检查,铸造)?在我的Eclipse RCP 3.7应用程序中,我有两个视图和一个(GEF)编辑器。视图包含检查表,允许用户通过选择来控制编辑器的内容。假设编辑器显示大学人员层次结构,一个视图将允许选择应显示其员工的部门,另一个视图允许选择应显示员工的当前学位级别。
即如果用户在一个视图中选择计算机科学和英语文学,并且 Post-Doc 和 Full Professor < / em> * 在另一方面,编辑器将显示工作人员(例如,节点),这些人员来自CS或EngLit部门的Post-Docs或Full Professor。但是,该模型包含了所有部门的所有工作人员。
我根据Eclipse Workbench: Using the Selection Service实现了视图和编辑器:编辑器有org.eclipse.ui.ISelectionListener
,视图都实现了org.eclipse.jface.viewers.ISelectionProvider
。视图维护一个侦听器列表,每当选择更改时,都会在循环中通知:
((ISelectionChangedListener) listeners.getListeners()[i]).selectionChanged( new SelectionChangedEvent(DeptView.this, new StructuredSelection({selection})))
到目前为止,我已经尝试了以下实现,但我对它们都不满意。
对于{selection}
,请使用自定义类(例如DeptSelection
),它会封装所选元素,或者更确切地说是它们指向的模型元素。我认为 这会打破松散耦合,因为DeptSelection
将在 Dept Plugin 中定义,它将与分开em>编辑器插件,同时我想允许客户端为听众也能听的选择添加扩展名。
对于{selection}
,只需传递所选元素(在本例中为org.eclipse.jface.viewers.CheckboxTableViewer#getCheckedElements()
),然后在编辑器中的ISelectionListener#selectionChanged()
中进行处理。这是笨拙,因为它涉及大量猜测:类型检查,转换等。此外,对于此解决方案,我然后将选择“保存”在抽象工具类SelectionUtil
中,在编辑器中读取(这里是根编辑部分的内容编辑部分),以将相应的模型元素添加到AbtractEditPart
的{{1}}返回的列表中。我(a)不确定使用抽象的util类是否会破坏松散耦合,以及(b)是否具有抽象的util类是一个好的设计模式
getModelChildren()
?* 我知道,不是最准确的例子,因为“正教授”和“博士后”不完全是学位。
答案 0 :(得分:1)
查看Adapter Pattern,IAdaptable界面,并使用您的实际对象填充StructuredSelection,而不是仅为传达选择而创建的其他容器(您已正确识别为有问题)。
编辑:此外,https://eclipse.org/articles/Article-WorkbenchSelections/article.html
答案 1 :(得分:1)
您可以将您放置在选择工具IAdaptable
中的对象设置为允许您查询实际需要使用的类的对象:
MyObject obj = ((IAdaptable)selectionObject).getAdapter(MyObject.class);
您的选择对象将包含:
public Object getAdapter(Class adapter)
{
if (adapter == MyObject.class)
return .... my object instance
return null;
}
您可以更进一步使用IAdapterFactory
类,它允许您使用完全独立的类来调整代码。类似的东西:
class AdapterFactory implements IAdapterFactory
{
@Override
public Object getAdapter(Object adaptableObject, Class adapterType)
{
if (adaptableObject instanceof MyObject && adapterType == MyObject.class)
{
... convert from 'adaptableObject' to MyObject
return myobject;
}
return null;
}
@Override
public Class<?> [] getAdapterList()
{
return new Class<?> [] {MyObject.class};
}
}
您可以使用适配器管理器或使用org.eclipse.core.runtime.adapters
扩展点以编程方式声明工厂。
使用此适配器管理器从您的选择中查找对象:
MyObject obj = (MyObject)Platform.getAdapterManager().getAdapter(selectionObject, MyObject.class);
Eclipse本身使用适配器工厂方法从用户界面对象适应像IFile这样的东西。