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上。

你可能感兴趣的:(eclipse,UI)