您的位置:首页 > 产品设计 > UI/UE

GEF Programmers' Guide 中文版(GEF 交互操作)

2010-07-08 10:48 351 查看
GEF


中的交互类型




这一节我们将讲述
GEF
框架中包含的各种交互操作和每个交互操作相关联的组件。交互可以是任何影响模型或者
UI
界面状态的行为。许多交互是可视化的,也有一些不能图形化地显示。交互可能包含一下内容:

1.

菜单操作
(
通常在工具栏、菜单栏和弹出菜单中
)

2.

点击


3.

点击并拖拽
.

4.

将鼠标停留在某处


5.

鼠标拖放


6.

按键
.

同时我们还将讲述每个交互的参与者和它们的处理,包括:

1.

处理输入的工具



2.

被选择的菜单操作



3.

ID
以及
EditPart
的工具或菜单操作处理的请求的实例。
ID

RequestConstants
类定义;


4.

处理请求的角色。它们是
EditPolicy
接口定义的常量;


5.

用来处理交互的编辑策略;


选择


(Selection


)


[thead]

[/thead]


Tools


Request


Edit Policies
and Roles


Actions


SelectionTool

MarqueeTool

SelectEditPartTracker



*GraphicalViewerKeyHandler

SelectionRequest

DirectEditRequest

REQ_SELECTION_HOVER

REQ_OPEN

REQ_DIRECT_EDIT

SelectionEditPolicy

DirectEditPolicy

SELECTION_FEEDBACK_ROLE

SelectAllAction


Viewer
中选择是最基本和普遍的交互操作,这里讨论的大部分的交互操作都基于选中的对象。而选择本身也是一个复杂的过程。上面的表单总结了选择工具以及它涉及到的请求、编辑策略和菜单操作。

首先定义一下选中对象
(Selection)
,选中的是
EditPartViewer
里的一系列
EditPart
。选中对象的修改是由
Viewer
提供的方法控制的,而不是直接操作对象本身。选中对象不会为空,即使所有的选中的对象都被清空了,
Viewer
的根模型对应的
EditPart
将默认被选中。最新一次选中的对象将作为首选对象。

与选中密切相关的是聚焦
(Focus)
。聚焦发生在一个单独的
EditPart
上,用于通过键盘操作选中的对象。通过改变聚焦点,用户可以在不修改选中对象的前提下由一个
EditPart
切换到另一个
EditPart
。如果没有显示的聚焦点,那么首选对象默认为聚焦对象。

Viewer
通知
EditPart
何时被选中,而
EditPart
负责显示选中和聚焦的状态。典型的,
EditPolicy
会给图形添加一些
Handle
表明它被选中。在
Logic
示例中,使用
ResizableEditPolicy

LED
和电路部分加上了
Handle
。黑色的部分标识首选对象。

选中对象的
Handle
关系到它的拖拽和大小,进一步关系到图形的布局管理器,所以通常是父
EditPart
安装相应的
EditPolicy
,使得子图形显示恰当的
Handle
。比如,安装了
XYLayoutPolicy

EditPart
将自动给它的子
EditPart
安装
ResizableEditPolicy
编辑策略。

连接可能通过修改连接图形的线条宽度来提示选中,比如
Logic
示例中的
WireEditPart
。连接的
Handle
是由
EndpointEditPart

BendpointEditPolicy
共同负责的。




Selection
Handles

选中对象的目标定位

(Targeting)

和反馈


选择对象的时候,
Selection Tool
首先使用
SelectionRequest
来定位目标
EditPart
。在极少数情况下,目标
EditPart
不可选中,这时候目标定位失败。

在不断的鼠标定位的过程中,
Selection Tool
将对当前的目标
EditPart
调用
showFeedback()
方法,向它传递一个类型为
REQ_SELECTION

SelectionRequest
。值得推荐的是,许多应用程序忽略了这个请求,因为当鼠标在图形上移动时,不断的刷新反馈会使用户崩溃。

因此,当用户的鼠标停留在某个图形上时,会额外发送一个类型为
REQ_SELECTION_HOVER
的反馈请求。很多时候,
EditPart
会这么处理这个请求

——

在图形上弹出一个对话框用来显示信息,就像工具提示条
(Tooltip)
一样。
SELECTION_FEEDBACK_ROLE
角色就用来处理这种反馈请求,如果你需要类似的反馈处理,记得在安装编辑策略的时候使用它。

使用这些反馈请求的好处是
Selection Tool
不用频繁的提示这些反馈信息。比如用户开始拖拽一个图形了,他可能不希望在拖拽的时候一直有一个弹出的消息框,提示你一些的反馈信息。还有一点需要提示,在其他工具激活的时候,不会再有选择反馈。

使用

DragTracker

进行选择


一旦用户点击鼠标,一个
DragTracker
的实例将被创建,用于进行选择目标定位。它将返回一个
SelectEditPartTracker
对象或者是
DragEditPartTracker
对象,来进行选择,具体返回哪一种类型的对象取决于是否允许拖拽。这些跟踪者
(Tracker)
将在恰当的时候修改选中对象,同时它还会根据
SHIFT
或者
CTRL
按键是否按下来来处理选中。这意味着一次可以选择多个对象。

填充模型的
EditPart
不会被
Tracker
选中,因为它不会出现在一个多重选中的情况下。这时候会产生
DeselectAddTracker
或者
MarqueeDragTracker
。记住在没有选中任何对象时,填充模型将被选中以保证选中对象不为空。

其它的选择请求


EditPart
可能会处理两个与选中相关的请求,这些请求与交互过程中鼠标点击相关。第一个是双击,在
GEF
称为展开
(RES_OPEN)
,这个请求用于处理打开、展开或者显示对话框等操作。也就是说,如果你想在图形上捕获双击事件,处理这个请求即可,不需要在图形上建立鼠标事件监听。另一个请求是直接编辑
((REQ_DIRECT_EDIT)
。举一个直接编辑的示例,对于一个文本框或者标签,用户可能想直接在界面上修改它的文字描述。首先选中图形,隔一段时间后再次单击这个图形,就可以产生这个请求了。如果注册了快捷键
(
一般为
F2)
,选中后点击
F2
可以获得同样的效果。注意需要隔一段时间再次点击,这是为了与双击请求进行区别。

菜单操作

Selection Actions


GEF
提供了用于全选的菜单操作——
SelectAllAction
,它会将当前
Viewer
下所有的
EditPart
都选中。

使用键盘选择

Selection using the Keyboard


如果在图形界面上安装了
GraphicalViewKeyHandler
,那么键盘选择就可以启用了。它负责接收当前工具传递来的按键事件,如果事件涉及到选择操作,
Selection Tool
将负责分发这些事件。

注意
DragTracker
不必用于
GEF

TreeViewer
,后者使用其他的方法处理选择、拖拽等操作。

基本模型操作



删除

(Delete)


[thead]

[/thead]


Tools


Requests


Edit Policies
and Roles


Actions


REQ_DELETE

COMPONENT_ROLE

CONNECTION_ROLE

RootComponentEditPolicy

DeleteAction



删除是所有
GEF
程序都应该支持的通用操作。工作台在编辑菜单上内置了一个全局的删除菜单操作,应用程序只用注册一下
DeleteAction
,就可以使用删除操作了。
DeleteAction
向当前选中的对象发送一个
REQ_DELETE
类型的请求,所有的
EditPart
都应该安装一个提示用户是否支持删除操作的编辑策略。

EditPart
分为基本组件
(Component)
和连接两种,组件是构成
EdiPart
结构的基本元素,它们都是
RootEditPart
的子
EdiPart
。而连接稍有不同,它们属于源端点对象和目的端点对象拥有的。

COMPONENT_ROLE
关键字用于安装组件编辑策略。用户可以用过扩展
ComponentEdiPartPolicy
并重写与删除命令相关的方法。
RootComponentEditPolicy
用于填充模型的
EditPart
,它的作用在于避免
Root Figure
被删除。
注意这里有几个概念需要区别一下:填充模型对应的

EditPart



content EditPart

,与

GraphicalViewer



RootEditPart

是不一样的。


COMPONENT_ROLE
关键字用于安装连接编辑策略,用户可以通过扩展
ConnectionEditPolicy
并重写与删除命令相关的方法来实现连接的删除操作。



实现删除操作的命令往往比较困难,尤其在有连接情况下。该命令必须判断被删除的对象是否拥有连接,或者它的子节点是否拥有连接,如果存在,这些连接都必须删除。注意在删除连接的过程中可能出现重复删除,比如同时选中了连接的源端点和目的端点。

创建


(Creation


)


[thead]

[/thead]


Tools


Requests


Edit Policies
and Roles


Actions


CreationTool



REQ_CREATE

Create

CONTAINER_ROLE

LAYOUT_ROLE

TREE_CONTAINER_ROLE

ContainerEditPolicy

LayoutEditPolicy

CopyTemplateAction

PasteTemplateAction

TemplateTransferDropTargetListener

TemplateTransferDragSourceListener



CreateRequest
用来给
EditPart
创建子节点,它以
REQ_CREATE
为标识。创建过程可能发生在以下三种情况下:点击、拖拽或粘贴。该请求提供位置、对象和对象类型信息,对象和对象类型信息都由
CreateFactory
提供。创建请求隐藏了
fcatory
,直接与创建的对象打交道。在一些时候,它还会包括尺寸信息。

产生

CreateRequest Producing CreateRequests


创建工具提供了加载光标模式来记录新创建的对象的位置。

当点击并拖动鼠标时,创建工具将跟踪用户定义的矩形的大小。

创建工具位于绘图板里,由
CreationToolEntry
实现。

松开鼠标时,创建工具可以保留设置并用于下次创建,也可以恢复为默认。

拖放也可以实现创建,拖拽的源可以是任何事物,一般来说是
PaletteViewer
。拖放需要使用类型为
Template
的绘图元素,而
TemplateTransfer
负责根据
Template
拖拽源转换为拖拽目的。同时
PaletteViewer
要注册
TemplateTransferDragSourceListener

TemplateTransferDropTargetListener
监听器。根据创建的模型的不同,这两个监听器都要重写,并获得与模型对应的请求。

CombinedTemplateCreationEntry
支持以上两种创建方式。

处理创建请求



目标
EditPart
负责显示反馈和返回用于创建模型的命令。
GEF
提供了两种处理创建操作的编辑策略。一种策略是为视图定制的,包括图形化的视图和树形结构的视图,对应的编辑策略分别为:
LAYOUT_ROLE

TREE_CONTAINER_ROLE


另一种策略只针对模型,应用程序可以借此来区分通过图形界面创建和非图形界面创建公用的部分。在大多数场景下,逻辑是在命令中实现的,因此这种编辑策略其实没有多大的用处。

LayoutEditPart
根据容器的布局管理器来完成创建过程,比如,如果容器使用了
XYLayout
布局,那么相应的创建命令中就必须使用
(x

y

w

h)
四个元素来对创建的子节点进行约束。不使用约束
(Constraint)
的布局可能会要求得到根据拖放位置计算出的位置索引
(Index)
,并以此来确定创建的子节点的位置。针对基本的布局类型,
GEF
内置了几个抽象的
EditPolicy
,用户可以扩展它们来实现自己的编辑策略。

TreeContainerEditPolicy
用于支持树形结构的
Viewer
的子节点创建,这时候它需要确定用于节点创建和反馈的索引位置。

PasteTemplateAction
可以用于在不使用鼠标的情况下创建对象,这使得创建更方便了。同时
CopyTemplateAction
会被添加到绘图板中。复制时,内部机制完成数据的转换和复制,紧接着在粘贴时,
PasteTemplateAction
会恢复转换的数据,产生
CreateRequest
并发送给
EditPart


这种交互操作中没有用到鼠标,因此新建节点的位置不确定,这也限制了在复制的时候只允许选中一个对象。



当创建命令被重做时,它必须保证恢复到第一次创建子节点时的状态。如果某个命令创建了子节点,接下来的命令又对这个节点进行了修改,那么此时的重做操作很可能失败。

移动和调整大小



[thead]

[/thead]


Tools


Requests


Edit Policies
and Roles


Actions


DragEditPartsTracker

ResizeTracker

ChangeBoundsRequest

AlignmentRequest

REQ_MOVE

REQ_ADD

REQ_ORPHAN

REQ_CLONE

REQ_ALIGN

REQ_RESIZE

LayoutEditPolicy

ResizableEditPolicy

ContainerEditPolicy

AlignmentAction

MatchSizeAction




移动操作







调整大小操作



DragEditPartsTracker
对基本的选择行为进行了扩展,它允许在图形编辑器中拖动选中的对象。这会带来三个潜在的交互操作:移动,重置父节点和复制。这三种操作都使用
ChangeBoundRequest

ChangeBoundRequest
继承自
GroupRequest
,它包含大小的增量、位置的偏移和鼠标的最终位置。

拖动选中对象时,如果拖动完毕后的对象仍处在它的父节点范围中,那么将产生
RES_MOVE
请求。如果越出范围,那么将产生重置父节点的请求——
REQ_ORPHAN
,这个请求将被发送至原来的父节点,同时新的父节点会产生一个新的请求——
RES_ADD
。当拖动鼠标的同时按下了
CTRL(MAC
系统中为
ALT)
,操作往往被视作复制,将产生
RES_CLONE
的请求,并发送给目标
EditPart


以上的请求都要求目标对象处理矩形信息和鼠标位置信息,然后
LayoutEditPolicy
接手负责处理请求,处理的过程依请求类型而定。对于使用四元约束式的布局管理器,原始的位置和大小信息都将废弃,更新为请求记录下来的新的位置和大小信息。对于用索引来布局的管理器,鼠标的位置仍然作为生成新的布局索引的依据。

可以选择用
ContainerEditPolicy
来处理在
ADD

ORPHAN

CLONE
请求中与布局无关的命令。

调整大小

Resizing


在同一个范围内修改图形的约束将带来大小调整。注意约束
(Constraint)
的左侧或者上侧改变时,节点的位置一般也随之更改了。大小调整只对支持约束的布局管理器有效,比如
XYLayout

ResizableEditPolicy
使用了
8
个用于调整大小的
Handle
,当对象被选中时,
ResizeTracker
负责响应大小调整。
SHIFT

CTRL
按键可以用来辅助完成大小调整操作。

显示在图形上
Handle
的数量和位置由图形所在的布局管理器决定,比如在表格中,会出现插入调整、依附、列间距和其他属性的
Handle
。有一些布局不要
Handle
,但是在图形的四个边角依然会出现
Handle
,以提示用户选中。拖拽这些
Handle
的效果与拖动图形一样。

Handle
和布局的关系如此紧密,因此强烈建议使用父节点的
LayoutEditPolicy
来安装
PRIMARY_DRAG_ROLE
编辑策略角色。如果在编辑中,容器的布局管理器发生变化了,这时候布局相关的编辑策略也会与新的布局绑定。同时所有子节点的编辑策略也将更新。

MatchSizeAction
可以根据首选对象的大小来匹配所有选中的对象。它的实现与手动调整单个对象的大小一样,也使用了同样的请求。

AlignmenAction
用于对齐多个对象的位置,它使用了
AlignmentRequest
请求。
AlignmentRequest
继承自
ChangeBoundsRequest
。在大多数情况下,
AlignmentAction
的行为与移动操作一样,不同的是,它可以根据首选对象和对齐的方向来对齐所有选中的对象。

连接创建

Connection Creation


[thead]

[/thead]


Tools


Requests


Edit Policies
and Roles


Actions


ConnectionCreationTool

ConnectionDragCreationTool

CreateConnectionRequest

REQ_CONNECTION_START

REQ_CONNECTION_END

GraphicalNodeEditPolicy

NODE_ROLE



ConnectionCreationTool
用于在节点之间创建连接。创建操作需要用户选中相应的工具,然后选择连接的两个端点。点击
ESC
将撤销连接的创建。
ConnectionDragCreationTool

与前者类似,区别是它是一次鼠标的拖拽。
ConnectionDragCreationTool

is similar, but the interaction is a
single mouse drag. This tool can be returned as the drag tracker from a handle
or even an editpart in some cases.

创建过程分为两部分,第一步是定义连接的源节点
(Source)
。源节点不仅仅包含节点信息,还可能还包括节点上某个特定的端口
(Port
,作为连接的锚点
)

REQ_CONNECTION_START
类型的
CreateConnectionRequest
请求这时候会确定源端点对应的
EditPart
,并且产生创建命令。这时候命令只保存了连接的源节点信息,还没有完全实现,
GEF
是不会尝试执行它,甚至都不会理会它是否可以执行。

第二步是定义连接的目的节点
(Target)

GEF
同样使用
CreateConnectionRequest
请求,但这次它的是
REQ_CONNECTION_END
类型的。在第一步中我们得到了一个创建的命令,保存在请求中。命令还没有完全实现,至少它要知道连接的另一个端点——目的节点的信息,这时候我们取出这个命令,将目的节点的信息保存到命令中。至此,才形成一个完整的连接创建命令。当然
GEF
也需要进行命令可执行性的判断,如果允许执行,那么将创建出一条新的连接。

上面的过程中,
source

target
对应的
EditPart
需要在连接创建的过程中显示一些反馈信息,比如图形可能会被一些高亮显示的依附点包围,提示它将是一个连接的端点。同时连接过程中会出现一条连接线
(ConnectionFigure)
,然后确定连接线的锚点。
GraphicalNodeEditPolicy
负责显示连接线,而
NodeEditPart
则负责为连接提供锚点。

连接的创建需要多个组件协作完成,同时也需要它们做出图形化的反馈显示,这些反馈包括被选中的节点周围出现的依附点
(
锚点
)
和新出现的连接线。

编辑连接



[thead]

[/thead]


Tools


Requests


Edit Policies
and Roles


Actions


ConnectionEndpointTracker

ReconnectRequest

REQ_RECONNECT_SOURCE

REQ_RECONNECT_TARGET

ConnectionEndpointEditPolicy

ENDPOINT_ROLE

GraphicalNodeEditPolicy

NODE_ROLE

拖动连接的端点的操作称为重置连接
(Reconnect)
,在端点上移动连接点的位置也属于重置连接。







GEF
使用
ConnectionEndpointEditPolicy
在连接的两个端点加上一些
Handle
,这个策略的角色为
ENDPOINT_ROLE
。每个
Handle
都会返回一个重置连接的
Tacker
,它们记录连接的端点位置。重置连接的命令由
GraphicalNodeEditPolicy
提供,命令的执行与连接的新端点相关。

在拖动连接端点的过程中,
Tracker
发送
ReconnectRequest
请求给新的端点对象,这个对象上安装的
GraphicalNodeEditPolicy
生成重置连接命令。重置连接命令需要知道连接的新旧端点,然后判断连接的重置是否有效,若有效将执行重置处理。


折线连接

(Bending Connections)


[thead]

[/thead]


Tools


Requests


Edit Policies
and Roles


Actions


ConnectionBendpointTracker

BendpointRequest

REQ_MOVE_BENDPOINT

REQ_CREATE_BENDPOINT

BendpointEditPolicy

CONNECTION_BENDPOINTS_ROLE

连接的路径有多种,有些连接使用拐点
(Bendpoint)
来定义连接的路径。我们可以通过安装
BendpointEditPolicy(CONNECTION_BENDPOINTS)
来编辑连接的拐点,而折点的修改将改变连接线的路径。这个编辑策略会在连接线上显示一系列的拐点,在用户选择修改连线路径的位置会出现一个代表拐点的
Handle


每个
Handle
都有一个
ConnectionBendpointTracker
,在用户尝试弯曲连接的时候,它会向连接对应的
EditPart
发送
BendpointRequest
请求。对于已有的拐点,请求有两种类型:
REQ_MOVE_BENDPOINT

REQ_CREATE_BENDPOINT
。当然将拐点拉回原来的位置,可以处理为移动拐点,也可以处理为删除拐点,视编辑策略的实现而定。








示例图显示了
Logic
中的连线。
ShortestPathConnectionRouter
在连接遇到阻碍时会计算出最短的路径并绕过阻碍,这就形成了一些拐点。拐点保存在连接路由的拐点列表汇总。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐