Posted on 2008-01-09 11:10
笑看人生 閱讀(1452)
評論(2) 編輯 收藏 所屬分類:
Java插件開發
哪個模型的控制器能接受在活動之間建立轉移的請求呢,只有活動模型的控制器了,因為活動模型中維護著活動的輸入和輸出轉移的列表,在活動控制器增加策略,使該控制器能接受建立轉移的請求,代碼如下:

protectedvoid createEditPolicies()
{
//allow removal of the associated model element
installEditPolicy(EditPolicy.COMPONENT_ROLE, new AbstractActivityComponentEditPolicy

());
//allow the creation of transitions and
// and the reconnection of transitions between AbstractActivity instances
installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new

TransitionGraphicalNodeEditPolicy());
}
這里安裝了TransitionGraphicalNodeEditPolicy策略,這個策略的代碼如下:
package com.example.workflow.policy;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.ReconnectRequest;
import com.example.workflow.commands.TransitionCreateCommand;
import com.example.workflow.model.AbstractActivity;

public class TransitionGraphicalNodeEditPolicy extends GraphicalNodeEditPolicy
{

protected Command getConnectionCompleteCommand(CreateConnectionRequest request)
{
TransitionCreateCommand cmd =
(TransitionCreateCommand)request.getStartCommand();
cmd.setTarget((AbstractActivity)getHost().getModel());
return cmd;
}

protected Command getConnectionCreateCommand(CreateConnectionRequest request)
{
AbstractActivity source = (AbstractActivity)getHost().getModel();
TransitionCreateCommand cmd = new TransitionCreateCommand(source);
request.setStartCommand(cmd);
return cmd;
}

protected Command getReconnectSourceCommand(ReconnectRequest request)
{
// TODO Auto-generated method stub
return null;
}

protected Command getReconnectTargetCommand(ReconnectRequest request)
{
// TODO Auto-generated method stub
return null;
}
}
這個類繼承了GraphicalNodeEditPolicy,并且覆蓋了getConnectionCreateCommand和getConnectionCompleteCommand,從這兩個方法的字面意思就明白它們在什么時候執行,在getConnectionCreateCommand方法中,新建一個TransitionCreateCommand命令對象,并且把轉移的起始活動放入該命令對象中,在getConnectionCompleteCommand方法中,得到在getConnectionCreateCommand方法中創建的命令,并且把轉移的目標活動放入命令中。TransitionCreateCommand命令的代碼如下:
package com.example.workflow.commands;
import java.util.Iterator;
import org.eclipse.gef.commands.Command;
import com.example.workflow.model.AbstractActivity;
import com.example.workflow.model.Transition;

public class TransitionCreateCommand extends Command
{

/** *//** The Transition instance. */
private Transition transition;

/** *//** Start endpoint for the Transition. */
private final AbstractActivity source;

/** *//** Target endpoint for the Transition. */
private AbstractActivity target;

public TransitionCreateCommand(AbstractActivity source)
{

if (source == null)
{
throw new IllegalArgumentException();
}
setLabel("connection creation");
this.source = source;
}

public boolean canExecute()
{
// disallow source -> source connections

if (source.equals(target))
{
return false;
}
// return false, if the source -> target connection exists already
for (Iterator iter = source.getSourceTransitions().iterator(); iter.hasNext


();)
{
Transition tran = (Transition) iter.next();

if (tran.getTarget().equals(target))
{
return false;
}
}
return true;
}

public void execute()
{
// create a new transition between source and target
transition = new Transition(source, target);
}

public void redo()
{
transition.reconnect();
}

public void setTarget(AbstractActivity target)
{

if (target == null)
{
throw new IllegalArgumentException();
}
this.target = target;
}

public void undo()
{
transition.disconnect();
}
}
在這個命令中,用剛才放入的兩個活動構建一個轉移對象,其實通過代碼我們知道最終執行的是在起始活動的輸入轉移列表中加入剛才新建的轉移對象,在目標活動的輸入轉移列表中加入新建的轉移對象。代碼如下:

void addTransition(Transition tran)
{

if (tran == null || tran.getSource() == tran.getTarget())
{
thrownew IllegalArgumentException();
}

if (tran.getSource() == this)
{
sourceTransitions.add(tran);
firePropertyChange(SOURCE_CONNECTIONS_PROP, null, tran);

} elseif (tran.getTarget() == this)
{
targetTransitions.add(tran);
firePropertyChange(TARGET_CONNECTIONS_PROP, null, tran);
}
}
我們看到,向活動維護的轉移列表中加入轉移時,活動模型通知控制器它的SOURCE_CONNECTIONS_PROP和TARGET_CONNECTIONS_PROP屬性發生變化了,因此在活動控制器中應該根據這兩個屬性來屬性活動的視圖,代碼如下:

publicvoid propertyChange(PropertyChangeEvent evt)
{
String prop = evt.getPropertyName();
if(AbstractActivity.SIZE_PROP.equals(prop)

||AbstractActivity.LOCATION_PROP.equals(prop))
{
refreshVisuals();

}elseif(AbstractActivity.SOURCE_TRANSITIONS_PROP.equals(prop))
{
refreshSourceConnections();

}elseif(AbstractActivity.TARGET_TRANSITIONS_PROP.equals(prop))
{
refreshTargetConnections();
}
}
這里刷新的不是活動的視圖,而是活動的輸入和輸入轉移對應的視圖。只修改這些代碼,還不能在編輯器中展示出新建的轉移,還應該讓活動控制器實現NodeEditPart接口,同時要實現這接口中的四個方法,代碼如下:
private ConnectionAnchor anchor;

protected ConnectionAnchor getConnectionAnchor()
{

if (anchor == null)
{
anchor = new ChopboxAnchor(getFigure());;
}
returnanchor;
}

public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart arg0)
{
return getConnectionAnchor();
}

public ConnectionAnchor getSourceConnectionAnchor(Request arg0)
{
return getConnectionAnchor();
}

public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart arg0)
{
return getConnectionAnchor();
}

public ConnectionAnchor getTargetConnectionAnchor(Request arg0)
{
return getConnectionAnchor();
}
這四個方法就是實現轉移和活動連接的錨點。另外我們還要覆蓋父類中的兩個方法,得到活動模型維護的輸入轉移和輸出轉移,代碼如下:

protected List getModelSourceConnections()
{
return getCastedModel().getSourceTransitions();
}

protected List getModelTargetConnections()
{
return getCastedModel().getTargetTransitions();
}
這樣我們就可以在活動之間建立轉移了,效果下圖:
這樣我們就在兩個活動之間建立了轉移。那么如何刪除轉移呢,要刪除活動之間的轉移,應該在轉移控制器中安裝策略,代碼如下:

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

protectedvoid createEditPolicies()
{
//Allows the removal of the transition model element

installEditPolicy(EditPolicy.CONNECTION_ROLE, new ConnectionEditPolicy()
{

protected Command getDeleteCommand(GroupRequest request)
{
returnnew TransitionDeleteCommand(getCastedModel());
}
});
}
這里安裝的是gef框架提供的策略,我們沒有創建自己的策略,而是直接覆蓋其中的getDeleteCommand,方法,在這個方法中新建了一個ransitionDeleteCommand命令,這個命令的代碼如下:
package com.example.workflow.commands;
import org.eclipse.gef.commands.Command;
import com.example.workflow.model.Transition;

public class TransitionDeleteCommand extends Command
{

/** *//** Transition instance to disconnect. */
private final Transition transition;

public TransitionDeleteCommand(Transition tran)
{

if (tran == null)
{
throw new IllegalArgumentException();
}
setLabel("Transition deletion");
this.transition = tran;
}

public void execute()
{
transition.disconnect();
}

public void undo()
{
transition.reconnect();
}
}
這個類最終執行的其實活動模型中的removeTransition方法,從活動模型維護的轉移列表中刪除它,而此時活動模型通知控制器自己的OURCE_CONNECTIONS_PROP和TARGET_CONNECTIONS_PROP屬性發生變化了,要刷新視圖,而這個我們在新建轉移時,已經實現,因而這兒不用在實現了。這樣運行程序,我們就可以刪除活動之間的轉移了。
接下來我們再給轉移控制器安裝一個策略,目的是當選擇轉移,轉移有個反饋,給用戶感覺是已經選擇了轉移,要不然,選擇和不選擇轉移,效果一樣,代碼如下:

protectedvoid createEditPolicies()
{
//Selection handle edit policy.
// Makes the transition show a feedback, when selected by the user.
installEditPolicy(EditPolicy.CONNECTION_ENDPOINTS_ROLE,
new ConnectionEndpointEditPolicy());
//Allows the removal of the transition model element

installEditPolicy(EditPolicy.CONNECTION_ROLE, new ConnectionEditPolicy()
{

protected Command getDeleteCommand(GroupRequest request)
{
returnnew TransitionDeleteCommand(getCastedModel());
}
});
}
下一節我們介紹如何在轉移上新建,刪除和移動拐點。