流程設(shè)計(jì)器開(kāi)發(fā)四(策略和命令部分)
Posted on 2008-01-04 08:49 笑看人生 閱讀(1405) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): Java插件開(kāi)發(fā)要實(shí)現(xiàn)向編輯器增加活動(dòng),我們應(yīng)該在面板上選一種活動(dòng)(開(kāi)始活動(dòng),普通活動(dòng),結(jié)束活動(dòng)),拖到編輯器中。為此我們必須在面板和編輯器中分別加監(jiān)聽(tīng)。修改WorkflowProcessEditor類(lèi)
在編輯器的GraphicalViewer加監(jiān)聽(tīng)
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);
}
};
}
同時(shí)我們還必須給面板加監(jiān)聽(tīng),覆蓋父類(lèi)的createPaletteViewerProvider()方法:
protected PaletteViewerProvider createPaletteViewerProvider() {
returnnew PaletteViewerProvider(getEditDomain()) {
protectedvoid configurePaletteViewer(PaletteViewer viewer) {
super.configurePaletteViewer(viewer);
viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
}
};
}
光在這兩個(gè)地方加監(jiān)聽(tīng),還不夠,這里還要引出gef的重要概念:策略(Policy),用過(guò)Rose的人都知道,我們可以新建一個(gè)類(lèi)圖,移動(dòng)它,刪除它,這在流程設(shè)計(jì)器中也可以,只是新建活動(dòng),移動(dòng)活動(dòng)等操作,用戶(hù)這些操作其實(shí)是對(duì)控制器的操作,比如用戶(hù)用鼠標(biāo)移動(dòng)活動(dòng),其實(shí)這過(guò)程包括用戶(hù)向控制器發(fā)出移動(dòng)活動(dòng)的請(qǐng)求(Request),控制器就調(diào)用相應(yīng)的命令(Command)來(lái)修改模型中活動(dòng)的位置屬性,而模型的位置屬性發(fā)生變化,又會(huì)通知控制器,控制器就會(huì)刷新視圖,改變活動(dòng)的位置,這樣,我們就移動(dòng)了活動(dòng),那么控制器是怎么根據(jù)請(qǐng)求的類(lèi)型調(diào)用相應(yīng)的命令的,這就是策略的作用,簡(jiǎn)單說(shuō),策略保存了請(qǐng)求類(lèi)型和命令的映射關(guān)系,它知道什么樣的請(qǐng)求要調(diào)用哪個(gè)命令。
明白策略的含義之后,就可以更好的理解我們下面的程序了。我們要向流程中增加一個(gè)活動(dòng),就要向流程控制器發(fā)出請(qǐng)求,因此,我們要在流程控制器中安裝策略,由于我們?cè)诰庉嬈髦胁捎媒^對(duì)定位方式,因此安裝XYLayoutEditPolicy策略,我們定義一個(gè)類(lèi)WorkflowProcessXYLayoutEditPolicy繼承它,
我們修改WorkflowProcessEditPart類(lèi)的createEditPolicies方法:
protectedvoid createEditPolicies() {
installEditPolicy(EditPolicy.LAYOUT_ROLE, new WorkflowProcessXYLayoutEditPolicy());
}
其實(shí)這個(gè)策略不僅可以處理創(chuàng)建活動(dòng)的請(qǐng)求,還可以處理改變活動(dòng)位置和大小的請(qǐng)求。
接下來(lái)我們來(lái)看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;
}
}
如果我們發(fā)出在編輯器中新建活動(dòng)的請(qǐng)求,流程根據(jù)安裝的策略,就會(huì)調(diào)用這個(gè)類(lèi)的getCreateCommand方法,為此我們要修改這個(gè)方法,如果我們發(fā)出改變活動(dòng)大小和位置的請(qǐng)求,就會(huì)調(diào)用createChangeConstraintCommand方法。
為了修改流程模型,在流程模型中增加一個(gè)活動(dòng),我們用命令來(lái)實(shí)現(xiàn)這個(gè)功能,命令都具有撤銷(xiāo),重做功能,我們只需覆蓋redo,undo方法就可以實(shí)現(xiàn)這功能。:
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);
}
/* 撤銷(xiāo)
*/
publicvoid undo() {
parent.removeChild(newActivity);
}
}
接下來(lái),我們還要修改WorkflowProcessXYLayoutEditPolicy的getCreateCommand方法,如果在編輯器中請(qǐng)求創(chuàng)建的對(duì)象是開(kāi)始活動(dòng),活動(dòng),結(jié)束活動(dòng)的一種,都會(huì)調(diào)用剛才新建的命令。
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;
}
public boolean addChild(AbstractActivity a) {
if (a != null && activities.add(a)) {
firePropertyChange(CHILD_ADDED_PROP, null, a);
return true;
}
return false;
}
為此我們?cè)趐ropertyChange應(yīng)作如下修改:
public void propertyChange(PropertyChangeEvent evt) {
String prop = evt.getPropertyName();
if (WorkflowProcess.CHILD_ADDED_PROP.equals(prop)
|| WorkflowProcess.CHILD_REMOVED_PROP.equals(prop)) {
refreshChildren();
}
}
以上程序的意思是,當(dāng)往流程模型中增加活動(dòng)或者從流程模型中刪除活動(dòng)時(shí),刷新流程模型包含子元素對(duì)應(yīng)的視圖,而流程模型的子元素是活動(dòng)模型,而活動(dòng)模型控制器的refreshVisuals()我們也沒(méi)有實(shí)現(xiàn),因此我們也應(yīng)該實(shí)現(xiàn)這個(gè)方法,定義如下:
private AbstractActivity getCastedModel() {
return (AbstractActivity) getModel();
}
protectedvoid refreshVisuals() {
Rectangle bounds = new Rectangle(getCastedModel().getLocation(),
getCastedModel().getSize());
((GraphicalEditPart) getParent()).setLayoutConstraint(this, getFigure(), bounds);
}
在編輯器的GraphicalViewer加監(jiān)聽(tīng)
















同時(shí)我們還必須給面板加監(jiān)聽(tīng),覆蓋父類(lèi)的createPaletteViewerProvider()方法:








光在這兩個(gè)地方加監(jiān)聽(tīng),還不夠,這里還要引出gef的重要概念:策略(Policy),用過(guò)Rose的人都知道,我們可以新建一個(gè)類(lèi)圖,移動(dòng)它,刪除它,這在流程設(shè)計(jì)器中也可以,只是新建活動(dòng),移動(dòng)活動(dòng)等操作,用戶(hù)這些操作其實(shí)是對(duì)控制器的操作,比如用戶(hù)用鼠標(biāo)移動(dòng)活動(dòng),其實(shí)這過(guò)程包括用戶(hù)向控制器發(fā)出移動(dòng)活動(dòng)的請(qǐng)求(Request),控制器就調(diào)用相應(yīng)的命令(Command)來(lái)修改模型中活動(dòng)的位置屬性,而模型的位置屬性發(fā)生變化,又會(huì)通知控制器,控制器就會(huì)刷新視圖,改變活動(dòng)的位置,這樣,我們就移動(dòng)了活動(dòng),那么控制器是怎么根據(jù)請(qǐng)求的類(lèi)型調(diào)用相應(yīng)的命令的,這就是策略的作用,簡(jiǎn)單說(shuō),策略保存了請(qǐng)求類(lèi)型和命令的映射關(guān)系,它知道什么樣的請(qǐng)求要調(diào)用哪個(gè)命令。
明白策略的含義之后,就可以更好的理解我們下面的程序了。我們要向流程中增加一個(gè)活動(dòng),就要向流程控制器發(fā)出請(qǐng)求,因此,我們要在流程控制器中安裝策略,由于我們?cè)诰庉嬈髦胁捎媒^對(duì)定位方式,因此安裝XYLayoutEditPolicy策略,我們定義一個(gè)類(lèi)WorkflowProcessXYLayoutEditPolicy繼承它,
我們修改WorkflowProcessEditPart類(lèi)的createEditPolicies方法:




其實(shí)這個(gè)策略不僅可以處理創(chuàng)建活動(dòng)的請(qǐng)求,還可以處理改變活動(dòng)位置和大小的請(qǐng)求。
接下來(lái)我們來(lái)看WorkflowProcessXYLayoutEditPolicy





















如果我們發(fā)出在編輯器中新建活動(dòng)的請(qǐng)求,流程根據(jù)安裝的策略,就會(huì)調(diào)用這個(gè)類(lèi)的getCreateCommand方法,為此我們要修改這個(gè)方法,如果我們發(fā)出改變活動(dòng)大小和位置的請(qǐng)求,就會(huì)調(diào)用createChangeConstraintCommand方法。
為了修改流程模型,在流程模型中增加一個(gè)活動(dòng),我們用命令來(lái)實(shí)現(xiàn)這個(gè)功能,命令都具有撤銷(xiāo),重做功能,我們只需覆蓋redo,undo方法就可以實(shí)現(xiàn)這功能。:






















































接下來(lái),我們還要修改WorkflowProcessXYLayoutEditPolicy的getCreateCommand方法,如果在編輯器中請(qǐng)求創(chuàng)建的對(duì)象是開(kāi)始活動(dòng),活動(dòng),結(jié)束活動(dòng)的一種,都會(huì)調(diào)用剛才新建的命令。










這下,我運(yùn)行這個(gè)項(xiàng)目,我們從面板選中一個(gè)活動(dòng),放在編輯器中,編輯器根本沒(méi)有反映,其實(shí)是我們少寫(xiě)了一個(gè)地方,我們向編輯器放一個(gè)活動(dòng),向流程控制器發(fā)出在編輯器中增加活動(dòng)的請(qǐng)求,流程編輯器根據(jù)安裝的策略,調(diào)用相應(yīng)的命令修改流程模型,在流程模型中增加活動(dòng)模型,而此時(shí)流程模型發(fā)生了變化,控制器應(yīng)該刷新流程模型對(duì)應(yīng)的視圖,而我們程序是沒(méi)有寫(xiě)這段代碼的,因此我們要修改WorkflowProcessEditPart的propertyChange方法,由于在WorkflowProcess模型中,當(dāng)向模型中增加活動(dòng)時(shí)通知控制器流程的CHILD_ADDED_PROP發(fā)生變化的,見(jiàn)如下代碼:







為此我們?cè)趐ropertyChange應(yīng)作如下修改:







以上程序的意思是,當(dāng)往流程模型中增加活動(dòng)或者從流程模型中刪除活動(dòng)時(shí),刷新流程模型包含子元素對(duì)應(yīng)的視圖,而流程模型的子元素是活動(dòng)模型,而活動(dòng)模型控制器的refreshVisuals()我們也沒(méi)有實(shí)現(xiàn),因此我們也應(yīng)該實(shí)現(xiàn)這個(gè)方法,定義如下:









這個(gè)方法的含義是取得活動(dòng)模型的位置,大小信息,把當(dāng)前活動(dòng)模型定位到編輯器的適當(dāng)位置。
這下,我們?cè)龠\(yùn)行項(xiàng)目,就可以順利把活動(dòng)添加到編輯器中了。
在下一節(jié),我們將介紹如何移動(dòng),刪除活動(dòng),改變活動(dòng)的大小,在活動(dòng)之間新建轉(zhuǎn)移