- 浏览: 27266 次
- 性别:
- 来自: 广州
文章分类
最新评论
一、GEF简介
GEF(Graphical Editing Framework)是一个图形化编辑框架,它允许开发人员以图形化的方式展示和编辑模型,从而提升用户体验。
GEF的优势是提供了标准的MVC(Model-View-Control)结构,开发人员可以利用GEF来完成以上这些功能,而不需要自己重新设计。与其他一些MVC编辑框架相比,GEF的一个主要设计目标是尽量减少模型和视图之间的依赖,好处是可以根据需要选择任意模型和视图的组合,而不必受开发框架的局限(实际上视图基本是Draw2D的实现)。
二、GEF各项目的关系图:
1、 Draw2D:建立了二维的图形库(树状图形部件Figure),负责显示二维的图形展示。
2、GEF:(Graphical Editing Framework)建立MVC构架,代码利用Draw2D作为自己的View部分,主要代码实现复杂的树状(于Model分别对应)的控制器。实现的框架具有很高的可复用等特性,例如:将图形部件功能分解为多个EditPolicy,这样使用者可以通过installEditPolicy接口来定制,以及扩充自己的某一功能特征。
3、EMF:(Eclipse Modeling Framework)首先在一个轻量级项目以及项目初期开发,Model常常采用拥有Property的Java对象来简单明了表示【即 Plain Old Java Objects (POJOs)】。EMF定义了一套Ecore元模型,使得Model具有易于维护、易于扩充、易于数据交换等特性的Model Framwork。因此、在实际中大型的项目中往往会采用Draw2D+GEF+EMF的方式来实现整体的MVC模式。例如:ROSE的最新版本 IBM.Rational.Software.Architect就是采用了这种构架。
4、GMF:(Graphical Modeling Framework )使用了GEF和EMF,建立了两个之间的桥梁框架,同时实现了一些领域上的典范应用,如UML图,甘特图,脑图等。(项目正在进行中这些功能还未完备。可以用来参考以实现自己的一个标准的GEF+EMF的应用)。
5、各项目依赖关系:
如上图:使用者可以有以下几种用法:
EMF: Model管理层
Draw2D: 二维图形展现
Draw2D + GEF: 二维图形的简单编辑模块
Draw2D + GEF + EMF: 二维图形的编辑模块
Draw2D + GEF + EMF + GMF:基于GMF提供的图形编辑功能之上扩展
三、Draw2D技术
1、Draw2D是什么?
轻量级框架:轻量级框架,使用LightweightSystem类把SWT和Draw2D 连接起来,它把鼠标事件和画图事件从SWT 转发给Draw2D的图形上。它是Draw2D的核心类。
Draw2d中的Graphics和GC的对比:
Graphics类的很多方法和GC的完全一样,尤其是绘制线和几何图形、显示图片以及字体等方面。但Graphics还提供了一个不同于GC的功能:它的对象可以在LightweightSystem中移动。这意味着当你想要改变一个图形组件的位置时,Draw2d提供了它自己的拖拽机制来将一个Figure移动到合适的位置。
2、 LightweightSystem 主要包含三个组成部件:
LightweightSystem不依赖于特定操作系统,这意味着你失去了SWT/Jface重量级组件的优势,比如快速的响应和本地外观风格,但你得到的,是对自己的组件的外观与行为的完全控制。
1).根图形【IFigure】: 根图形是RootFigure类的实例,应用程序的根图形必须建立在它之上。它继承了一些SWT Canvas的图形环境,如颜色,字体等。
2).事件转发器【EventDispatcher】: 事件转发器把SWT事件转换成相应Draw2D事件。它可以跟踪那个图形被聚焦,那个图形是被鼠标点击的目标图形。它还控制tooltip的激活。它为想捕捉鼠标的图形提供支持。
3).更新管理器【UpdateManager】:更新管理器是负责画和更新Draw2D图形。当一个画的请求被事件转发器从SWT canvas发送到LightweightSystem上时,LightweightSystem调用更新管理器performUpdate()方法。一般管理器维持着一个List列表,该列表包含无效的或需要重画的图形。
3、Figure类
Draw2D的界面中看到的都是图形,即Figure类的实例。它在一个重量级的窗口中模拟一个重量级图形系统。在不消耗太多系统资源情况下,他们允许你创建一个复杂的图形展示。图形都应该建立在根图形之上。
Figure的绘制过程:
1).paintfigure() 图形绘制本身
2).paintclientarea() 绘制该图形的子图形
3).paintborder() 绘制该图形的修饰边框
验证:当图形的大小或位置需要被计算时(如图形的位置发生变化时),Draw2D将使用验证。
1).validate( ) 要求图形的布局管理器重新布局它的子图形。
2).revalidate( ) 首先调用invalidate( )方法(该方法会使该图形及其父链上的图形无效),其次,添加该图形及其父链到更新管理器的无效List上。
四、GEF的MVC
1、GEF的优势是提供了标准的MVC(Model-View-Control)结构。与其他的一些MVC框架相比,GEF的一个主要设计目标是尽量减少模型和视图之间的依赖,好处是可以根据需要选择任意模型和视图的组合,而不必受开发框架的限制。
2、 GEF中MVC框架的实现
通过第二章的内容,结合图4.2中我们可以得到一个结论:
View部分:GEF利用Draw2D的Figuer作为自己的View。
Model部分:往往内部包含了千差万别、不可预知的商业信息。因此GEF框架应该尽量减少约束。
Controller部分: EditPart中建立了与其对应的Draw2D的Figure和用户自定义的Model结点建立一一关联的关系。
Controller(EditPart)也是树形的层级,这样的话更能容易的对具体具有树形结构的Model,进行特殊化UI和相关的行为处理方式,更容易进行功能分解。
因此在设计Controller(EditPart)时,只需处理自身逻辑、管理子Controller、通知父Controller。
3、 如何使用GEF来创建Model/Figure/EditPart
1).从上图可以看出在GEF是通过EditPartFactory根据以存在的Model 来创建并设置不同的EditPart。
EditPartFactory的接口如下:
EditPart createEditPart(EditPart context, Object model);
2).其中model是Object类型,因此可以看出在GEF对model没什么过多的约束,context是于要创建的EditPart有关联的EditPart,例如是将要创建EditPart的Parent。
参考时序图:GEF创建Editor时序图
五、EditPart
1、EditPolicy
六、GEF的事件转义与事件传递:Tool
1、用户输入(系统UI事件)与UI业务语义
在界面操作过程中,我们希望面对的是边框调整事件,图形移动事件,或者是编辑文本事件,而不是原始的鼠标和键盘事件?
术语定义:
系统UI事件:一般由某些计算机人机交互硬件发出信号,并且经操作系统理解后产生的事件,例如:原始的鼠标的移动、点击和键盘的敲击事件等。
UI业务语义事件: 由系统UI事件和其它UI业务语义事件触发,由UI业务代码理解后产生的事件(操作系统不可理解,同时无任何领域的业务语义),如2D图形的尺寸调整,2D图形的点击,2D图形的移动。(其实不仅限于事件的转义,包括UI的改变,也需要由系统UI语义转换到UI业务语义来使用)
UI业务语义事件在Controller控制中的优点是易于理解、维护和扩充,具体的主要有以下方面:
a.减少系统UI事件判断逻辑部分代码的重复。比如在Controller部分代码无需分步着大量逻辑重复的代码,当鼠标移动时去判断究竟是一个2D图形的尺寸改变,还是一个2D图形的移动,还是一组2D图形的移动,还是2D图形DragAndDrop的动作。
b.Controller部分的代码语义明确。在Controller内部处理代码和接口中直接面对的是UI业务语义,如图形的移动,图形的尺寸改变,这样、代码易于理解、调试等。
b.Controller部分代码无需为系统UI事件保存状态。如2D图形的移动中,如果这些事件直接在Controller中处理,从开始MouseDown,到MouseMove,到MouseUp过程中,在Controller中要集中保留这样众多状态,极易造成Controller代码具体多头职责的症状,从而患上严重的精神分裂:)。
2、GEF给出的解决方案
GEF通过Tools(根interface是Tool),当然在视图上的Menu和Toolbar是通过Action发出,这个是eclipse的Workbench机制,在此就不讨论了。
从Tool继承的这些类均处理一个或者一类UI业务语义事件,其中需要保留中间状态的子类均以XXXTracker形式出现。
首先这些Tool的实现类通过Tool的接口(上图右边),接收界面来的事件,然后调用内部方法,例如键盘按下事件(AbstractTool. handleButtonDown())之类的handle***()的方法;这样通过AbstractTool的具体实现类中的内部函数getTargetRequest()[createTargetRequest()]和getSourceRequest()[createSourceRequest()],把系统UI事件转换为UI业务语义事件叫Request(如图6.3)。至此Tool会通过调用相关联的EditPart的接口将UI业务语义事件通知到EditPart中。于是在Controller(EditPart)中仅仅需要理解处理Request对象。
Tool这些事件接口,如何从Viewer传递过来的呢?
注意以下两方面
1)、创建这些关键事件处理链的过程(注意图上的粗体文字);
2)、消息从SWT中Canvas实例传递到Tool过程(图D中注释标签的顺序)
学习了Tool产生Request的机制,可以帮助我们调试GEF,同时如果在大家自己的程序中需要有新的UI交互类型,也可以试着建立自己的Tool类产生新的Request,这样在自己的EditPart产生对应的Command,这样就可以处理实现新的UI交互类型。
自定义Request
从本章的内容,理解了SWT的UI输入如何传到GEF的Tool中,并知道Too是用来对系统UI输入进行转义并转换成EditPart能理解的Request,而最终会由EditPart的EditPolicy来处理Tool产生的Request。
那么我们就可以针对GEF的机制来制定我们自用的Request来实现我们特定的功能。
假设我们需要有一个功能,当通过Tool,左键画布上选中的节点,并改变节点的颜色。
1)、修改Node,增加用于反映颜色的变量
模型里节点(Node)类里没有反映颜色的成员变量,所以先要在Node类里添加一个color属性,以及相应的 getter/setter方法,注意这个setter方法里要和其他成员变量的setter方法一样传递模型改变的消息。仿照其他成员变量,还应该有一个静态字符串变量,用来区分消息对应哪个属性。
final public static String PROP_COLOR = "COLOR";
protected RGB color = new RGB(255, 255, 255);
public RGB getColor() {
return color;
}
public void setColor(RGB color) {
if (this.color.equals(color)) {
return;
}
this.color = color;
firePropertyChange(PROP_COLOR, null, color);
}
2)、修改NodePart支持当Node的color属性的值改变时进行视图的刷新
修改NodePart里的propertyChanged()和 refreshVisuals()方法,在前者里增加对color属性的响应,在后者里将NodeFigure的背景颜色设置为Node的color属性对应的颜色。
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(Node.PROP_COLOR))//Response to color change
refreshVisuals();
}
}
protected void refreshVisuals() {
((NodeFigure) this.getFigure()).setBackgroundColor(new Color(null, node.getColor()));
}
3)、自定义一个Request
因为目的是改变颜色,所以不妨叫做ChangeColorRequest。它应当继承自org.eclipse.gef.Request,我们需要ChangeColorRequest上带有两样信息:1.需要改变颜色的节点;2.目标颜色。因此它应该有这两个成员变量。
public class ChangeColorRequest extends Request{
final static public String REQ_CHANGE_COLOR="REQ_CHANGE_COLOR";
private Node node;
private RGB color;
public ChangeColorRequest(Node node, RGB color) {
super();
this.color = color;
this.node = node;
setType(REQ_CHANGE_COLOR);
}
public RGB getColor() {
return color;
}
public Node getNode() {
return node;
}
public void setNode(Node node) {
this.node = node;
}
public void setColor(RGB color) {
this.color = color;
}
}
ChangeColorRequest看起来和一个JavaBean差不多,的确如此,因为Request的作用就是传递翻译后的鼠标事件。如果你看一下org.eclipse.gef.Request的代码,你会发现Request还有一个type属性,这个属性一般是一个字符串(在gef的RequestConstants里预定义了一些,如RequestConstants.REQ_SELECTION_HOVER), EditPolicy可以根据它决定是否处理这个Request。在我们的例子里,顺便定义了这样一个常量字符串REQ_CHANGE_COLOR,在后面的 ChangeColorEditPolicy里会用到它。
4)、需要覆盖SelectionTool的handleButtonDown
(PS:尽量做到复用,GEF中已经提供了很多很好用的Tool的实现类,我们通过对GEF中Tool的类继承树中具体实现类的理解来选择比较符合我们当前需要实现功能的Tool实现类,并覆盖其中方法来达到代码复用,也能更快的实现功能。)
我们理解了对节点上色这个需求后,发现“上色工具”的用法和“选择工具”基本上差不多。显然,我们需要覆盖的是handleButtonDown()方法,用来告诉gef如果用户当前选择了这个工具,在画布区域按下鼠标会发生什么事情。
代码如下:
public class ChangeColorTool extends SelectionTool {.
private RGB color;
public ChangeColorTool(RGB color) {
super();
this.color = color;
}
@Override
protected boolean handleButtonDown(int button) {
//Get selected editpart
EditPart editPart = this.getTargetEditPart();
if (editPart instanceof NodePart) {
NodePart nodePart = (NodePart) editPart;
Node node = (Node) nodePart.getModel();
//Create an instance of ChangeColorRequest
ChangeColorRequest request = new ChangeColorRequest(node, color);
//Get command from the editpart
Command command = editPart.getCommand(request);
//Execute the command
this.getDomain().getCommandStack().execute(command);
return true;
}
return false;
}
}
5)、实现改变颜色的Command
GEF里任何对模型的修改都是通过command完成的,因此一个ChangeColorCommand肯定是需要的。
public class ChangeColorCommand extends Command{
private RGB oldColor;
@Override
public void execute() {
oldColor = node.getColor();
node.setColor(color);
}
@Override
public void undo() {
node.setColor(oldColor);
}
}
6)、增加Policy来处理ChangeColorRequest
EditPolicy负责接收所有的Request,所以还要创建一个ChangeColorEditPolicy。
public class ChangeColorEditPolicy extends AbstractEditPolicy {
final static public String CHANGE_COLOR_ROLE = "CHANGE_COLOR_ROLE";
@Override
public Command getCommand(Request request) {
//Judge whether this request is intersting by its type
if (request.getType() == ChangeColorRequest.REQ_CHANGE_COLOR) {
ChangeColorRequest theRequest = (ChangeColorRequest) request;
//Get information from request
Node node = theRequest.getNode();
RGB color = theRequest.getColor();
//Create corresponding command and return it
ChangeColorCommand command = new ChangeColorCommand(node, color);
return command;
}
return null;
}
}
7)、在NodePart中增加ChangeColorEditPolicy
protected void createEditPolicies() {
//Add change color editpolicy
installEditPolicy(ChangeColorEditPolicy.CHANGE_COLOR_ROLE,new ChangeColorEditPolicy());
}
GEF(Graphical Editing Framework)是一个图形化编辑框架,它允许开发人员以图形化的方式展示和编辑模型,从而提升用户体验。
GEF的优势是提供了标准的MVC(Model-View-Control)结构,开发人员可以利用GEF来完成以上这些功能,而不需要自己重新设计。与其他一些MVC编辑框架相比,GEF的一个主要设计目标是尽量减少模型和视图之间的依赖,好处是可以根据需要选择任意模型和视图的组合,而不必受开发框架的局限(实际上视图基本是Draw2D的实现)。
二、GEF各项目的关系图:
图2.1
1、 Draw2D:建立了二维的图形库(树状图形部件Figure),负责显示二维的图形展示。
2、GEF:(Graphical Editing Framework)建立MVC构架,代码利用Draw2D作为自己的View部分,主要代码实现复杂的树状(于Model分别对应)的控制器。实现的框架具有很高的可复用等特性,例如:将图形部件功能分解为多个EditPolicy,这样使用者可以通过installEditPolicy接口来定制,以及扩充自己的某一功能特征。
3、EMF:(Eclipse Modeling Framework)首先在一个轻量级项目以及项目初期开发,Model常常采用拥有Property的Java对象来简单明了表示【即 Plain Old Java Objects (POJOs)】。EMF定义了一套Ecore元模型,使得Model具有易于维护、易于扩充、易于数据交换等特性的Model Framwork。因此、在实际中大型的项目中往往会采用Draw2D+GEF+EMF的方式来实现整体的MVC模式。例如:ROSE的最新版本 IBM.Rational.Software.Architect就是采用了这种构架。
4、GMF:(Graphical Modeling Framework )使用了GEF和EMF,建立了两个之间的桥梁框架,同时实现了一些领域上的典范应用,如UML图,甘特图,脑图等。(项目正在进行中这些功能还未完备。可以用来参考以实现自己的一个标准的GEF+EMF的应用)。
5、各项目依赖关系:
图2.2
如上图:使用者可以有以下几种用法:
EMF: Model管理层
Draw2D: 二维图形展现
Draw2D + GEF: 二维图形的简单编辑模块
Draw2D + GEF + EMF: 二维图形的编辑模块
Draw2D + GEF + EMF + GMF:基于GMF提供的图形编辑功能之上扩展
三、Draw2D技术
1、Draw2D是什么?
轻量级框架:轻量级框架,使用LightweightSystem类把SWT和Draw2D 连接起来,它把鼠标事件和画图事件从SWT 转发给Draw2D的图形上。它是Draw2D的核心类。
Draw2d中的Graphics和GC的对比:
Graphics类的很多方法和GC的完全一样,尤其是绘制线和几何图形、显示图片以及字体等方面。但Graphics还提供了一个不同于GC的功能:它的对象可以在LightweightSystem中移动。这意味着当你想要改变一个图形组件的位置时,Draw2d提供了它自己的拖拽机制来将一个Figure移动到合适的位置。
2、 LightweightSystem 主要包含三个组成部件:
LightweightSystem不依赖于特定操作系统,这意味着你失去了SWT/Jface重量级组件的优势,比如快速的响应和本地外观风格,但你得到的,是对自己的组件的外观与行为的完全控制。
1).根图形【IFigure】: 根图形是RootFigure类的实例,应用程序的根图形必须建立在它之上。它继承了一些SWT Canvas的图形环境,如颜色,字体等。
2).事件转发器【EventDispatcher】: 事件转发器把SWT事件转换成相应Draw2D事件。它可以跟踪那个图形被聚焦,那个图形是被鼠标点击的目标图形。它还控制tooltip的激活。它为想捕捉鼠标的图形提供支持。
3).更新管理器【UpdateManager】:更新管理器是负责画和更新Draw2D图形。当一个画的请求被事件转发器从SWT canvas发送到LightweightSystem上时,LightweightSystem调用更新管理器performUpdate()方法。一般管理器维持着一个List列表,该列表包含无效的或需要重画的图形。
3、Figure类
Draw2D的界面中看到的都是图形,即Figure类的实例。它在一个重量级的窗口中模拟一个重量级图形系统。在不消耗太多系统资源情况下,他们允许你创建一个复杂的图形展示。图形都应该建立在根图形之上。
Figure的绘制过程:
1).paintfigure() 图形绘制本身
2).paintclientarea() 绘制该图形的子图形
3).paintborder() 绘制该图形的修饰边框
验证:当图形的大小或位置需要被计算时(如图形的位置发生变化时),Draw2D将使用验证。
1).validate( ) 要求图形的布局管理器重新布局它的子图形。
2).revalidate( ) 首先调用invalidate( )方法(该方法会使该图形及其父链上的图形无效),其次,添加该图形及其父链到更新管理器的无效List上。
四、GEF的MVC
1、GEF的优势是提供了标准的MVC(Model-View-Control)结构。与其他的一些MVC框架相比,GEF的一个主要设计目标是尽量减少模型和视图之间的依赖,好处是可以根据需要选择任意模型和视图的组合,而不必受开发框架的限制。
2、 GEF中MVC框架的实现
图4.1 MVC的示例图
图4.2 GEF的MVC实现
图4.3 GEF通过EditPart来管理Model和Figure
通过第二章的内容,结合图4.2中我们可以得到一个结论:
View部分:GEF利用Draw2D的Figuer作为自己的View。
Model部分:往往内部包含了千差万别、不可预知的商业信息。因此GEF框架应该尽量减少约束。
Controller部分: EditPart中建立了与其对应的Draw2D的Figure和用户自定义的Model结点建立一一关联的关系。
Controller(EditPart)也是树形的层级,这样的话更能容易的对具体具有树形结构的Model,进行特殊化UI和相关的行为处理方式,更容易进行功能分解。
因此在设计Controller(EditPart)时,只需处理自身逻辑、管理子Controller、通知父Controller。
3、 如何使用GEF来创建Model/Figure/EditPart
图4.4 GEF创建MVC相关类
1).从上图可以看出在GEF是通过EditPartFactory根据以存在的Model 来创建并设置不同的EditPart。
EditPartFactory的接口如下:
EditPart createEditPart(EditPart context, Object model);
2).其中model是Object类型,因此可以看出在GEF对model没什么过多的约束,context是于要创建的EditPart有关联的EditPart,例如是将要创建EditPart的Parent。
参考时序图:GEF创建Editor时序图
五、EditPart
1、EditPolicy
六、GEF的事件转义与事件传递:Tool
1、用户输入(系统UI事件)与UI业务语义
在界面操作过程中,我们希望面对的是边框调整事件,图形移动事件,或者是编辑文本事件,而不是原始的鼠标和键盘事件?
术语定义:
系统UI事件:一般由某些计算机人机交互硬件发出信号,并且经操作系统理解后产生的事件,例如:原始的鼠标的移动、点击和键盘的敲击事件等。
UI业务语义事件: 由系统UI事件和其它UI业务语义事件触发,由UI业务代码理解后产生的事件(操作系统不可理解,同时无任何领域的业务语义),如2D图形的尺寸调整,2D图形的点击,2D图形的移动。(其实不仅限于事件的转义,包括UI的改变,也需要由系统UI语义转换到UI业务语义来使用)
UI业务语义事件在Controller控制中的优点是易于理解、维护和扩充,具体的主要有以下方面:
a.减少系统UI事件判断逻辑部分代码的重复。比如在Controller部分代码无需分步着大量逻辑重复的代码,当鼠标移动时去判断究竟是一个2D图形的尺寸改变,还是一个2D图形的移动,还是一组2D图形的移动,还是2D图形DragAndDrop的动作。
b.Controller部分的代码语义明确。在Controller内部处理代码和接口中直接面对的是UI业务语义,如图形的移动,图形的尺寸改变,这样、代码易于理解、调试等。
b.Controller部分代码无需为系统UI事件保存状态。如2D图形的移动中,如果这些事件直接在Controller中处理,从开始MouseDown,到MouseMove,到MouseUp过程中,在Controller中要集中保留这样众多状态,极易造成Controller代码具体多头职责的症状,从而患上严重的精神分裂:)。
2、GEF给出的解决方案
图6.1 GEF给出的解决方案
GEF通过Tools(根interface是Tool),当然在视图上的Menu和Toolbar是通过Action发出,这个是eclipse的Workbench机制,在此就不讨论了。
图6.2 Tool的类继承树
从Tool继承的这些类均处理一个或者一类UI业务语义事件,其中需要保留中间状态的子类均以XXXTracker形式出现。
首先这些Tool的实现类通过Tool的接口(上图右边),接收界面来的事件,然后调用内部方法,例如键盘按下事件(AbstractTool. handleButtonDown())之类的handle***()的方法;这样通过AbstractTool的具体实现类中的内部函数getTargetRequest()[createTargetRequest()]和getSourceRequest()[createSourceRequest()],把系统UI事件转换为UI业务语义事件叫Request(如图6.3)。至此Tool会通过调用相关联的EditPart的接口将UI业务语义事件通知到EditPart中。于是在Controller(EditPart)中仅仅需要理解处理Request对象。
图6.3 Request的类继承树
Tool这些事件接口,如何从Viewer传递过来的呢?
图6.4 从SWT的系统UI Input到GEF的Tool
注意以下两方面
1)、创建这些关键事件处理链的过程(注意图上的粗体文字);
2)、消息从SWT中Canvas实例传递到Tool过程(图D中注释标签的顺序)
学习了Tool产生Request的机制,可以帮助我们调试GEF,同时如果在大家自己的程序中需要有新的UI交互类型,也可以试着建立自己的Tool类产生新的Request,这样在自己的EditPart产生对应的Command,这样就可以处理实现新的UI交互类型。
自定义Request
从本章的内容,理解了SWT的UI输入如何传到GEF的Tool中,并知道Too是用来对系统UI输入进行转义并转换成EditPart能理解的Request,而最终会由EditPart的EditPolicy来处理Tool产生的Request。
那么我们就可以针对GEF的机制来制定我们自用的Request来实现我们特定的功能。
假设我们需要有一个功能,当通过Tool,左键画布上选中的节点,并改变节点的颜色。
1)、修改Node,增加用于反映颜色的变量
模型里节点(Node)类里没有反映颜色的成员变量,所以先要在Node类里添加一个color属性,以及相应的 getter/setter方法,注意这个setter方法里要和其他成员变量的setter方法一样传递模型改变的消息。仿照其他成员变量,还应该有一个静态字符串变量,用来区分消息对应哪个属性。
final public static String PROP_COLOR = "COLOR";
protected RGB color = new RGB(255, 255, 255);
public RGB getColor() {
return color;
}
public void setColor(RGB color) {
if (this.color.equals(color)) {
return;
}
this.color = color;
firePropertyChange(PROP_COLOR, null, color);
}
2)、修改NodePart支持当Node的color属性的值改变时进行视图的刷新
修改NodePart里的propertyChanged()和 refreshVisuals()方法,在前者里增加对color属性的响应,在后者里将NodeFigure的背景颜色设置为Node的color属性对应的颜色。
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(Node.PROP_COLOR))//Response to color change
refreshVisuals();
}
}
protected void refreshVisuals() {
((NodeFigure) this.getFigure()).setBackgroundColor(new Color(null, node.getColor()));
}
3)、自定义一个Request
因为目的是改变颜色,所以不妨叫做ChangeColorRequest。它应当继承自org.eclipse.gef.Request,我们需要ChangeColorRequest上带有两样信息:1.需要改变颜色的节点;2.目标颜色。因此它应该有这两个成员变量。
public class ChangeColorRequest extends Request{
final static public String REQ_CHANGE_COLOR="REQ_CHANGE_COLOR";
private Node node;
private RGB color;
public ChangeColorRequest(Node node, RGB color) {
super();
this.color = color;
this.node = node;
setType(REQ_CHANGE_COLOR);
}
public RGB getColor() {
return color;
}
public Node getNode() {
return node;
}
public void setNode(Node node) {
this.node = node;
}
public void setColor(RGB color) {
this.color = color;
}
}
ChangeColorRequest看起来和一个JavaBean差不多,的确如此,因为Request的作用就是传递翻译后的鼠标事件。如果你看一下org.eclipse.gef.Request的代码,你会发现Request还有一个type属性,这个属性一般是一个字符串(在gef的RequestConstants里预定义了一些,如RequestConstants.REQ_SELECTION_HOVER), EditPolicy可以根据它决定是否处理这个Request。在我们的例子里,顺便定义了这样一个常量字符串REQ_CHANGE_COLOR,在后面的 ChangeColorEditPolicy里会用到它。
4)、需要覆盖SelectionTool的handleButtonDown
(PS:尽量做到复用,GEF中已经提供了很多很好用的Tool的实现类,我们通过对GEF中Tool的类继承树中具体实现类的理解来选择比较符合我们当前需要实现功能的Tool实现类,并覆盖其中方法来达到代码复用,也能更快的实现功能。)
我们理解了对节点上色这个需求后,发现“上色工具”的用法和“选择工具”基本上差不多。显然,我们需要覆盖的是handleButtonDown()方法,用来告诉gef如果用户当前选择了这个工具,在画布区域按下鼠标会发生什么事情。
代码如下:
public class ChangeColorTool extends SelectionTool {.
private RGB color;
public ChangeColorTool(RGB color) {
super();
this.color = color;
}
@Override
protected boolean handleButtonDown(int button) {
//Get selected editpart
EditPart editPart = this.getTargetEditPart();
if (editPart instanceof NodePart) {
NodePart nodePart = (NodePart) editPart;
Node node = (Node) nodePart.getModel();
//Create an instance of ChangeColorRequest
ChangeColorRequest request = new ChangeColorRequest(node, color);
//Get command from the editpart
Command command = editPart.getCommand(request);
//Execute the command
this.getDomain().getCommandStack().execute(command);
return true;
}
return false;
}
}
5)、实现改变颜色的Command
GEF里任何对模型的修改都是通过command完成的,因此一个ChangeColorCommand肯定是需要的。
public class ChangeColorCommand extends Command{
private RGB oldColor;
@Override
public void execute() {
oldColor = node.getColor();
node.setColor(color);
}
@Override
public void undo() {
node.setColor(oldColor);
}
}
6)、增加Policy来处理ChangeColorRequest
EditPolicy负责接收所有的Request,所以还要创建一个ChangeColorEditPolicy。
public class ChangeColorEditPolicy extends AbstractEditPolicy {
final static public String CHANGE_COLOR_ROLE = "CHANGE_COLOR_ROLE";
@Override
public Command getCommand(Request request) {
//Judge whether this request is intersting by its type
if (request.getType() == ChangeColorRequest.REQ_CHANGE_COLOR) {
ChangeColorRequest theRequest = (ChangeColorRequest) request;
//Get information from request
Node node = theRequest.getNode();
RGB color = theRequest.getColor();
//Create corresponding command and return it
ChangeColorCommand command = new ChangeColorCommand(node, color);
return command;
}
return null;
}
}
7)、在NodePart中增加ChangeColorEditPolicy
protected void createEditPolicies() {
//Add change color editpolicy
installEditPolicy(ChangeColorEditPolicy.CHANGE_COLOR_ROLE,new ChangeColorEditPolicy());
}
发表评论
-
GEF入门参考
2014-08-07 09:37 575一些网站 http://www.ibm.com/develo ... -
GEF入门参考
2014-08-07 09:36 519一些网站 http://www.ibm.com/develo ... -
SWT-GEF事件转义相关类
2014-08-07 09:35 795在Draw2d中,Lightweight是gef图形系统的”s ... -
GEF中Editor创建的时序图
2014-08-07 09:33 536以eclipse网站上例子A Shape Diagram Ed ... -
org.eclipse.core.resources.builders扩展点-转载
2013-10-12 14:28 2363org.eclipse.core.resources. ... -
org.eclipse.ui.decorators 使用(转)
2013-10-12 14:24 603org.eclipse.ui.decorators这个扩展点可 ... -
org.eclipse.ui.menus扩展点
2013-06-06 11:17 1841eclipse插件开发中 ... -
Eclipse开发中的 NoClassDefFoundError
2013-03-26 16:18 1142在eclipse插件开发过程中,需要引入很多的第三方j ... -
Eclipse事件与通讯
2013-01-18 15:58 928在开发Eclipse插件开发rcp过程中需要用到很多的 ... -
使用代码生成插件工程,脱离eclipse本身的新建工程向导(3)
2012-11-22 10:58 1138在第二步中需要有个PluginClassCodeGen ... -
使用代码生成插件工程,脱离eclipse本身的新建工程向导(2)
2012-11-22 10:52 3707在第一步完成后,我从pde的向导代码入手看eclips ... -
使用代码生成插件工程,脱离eclipse本身的新建工程向导(1)
2012-11-22 10:43 1730第一步,新建一个普通的Java工程。在网上,我找到了网 ... -
插件开发基础类(转载)
2012-09-25 16:36 7521..IWorkbench: workbench是e ... -
获取需要平台的信息
2012-09-25 16:16 734开发rcp程序的时候,需要获取许多平台和编辑器的相关信 ...
相关推荐
图形编辑框架,是Eclipse旗下的强有力的Tool Project。利用GEF可以轻松实现类似于Visual Editor的可视化图形编辑应用程序,即以图形化的方式展示和编辑模型。
gef all 3.5.2 源码
这是我自己在学习GEF的时候做的一些总结。 1、GEF中的概念比如Command,Tool,Request等等。 2、GEF中使用到的几种设计模式。 3、GEF中对鼠标键盘事件处理的机制、流程。
GEF入门必读 GEF入门系列 GEF-whole-upload 感谢八进制
RCP与GEF的课件,简单的介绍了RCP和GEF中的各组件的功能,已经工作流程
我下的资源的打包,希望有帮助,包括:GEF_Tutorial,GEF实例,入门教程,GEF-whole-upload
GEF简易教程-学习GEF的入门教程,不错的gef入门教程
GEF eclipse 插件
gef 绘图折线的实现方法。 gef API chm 格式
GEF: Graphical Editing Framework <br>GEF是一套MVC Framework,它能帮你比较容易的建立图形化的编辑器,V(View)的部分常常是基于SWT的Draw2D,因此Draw2D也看作是GEF的一部分。依赖:org.eclipse.gef***, org...
GEF.rar GEF.rar GEF.rar
Agenda Start things off What is GEF? GEF Demo Draw2d Overview Example GEF Overview Break Hands-on Activity: Shapes Example
GEF理解之第三部分,学习gef必备文档资料啊,值得下载
GEF理解之第一部分,学习gef必备文档资料啊,值得下载
Eclipse插件GEF的介绍,对于学习GEF有很大帮助
GEF 入门系列 GEF
GEF Example Source Code,
gef开发实例 gef开发的好例子,比较简单的实现了MVC的架构
Gef入门开发,详细解析。 Gef入门开发,详细解析 Gef入门开发,详细解析
这是我参考了一些其他资料,自己写的一个GEF示例程序。 在这个demo中你可以看到以下的功能: 1. 往画布上添加多种节点 2. 节点之间的连线 3. 节点内容的编辑功能 4. 删除连线 5. 删除节点 6. 对节点的拖动以改变...