没办法,这几天一直在生病.也不是太严重.就是在家呆着,老爸把空调弄成20度(老妈解释,冰箱冷藏功能坏了,暂时用空调顶一下
)结果呢太凉,到外面又太热.一凉一热俺就病了.看来咱还是不能享受啊!不多说了,咱继续,还有一点,最近在看Junit(暂时是理论).所以呢,gef系列也可能上的慢一些!!
咱们接着上回来说.EditPart我们已经介绍过了.是否还记得createEditPolicies()这个方法.我们给他的解释是"安装相应的策略".比如ShapeEditPart这个类中的:
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/** *//** *//** *//**安置策略*/
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
protected void createEditPolicies()
{
//安装删除策略
installEditPolicy(EditPolicy.COMPONENT_ROLE, new ShapeComponentEditPolicy());
//安装建立,更改连接策略
installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new ShapeConnectionEditPolicy());
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
之前,我们已经说过,在EditPart,我们通过不同角色(即就是客户端的操作的抽象),来寻找不同的策略,去执行不同的命令.这样,一方面,可以把代码从EditPart中解放处 理,分别由不同的EditPolicies进行处理,另一方面,用户可以着力于自己的关注点.(我们可以举个例子:用户用鼠标移动活动,其实这过程包括用户向控制器发出移动活动的请求(Request),控制器就调用相应的命令(Command)来修改模型中活动的位置属性,而命令的调用时通过寻找编辑策略来完成的。而模型的位置属性发生变化,又会通知控制器,控制器就会刷新视图,改变活动的位置)
那我们先看上面那个createEditPolicies()中的两个策略。ShapeComponentEditPolicy提供命令将一个图形从图删除。
其角色是 EditPolicy.COMPONENT_ROLE。注意安装策略时要指定相应的角色(Role),角色只是一个标识,在同一个EditPart中不能存在两个相同角色的编辑策略,读者可以在GEF的联机文档(http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.gef.doc.isv/guide/guide.html )中找到详细的编辑策略、请求和角色说明。其代码是
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class ShapeComponentEditPolicy extends ComponentEditPolicy
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**
* 删除策略
* 建立删除命令
* @author hya
* */
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
protected Command createDeleteCommand(GroupRequest deleteRequest)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Object parent = getHost().getParent().getModel();
Object child = getHost().getModel();
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (parent instanceof DiagramModel && child instanceof ShapeModel)
{
return new DeleteShapeCommand((DiagramModel) parent, (ShapeModel) child);
}
return super.createDeleteCommand(deleteRequest);
}
}
我们可以看到,这个策略中调用了删除图形的命令。我们的命令将在另一个类中定义,他们其实都是对模型的操作。所有的命令都要继承自Command。如上面的DeleteShapeCommand类:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class DeleteShapeCommand extends Command
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private final ShapeModel child;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//** 容器 */
private final DiagramModel parent;
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**连接点列表(源点) */
private List sourceConnections;
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//** 连接点列表(终点) */
private List targetConnections;
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/** *//**记录子图是否从容器中删除 */
private boolean isRemoved;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public DeleteShapeCommand(DiagramModel parent, ShapeModel child)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (parent == null || child == null)
{
throw new IllegalArgumentException();
}
setLabel("shape deletion");
this.parent = parent;
this.child = child;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void addConnections(List connections)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for (Iterator iter = connections.iterator(); iter.hasNext();)
{
Connection conn = (Connection) iter.next();
conn.reconnect();
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public boolean canUndo()
{
return isRemoved;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void execute()
{
sourceConnections = child.getSourceConnections();
targetConnections = child.getTargetConnections();
redo();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void redo()
{
isRemoved = parent.removeChild(child);
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (isRemoved)
{
removeConnections(sourceConnections);
removeConnections(targetConnections);
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void removeConnections(List connections)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for (Iterator iter = connections.iterator(); iter.hasNext();)
{
Connection conn = (Connection) iter.next();
conn.disconnect();
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void undo()
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (parent.addChild(child))
{
addConnections(sourceConnections);
addConnections(targetConnections);
}
}
}
command是gef的内部实现,在命令中我们还要定义UNDO/redo的功能。gef将他们发入命令堆栈,以实现多次取消/重做的功能。我们可以看到,命令就是针对模型的一些相关操作。
前面涉及到的第二个策略是针对连接线的增加和更改。
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class ShapeConnectionEditPolicy extends GraphicalNodeEditPolicy
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
@Override
protected Command getConnectionCompleteCommand(
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
CreateConnectionRequest request)
{
ConnectionCreateCommand cmd = (ConnectionCreateCommand) request
.getStartCommand();
cmd.setTarget((ShapeModel) getHost().getModel());
return cmd;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
@Override
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
protected Command getConnectionCreateCommand(CreateConnectionRequest request)
{
ShapeModel source = (ShapeModel) getHost().getModel();
ConnectionCreateCommand cmd = new ConnectionCreateCommand(source);
request.setStartCommand(cmd);
return cmd;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
@Override
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
protected Command getReconnectSourceCommand(ReconnectRequest request)
{
Connection conn = (Connection) request.getConnectionEditPart().getModel();
ShapeModel newSource = (ShapeModel) getHost().getModel();
ConnectionReconnectCommand cmd = new ConnectionReconnectCommand(conn);
cmd.setNewSource(newSource);
return cmd;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
@Override
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
protected Command getReconnectTargetCommand(ReconnectRequest request)
{
Connection conn = (Connection) request.getConnectionEditPart().getModel();
ShapeModel newTarget = (ShapeModel) getHost().getModel();
ConnectionReconnectCommand cmd = new ConnectionReconnectCommand(conn);
cmd.setNewTarget(newTarget);
return cmd;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
我们通过不同的request来找到不同的命令来执行相关的操作。比如我们要建立一个连接,gef将调用getConnectionCompleteCommand和getConnectionCreateCommand方法,即该策略被要求创建一个连接命令。如果这个方法返回null,表示这个连接不能从所给的模型元素开始。如果允许连接的话,将创建新的命令,并作为起始命令存储在请求中。当用户点击另一个可视图形时,会要求策略提供一个连接完成命令。这是一个根据起始命令创建的新命令,而起始命令中包含了连接结束点的信息。那么创建连接命令的类我们就可以预见它是一系列针对Connection模型的操作:
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class ConnectionCreateCommand extends Command
{
private Connection connection;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private final ShapeModel source;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private ShapeModel target;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public ConnectionCreateCommand(ShapeModel source)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (source == null)
{
throw new IllegalArgumentException();
}
this.source = source;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void execute()
{
// 建立新连接
connection = new Connection(source, target);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void redo()
{
connection.reconnect();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//设置目的连接点
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void setTarget(ShapeModel target)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (target == null)
{
throw new IllegalArgumentException();
}
this.target = target;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void undo()
{
connection.disconnect();
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
那么过程我们就可以基本连接起来了:接着上面的说,我们增加连接线是执行了相应的命令。对相应的模型进行操作。当模型改变时,我们模型就调用firePropertyChange(String property, Object oldValue,Object newValue) 方法来同时EditPart增加了连接,然后刷新视图,反映改变。 (红色部分,得过程及代码实现见二,三天的帖子)
其他EditPart中安装的策略,和执行的命令原理是一样的,在这里我们不再赘述。