在这说一下,其实GEF七天,并不是把我每天知识的总结,而是学习了GEF七天,我想通过这样一种方式将我这七天的收获和对GEF框架的理解,写出来,也算是对这一周的总结吧
其实这一章我们介绍gef的核心控制器了,在写之前,我们先介绍一下GEF要用到的设计模式.
在学GEF中给我感受最深的是,设计模式无处不在,除了上章中说的观察者模式外.GEF框架还运用了COMMAND(命令)模式,Policy(策略)模式.这两个模式,策略模式,貌似本团对有人介绍过了,而command模式是我现研究的(也许会单独写个随笔,谈谈心得).
好了,我们言归正传.先说一下,GEF控制器的实现原理.
控制器是由一组EditPart对象共同组成的,每一个模型对象都对应一个EditPart对象。应用程序中需要有一个EditPartFactory对象负责根据给定模型对象创建对应的EditPart对象,这个工厂类将在创建模型时被调用。
控制器是GEF中最复杂的一部分,GEF把控制器完成的工作又分成了几个部分,包括请求和编辑策略及引申出来的命令模式,如下图:
用户的编辑操作被转换为一系列请求(Request),Eclipse中有很多种类的请求,这些种类在GEF里被成为角色(Role)。在GEF里有图形 化和非图形化这两大类角色,前者如“LayoutRole”对应和布局有关的操作,后者如“ConnectionRole”对应和连接有关的操作等。角色 这个概念是通过编辑策略(EditPolicy)来实现的,EditPolicy的主要功能是根据请求创建相应的命令(Command),而后者会直接操 作模型对象。
对每一个EditPart,用户都可以“安装”一些EditPolicy。用户对这个EditPart的特定操作会被交给已安装的对应EditPolicy处理。这样做的直接好处是可以在不同EditPart之间共享一些重复操作。
这样说有点抽象,还是用代码说话,接着上回那个DEMO来所,该是editpart部分了.
对于模型的每个独立部分,我们都必须定义控制器。所谓“独立”,指的是这个实体 都可以作为用户操作的对象。一个比较好的原则就是任何可以被选择,或删除的对象 都应该有它自己的编辑部件(来自于IBM)。
所有的部件均实现了createFigure()(返回模型在视图中的图形表示), createEditPolicies()(安装相应的策略),refreshVisuals() (刷新视图), propertyChange()(接受模型改变并执行不同的操作,刷新视图) ,activate()(自 己加入设为监听器) 和 deactivate()(将自己从监听器的列表中移除)五个方法。
所以由上回的模型,我们就可以建立控制器了,首先我们将他也抽象化:
现建基类SpecificPart
package hya.gef.demo.shapes.parts;

import hya.gef.demo.shapes.models.ElementModel;

import java.beans.PropertyChangeListener;

import org.eclipse.gef.editparts.AbstractGraphicalEditPart;


然后是shape模型对应的part类
由于图形之间是可以连接的所以我们还同时让其实NodeEditPart接口。通过实现这个接口,编辑部件可以定义源锚点和目标锚点,锚点就是图形和连接接触的连接点 。重写了getModelSourceConnections方法和getModelTargetConnections方法。这两个方法的任务就是要通知GEF有关该图形的源连接和目标连接
createFigure()方法,根据返回的对象不同,返回 不同的图形实例(矩形,三角形和圆形)。主要通过方法createFigureByGetModel()来判断。
createEditPolicies()安装了两个策略,ShapeComponentEditPolicy提供命 令将一个 图形从图删除。第二个策略处理图形间连接的创建和转移,它的索引字是 GRAPHICAL_NODE_ROLE。
其他的两个模型对应的part也差不多
DiagamEditPart
package hya.gef.demo.shapes.parts;

import hya.gef.demo.shapes.models.DiagramModel;
import hya.gef.demo.shapes.parts.policy.ShapesXYEditPolicy;

import java.beans.PropertyChangeEvent;
import java.util.List;

import org.eclipse.draw2d.ConnectionLayer;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.ShortestPathConnectionRouter;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.editpolicies.RootComponentEditPolicy;


ConnectionEditPart

package hya.gef.demo.shapes.parts;

import hya.gef.demo.shapes.commands.ConnectionDeleteCommand;
import hya.gef.demo.shapes.models.Connection;


import org.eclipse.draw2d.BendpointConnectionRouter;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PolygonDecoration;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editparts.AbstractConnectionEditPart;
import org.eclipse.gef.editpolicies.ConnectionEditPolicy;
import org.eclipse.gef.editpolicies.ConnectionEndpointEditPolicy;
import org.eclipse.gef.requests.GroupRequest;

}
连接编辑部件,它继承自AbstractConnectionEditPart类。createFigure()方法返回了一个带箭头的连接线。
他安装了两个策略第一个是ConnectionComponentPolicy,它提供删除命令给Delete菜单项 所需要的action。第二个策略提供了一种视觉上的选择反馈,即当一个连接被拖动时,GEF 没有办法获取连接两端的标识.
那么GEF是怎么知道模型与PART之间的对应关系的呢,所以应该建立模型与part之间的映射,这个我们用到了工厂模式
建立part工厂:ShapesEditPartFactory

package hya.gef.demo.shapes.parts;

import hya.gef.demo.shapes.models.Connection;
import hya.gef.demo.shapes.models.DiagramModel;
import hya.gef.demo.shapes.models.ShapeModel;

import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;



}
这是,核心的part就建立完了.我们可以看到他们当中的方几乎一样,狭义回我们将加入策略和命令部分,并更加详细的通过代码来说明GEF的工作过程.