欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

GEF中Palette项的属性页显示

程序员文章站 2024-03-24 11:33:10
...

一般来说我们只需要在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