惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - 般若菩提

GEF源码分析(六) GEF 的EditPart的职能分离 __ 跨国时尚媒体集团广告部门 的故事 二 GEF源码分析(五) GEF 的EditPart的职能分离 __ 跨国时尚媒体集团广告部门 的故事 GEF源码分析(三) GEF 的树状构架 ___ Model/EditPart/Figure GEF源码分析(三) 模拟GEF设计思路,解剖GEF2 附图:包含GEF的Editor创建时序图 GEF源码分析(二) 模拟GEF设计思路,解剖GEF 1 GEF源码分析(一) eclipse的GEF相关项目说明 项目管理杂谈之打造软件团队 兄弟姐妹们测试一下你的职业倾向:〉 CodeReview的思索 eclipse内部类部分框架 eclipse工作台概念图 转载自CSDN:Martin Fowler:设计已死? 诸子百家与项目管理 之 孙子兵法篇(项目管理的整体思维) 世界可用性日你听说了嘛? 经典搞笑故事,结婚的男同胞注意哦;) 少时好坏,中时对错,老时因果 SharpDevelop自动命令启动UI部分(看SharpDevelop源码分析笔记随想) 强烈推荐两本经典OO书籍以及对用例编写的启发 - 般若菩提 - 博客园 哲学离我们有多远?
GEF源码分析(四) GEF 消息转义 ___ Tool的作用
般若菩提 · 2005-12-05 · via 博客园 - 般若菩提

郁闷!同志们没有留言,不知是写的太差,何处需要改进,还是大家觉得对自己没有用处.... 

GEF源码分析(四) GEF 消息转义 ___ Tool的作用

接着上一节:

我们先解决如下问题:

在界面操作过程中,我们希望面对的是边框调整事件,图形移动事件,或者是编辑文本事件,而不是原始的鼠标和键盘事件?

术语定义:

系统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代码具体多头职责的症状,从而患上严重的精神分裂:)

于是乎GEFFrameWork有给出以下的解决方案:

A

如上图

A

GEF通过Tools(interfaceTool),当然在视图上的MenuToolbar是通过Action发出,这个是eclipseWorkbench机制,在此就不讨论了。以下是Tool的类继承树:

B

从上图

B可以看出

Tool继承的这些类均处理一个或者一类UI业务语义事件,其中需要保留中间状态的子类均以XXXTracker形式出现。

首先这些Tool的实现类通过Tool的接口(上图右边),接收界面来的事件,然后调用内部handleXXX,这样通过内部函数getTargetRequest()[createTargetRequest()]和getSourceRequest()[createSourceRequest()],把系统UI事件转换为UI业务语义事件叫Request(如图C)。至此Tool会通过调用相关联的EditPart的接口将UI业务语义事件通知到EditPart中。于是在Controller(EditPart)中仅仅需要理解处理Request对象。

C

下面以ResizeTracker代码为例:

class ResizeTracker

protected Request createSourceRequest() {

ChangeBoundsRequest request;

request = new ChangeBoundsRequest(REQ_RESIZE);

request.setResizeDirection(getResizeDirection());

return request;

}

protected Command getCommand() {

List editparts = getOperationSet();

EditPart part;

CompoundCommand command = new CompoundCommand();

command.setDebugLabel("Resize Handle Tracker");//$NON-NLS-1$

for (int i = 0; i < editparts.size(); i++) {

part = (EditPart)editparts.get(i);

command.add(part.getCommand(getSourceRequest()));

}

return command.unwrap();

}

protected void eraseTargetFeedback() {

if (!getFlag(FLAG_TARGET_FEEDBACK))

return;

if (getTargetEditPart() != null)

getTargetEditPart().eraseTargetFeedback(getSourceRequest());

setFlag(FLAG_TARGET_FEEDBACK, false);

}

protected boolean handleButtonUp(int button) {

if (stateTransition(STATE_DRAG_IN_PROGRESS, STATE_TERMINAL)) {

eraseSourceFeedback();

eraseTargetFeedback();

performDrag();

}

return true;

}

最后还有个问题是


Tool
这些事件接口,如何从Viewer传递过来的呢?

我画了一个简要的类图


D


参照上图,下面罗列重要代码:

大家主要以下两方面

一、创建这些关键事件处理链的过程(注意图上的粗体文字);

二、消息从SWTCanvas实例传递到Tool过程(图D中注释标签的顺序);

class GraphicalEditor

public void createPartControl(Composite parent) {

createGraphicalViewer(parent);

}

protected void createGraphicalViewer(Composite parent) {

GraphicalViewer viewer = new ScrollingGraphicalViewer();

viewer.createControl(parent);

setGraphicalViewer(viewer);

configureGraphicalViewer();

hookGraphicalViewer();

initializeGraphicalViewer();

}

protected void setGraphicalViewer(GraphicalViewer viewer) {

getEditDomain().addViewer(viewer);

this.graphicalViewer = viewer;

}

class EditDomain

public void addViewer(EditPartViewer viewer) {

viewer.setEditDomain(this);

if (!viewers.contains(viewer))

viewers.add(viewer);

}

class GraphicalViewerImpl

public void setEditDomain(EditDomain domain) {

super.setEditDomain(domain);

// Set the new event dispatcher, even if the new domain is null.  This will dispose

// the old event dispatcher.

getLightweightSystem()

.setEventDispatcher(eventDispatcher = new DomainEventDispatcher(domain, this));

}

private final LightweightSystem lws = createLightweightSystem();

class ScrollingGraphicalViewer

public void setEditDomain(EditDomain domain) {

super.setEditDomain(domain);

// Set the new event dispatcher, even if the new domain is null.  This will dispose

// the old event dispatcher.

getLightweightSystem()

.setEventDispatcher(eventDispatcher = new DomainEventDispatcher(domain, this));

}

class LightweightSystem

public void setEventDispatcher(EventDispatcher dispatcher) {

this.dispatcher = dispatcher;  //在此Shapes例子中是DomainEventDispatcher

dispatcher.setRoot(root);

dispatcher.setControl(canvas);

}

protected void addListeners() {

EventHandler handler = createEventHandler();

canvas.getAccessible().addAccessibleListener(handler);

canvas.getAccessible().addAccessibleControlListener(handler);

canvas.addMouseListener(handler);

canvas.addMouseMoveListener(handler);

canvas.addMouseTrackListener(handler);

canvas.addKeyListener(handler);

canvas.addTraverseListener(handler);

canvas.addFocusListener(handler);

canvas.addListener(SWT.MouseWheel, handler);

……

setEventDispatcher(getEventDispatcher());

}

class EventHandler

implements MouseMoveListener, MouseListener, AccessibleControlListener, KeyListener,

TraverseListener, FocusListener, AccessibleListener, MouseTrackListener,

Listener

{

public void keyPressed(KeyEvent e) {

 //在此Shapes例子中是DomainEventDispatcher

getEventDispatcher().dispatchKeyPressed(e);

}

public void mouseDoubleClick(MouseEvent e) {

getEventDispatcher().dispatchMouseDoubleClicked(e);

}

public void mouseMove(MouseEvent e) {

getEventDispatcher().dispatchMouseMoved(e);

}

public void mouseUp(MouseEvent e) {

getEventDispatcher().dispatchMouseReleased(e);

}

}

这样、在图ARequest发送到EditPart机制做了简要的探讨。

学习了Tool产生Request的机制,可以帮助我们调试GEF,同时如果在大家自己的程序中需要有新的UI交互类型,也可以试着建立自己的Tool类产生新的Request,这样在自己的EditPart产生对应的Command,这样就可以处理实现新的UI交互类型。

在下一篇我们探讨一下有关图A中的EditPart如何产生Command,以及执行Command问题。