关键字: gef控制器
控制器是GEF框架的核心,它负责模型和视图之间的通信。

1.控制器的功能

在GEF的MVC结构里,控制器是模型与视图之间的桥梁,也是整个GEF的核心,它不仅要监听模型的变化,当用户编辑视图时,还要把编辑结果反应到模型上。
在GEF中,控制器是由一组EditPart对象共同组成的,每一个模型对象都对应一个EditPart对象。应用程序中需要有一个EditPartFactory对象负责根据给定模型对象创建对应的EditPart对象,这个工厂类将在创建模型时被调用。
控制器是GEF中最复杂的一部分,GEF把控制器完成的工作又分成了几个部分,包括请求和编辑策略及引申出来的命令模式,如下图:

用户的编辑操作被转换为一系列请求(Request),Eclipse中有很多种类的请求,这些种类在GEF里被成为角色(Role)。在GEF里有图形 化和非图形化这两大类角色,前者如“LayoutRole”对应和布局有关的操作,后者如“ConnectionRole”对应和连接有关的操作等。角色 这个概念是通过编辑策略(EditPolicy)来实现的,EditPolicy的主要功能是根据请求创建相应的命令(Command),而后者会直接操 作模型对象。
对每一个EditPart,用户都可以“安装”一些EditPolicy。用户对这个EditPart的特定操作会被交给已安装的对应EditPolicy处理。这样做的直接好处是可以在不同EditPart之间共享一些重复操作。

2.控制器的实现

    每一个模型都会对应一个控制器,控制器主要负责模型和视图的同步。控制器要监听模型的属性改变的事件,并通知视图更新。另外,控制器还要设置相应的编辑策略,用来处理由视图接收的请求。

实现一个EditPart一般来说需要重载performRequest、getCommand、 activate、deactivate和refreshVisuals函数,并实现createEditPolicies、createFigure接 口函数,为了让EditPart能够成为PropertyChangeListener,你还必须实现PropertyChangeListener接 口。performRequest和getCommand将在第3节介绍,activate和deactivate用于处理当EditPart处于激活或 者非激活状态时的操作,一般来说,可以在这两个函数中注册和移除自己监听者的角色。refreshVisuals函数用于更新自己的视图。
java 代码

1.package com.example.parts;
2.
3.import java.beans.PropertyChangeEvent;
4.import java.beans.PropertyChangeListener;
5.import java.util.List;
6.
7.import org.eclipse.draw2d.ChopboxAnchor;
8.import org.eclipse.draw2d.ConnectionAnchor;
9.import org.eclipse.draw2d.IFigure;
10.import org.eclipse.draw2d.geometry.Dimension;
11.import org.eclipse.draw2d.geometry.Point;
12.import org.eclipse.draw2d.geometry.Rectangle;
13.import org.eclipse.gef.ConnectionEditPart;
14.import org.eclipse.gef.EditPolicy;
15.import org.eclipse.gef.GraphicalEditPart;
16.import org.eclipse.gef.NodeEditPart;
17.import org.eclipse.gef.Request;
18.import org.eclipse.gef.RequestConstants;
19.import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
20.import org.eclipse.gef.tools.DirectEditManager;
21.import org.eclipse.jface.viewers.TextCellEditor;
22.
23.import com.example.figures.NodeFigure;
24.import com.example.model.Node;
25.import com.example.policies.NodeDirectEditPolicy;
26.import com.example.policies.NodeEditPolicy;
27.import com.example.policies.NodeGraphicalNodeEditPolicy;
28.
29.public class NodePart extends AbstractGraphicalEditPart implements PropertyChangeListener, NodeEditPart {30.
31.protected DirectEditManager manager;
32.//处理请求
33.public void performRequest(Request req) {
34.if (req.getType().equals(RequestConstants.REQ_DIRECT_EDIT)) {
35.if (manager == null) {
36.NodeFigure figure = (NodeFigure) getFigure();
37.manager = new NodeDirectEditManager(this, TextCellEditor.class, new NodeCellEditorLocator(figure));
38.}
39.manager.show();
40.}
41.}
42.//监听模型属性改变
43.public void propertyChange(PropertyChangeEvent evt) {
44.if (evt.getPropertyName().equals(Node.PROP_LOCATION))
45.//更新视图
46.refreshVisuals();
47.else if (evt.getPropertyName().equals(Node.PROP_NAME))
48.refreshVisuals();
49.else if (evt.getPropertyName().equals(Node.PROP_INPUTS))
50.//更新连接
51.refreshTargetConnections();
52.else if (evt.getPropertyName().equals(Node.PROP_OUTPUTS))
53.refreshSourceConnections();
54.}
55.//创建模型对应的视图
56.protected IFigure createFigure() {
57.return new NodeFigure();
58.}
59.//设置编辑策略
60.protected void createEditPolicies() {
61.installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, new NodeDirectEditPolicy());
62.installEditPolicy(EditPolicy.COMPONENT_ROLE, new NodeEditPolicy());
63.installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new NodeGraphicalNodeEditPolicy());
64.}
65.//注册自己成为模型的监听器
66.public void activate() {
67.if (isActive()) {
68.return;
69.}
70.super.activate();
71.((Node) getModel()).addPropertyChangeListener(this);
72.}
73.//把自己从模型的监听器中删除
74.public void deactivate() {
75.if (!isActive()) {
76.return;
77.}
78.super.deactivate();
79.((Node) getModel()).removePropertyChangeListener(this);
80.}
81.//更新视图的显示
82.protected void refreshVisuals() {
83.Node node = (Node) getModel();
84.Point loc = node.getLocation();
85.Dimension size = new Dimension(150, 40);
86.Rectangle rectangle = new Rectangle(loc, size);
87.((NodeFigure) this.getFigure()).setName(((Node) this.getModel()).getName());
88.((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), rectangle);
89.}
90.
91.//------------------------------------------------------------------------
92.// Abstract methods from NodeEditPart
93.//得到源连接的连接点
94.public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {
95.return new ChopboxAnchor(getFigure());
96.}
97.
98.public ConnectionAnchor getSourceConnectionAnchor(Request request) {
99.return new ChopboxAnchor(getFigure());
100.}
101.//得到目标连接的连接点
102.public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {
103.return new ChopboxAnchor(getFigure());
104.}
105.
106.public ConnectionAnchor getTargetConnectionAnchor(Request request) {
107.return new ChopboxAnchor(getFigure());
108.}
109.//得到以模型作为源的连接列表
110.protected List getModelSourceConnections() {
111.return ((Node) this.getModel()).getOutgoingConnections();
112.}
113.//得到以模型作为目标的连接列表
114.protected List getModelTargetConnections() {
115.return ((Node) this.getModel()).getIncomingConnections();
116.}
117.
118.}

EditPart(确切的说是AbstractGraphicalEditpart)另外一个需要实现的重要方法是createFigure(), 这个方法应该返回模型在视图中的图形表示,是一个IFigure类型对象。一般都把这些图形放在figures包里,例子里只有NodeFigure一个 自定义图形,Diagram对象对应的是GEF自带的名为FreeformLayer的图形,它是一个可以在东南西北四个方向任意扩展的层图形;而 Connection对应的也是GEF自带的图形,名为PolylineConnection,这个图形缺省是一条用来连接另外两个图形的直线,在例子里 我们通过setTargetDecoration()方法让连接的目标端显示一个箭头。
最后,要为EditPart增加适当的EditPolicy,这是通过覆盖EditPart的createEditPolicies()方法来实现 的,每一个被”安装”到EditPart中的EditPolicy都对应一个用来表示角色(Role)的字符串。对于在模型中有子元素的 EditPart,一般都会安装一个EditPolicy.LAYOUT_ROLE角色的EditPolicy(见下面的代码),后者多为 LayoutEditPolicy的子类;对于连接类型的EditPart,一般要安装 EditPolicy.CONNECTION_ENDPOINTS_ROLE角色的EditPolicy,后者则多为 ConnectionEndpointEditPolicy或其子类,等等。
installEditPolicy(EditPolicy.LAYOUT_ROLE, new DiagramLayoutEditPolicy());
用户的操作会被当前工具(缺省为选择工具SelectionTool)转换为请求(Request),请求根据类型被分发到目标EditPart所安装的EditPolicy,后者根据请求对应的角色来判断是否应该创建命令并执行。
在GEF里,这个弹出的编辑器由DirectEditManager类负责管理,在我们的NodePart类里,通过覆盖 performRequest()方法响应用户的DirectEdit请求,在这个方法里一般要构造一个DirectEditManager类的实例(例 子中的NodeDirectEditManager),并传入必要的参数,包括接受请求的EditPart(就是自己,this)、编辑器类型(使用 TextCellEditor)以及用来定位编辑器的CellEditorLocator(NodeCellEditorLocator),然后用 show()方法使编辑器显示出来,而编辑器中显示的内容已经在构造方法里得到。简单看一下NodeCellEditorLocator类,它的关键方法 在relocate()里,当编辑器里的内容改变时,这个方法被调用从而让编辑器始终处于正确的坐标位置。DirectEditManager有一个重要 的initCellEditor()方法,它的主要作用是设置编辑器的初始值。在我们的例子里,初始值设置为被编辑NodePart对应模型 (Node)的name属性值;这里还另外完成了设置编辑器字体和选中全部文字(selectAll)的功能,因为这样更符合一般使用习惯。
在NodePart里还要增加一个角色为DIRECT_EDIT_ROLE的EditPolicy,它应该继承自 DirectEditPolicy,有两个方法需要实现:getDirectEditCommand()和showCurrentEditValue (),虽然还未遇到过,但前者的作用你不应该感到陌生–在编辑结束时生成一个Command对象将修改结果作用到模型;后者的目的是更新Figure中 的显示,虽然我们的编辑器覆盖了Figure中的文本,似乎并不需要管Figure的显示,但在编辑中时刻保持这两个文本的一致才不会出现”盖不住”的情 况,例如当编辑器里的文本较短时。
上例通过继承AbstractGraphicalEditPart类实现了一个EditPart,另外,当GEF框架创建一个模型时,都会为此模型创建一 个对应的控制器。创建控制器的操作是在控制器工厂中完成的,用户可以在编辑器初始化时指定控制器工厂,例如:“getGraphicalViewer ().setEditPartFactory(new PartFactory())”,其中PartFactory为控制器工厂,代码如下:
java 代码

1./*
2.* Created on 2005-1-24
3.*
4.* TODO To change the template for this generated file go to
5.* Window - Preferences - Java - Code Style - Code Templates
6.*/
7.package com.example.parts;
8.
9.import org.eclipse.gef.EditPart;
10.import org.eclipse.gef.EditPartFactory;
11.
12.import com.example.model.Connection;
13.import com.example.model.Diagram;
14.
15.public class PartFactory implements EditPartFactory {16.
17.public EditPart createEditPart(EditPart context, Object model) {
18.EditPart part = null;
19.//根据模型创建相应的EditPart
20.if (model instanceof Diagram)
21.part = new DiagramPart();
22.else if (model instanceof Connection)
23.part = new ConnectionPart();
24.else
25.part = new NodePart();
26.//设置EditPart对应的模型
27.part.setModel(model);
28.//返回根据模型创建的EditPart
29.return part;
30.}
31.}

通过创建控制器和控制器工厂,GEF编辑器将会知道在模型创建后,自动调用控制器工厂创建对应的空气,从而实现模型和控制器的一一对应关系。

GEF原理及实现系列(四、控制器)相关推荐

  1. GEF原理及实现系列(一、GEF概述)

    GEF(Graphical Editor Framework)是一个图形化编辑框架,它允许开发人员以图形化的方式展示和编辑模型,从而提升用户体验. 本系列介绍GEF中的几个基本概念,包括如下部分: 1 ...

  2. GEF原理及实现系列(二、模型)

    GEF的模型只与控制器打交道,而不知道任何与视图有关的东西. 1.模型的功能 在GEF框架中,模型(Model)是非常简单的一部分,用户可把模型理解成一个简单的可持久化的实体.但为了能让控制器知道模型 ...

  3. 嵌入式系统原理及应用《基于ARM Cortex-M3 内核的STM32F103系列微控制器》思维导图

    嵌入式系统原理及应用 <基于ARM Cortex-M3 内核的STM32F103系列微控制器>课程思维导图 目录 第一章 嵌入式系统概论 第二章 嵌入式系统开发 第三章 ARM Corte ...

  4. iOS开发UINavigation系列四——导航控制器UINavigationController

    iOS开发UINavigation系列四--导航控制器UINavigationController 一.引言 在前面的博客中,我么你介绍了UINavigationBar,UINavigationIte ...

  5. 基于c语言c8051f系列微控制器原理与应用,基于C语言C8051F系列微控制器原理与应用...

    第1章 微控制器的原理 1.1 微控制器与计算机的关系 1.2 微控制器系统简介 1.3 微控制器的发展 1.4 8位机发展的3次技术飞跃 第2章 C8051 F系列单片机结构 2.1 C8051F系 ...

  6. Git使用 从入门到入土 收藏吃灰系列(四) Git工作原理

    文章目录 一.前言 一.Git基本理论(核心) 1.1工作区 1.2工作流程 一.前言 参考安装Git 详细安装教程 参考视频B站 Git最新教程通俗易懂,这个有点长,感觉讲的精华不多 参考视频『Gi ...

  7. STM32系列微控制器入门介绍

    文章目录 目的 基础需求 电路基础 编程语言 入门介绍 官方网站 型号选择 开发方式 开发工具 程序调试 固件烧录 资料说明 总结 目的 STM32是意法半导体(ST)推出的主要基于ARM Corte ...

  8. MSP430系列微控制器简介

    内容涉及以下: ●按照所处理的信号,对电子线路的分类 ●数字电路的特点 ●常用数字集成电路器件的种类和特点 ●微控制器(Microcontroller,MCU)的结构 ●德州仪器(TI)公司MSP43 ...

  9. 倍福模块通讯协议_认识倍福(Beckhoff)CX5100系列嵌入式控制器

    今天这篇文章,我们来认识下倍福(Beckhoff)CX5100系列嵌入式控制器. 倍福CX5100系列嵌入式控制包括:CX5120.CX5130和CX5140系列. 1.CX5120系列 CX5120 ...

最新文章

  1. 基础理论研究是人工智能持续发展的保证
  2. linux按内容查找文件
  3. 一位Python初学者的自白:Python小白眼中的装饰器
  4. NOSQL系列-Redis精简版安装与Ruby测试
  5. base 镜像 - 每天5分钟玩转容器技术(10)
  6. K-Backup备份office文件的具体操作。
  7. eureka 集群失败的原因_eureka集群中的疑问?
  8. 互联网架构设计漫谈 (2)
  9. 不合群的人,经常习惯一个人独来独往,这样的人有出息吗?
  10. linux计划任务一小时,linux,计划任务,每小时执行一次(共7篇).docx
  11. android常用窗口动画,android 自定义dialog,窗口动画,
  12. 学点 C 语言(32): 函数 - 返回值
  13. lol全队消息怎么发_英雄联盟如何发全部消息,LOL怎样发送消息给全部
  14. 盘点近年25家外卖O2O,谁比谁难过
  15. 网络对时设备(NTP校时)如何守护安全日志
  16. 黑苹果SSDT修正关机/重启问题
  17. 爱奇艺校招map优先队列笔试题字符串的价值
  18. h5实现上下滑动切页
  19. Mybatis-Plus进阶之扩展插件
  20. 小孩厌学,与其说教,不如和他写个游戏

热门文章

  1. 虚拟pc服务器 翻译,单机服务器配置文件;ServerSettings.ini【翻译】
  2. 一文详解立体匹配(附代码)
  3. 笔记本合上盖子不休眠
  4. 旷视科技 face++ 嵌入式软件开发-面试---深度好文
  5. Python中文社区开源项目计划:ImagePy
  6. 电视hdmi接口在哪_变废为宝!把旧笔记本电脑当电视盒子用
  7. 顺丰bsp物流下单php接口测试,golang 调用顺丰API接口测试-Go语言中文社区
  8. 2020大疆校招B卷第二题
  9. 【数据库】云数据库rds是什么意思?有什么优势?
  10. 文件服务器禁用u盘复制数据,如何禁止U盘拷贝