GEF原理及实现系列(四、控制器)
关键字: 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原理及实现系列(四、控制器)相关推荐
- GEF原理及实现系列(一、GEF概述)
GEF(Graphical Editor Framework)是一个图形化编辑框架,它允许开发人员以图形化的方式展示和编辑模型,从而提升用户体验. 本系列介绍GEF中的几个基本概念,包括如下部分: 1 ...
- GEF原理及实现系列(二、模型)
GEF的模型只与控制器打交道,而不知道任何与视图有关的东西. 1.模型的功能 在GEF框架中,模型(Model)是非常简单的一部分,用户可把模型理解成一个简单的可持久化的实体.但为了能让控制器知道模型 ...
- 嵌入式系统原理及应用《基于ARM Cortex-M3 内核的STM32F103系列微控制器》思维导图
嵌入式系统原理及应用 <基于ARM Cortex-M3 内核的STM32F103系列微控制器>课程思维导图 目录 第一章 嵌入式系统概论 第二章 嵌入式系统开发 第三章 ARM Corte ...
- iOS开发UINavigation系列四——导航控制器UINavigationController
iOS开发UINavigation系列四--导航控制器UINavigationController 一.引言 在前面的博客中,我么你介绍了UINavigationBar,UINavigationIte ...
- 基于c语言c8051f系列微控制器原理与应用,基于C语言C8051F系列微控制器原理与应用...
第1章 微控制器的原理 1.1 微控制器与计算机的关系 1.2 微控制器系统简介 1.3 微控制器的发展 1.4 8位机发展的3次技术飞跃 第2章 C8051 F系列单片机结构 2.1 C8051F系 ...
- Git使用 从入门到入土 收藏吃灰系列(四) Git工作原理
文章目录 一.前言 一.Git基本理论(核心) 1.1工作区 1.2工作流程 一.前言 参考安装Git 详细安装教程 参考视频B站 Git最新教程通俗易懂,这个有点长,感觉讲的精华不多 参考视频『Gi ...
- STM32系列微控制器入门介绍
文章目录 目的 基础需求 电路基础 编程语言 入门介绍 官方网站 型号选择 开发方式 开发工具 程序调试 固件烧录 资料说明 总结 目的 STM32是意法半导体(ST)推出的主要基于ARM Corte ...
- MSP430系列微控制器简介
内容涉及以下: ●按照所处理的信号,对电子线路的分类 ●数字电路的特点 ●常用数字集成电路器件的种类和特点 ●微控制器(Microcontroller,MCU)的结构 ●德州仪器(TI)公司MSP43 ...
- 倍福模块通讯协议_认识倍福(Beckhoff)CX5100系列嵌入式控制器
今天这篇文章,我们来认识下倍福(Beckhoff)CX5100系列嵌入式控制器. 倍福CX5100系列嵌入式控制包括:CX5120.CX5130和CX5140系列. 1.CX5120系列 CX5120 ...
最新文章
- 基础理论研究是人工智能持续发展的保证
- linux按内容查找文件
- 一位Python初学者的自白:Python小白眼中的装饰器
- NOSQL系列-Redis精简版安装与Ruby测试
- base 镜像 - 每天5分钟玩转容器技术(10)
- K-Backup备份office文件的具体操作。
- eureka 集群失败的原因_eureka集群中的疑问?
- 互联网架构设计漫谈 (2)
- 不合群的人,经常习惯一个人独来独往,这样的人有出息吗?
- linux计划任务一小时,linux,计划任务,每小时执行一次(共7篇).docx
- android常用窗口动画,android 自定义dialog,窗口动画,
- 学点 C 语言(32): 函数 - 返回值
- lol全队消息怎么发_英雄联盟如何发全部消息,LOL怎样发送消息给全部
- 盘点近年25家外卖O2O,谁比谁难过
- 网络对时设备(NTP校时)如何守护安全日志
- 黑苹果SSDT修正关机/重启问题
- 爱奇艺校招map优先队列笔试题字符串的价值
- h5实现上下滑动切页
- Mybatis-Plus进阶之扩展插件
- 小孩厌学,与其说教,不如和他写个游戏
热门文章
- 虚拟pc服务器 翻译,单机服务器配置文件;ServerSettings.ini【翻译】
- 一文详解立体匹配(附代码)
- 笔记本合上盖子不休眠
- 旷视科技 face++ 嵌入式软件开发-面试---深度好文
- Python中文社区开源项目计划:ImagePy
- 电视hdmi接口在哪_变废为宝!把旧笔记本电脑当电视盒子用
- 顺丰bsp物流下单php接口测试,golang 调用顺丰API接口测试-Go语言中文社区
- 2020大疆校招B卷第二题
- 【数据库】云数据库rds是什么意思?有什么优势?
- 文件服务器禁用u盘复制数据,如何禁止U盘拷贝