工作流设计器之创建节点的流程


第 9 章 创建节点的流程

用户使用鼠标从palette中将节点拖放到画布上。

9.1. 拖放执行次序

0109-01.png

拖放次序

图 9.1. 拖放次序


鼠标操作

MOUSE_DOWN时,从palette获得当前拖拽的节点类型,这个节点类型是通过palette中的dom设置得到的,对应的设置在PaletteHelper中。

MOUSE_MOVE时,使用DRAGGING_NODE显示拖动图元,这个拖动中图元的信息也是从PaletteHelper中获得的。

MOUSE_UP时,根据palette中获得的节点类型,从ModelFactory中创建Model,并记录当前鼠标在画布上的相对位移,使用两者组装CreateNodeRequest。

请求及命令流程

CreateNodeRequest对应的EditPart是将要添加的节点的父节点,在不存在节点嵌套的情况下将使用rootEditPart.getContents()获得的顶级EditPart。

在此EditPart上执行createCommand(request),根据CreateNodeRequest创建CreateNodeCommand,CreateNodeCommand中保存新创建的model,画布上拖放的坐标和父节点对应的model(即当前处理request的EditPart所对应的model)。

提示

考虑不要让EditPart承担创建Command的责任,让Tracker去创建Command。

CreateNodeCommand将发送给CommandStack,CreateNodeCommand在执行过程中会调用parentModel.addChild(childModel),将新增节点模型添加到父节点模型中。

在parentModel的addChild()方法中,将触发"CHILD_ADDED"事件,绑定在Model上的EditPart会调用notifyChanged()方法,notifyChanged()中将调用refresh()方法对整个EditPart进行刷新。这个过程中会执行ProcessEditPart下所有图形的刷新。

警告

此处已经不再调用refreshChildren(),因为我们很确定添加了哪个节点,所以不用再去让父节点去遍历匹配下面的所有子节点,我们手工调用createChild()和addChild()就可以实现将新增子节点显示在画布上的效果。

此处的描述和对应的序列图都需要进行修改。

9.2. 刷新EditPart

警告

因为现在添加一个节点已经不会导致所有子节点刷新,所以这里的刷新EditPart次序应该放在其他章节中。实际上,最终重构之后,应该只有导入时才需要进行完全刷新。

基本的EditPart的关系是树形结构,每个parent节点下拥有多个child节点。

NodeEditPart在EditPart的基础上添加了多个sourceConnections和targetConnections。

ConnectionEditPart在EditPart的基础上添加了source和target的关联。


NodeEditPart刷新流程0109-02.png

图 9.2. NodeEditPart刷新流程


AbstractEditPart中的refresh()实际调用堆栈如下:

AbstractEditPart.refresh();
  AbstractGraphicalEditPart.refreshVisuals()
    AbstractGraphicalEditPart.getModel();
    AbstractGraphicalEditPart.getFigure();
      GraphicalViewport.update();
  AbstractGraphicalEditPart.refreshChildren();
    NodeEditPart.getModelChildren();
    ====================================
    [compare modelChildren and children]
      if
        childEditPart exists
      then
        childEditPart.refresh()
      else
        createChild(childModel)
        addChild(childEditPart)
    ====================================

createChlid()以及addChild()的流程

AbstractEditPart.createChild(model)
  EditPartFactory.createEditPart(model)
AbstractEditPart.addChild(editPart)
  AbstractEditPart.children.push(editPart)
  [editPart.setParent(this)]
  AbstractEditpart.addChildVisuals(editPart)
  ====================================
  if
    editPart is node
  then
    editPart.getFigure()
    LAYER_NODE.addChild(figure)
    figure.render()
  else if
    editPart is connection
  then
    if
      editPart.source != null and editPart.target != null
    then
      editPart.getFigure()
      LAYER_CONNECTION.addChild(figure)
      figure.render()
  ====================================

NodeEditPart的refresh()中会额外比对incomingConnections和outgoingConnections,这个过程将新增的connection图形显示到画布上。

警告

这里存在的一个问题,无论是什么Figure都会直接添加到NODE_LAYER中,这对我们想实现父子图形的场景就没辙了。所以以后这部分估计要重新设计了。

case 'CHILD_ADDED':
    //this.refreshChildren();
    var modelChild = option;
    var editPart = this.createChild(modelChild);
    this.addChild(editPart);

    modelChild.parent = this.model;
    editPart.parent = this;
    break;

在处理CHILD_ADDED这个事件中的createChild()也许应该修改成createEditPart(),因为这个方法中并不能让modelChild与parent进行关联。

而后续的modelChild与parent之间的关联部分不应该直接操作属性,而是应该通过方法。实际上数据模型的操作就应该放在CreateNodeCommand里。

CreateNodeCommand中:

redo: function() {
    this.parentNode.addChild(this.childNode);
},

undo: function() {
    this.parentNode.removeChild(this.childNode);
}

NodeModel中,可以看到parent与child的关联已经完成了,上面在EditPart中对child和parent的关联根本就是浪费。

addChild: function(child) {
    this.children.push(child);
    child.setParent(this);

    this.notify(this.CHILD_ADDED, child);
},
removeChild: function(child) {
    this.children.remove(child);
    child.setParent(null);

    //this.notify(this.CHILD_REMOVED_FROM_PARENT, child);
    child.notify('CHILD_REMOVED_FROM_PARENT', child);
},

removeChild()中只是将child与parent的关联去掉,然后触发CHILD_REMOVED_FROM_PARENT。

case 'CHILD_REMOVED_FROM_PARENT':
    this.parent.removeChild(this);
    this.model.removeChangeListener(this);
    break;

EditPart里做两件事情,第一把当前editpart与parent脱离关系,第二把自己从model的监听器列表中删除。这样实际上就把EditPart给作废掉了。

但是还没有看到删除图形的部分,应该是在parent.removeChild()时顺便进行了。


上一篇 下一篇

评论



分享