[zt]第四章 GEF框架(3)

FROM:http://www.blog.edu.cn/user1/19180/archives/2005/1025573.shtml

4.4   请求说明  

  处于MVC核心地位的EditPart,负责控制模型和视图,以及接受用户的请求。请求(Request)构成了用户一种用户接口(UI),系统将各种操作(鼠标、键盘)封装成不同的Request传递给EditPart进行处理。

    另一个和请求有关的概念是EditPolicy,这可以看成是一种代理,它可以分担EditPart处理请求的责任,增加软件的复用性。前面说过EditPolicy不是必需的,因为所有的请求都可以在EditPart中进行处理,然而使用EditPolicy还有一个好处就是——它可对请求进行进一步的分发(Dispatch),使得结构更清晰更容易理解(但如果你去看Policy的源代码,你会发现其实它也拥有一个getCommand操作,分发就是在那里进行的)。

    下面我给出对块状元素的3个请求,并且给出应用哪些EditPolicy可以处理这个请求。

4.4.1  创建一个块状元素

    创建一个块状元素的请求是CreateRequest,你可以通过比较RequestConstants.REQ_CREATE来确定这个请求(就是说你可以调用Request.getType来比较)。

    LayoutEditPolicy的getCreateCommand函数可以用来处理这个请求。

    通过调用CreateRequest.getNewObject方法,你可以创建一个新的元素,而通过调用CreateRequest.getNewObjectType函数可以获得新元素的类型,这是一个Class对象。通过调用CreateRequest.getLocation函数可以获得块状元素的左上点的坐标,调用CreateRequest.getSize函数则可以获得块状元素的大小,或者调用EditPolicy的getConstraintFor函数直接获得Rectangle。如果你用的是XYLayoutEditPolicy(对应XYLayout),那么获得大小和位置的操作是有意义的,如果你使用的是OrderedLayoutEditPolicy(对应ToolbarLayout和FlowLayout等),那么这两个属性将没有意义。这两个Policy分别对应不同的布局方法,不能混用。

4.4.2  重设一个块状元素的边界 

   重设一个块状元素的边界的请求是ChangeBoundsRequest,它对应两个请求类型:REQ_MOVE和REQ_RESIZE(同样在RequestConstants中定义,下同)。按照GEF的帮助所说,如果新的大小和原大小相同,GEF将产生一个REQ_MOVE请求,否则产生REQ_RESIZE请求,但显然REQ_RESIZE请求包含REQ_MOVE请求的情况。如果你只想处理移动请求,而不想(或者说不允许)处理REQ_RESIZE请求,那么你可以在EditPart中仅仅对REQ_MOVE进行相应,否则你需要对这两个进行处理。如果你使用父亲处理子女的移动请求(通常是这样做的),那么对应的请求类行是REQ_MOVE_CHILDREN和REQ_RESIZE_CHILDREN。

    对于父EditPart处理的情况,如果你使用的是XYLayoutEditPolicy,那么XYLayoutEditPolicy.createChangeConstraintCommand函数将用来处理这两个请求,它对应的是XYLayout布局。如果你使用的是诸如流布局一类的布局(也就是使用OrderedLayoutEditPolicy及其子类),那么createMoveChildCommand函数将用来处理移动元素的请求(这类布局不支持子元素的变形),而它的移动策略也不过是改变子元素的顺序,具体的可以参考GEF的API。

    通过调用ChangeBoundsRequest的getTransformedRectangle函数获得新的Rectangle(参数是原来的Rectangle,它会进行位置变换)。

4.4.3  删除一个块状元素

    删除一个块状元素的请求是GroupRequest(它还能代表其它的请求),其中类型是REQ_DELETE。这个请求只能由被删除的元素进行相应。

    ComponentEditPolicy的createDeleteCommand可以处理删除消息。

    然而,你可能会发现,即使你完成了所有的代码,但是无论你怎么按下Delete键,元素就是不会被删除(实际上,请求根本就没有产生)。这就是删除请求的不同之处:删除请求的发起者实际上是之前我们忽略的actionBar(工具栏),Delete键是工具栏的一个快捷操作而已。因此为了能让删除操作有效,我们必须定义工具栏。首先要实现工具栏的类,下面的例子能够帮助你实现一个简单的工具栏:

Request简介之SELECTION_FEEDBACK_ROLE

    这个角色专门用来处理和选择有关的请求,当一个对象被选中时(可能是由于各种原因被选中),GEF会使用到这个角色。因此,我们可以安装这个角色,来处理这些选择消息。

    安装这个角色的方法是,继承并安装SelectionEditPolicy,不过单纯继承GraphicalEditPolicy却更为简便,SelectionEditPolicy是raphicalEditPolicy的子类。所以下面通过继承一个GraphicalEditPolicy,来介绍这个角色。GraphicalEditPolicy并不是抽象类,因此没有抽象函数以待实现。对于常见的应用,我们关心以下几个操作:
‍showTargetFeedback
eraseTargetFeedback
‍getTargetEditPart
前两个操作在默认情况下什么也不做,第三个操作默认情况下返回null。首先我们看showTargetFeedback和eraseTargetFeedback的作用,为了说明这个问题,我们假定一个场景,我们希望一个矩形的元素,当我们向其中加入其他模型时,这个元素可以具有“热敏”风格,这个时候,我们可以重载showTargetFeedback函数如下:

java 代码
  1. public void showTargetFeedback(Request request){   
  2.     if(request.getType().equals(RequestConstants.REQ_ADD)||   
  3.         request.getType().equals(RequestConstants.REQ_CREATE)   
  4.     ) {   
  5.     /*  
  6.      * 保存元素的背景色‍   
  7.      * 将矩形元素高亮显示  
  8.      */  
  9.     }   
  10. ‍}  

 

REQ_ADD是想该矩形元素添加已经存在的模型时的请求,REQ_CREATE是向该元素中创建新的子模型。当然,这里的请求类型还可以是REQ_MOVE、REQ_CLONE、REQ_CONNECTION_START、REQ_CONNECTION_END等等。需要说明的是,REQ_MOVE并非移动这个Policy所在的模型,而是指一些子模型在这个模型内部移动,换句话说就是移动内部模型。然后再看看eraseTargetFeedback函数,它用来还原showTargetFeedback造成的影响,因此比较简单:

java 代码
  1. public void eraseTargetFeedback(Request request){   
  2.     /*  
  3.      * 如果模型被高亮显示,则恢复其原有的背景色  
  4.      * 反之什么也不用做‍  
  5.      */  
  6. }  


    现在再来看看getTargetEditPart函数,这个函数的作用是返回选中的EditPart,在默认情况下,它返回null或者自己,则GEF选中这个EditPart。对于一些特殊需求,我们允许它返回不是自己的EditPart,比如下面的情况:我们希望当我第一次选中一个元素时,则选中这个元素,否则选中它的父亲(容器)。为了达到这个目的,我们可以这样写:

java 代码
  1. public EditPart getTargetEditPart(Request request){‍   
  2.     if(request.getType().equals(RequestConstants.REQ_SELECTION)) {   
  3.         EditPart part = getHost();‍   
  4.         if(!(part.getParent() instanceof DiagramPart)&&   
  5.             part.getSelected()!=EditPart.SELECTED_NONE) {‍   
  6.                 part = part.getParent();   
  7.             }   
  8.             return part;   
  9.         }   
  10.     return null;   
  11. ‍}  

在这里我们假设DiagramPart是根EditPart,因为选中根EditPart没有意义。另一点需要说明的是,getSelected的返回值,包括SELECTED_NONE、SELECTED、SELECTED_PRIMARY,详细地的信息,可以参考GEF的帮助。

java 代码
  1. package pku.oo.ui.actions;   
  2.   
  3. import org.eclipse.gef.ui.actions.ActionBarContributor;   
  4. import org.eclipse.gef.ui.actions.DeleteRetargetAction;   
  5. import org.eclipse.gef.ui.actions.RedoRetargetAction;   
  6. import org.eclipse.gef.ui.actions.UndoRetargetAction;   
  7. import org.eclipse.jface.action.IToolBarManager;   
  8. import org.eclipse.ui.actions.ActionFactory;   
  9.   
  10. public class DiagramActionBarContributor extends ActionBarContributor {   
  11.   
  12.   
  13.     protected void buildActions() {   
  14.         addRetargetAction(new UndoRetargetAction());   
  15.         addRetargetAction(new RedoRetargetAction());   
  16.         addRetargetAction(new DeleteRetargetAction());   
  17.   
  18.     }   
  19.     protected void declareGlobalActionKeys() {   
  20.         // TODO Auto-generated method stub   
  21.   
  22.     }   
  23.     public void contributeToToolBar(IToolBarManager toolBarManager) {   
  24.         toolBarManager.add(getAction(ActionFactory.UNDO.getId()));   
  25.         toolBarManager.add(getAction(ActionFactory.REDO.getId()));   
  26.         toolBarManager.add(getAction(ActionFactory.DELETE.getId()));   
  27.     }   
  28. }   

 


同时,在plugin.xml中在Extensions里设置好contributorClass,详细请看第一部分。

4.4.4  处理连接(connection)   

Connection是个复杂的话题,这里先不阐述处理连接相关的方法(虽然和处理块状元素类似)。在以后的章节中,会专门解决连接的问题(包括绘制、控制、常用操作等等)。

4.4.5  添加EditPolicy

    之前说过,每个EditPolicy都扮演一个角色(role),只有正确设置角色,EditPolicy才能正常工作。你可以在EditPart的createEditPolicies中为这个EditPart添加EditPolicy。

    下面给出一些角色和它们对应的EditPolicy,其中也包括上面提到的几个EditPolicy:
    EditPolicy.LAYOUT_ROLE:对应所有的LayoutEditPolicy,对于具有子EditPart的Part是必须的。
    EditPolicy.COMPONENT_ROLE:对应所有的ComponentEditPolicy,元素能够被删除的话,你应该添加这个角色。
    EditPolicy.DIRECT_EDIT_ROLE:对应DirectEditManager,它用来处理在位编辑(In place edit),关于在位编辑的话题,也许将来会在一个小品文中叙述。
    EditPolicy.GRAPHICAL_NODE_ROLE:对应GraphicalNodeEditPolicy,如果这个块状元素能够被连接附着,那么它应该使用这个policy,我会在讲连接的时候说明这个policy的用法。
    EditPolicy.SELECTION_FEEDBACK_ROLE:对应GraphicalEditPolicy,这是一个处理鼠标选中的反馈角色,比如你想另元素具有热敏特性,可以使用这个角色。同样,关于这个角色的话题,也会出现在某个小品文中。
    EditPolicy.CONNECTION_ENDPOINTS_ROLE:对应ConnectionEndpointEditPolicy,这是一个关于连接的角色,这个类是可以直接被实例化的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值