【原创】GEF的控制器和请求编辑策略(二十四)

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

  控制器的功能

  在GEF的MVC结构里,控制器(Control)是模型与视图之间的桥梁,也是整个GEF的核心。它不仅要监听模型的变化,当用户编辑视图时,还要把编辑结果反映到模型上。

  在GEF中,控制器是由一组EditPart对象共同组成的,每一个模型对象都对应一个EditPart对象。应用程序中需要有一个EditPartFactory对象负责根据给定模型对象创建对应的EditPart对象,这个工厂类将在创建模型时被调用。

  控制器是GEF中最复杂的一部分,GEF把控制器完成的工作又分成了几个部分,包括请求和编辑策略及引申出来的命令模式,如图1所示。

13081368_200807170859211.jpg

图1 控制器

  用户的编辑操作被转换为一系列请求(Request),Eclipse中有很多种类的请求,这些种类在GEF里被称为角色(Role)。在GEF里有图形化和非图形化这两大类角色,前者如“Layout Role”对应和布局有关的操作,后者如“Connection Role”对应和连接有关的操作等。角色这个概念是通过编辑策略(EditPolicy)来实现的,EditPolicy的主要功能是根据请求创建相应的命令(Command),而后者会直接操作模型对象。

  对每一个EditPart,用户都可以“安装”一些EditPolicy。用户对这个EditPart的特定操作会被交给已安装的对应EditPolicy处理。这样做的直接好处是可以在不同EditPart之间共享一些重复操作。

  控制器的实现

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

  例程1 NodePart.java

  public class NodePart extends AbstractGraphicalEditPart implements

  PropertyChangeListener, NodeEditPart {

  protected DirectEditManager manager;

  //处理请求

  public void performRequest(Request req) {

  if (req.getType().equals(RequestConstants.REQ_DIRECT_EDIT)) {

  if (manager == null) {

  NodeFigure figure = (NodeFigure) getFigure();

  manager = new NodeDirectEditManager(this,

  TextCellEditor.class, new NodeCellEditorLocator(figure));

  }

  manager.show();

  }

  }

  //监听模型属性改变

  public void propertyChange(PropertyChangeEvent evt) {

  if (evt.getPropertyName().equals(Node.PROP_LOCATION))

  refreshVisuals();

  else if (evt.getPropertyName().equals(Node.PROP_NAME))

  refreshVisuals();

  else if (evt.getPropertyName().equals(Node.PROP_INPUTS))

  refreshTargetConnections();

  else if (evt.getPropertyName().equals(Node.PROP_OUTPUTS))

  refreshSourceConnections();

  }

  //创建模型对应的视图

  protected IFigure createFigure() {

  return new NodeFigure();

  }

  //设置编辑策略

  protected void createEditPolicies() {

  installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, new NodeDirectEditPolicy());

  installEditPolicy(EditPolicy.COMPONENT_ROLE, new NodeEditPolicy());

  installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new

  NodeGraphicalNodeEditPolicy());

  }

  //注册自己成为模型的监听器

  public void activate() {

  if (isActive()) {

  return;

  }

  super.activate();

  ((Node) getModel()).addPropertyChangeListener(this);

  }

  //把自己从模型的监听器中删除

  public void deactivate() {

  if (!isActive()) {

  return;

  }

  super.deactivate();

  ((Node) getModel()).removePropertyChangeListener(this);

  }

  //更新视图的显示

  protected void refreshVisuals() {

  Node node = (Node) getModel();

  Point loc = node.getLocation();

  Dimension size = new Dimension(150, 40);

  Rectangle rectangle = new Rectangle(loc, size);

  ((NodeFigure) this.getFigure()).setName(((Node) this.getModel()).getName());

  ((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(),

  rectangle);

  }

  //得到源连接的连接点

  public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {

  return new ChopboxAnchor(getFigure());

  }

  public ConnectionAnchor getSourceConnectionAnchor(Request request) {

  return new ChopboxAnchor(getFigure());

  }

  //得到目标连接的连接点

  public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {

  return new ChopboxAnchor(getFigure());

  }

  public ConnectionAnchor getTargetConnectionAnchor(Request request) {

  return new ChopboxAnchor(getFigure());

  }

  //得到以模型作为源的连接列表

  protected List getModelSourceConnections() {

  return ((Node) this.getModel()).getOutgoingConnections();

  }

  //得到以模型作为目标的连接列表

  protected List getModelTargetConnections() {

  return ((Node) this.getModel()).getIncomingConnections();

  }

  }

  上例通过继承AbstractGraphicalEditPart类实现了一个EditPart,另外,当GEF框架创建一个模型时,都会为此模型创建一个对应的控制器。

  创建控制器

  创建控制器的操作是在控制器工厂中完成的,用户可以在编辑器初始化时指定控制器工厂,例如“getGraphicalViewer().setEditPartFactory (new PartFactory());”,其中PartFactory为控制器工厂,代码如例程2所示。

  例程2 PartFactory.java

  public class PartFactory implements EditPartFactory {

  public EditPart createEditPart(EditPart context, Object model) {

  EditPart part = null;

  //根据模型创建相应的EditPart

  if (model instanceof Diagram)

  part = new DiagramPart();

  else if (model instanceof Connection)

  part = new ConnectionPart();

  else

  part = new NodePart();

  //设置EditPart对应的模型

  part.setModel(model);

  //返回根据模型创建的EditPart

  return part;

  }

  }

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

  请求和编辑策略

  请求和编辑策略是GEF框架中减轻控制器的负担、减小代码耦合度而实现的一种解决方案。

  请求和编辑策略

  请求和编辑策略(Request and EditPolicies)对初学者来说是比较难理解的部分,但正是因为这种机制才使得GEF框架功能强大,而且非常灵活。想象一下,如果用户所有操作的响应都由EditPart来处理会怎样,如果这样的话,EditPart的代码将会“又臭又长”,这是让人无法忍受的。

  在EditPart中,可以通过设置不同的编辑策略(EditPolicies)来处理不同的请求,这样,一方面,可以把代码从EditPart中解放出来,分别由不同的EditPolicies进行处理,另一方面,用户可以着力于自己的关注点,但由此也增加读者学习GEF框架的时间。

  另外,在EditPart中设置编辑策略时,要指定相应的角色(Role),角色只是一个标识,在同一个EditPart中不能存在两个相同角色的编辑策略,读者可以在GEF的联机文档中找到详细的编辑策略、请求和角色说明。

  编辑策略的实现

  控制器中通过createEditPolicies方法添加编辑策略,每种编辑策略负责处理相应的请求。通常请求一般会对模型进行操作,在EditPolicies中,可以通过命令的方式操作模型,命令将在后面介绍。EditPolicies的示例代码如例程3所示。

  例程3 DiagramLayoutEditPolicy.java

  public class DiagramLayoutEditPolicy extends XYLayoutEditPolicy {

  protected Command createAddCommand(EditPart child, Object constraint) {

  return null;

  }

  //创建模型位置改变的命令

  protected Command createChangeConstraintCommand(EditPart child, Object constraint) {

  //如果位置改变的不是Node则返回

  if (!(child instanceof NodePart))

  return null;

  if (!(constraint instanceof Rectangle))

  return null;

  MoveNodeCommand cmd = new MoveNodeCommand();

  cmd.setNode((Node) child.getModel());

  //设置模型新的位置信息

  cmd.setLocation(((Rectangle) constraint).getLocation());

  return cmd;

  }

  //获得创建模型的命令

  protected Command getCreateCommand(CreateRequest request) {

  //判断请求创建的是否为Node

  if (request.getNewObject() instanceof Node) {

  //新建CreateNodeCommand

  CreateNodeCommand cmd = new CreateNodeCommand();

  //设置父模型

  cmd.setDiagram((Diagram) getHost().getModel());

  //设置当前模型

  cmd.setNode((Node) request.getNewObject());

  Rectangle constraint = (Rectangle) getConstraintFor(request);

  //设置模型的位置信息

  cmd.setLocation(constraint.getLocation());

  //返回Command对象

  return cmd;

  }

  return null;

  }

  protected Command getDeleteDependantCommand(Request request) {

  return null;

  }

  }

  通过实现此编辑策略,GEF编辑器将能够处理XYLayoutEditPolicy所能响应的相关请求,并交由相应的Command进行处理。

fj.pngimage001.jpg

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/13081368/viewspace-402572/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/13081368/viewspace-402572/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值