锁定老帖子 主题:基于EMF.EDIT实现GEF编辑器属性页
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-11-29
最后修改:2009-11-29
GEF配合EMF是很常用的eclipse可视化应用的解决方案,用EMF的好处就是可以根据uml,schema等生成应用模型代码,并且emf生成的模型代码包含模型的监听机制,省去了很多代码量。同样EMF.EDIT框架包含了模型的content,label provider和property source的支持,应用可以方便使用使用,你可以看到EMF.EDIT框架为每个模型生成了命名形式为 ****ProviderAdapter的类,继承自ItemProviderAdapter,又实现了诸如IEditingDomainItemProvider, IStructuredItemContentProvider, ITreeItemContentProvider, IItemLabelProvider, IItemPropertySource的接口,看出来了吧,这个了还是干了很多事儿的。今天主要讨论如何利用EMF.EDIT提供的对模型property source的支持,实现gef编辑器属性页(又省了N多代码啊,实现属性页支持一般要实现自己的IPropertySource和IPropertyDescriptor,很多代码啊)。先看一下实现后的样子,使用了eclipse tabbed property page: Category tab: A to Z tab: 咋实现的呢?由于俺也有2年多没摸gef/emf了,于是乎想起了当年作为入门学习的八进制同学的blog(http://www.cnblogs.com/bjzhanghao)借鉴了关于利用emf实现属性页的那篇文章,有兴趣的可以看一下。但是使用EMF.EDIT实现属性也还是有点问题。主要有: 1. 没有实现属性分类的可配置化,只能a-z的排列 2. 由于emf属性页改变模型使用emf自己的command框架,和gef的command框架不同,这就造成emf属性页修改模型后,undo有点问题。这个问题八进制也提过,不过现在我看了一下,似乎没当时那么严重了,gef/emf也在发展,dirty可以显示,就是undo完了值有问题。一会儿详细说明原因和解决办法。 下面就谈谈俺如何解决上面这两个问题的,不知道各位大侠有否更好的解决方法,希望指教点化。 先说第2点吧,导致undo问题的原因是在ItemPropertyDescriptor中的setPropertyValue(Object object, Object value)方法,第二个参数value不是真正要改变的值,而是PropertyValueWrapper对象,这个要归功于ItemPropertyDescriptor中的getPropertyValue方法把原本的属性值包装成了PropertyValueWrapper对象,于是乎SetValueCommand中保存的需要undo的属性值是PropertyValueWrapper类型,于是乎在undo是调用setPropertyValue就会出错。 解决办法很简单,实现自己的ItemPropertyDescriptor覆盖setPropertyValue方法: public class KulItemPropertyDescriptor extends ItemPropertyDescriptor { public KulItemPropertyDescriptor(AdapterFactory adapterFactory, ResourceLocator resourceLocator, String displayName, String description, EStructuralFeature feature, boolean isSettable, boolean multiLine, boolean sortChoices, Object staticImage, String category, String [] filterFlags) { super(adapterFactory, resourceLocator, displayName, description, feature, isSettable, multiLine, sortChoices, staticImage, category, filterFlags); } @Override public void setPropertyValue(Object object, Object value) { Object validValue = null; if(value instanceof PropertyValueWrapper) { validValue = ((PropertyValueWrapper) value).getEditableValue(null); } else { validValue = value; } super.setPropertyValue(object, validValue); } } 要使用自己的ItemPropertyDescriptor,需要做的就是实现自己ItemProviderAdapter,让所有**PropertyAdapter继承它,参考代码:
public class CustomItemProviderAdapter extends ItemProviderAdapter { public CustomItemProviderAdapter(AdapterFactory adapterFactory) { super(adapterFactory); } protected ItemPropertyDescriptor createItemPropertyDescriptor( AdapterFactory adapterFactory, ResourceLocator resourceLocator, String displayName, String description, EStructuralFeature feature, boolean isSettable, boolean multiLine, boolean sortChoices, Object staticImage, String category, String[] filterFlags) { return new KulItemPropertyDescriptor( adapterFactory, resourceLocator, displayName, description, feature, isSettable, multiLine, sortChoices, staticImage, category, filterFlags); } }
好,现在第2个问题解决了,第一个问题其实也好解决。应为EMF.EDIT生成的代码,默认每个属性的category是null,可以看一下**ProviderAdapter中的创建PropertyDescriptor的方法,要给属性赋予一个category于是乎实现自己的PropertySource在覆盖createPropertyDescriptor方法,返回自己的IPropertyDescriptor,在自己的IPropertyDescriptor中重写getCategory方法就ok了,参考代码: private class KulPropertySource extends PropertySource { private PropertyHolderType propertyHolder = null; public KulPropertySource(Object object, IItemPropertySource itemPropertySource) { super(object, itemPropertySource); propertyHolder = PropertyConfigLoader.getInstance() .getPropertyHolder(((EObject) object).eClass().getName()); } public IPropertyDescriptor[] getPropertyDescriptors() { Collection<IPropertyDescriptor> result = new ArrayList<IPropertyDescriptor>(); List<IItemPropertyDescriptor> itemPropertyDescriptors = itemPropertySource .getPropertyDescriptors(object); if (itemPropertyDescriptors != null) { for (IItemPropertyDescriptor itemPropertyDescriptor : itemPropertyDescriptors) { result.add(createPropertyDescriptor(itemPropertyDescriptor)); } } return result.toArray(new IPropertyDescriptor[result.size()]); } protected IPropertyDescriptor createPropertyDescriptor( IItemPropertyDescriptor itemPropertyDescriptor) { return new PropertyDescriptor(object, itemPropertyDescriptor) { public String getCategory() { CategoryType ct = PropertyConfigLoader.getInstance() .getCategory(propertyHolder,itemPropertyDescriptor.getDisplayName(object)); if(ct != null) { return ct.getId(); } return "Other"; } }; } } 这个KulPropertySource类是啥?怎么用?其实这个就是你自己的IPropertySourceProvider中getPropertySource要返回的PropertySource对象。那IPropertySourceProvider又是啥?这个就是UndoablePropertySheetEntry.setPropertySourceProvider()方法要传入的参数,UndoablePropertySheetEntry是啥?就是PropertySheetPage.setRootEntry()要传入的参数,PropertySheetPage是啥?你因该了解吧。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 2694 次