FROM:http://www.blog.edu.cn/user1/19180/archives/2005/372857.shtml
3 Palette的设置
如果你的主界面的继承自GraphicalEditorWithPalette抽象类,那么在初始化主界面的时候,我们必须实现接口getPaletteRoot函数,向系统返回Palette的根。
之前曾经说过,Palette是一个树形结构,在这个结构中有四种主要的节点类型:PaletteRoot、PaletteGroup、PaletteDrawer、ToolEntry,其中,PaletteRoot、PaletteGroup、PaletteDrawer都继承自PaletteContainer,PaletteContainer和ToolEntry则都继承自PaletteEntry,这是Palette树结构的基类。getPaletteRoot就是要向系统返回PaletteRoot对象。
PaletteRoot对象是Palette树结构的树根,可以通过add函数向其中插入PaletteEntry对象。PaletteRoot继承自PaletteContainer,它对PaletteContainer的扩展主要是getDefaultEntry和setDefaultEntry函数,这两个函数分别用来获得和设置缺省操作。注意setDefaultEntry函数的参数是一个ToolEntry类型。
PaletteGroup继承自PaletteContainer类,和PaletteRoot类似,它也可以包含其它的PaletteEntry对象。它没有增加新的操作,只是重设了PaletteContainer中的一些属性。和PaletteDrawer对象不同,PaletteGroup对象不能折叠它的子女,也没有标签。
PaletteDrawer是一个抽屉类型,同样继承自PaletteContainer类,它可以用来归类一组ToolEntry,它们有一个标签,点击这个标签的时候,这组ToolEntry就会被折叠起来。PaletteDrawer对象和PaletteGroup最大的不同就是,PaletteDrawer不能包括container,但是PaletteGroup可以包括别的container,亦即PaletteDrawer不能拥有子树。
ToolEntry是直接继承自PaletteEntry,它描述一个单独的工具,它是一个叶子节点。我们不能向它插入子女,它只能作为上述三个类的子女。ToolEntry是工具入口的父类,其下还有一些子类,常用的比如SelectionToolEntry、MarqueeToolEntry、CreationToolEntry、CombinedTemplateCreationEntry、ConnectionCreationToolEntry。
SelectionToolEntry用于创建选择工具,MarqueeToolEntry则用于创建区域选择工具,你可以直接使用没有参数的构造函数,也可以在构造函数中加入String参数指明工具的名称(默认情况下会有英文工具名)。
CreationToolEntry用于创建一个元素,它是CombinedTemplateCreationEntry和ConnectionCreationToolEntry的基类,它的构造函数是:
java 代码
- CreationToolEntry
- (
- String label,
- String shortDesc,
- CreationFactory factory,
- ImageDescriptor iconSmall,
- ImageDescriptor iconLarge
- )
其中,label是工具的标签,shortDesc是简短的描述,iconSmall和iconLarge是图标,可以设为null。factory是你要创建的元素的创建工厂,这里由于GEF使用了Abstract Factory模式。你可以使用SimpleFactory的实例生成这个工厂,SimpleFactory的构造方法是SimpleFactory(Class aClass),注意它的参数是一个Class对象,你可以使用[类名].class来得到这个对象。现在还有一个问题就是,我应该使用哪个元素的.class呢?换句话说,这个工具创建的哪个对象呢?这里应该注意的是,你创建的对象应该是一个模型元素。原来说过,GEF采用MVC框架,而GEF首先创建M,然后根据M创建C,并在创建C的时候创建V。而根据模型创建EditPart的映射,是在GraphicalEditorWithPalette->configureGraphicalViewer中使用setEditPartFactory来完成的,这又是一个使用Abstract Factory的例子。关于EditPartFactory的问题,我们在后面会有说明。下面举一个例子,比如我要创建一个矩形绘制工具,那么我应该这么写new CreationToolEntry("矩形", "创建一个矩形", new SimpleFactory(RectangleModel.class), null, null),注意RectangleModel是矩形的模型,里面存储了有关这个矩形对象的信息,当然至于是什么信息,就根据你的应用自行定夺了。
CombinedTemplateCreationEntry用于创建可以拖拽的创建工具,它和CreateToolEntry类似,只是它可以进行拖拽。但是要想这个工具支持拖拽,还要给界面增加响应拖拽的消息,所以一般情况下可以用CreationToolEntry代替。它的构造函数和CreationToolEntry类似:
java 代码
- CombinedTemplateCreationEntry
- (
- String label,
- String shortDesc,
- Object template,
- CreationFactory factory,
- ImageDescriptor iconSmall,
- ImageDescriptor iconLarge
- )
第三个参数template就可以设置为factory中的Class对象。
ConnectionCreationToolEntry用于描述创建线形元素的工具,它的构造方法和CreationToolEntry相同。仔细研究ConnectionCreationToolEntry的构造函数,发现其中有一条语句是setToolClass(ConnectionCreationTool.class),这好像是指明了该工具使用的创建工具,这和JBOO的思想很像,将来有时间可以研究一下。
现在再让我们回到NotationBuilderEditor的那个代码中,我们发现在getPaletteRoot函数中,我们是这么写的:
java 代码
- protected PaletteRoot getPaletteRoot() {
- if (this.paletteRoot == null) {
- this.paletteRoot = PaletteFactory.createPalette();
- }
- return this.paletteRoot;
- }
这段代码中首先使用单键模式,然后使用PaletteFactory.createPalette()函数构造PaletteRoot对象。这个PaletteFactory也是我们编写的用于创建PaletteRoot的类,当然你也可以在getPaletteRoot函数中直接进行创建。下面就给出PaletteFactory的源代码:
java 代码
- package pku.oo.util;
-
- import java.util.ArrayList;
- import java.util.List;
-
- import org.eclipse.gef.palette.CombinedTemplateCreationEntry;
- import org.eclipse.gef.palette.ConnectionCreationToolEntry;
- import org.eclipse.gef.palette.CreationToolEntry;
- import org.eclipse.gef.palette.MarqueeToolEntry;
- import org.eclipse.gef.palette.PaletteContainer;
- import org.eclipse.gef.palette.PaletteDrawer;
- import org.eclipse.gef.palette.PaletteGroup;
- import org.eclipse.gef.palette.PaletteRoot;
- import org.eclipse.gef.palette.SelectionToolEntry;
- import org.eclipse.gef.palette.ToolEntry;
- import org.eclipse.gef.requests.SimpleFactory;
-
- import pku.oo.model.RectangleModel;
-
-
- public class PaletteFactory {
- public static PaletteRoot createPalette() {
- PaletteRoot paletteRoot = new PaletteRoot();
- paletteRoot.addAll(createCategories(paletteRoot));
- return paletteRoot;
- }
-
- private static List createCategories(PaletteRoot root) {
- List <palettecontainer></palettecontainer> categories = new ArrayList <palettecontainer></palettecontainer> ();
-
- categories.add(createGeneralControlGroup(root));
- categories.add(createGraphicsDrawer());
- categories.add(createLayoutDrawer());
- categories.add(createDecoratorDrawer());
-
- return categories;
- }
-
- private static PaletteContainer createGeneralControlGroup(PaletteRoot root) {
- PaletteGroup controlGroup = new PaletteGroup("工具栏");
-
- List<toolentry></toolentry> entries = new ArrayList<toolentry></toolentry>();
- ToolEntry tool =null;
- tool = new SelectionToolEntry("选择工具");
- entries.add(tool);
- root.setDefaultEntry(tool);
-
- tool=new MarqueeToolEntry("区域选择工具");
- entries.add(tool);
-
- controlGroup.addAll(entries);
- return controlGroup;
- }
- private static PaletteContainer createGraphicsDrawer() {
- PaletteDrawer drawer = new PaletteDrawer("基本图元");
- List<toolentry></toolentry> entries = new ArrayList<toolentry></toolentry>();
- ToolEntry tool = new CreationToolEntry("矩形", "创建一个矩形", new SimpleFactory(
- RectangleModel.class), null, null);
- entries.add(tool);
- drawer.addAll(entries);
- return drawer;
-
- }
-
- private static PaletteContainer createLayoutDrawer() {
-
- PaletteDrawer drawer = new PaletteDrawer("布局");
- List<toolentry></toolentry> entries = new ArrayList<toolentry></toolentry>();
- drawer.addAll(entries);
- return drawer;
- }
- private static PaletteContainer createDecoratorDrawer() {
-
- PaletteDrawer drawer = new PaletteDrawer("修饰");
- List<toolentry></toolentry> entries = new ArrayList<toolentry></toolentry>();
- drawer.addAll(entries);
- return drawer;
- }
- }
4 Outline Page的设置
这里只是介绍如何配置Outline Page,由于Outline Page的原理和主编辑器框架十分类似,因此其结构也比较复杂,关于如何编写Outline Page,将在后面说明。
在上面的NotationBuilderEditor例子中,getAdapter函数是这样写的:
java 代码
- public Object getAdapter(Class type) {
- if (type == IContentOutlinePage.class)
- return new OutlinePage();
- return super.getAdapter(type);
- }
我们说过,这个getAdapter不仅可以创建大纲视图,还可以创建其它的附属视图,那么你需要根据这个type来进行创建。对于大纲视图来说,我们创建了一个OutlinPage对象,这个对象的代码也在上面给出了,它是作为NotationBuilderEditor的内嵌类出现的,我们再重放一下它的代码:
java 代码
- class OutlinePage extends ContentOutlinePage {
- public OutlinePage() {
- super(new TreeViewer());
- }
-
- public void init(IPageSite pageSite) {
- super.init(pageSite);
- }
-
- public void createControl(Composite parent) {
- super.createControl(parent);
- getSelectionSynchronizer().addViewer(getViewer());
- getViewer().setEditDomain(getEditDomain());
- getViewer().setEditPartFactory(new TreePartFactory());
- getViewer().setContents(getDiagram());
- }
-
- public void dispose() {
- getSelectionSynchronizer().removeViewer(getViewer());
- super.dispose();
- }
- }
仔细看OutlinePage的createControl函数中的语句是否感觉似曾相识呢?不错,它和NotationBuilderEditor中的很多语句都很像,这就表明Outline Page的工作原理和主界面(具体说就是GraphicalEditorWithPalette)的原理是相似的,下面简单说明一下:首先,这个Outline Page设置了自己的同步的视图(getSelectionSynchronizer),那就是我们的主界面视图,然后它设置自己的编辑区域和EditPartFactory,最后设置自己的编辑内容,这和主编辑区域的内容是一样的,因为它们都是对同一文档进行编辑,只不过是不同的表现形式。大纲一旦设置了自己的EditPartFactory,当它发现自己的同步视图发生了变化(注意,它监测的是同步视图的模型部分),就会调用自己的EditPartFactory来更新自己的视图,其过程同样先是创建模型对应的EditPart,由EditPart创建Figure。
5 EditPartFactory
EditPartFactory的作用,抽象地讲,是要建立模型和EditPart之间的映射,使得系统可以根据模型创建对应的EditPart。EditPartFactory并不难写,只是模型、EditPart的概念和关系现在还不能解释,等到下一个章节会有说明。下面的一个例子给出了一个简单的EditPartFactory:
java 代码
- package pku.oo.part;
-
- import org.eclipse.gef.EditPart;
- import org.eclipse.gef.EditPartFactory;
-
- import pku.oo.model.Diagram;
- import pku.oo.model.RectangleModel;
-
-
- public class PartFactory implements EditPartFactory {
-
- public EditPart createEditPart(EditPart context, Object model) {
- EditPart part = null;
- if (model instanceof Diagram)
- part = new DiagramPart();
- else if(model instanceof RectangleModel) {
- part = new RectanglePart();
- }
-
- part.setModel(model);
- return part;
- }
- }
其中只有一个函数createEditPart,context是上下文,model是模型。这里需要注意的是,不要忘记为主编辑区域创建EditPart。