posts - 36, comments - 30, trackbacks - 0, articles - 3

流程设计器开发四(策略和命令部分)

Posted on 2008-01-04 08:49 笑看人生 阅读(1391) 评论(0)  编辑  收藏 所属分类: Java插件开发
要实现向编辑器增加活动,我们应该在面板上选一种活动(开始活动,普通活动,结束活动),拖到编辑器中。为此我们必须在面板和编辑器中分别加监听。修改WorkflowProcessEditor类
在编辑器的GraphicalViewer加监听

protectedvoid initializeGraphicalViewer() {
    
super.initializeGraphicalViewer();
    GraphicalViewer viewer 
= getGraphicalViewer();
    viewer.setContents(getModel()); 
// set the contents of this editor
    
    
// listen for dropped parts
    viewer.addDropTargetListener(createTransferDropTargetListener());
}

 
private TransferDropTargetListener createTransferDropTargetListener() {
    returnnew TemplateTransferDropTargetListener(getGraphicalViewer()) 
{
       
protected CreationFactory getFactory(Object template) {
           returnnew SimpleFactory((Class) template);
       }

    }
;
}

同时我们还必须给面板加监听,覆盖父类的createPaletteViewerProvider()方法:

protected PaletteViewerProvider createPaletteViewerProvider() {
       returnnew PaletteViewerProvider(getEditDomain()) 
{
           protectedvoid configurePaletteViewer(PaletteViewer viewer) 
{
              
super.configurePaletteViewer(viewer);            
           viewer.addDragSourceListener(
new TemplateTransferDragSourceListener(viewer));
           }

       }
;
}

光在这两个地方加监听,还不够,这里还要引出gef的重要概念:策略(Policy),用过Rose的人都知道,我们可以新建一个类图,移动它,删除它,这在流程设计器中也可以,只是新建活动,移动活动等操作,用户这些操作其实是对控制器的操作,比如用户用鼠标移动活动,其实这过程包括用户向控制器发出移动活动的请求(Request),控制器就调用相应的命令(Command)来修改模型中活动的位置属性,而模型的位置属性发生变化,又会通知控制器,控制器就会刷新视图,改变活动的位置,这样,我们就移动了活动,那么控制器是怎么根据请求的类型调用相应的命令的,这就是策略的作用,简单说,策略保存了请求类型和命令的映射关系,它知道什么样的请求要调用哪个命令。

明白策略的含义之后,就可以更好的理解我们下面的程序了。我们要向流程中增加一个活动,就要向流程控制器发出请求,因此,我们要在流程控制器中安装策略,由于我们在编辑器中采用绝对定位方式,因此安装XYLayoutEditPolicy策略,我们定义一个类WorkflowProcessXYLayoutEditPolicy继承它,

我们修改WorkflowProcessEditPart类的createEditPolicies方法:
protectedvoid createEditPolicies() 
       installEditPolicy(EditPolicy.LAYOUT_ROLE, 
new WorkflowProcessXYLayoutEditPolicy());
       
}

其实这个策略不仅可以处理创建活动的请求,还可以处理改变活动位置和大小的请求。
接下来我们来看WorkflowProcessXYLayoutEditPolicy


package com.example.workflow.policy;
 
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
import org.eclipse.gef.requests.CreateRequest;
 
publicclass WorkflowProcessXYLayoutEditPolicy 
extends XYLayoutEditPolicy{
 
    
protected Command createChangeConstraintCommand(EditPart arg0, Object arg1) {
       
// TODO Auto-generated method stub
       returnnull;
    }

 
    
protected Command getCreateCommand(CreateRequest arg0) {
       
// TODO Auto-generated method stub
       returnnull;
    }

 
}

如果我们发出在编辑器中新建活动的请求,流程根据安装的策略,就会调用这个类的getCreateCommand方法,为此我们要修改这个方法,如果我们发出改变活动大小和位置的请求,就会调用createChangeConstraintCommand方法。
为了修改流程模型,在流程模型中增加一个活动,我们用命令来实现这个功能,命令都具有撤销,重做功能,我们只需覆盖redo,undo方法就可以实现这功能。:

package com.example.workflow.commands;
 
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.commands.Command;
 
import com.example.workflow.model.AbstractActivity;
import com.example.workflow.model.WorkflowProcess;
 
 
 
publicclass AbstractActivityCreateCommand 
extends Command{
    
    
private AbstractActivity newActivity;
    
    privatefinal WorkflowProcess parent;
    
    
private Rectangle bounds;
 
    
public AbstractActivityCreateCommand(AbstractActivity newActivity, WorkflowProcess parent, Rectangle bounds) {
       
this.newActivity = newActivity;
       
this.parent = parent;
       
this.bounds = bounds;
       setLabel(
"activity creation");
    }

 
    
    publicboolean canExecute() 
{
       returnnewActivity 
!= null && parent != null && bounds != null;
    }

 
    
/* (non-Javadoc)
     * @see org.eclipse.gef.commands.Command#execute()
     
*/

    publicvoid execute() 
{
       newActivity.setLocation(bounds.getLocation());
       Dimension size 
= bounds.getSize();
       
if (size.width > 0 && size.height > 0)
           newActivity.setSize(size);
       redo();
    }

 
    
/* 重做
     
*/

    publicvoid redo() 
{
       parent.addChild(newActivity);
    }

 
    
/* 撤销
     
*/

    publicvoid undo() 
{
       parent.removeChild(newActivity);
    }

}


接下来,我们还要修改WorkflowProcessXYLayoutEditPolicy的getCreateCommand方法,如果在编辑器中请求创建的对象是开始活动,活动,结束活动的一种,都会调用刚才新建的命令。

protected Command getCreateCommand(CreateRequest request) {
       Object childClass 
= request.getNewObjectType();
       
if (childClass == StartActivity.class
              
||childClass == Activity.class
              
||childClass == EndActivity.class{          
           returnnew AbstractActivityCreateCommand((AbstractActivity)request.getNewObject(), 
                  (WorkflowProcess)getHost().getModel(), (Rectangle)getConstraintFor(request));
       }

       
return null;
}

 

这下,我运行这个项目,我们从面板选中一个活动,放在编辑器中,编辑器根本没有反映,其实是我们少写了一个地方,我们向编辑器放一个活动,向流程控制器发出在编辑器中增加活动的请求,流程编辑器根据安装的策略,调用相应的命令修改流程模型,在流程模型中增加活动模型,而此时流程模型发生了变化,控制器应该刷新流程模型对应的视图,而我们程序是没有写这段代码的,因此我们要修改WorkflowProcessEditPart的propertyChange方法,由于在WorkflowProcess模型中,当向模型中增加活动时通知控制器流程的CHILD_ADDED_PROP发生变化的,见如下代码:

public boolean addChild(AbstractActivity a) {
       
if (a != null && activities.add(a)) {
           firePropertyChange(CHILD_ADDED_PROP, 
null, a);
           
return true;
       }

       
return false;
}

为此我们在propertyChange应作如下修改:

public void propertyChange(PropertyChangeEvent evt) {
       String prop 
= evt.getPropertyName();
       
if (WorkflowProcess.CHILD_ADDED_PROP.equals(prop)
              
|| WorkflowProcess.CHILD_REMOVED_PROP.equals(prop)) {
           refreshChildren();
        }

}

以上程序的意思是,当往流程模型中增加活动或者从流程模型中删除活动时,刷新流程模型包含子元素对应的视图,而流程模型的子元素是活动模型,而活动模型控制器的refreshVisuals()我们也没有实现,因此我们也应该实现这个方法,定义如下:

private AbstractActivity getCastedModel() {
       
return (AbstractActivity) getModel();
    }

    
    protectedvoid refreshVisuals() 
{      
       Rectangle bounds 
= new Rectangle(getCastedModel().getLocation(),
              getCastedModel().getSize());
       ((GraphicalEditPart) getParent()).setLayoutConstraint(
this, getFigure(), bounds);
}

这个方法的含义是取得活动模型的位置,大小信息,把当前活动模型定位到编辑器的适当位置。
这下,我们再运行项目,就可以顺利把活动添加到编辑器中了。

在下一节,我们将介绍如何移动,删除活动,改变活动的大小,在活动之间新建转移


只有注册用户登录后才能发表评论。


网站导航: