上一篇Eclipse GEF中对draw2d进行了一介绍,这一篇主要是GEF(MVC)的一些内容。GEF中的MVC如下图所示:
简而言之,视图层View就是我们能看到的东西,模型Model主要存储展示的数据,毕竟图形只是图形不能包含任何又实在意义的东西,我们操作的任何数据都要存放在Model层,Controller是一个很忙的角色,它随时待命,把Model的数据传送给View层,最终形成我们所看到的图形与数据。
在上一篇文章类图的Figure,即我们利用Draw2D作为我们的视图层,但是只是有视图,没有其它实用的功能,下面通过一些实例为我们的例子添加一些实用的功能。
在这里先不对API中的接口和类做过多的分析,在后续的文章中有机会写到,首先我们要先定义一个Controller,在gef/editpart包中为我们封装好了一个类:AbstractGraphicalEditPart,这个类封装了一些图形操作需要用到的方法(如添加图形间的连接),省去了我们自己编写图形EditPart的工作。下面我们创建一个UMLEditPart类,继承AbstractGraphicalEditPart,这样我们的AbstractUMLEditPart就具有图形EditPart相关的功能了,并且实现NodeEditPart接口,使我们的EditPart类具有节点EditPart功能。
没有任何实现方法的UMLEditPart类如下:
package com.blog.uml.editpart;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
public class UMLEditPart extends AbstractGraphicalEditPart implements NodeEditPart{
//NodeEditPart中声明的方法,根据ConnectionEditPart获取源连接锚
@Override
public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart arg0) {
// TODO Auto-generated method stub
return null;
}
//NodeEditPart中声明的方法,根据Request获取源连接锚
@Override
public ConnectionAnchor getSourceConnectionAnchor(Request arg0) {
// TODO Auto-generated method stub
return null;
}
//获取目标连接锚
@Override
public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public ConnectionAnchor getTargetConnectionAnchor(Request arg0) {
// TODO Auto-generated method stub
return null;
}
//创建Figure
@Override
protected IFigure createFigure() {
// TODO Auto-generated method stub
return null;
}
//创建EditPolicies
@Override
protected void createEditPolicies() {
// TODO Auto-generated method stub
}
}
上面的方法确实让人初次看让人搞不明白,如果之前对GEF有一定了解,可能会容易看懂,但是第一次看(学习GEF一定要对Java很熟悉),上面又很多陌生的类比如Request 、EditPolicy,这涉及到GEF的架构。
上图是EclipseHelp中的GEF经典的high-level view在Interaction Boundary右侧的部分Controller、Model、Figure我们多少熟悉一点,另外还有EditPartViewer ,一个EditPart如果想要展现它的View,必须要有一个依托,这个依托者称为EditPartViewer ,或者说是View的承载者。
EditPart介绍
EditPart关联着视图与模型,但同样也有自己的结构,与Figure和Model相同,EditPart同样维护子EditPart,举一个例子,一个Model可能是由包含多个节点的图构成的,同样一个图的EditPart也可能包含多节点的图EdiPart孩子:
现在假设现在要对EdiPart进行编辑操作,在编辑过程中就会产生模型与视图的交互,交互过程如下:
1.所谓的交互一定是事件引起的,比如键盘,鼠标,拖拽等,那么在发送这些交互请求之前一定要确定交给哪个EditPart处理(其实过程要更复杂),在有鼠标的操作中,可以认为此时的target就是鼠标所指向的那一部分,当然有些操作并没有target。
2.有些交互操作是需要反馈的,比如鼠标正在拖拽图中一个顶点,由于我们的鼠标一直指向的部分是图,或者说我们移动节点,无非就是想要把节点放到图中的某一坐标,此时的Target就是这个图,而正在移动的节点就是source,source就是正在被操作的对象,source最后会置于相应的target上,这就是target和source的区别,英文的意思很符合这个特点,当正如开始所说的,移动节点source时每一步都是需要反馈的,也就是节点确实被移动了。
3.以上的操作现在只经过了用户,EditPart和视图,还没有经过Modal,所以下一步必然和Modal有关了 ,既然交互后视图的某一部分发生相应的变化,与之相关联的Modal属性值必然会发生相应的更改,属性变化是Command起了作用,Command指令旨在接受EditPart发出的命令,作用于Modal,使之做出相应的更改,当然如果Command处理后认为不可执行,也会反映给操作的用户
EditPolicies
EditPart不直接处理请求,而是委托给EditPolicy处理,每一个EditPolicy都关注一个Editing,所以在创建EditPart的时候需要为其指定一些EditPolicy。这种设计模式可以方便的为EditPart添加功能。
EditDomain
编辑域是一个起到管理作用的类,它绑定了一个编辑器、若干个查看器和若干个工具。因此它定义了真实的编辑器。编辑域还提供一个命令堆栈,用来保存所有执行过的命令,有两点好处:
1.可实现重做和不做的操作
2.可查看模型是否被改动。
The Selection Tool
在现代的应用程序中,程序要实现的一个最重要功能就是拖拽。
为了使用户在GEF应用中实现拖拽更加容易,GEF本身提供了一些类和概念。例如,你不需要处理SWT的拖拽源对象[DragSource]和其他低级别的对象。
在GEF中,用户需要实现的就是向编辑查看器[EditPartViewer]添加拖拽源监听者[TransferDragSourceListener]和拖拽目标监听者[TransferDrogTargetListener]。前者的可以使编辑查看器成为拖拽源,即支持用户从该编辑查看器中往出拽,而后者可以使编辑查看器成为拖拽目标,即支持用户向该编辑查看器里拖。
当在GEF应用中为查看器实现拖拽监听者时,要确保该类继承的父类来自于GEF框架。
拖拽原理:当用户在支持拖拽源的查看器上拽出时,GEF框架产生一个相应的模版对象,该对象将从框架中获得用户想要创建对象的类信息。当用户在支持拖拽目标的查看器上松开鼠标时,拖放结束的事件将产生,TemplateTransferDropTargetListener对象将根据模版对象创建相应的实例。