GEF中Palette项的属性页显示
一般来说我们只需要在GraphicalViewer部分显示在Property页即可。
要支持GraphicalViewer和PaletteViewer都能对属性页有支持,就有点复杂。
每个Site只能有一个SelectionProvider,正是这个SelectionProvider里选中的对象才有可能显示在属性页。在GEF中,情况下,GraphicalViewer被设置为这个EditorSite的SelectionProvider。因为只能有一个SelectionProvider,因此我们不能同时设置PaletteViewer为SelectionProvider。
所以,首先我们就需要自定义一个SelectionProvider,它聚合这两部分的Provider,并且在这两者之间切换,如下:
public class CustomSelectionProvider implements ISelectionProvider,
FocusListener {
private GraphicalViewer graphicalViewer;
private PaletteViewer paletteViewer;
private Widget focusControl;
public CustomSelectionProvider(GraphicalViewer graphicalViewer,
PaletteViewer paletteViewer) {
super();
this.graphicalViewer = graphicalViewer;
this.paletteViewer = paletteViewer;
this.graphicalViewer.getControl().addFocusListener(this);
this.paletteViewer.getControl().addFocusListener(this);
}
public void addSelectionChangedListener(ISelectionChangedListener listener) {
graphicalViewer.addSelectionChangedListener(listener);
paletteViewer.addSelectionChangedListener(listener);
}
public ISelection getSelection() {
if (focusControl == graphicalViewer.getControl())
return graphicalViewer.getSelection();
else if (focusControl == paletteViewer.getControl()) {
return paletteViewer.getSelection();
}
return null;
}
public void removeSelectionChangedListener(
ISelectionChangedListener listener) {
graphicalViewer.removeSelectionChangedListener(listener);
paletteViewer.removeSelectionChangedListener(listener);
}
public void setSelection(ISelection selection) {
if (focusControl == graphicalViewer.getControl())
graphicalViewer.setSelection(selection);
else if (focusControl == paletteViewer.getControl())
paletteViewer.setSelection(selection);
}
public void focusGained(FocusEvent e) {
focusControl = e.widget;
if (paletteViewer.getControl() == focusControl) {
ISelection selection = paletteViewer.getSelection();
setSelection(null);
setSelection(selection);
} else if (graphicalViewer.getControl() == focusControl) {
ISelection selection = graphicalViewer.getSelection();
setSelection(null);
setSelection(selection);
}
}
public void focusLost(FocusEvent e) {
}
}
有了这个自定义的SelectionProvider,我们就可以用它来替换Editor中缺省的GraphicalViewer,重写Editor的createPartControl()方法:
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
PaletteViewer paletteViewer = ((CustomPaletteViewerProvider) getPaletteViewerProvider())
.getPaletteViewer();
CustomSelectionProvider selectionProvider = new CustomSelectionProvider(
getGraphicalViewer(), paletteViewer);
getSite().setSelectionProvider(selectionProvider);
}
这里的CustomPaletteViewerProvider也是一个自定义的PaletterViewerProvider,因为缺省的PaletterViewerProvider没有提供方法返回对象的PaletteViewer。自定义一个也很简单,增加一个返回PaletteViewer的方法即可:
public class CustomPaletteViewerProvider extends PaletteViewerProvider {
private PaletteViewer paletteViewer;
public CustomPaletteViewerProvider(EditDomain graphicalViewerDomain) {
super(graphicalViewerDomain);
}
@Override
public PaletteViewer createPaletteViewer(Composite parent) {
paletteViewer = super.createPaletteViewer(parent);
return paletteViewer;
}
public PaletteViewer getPaletteViewer() {
return paletteViewer;
}
}
然后用这个PaletteViewerProvider替换缺省的,重写Editor中的方法:
@Override
protected PaletteViewerProvider createPaletteViewerProvider() {
return new CustomPaletteViewerProvider(getEditDomain());
}
这样,一个可以左右切换的SelectionProvider就准备好了,它可以同时支持Palette和Graphical两个部分。
最后一个步骤就是怎么让Property View感知他们。每次一个Site上的SelectionProvider选项发生变动的时候,Property View都会被通知,去检查当前选中对象是否支持在Property页上显示。一个能够在Property页上显示的对象有两种实现方式:
1.对象实现IPropertySource接口
2.对象实现IAdaptable接口,在方法getAdater(Class)里,实现IPropertySource.class的支持。
如果用第一种方法,那显示我们需要重写所有的Palette部分,那比较复杂。因此我们选择第二种方法。
对于第二种方式,如果在每种节点类型的getAdapter(Class)方法里追加IPropertySource的实现,那最终结果和使用方法一一样,得把整个Palette都重写一次。
对于方法2,我们还有第二个选项,扩展“org.eclipse.core.runtime.adapters”扩展点。
所有的Palette上的对象,也都是一个AbstractEditPart,这个对象的getAdapter(Class)的实现是:如果没有找着匹配的实现,则最后会查找Eclipse里所有已经注册的adapter对。例如:
public Object getAdapter(Class key) {
if (AccessibleEditPart.class == key)
return getAccessibleEditPart();
return Platform.getAdapterManager().getAdapter(this, key);
}
因此我们可以通过扩展“org.eclipse.core.runtime.adapters”扩展点来达到目的,可以如下扩展:
<extension
point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="org.eclipse.gef.ui.palette.editparts.PaletteEditPart"
class="。。。.PaletteAdapterFactory">
<adapter
type="org.eclipse.ui.views.properties.IPropertySourceProvider">
</adapter>
</factory>
</extension>
其中adaptableType表示对哪种类型的结点应用,adapter里的type表示这个adapter应该返回一个什么类型的对象,class就是具体的实现类。例如一个简单的实现如下:
public class PaletteAdapterFactory implements IAdapterFactory {
public Object getAdapter(Object adaptableObject, Class adapterType) {
return new CustomPropertySourceProvider(
(PaletteEditPart) adaptableObject);
}
public Class<PaletteEditPart>[] getAdapterList() {
return new Class[] { PaletteEditPart.class };
}
}
class CustomPropertySourceProvider implements IPropertySourceProvider {
private PaletteEditPart editPart;
public CustomPropertySourceProvider(PaletteEditPart editPart) {
this.editPart = editPart;
}
public IPropertySource getPropertySource(Object object) {
return new CustomPropertySource(editPart);
}
}
class CustomPropertySource implements IPropertySource {
private PaletteEditPart editPart;
public CustomPropertySource(PaletteEditPart editPart) {
this.editPart = editPart;
}
public Object getEditableValue() {
return null;
}
public IPropertyDescriptor[] getPropertyDescriptors() {
IPropertyDescriptor[] descriptors = new IPropertyDescriptor[1];
descriptors[0] = new TextPropertyDescriptor("TEXT", "ToString");
return descriptors;
}
public Object getPropertyValue(Object id) {
return editPart.toString();
}
public boolean isPropertySet(Object id) {
return true;
}
public void resetPropertyValue(Object id) {
}
public void setPropertyValue(Object id, Object value) {
}
}
这个实现的效果就是,每次选中Palette中的一个结点,则把它的toString()结果显示在Property上。
上一篇: vue 后端直接返回文件流 如何进行操作