GEF作为一个图形框架,对于其中图形元素的属性的设定是非常重要的,这是因为每一个图形元素的背后都是一个模型,而这些模型可以包含很多业务数据,如果我们最终选定GEF作为我们应用的解决方案的话,我们可以利用property view来实现对这些业务数据属性的设定; 这就是我们这里即将讨论的问题。
Eclipse中property view一共有两种,普通的property view,也就是key/value类型的property view和tabbed property view,后者将viewer分成了若干个tab page;利用tab page将不同的属性分组;从我使用的经验来看,我比较倾向于前者,因为前者可以解决绝大部分的问题,即便是我们希望编辑一个非常复杂的属性,也可以自定义属性编辑器来完成。比如我们常用的SWT Designer就是使用了第一种方式,当然我们不能否认后一种方式由于可以在property viewer中自定义布局及控件,界面比较炫,但是由于需要三个扩展点的配合,操作起来还是比较麻烦的;不过这里我不是要讨论两者的优劣,而是要讨论如何使用这两个东西,因此还是书归正传吧。
org.eclipse.ui.views.properties.tabbed,这是绝不能少的。只有这样,属性页面才能显示出来;
首先要想使用eclipse的property view,必须在相应的RCP程序或者Plugin程序中配置Dependencies,如果是第一种,需要增加org.eclipse.ui.views,如果是后一种,需要增加
其次,如果应用为RCP,那么可以在视图文件中以“org.eclipse.ui.views.PropertySheet”为id值,增加一个view,这个id就是Eclipse默认的属性页id;如果你记不住,那么用IPageLayout.ID_PROP_SHEET好了;当然这一步并不是必须的,你可以在自己的WorkbenchWindowAdvisor中配置setShowFastViewBars(true);这样程序运行时就可以通过fast view bar来动态打开这个view了,怎么做随你;我的建议是两者都要,以防用户将属性页关闭了,无法打开;(题外话是可以建一个Command/Action来打开属性页,但是我觉得没有必要);
经过以上两步,我们的准备工作就完成了,下面就是如何在我们的Editor点选了某一个图形元素时,属性页能够被通知。事实上这里说的图形元素是不确切的,而应该是这个图形元素对应的模型元素;让我们把眼光放得更宽广一点,事实上并不仅仅局限于GEF,任何实现了IPropertySource接口的模型元素都可以被属性页显示出来;
模型元素实现IPropertySource后需要实现以下方法,具体含义就不说了:
·public Object getEditableValue();
·public IPropertyDescriptor[] getPropertyDescriptors();
·public Object getPropertyValue(Object id);
·public boolean isPropertySet(Object id);
·public void resetPropertyValue(Object id);
·public void setPropertyValue(Object id, Object value);
其中最最重要的是第1、2和6个方法;尤其是第二个方法尤为重要。在定义PropertyDescriptor时,Eclipse已经提供了两个主要的属性描述类TextPropertyDescriptor和ComboBoxPropertyDescriptor,分别对应文本框和组合下拉框,但是如果是比较复杂的属性,例如像字体、颜色这样的属性,相应的属性描述类就要自己定义了,这时需要继承PropertyDescriptor类定义自己的属性描述类,而在定义这个类的过程中,必须指定相应的CellEditor,也就是属性编辑器类,我的建议是对于非常复杂的属性,比如属性中包含了很多不同类型的子属性,这些子属性的个数会发生变化等等,那么可以定义一个DialogCellEditor的子类,以对话框的形式显示所有的子属性,并在对话框中对有子属性进行显示、操作。也就是说:
MyPropertyDescriptor(继承PropertyDescriptor)--->MyCellEditor(继承CellEditor)--->MyDialog(继承Dialog)--->子属性显示、操作;
经过这些操作对于第一种property view已经足够了,在GEF应用中当你选择了某一个图形时,其属性就能显示出来了。但是对于后者来说,这还远远不够,因为它比较吊!
对于tabbed property view来说,以上的步骤是不能缺的,除此而外还需要配置org.eclipse.ui.views.properties.tabbed.propertyContributor、org.eclipse.ui.views.properties.tabbed.propertyTabs和org.eclipse.ui.views.properties.tabbed.propertySections三个扩展点;第一个扩展点的最主要作用是通知属性页究竟是workbench part为属性页提供属性,说白了(我的理解,就是所有我们想最终选择的那些元素放在了哪个workbench part上),因此相应的contributorId往往是editor的id;这里需要超级注意的是对于GEF应用来说,必须要配置typeMapper,也就是定义实现ITypeMapper的类,如下:
public Class mapType(Object object) {
Class type = object.getClass();
if(object instanceof EditPart) {
type = ((EditPart)object).getModel().getClass();
}
return type;
}
没有这一步,毛也显示不出来;其实我们可以通过以上代码看出,这个转换就是将控制器转换为模型;此外相应的editor必须继承ITabbedPropertySheetPageContributor接口,提供getContributorId()方法,也就是返回editor的ID;而且还要重载getAdapter方法提供如下实现:
public Object getAdapter(Class adapter) {
if(adapter == IPropertySheetPage.class) {
return new TabbedPropertySheetPage(this);
}
return super.getAdapter(adapter);
}
当完成了以上所有步骤之后,分页的属性页就显示出来了。具体的Section的定义就不说了,其实不过是定义public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage)这个函数罢了;它和其他的createControl没什么区别,只是我们可以利用getWidgetFactory()来构造界面元素,其他的没有什么新鲜的;
以上就是属性页在GEF中的应用。