般若菩提(丁丁)  

GEF源码分析(三) GEF 的树状构架 ___ Model/EditPart/Figure

树状对象模型 建立过程
 

如果要建立可编辑2D图形程序,比较基本的要有以下几个主要需求

  • 一方面我们有一个model对象组,这些包含了拥有一些业务以及UI展现上的数据;
  • 另一方面我们有一个视图它将包含一组可视化对象,这些可视化对象定义了如何在屏幕上描绘;
  • 用户能够使用鼠标和键盘修改图形视图。这需要在程序的内部通过某种方式建立在UI对象和model关联方式,透过二者的关联,当视图发生改变时,需要引发model改变,而model也有可能由于某种业务逻辑发生改变,需要通知放映到视图上。

这样我们就提供给用户一个图形交互的方式来修改业务model,具有这种能力的程序我们可以称之为可编辑2D图形程序(a graphical editor)。

 

 

上一篇讨论到在GEF框架中形成了三个对应的树状对象模型。


为了达到之上的需求,GEF通过EditPart如上图建立了Viewmodel之间的关联关系。


于是问题随之而来:

这些树状对象模型 如何?何时?创建

尤其困难的是通过怎样简捷的方法在EditPart中建立它们的关联呢?

 

 

GEF给出如下答案:


 

从上图可以看出在GEF是通过EditPartFactory根据以存在的Model 来创建并设置不同的EditPart

EditPartFactory的接口如下:

EditPart createEditPart(EditPart context, Object model);

其中modelObject类型,因此可以看出在GEFmodel没什么过多的约束,context是于要创建的EditPart有关联的EditPart,例如是将要创建EditPartParent

这样GEF通过一下时序图就非常轻松的(学起来可不轻松:(,根据model对象框架建立了另外两个EditPartsFigures树状体系。[链接]见下附图 时序图

其中在创建过程中重要的方法:

class ShapesEditor

protected void configureGraphicalViewer() { .. }

protected void initializeGraphicalViewer() {..}

 

class ShapesEditPartFactory

public EditPart createEditPart(EditPart context, Object modelElement) {

// get EditPart for model element

EditPart part = getPartForElement(modelElement);

// store model element in EditPart

part.setModel(modelElement);

return part;

}

 

/**

* Maps an object to an EditPart.

* @throws RuntimeException if no match was found (programming error)

*/

private EditPart getPartForElement(Object modelElement) {

//根据不同的model产生不同EditPart

if (modelElement instanceof ShapesDiagram) {

return new DiagramEditPart();

}

if (modelElement instanceof Shape) {

return new ShapeEditPart();

}

if (modelElement instanceof Connection) {

return new ConnectionEditPart();

}

throw new RuntimeException(

"Can't create part for model element: "

+ ((modelElement != null) ? modelElement.getClass().getName() : "null"));

}

 

 

class ShapeEditPart

public void setModel(Object model) {

if (getModel() == model)

return;

this.model = model;

}

 

protected IFigure createFigure() {

IFigure f = createFigureForModel();

f.setOpaque(true); // non-transparent figure

f.setBackgroundColor(ColorConstants.green);

return f;

}

 

/**

* Return a IFigure depending on the instance of the current model element.

* This allows this EditPart to be used for both sublasses of Shape.

*/

private IFigure createFigureForModel() {

//根据不同的model创建不同的figure

if (getModel() instanceof EllipticalShape) {

return new Ellipse();

} else if (getModel() instanceof RectangularShape) {

return new RectangleFigure();

} else {

// if Shapes gets extended the conditions above must be updated

throw new IllegalArgumentException();

}

}



 

至此、我们就得到了树状的MVC框架,但是,还是有些问题没有解决:
例如、已存在一个三角图形EditPart,我们想重用它,但是我们还需要增加(或删去)边框可调整的特性,如何保证无需重新建立一个新的EditPart,或者做出丑陋的继承,当功能不断组合后,出现无数子EditPart类?
在界面操作过程中,我们希望面对的是边框调整事件,或者是编辑文本事件,而不是原始的鼠标和键盘事件?
希望EditPart能够自动无误地把事件通知到相应的父及子EditPart中,同时能够按照正确的顺序对事件做出响应?
如何由框架自动完成Undo及Redo功能?
.....

posted on 2005-12-01 11:09  般若菩提  阅读(3036)  评论(2编辑  收藏  举报