GEF七天之第四天

    没办法,这几天一直在生病.也不是太严重.就是在家呆着,老爸把空调弄成20度(老妈解释,冰箱冷藏功能坏了,暂时用空调顶一下)结果呢太凉,到外面又太热.一凉一热俺就病了.看来咱还是不能享受啊!不多说了,咱继续,还有一点,最近在看Junit(暂时是理论).所以呢,gef系列也可能上的慢一些!!

     咱们接着上回来说.EditPart我们已经介绍过了.是否还记得createEditPolicies()这个方法.我们给他的解释是"安装相应的策略".比如ShapeEditPart这个类中的:

 

 /** *//**安置策略*/
    
protected void createEditPolicies() {
        
//安装删除策略
        installEditPolicy(EditPolicy.COMPONENT_ROLE, new ShapeComponentEditPolicy());
        
//安装建立,更改连接策略
        installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new ShapeConnectionEditPolicy());
   }

   之前,我们已经说过,在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 )中找到详细的编辑策略、请求和角色说明。其代码是

public class ShapeComponentEditPolicy extends ComponentEditPolicy {

/**
 * 删除策略
 * 建立删除命令
 * 
@author hya
 * 
*/

protected Command createDeleteCommand(GroupRequest deleteRequest) {

    Object parent 
= getHost().getParent().getModel();
    Object child 
= getHost().getModel();
    
if (parent instanceof DiagramModel && child instanceof ShapeModel) {
        
return new DeleteShapeCommand((DiagramModel) parent, (ShapeModel) child);
    }

    
return super.createDeleteCommand(deleteRequest);
}

}

我们可以看到,这个策略中调用了删除图形的命令。我们的命令将在另一个类中定义,他们其实都是对模型的操作。所有的命令都要继承自Command。如上面的DeleteShapeCommand类:

 

 


public class DeleteShapeCommand extends Command {

private final ShapeModel child;

/** 容器 */
private final DiagramModel parent;
/**连接点列表(源点) */
private List sourceConnections;
/** 连接点列表(终点) */
private List targetConnections;
/**记录子图是否从容器中删除 */
private boolean isRemoved;

public DeleteShapeCommand(DiagramModel parent, ShapeModel child) {
    
if (parent == null || child == null{
        
throw new IllegalArgumentException();
    }

    setLabel(
"shape deletion");
    
this.parent = parent;
    
this.child = child;
}



private void addConnections(List connections) {
    
for (Iterator iter = connections.iterator(); iter.hasNext();) {
        Connection conn 
= (Connection) iter.next();
        conn.reconnect();
    }

}



public boolean canUndo() {
    
return isRemoved;
}


public void execute() {
    sourceConnections 
= child.getSourceConnections();
    targetConnections 
= child.getTargetConnections();
    redo();
}



public void redo() {
    isRemoved 
= parent.removeChild(child);
    
if (isRemoved) {
        removeConnections(sourceConnections);
        removeConnections(targetConnections);
    }

}



private void removeConnections(List connections) {
    
for (Iterator iter = connections.iterator(); iter.hasNext();) {
        Connection conn 
= (Connection) iter.next();
        conn.disconnect();
    }

}


public void undo() {
    
if (parent.addChild(child)) {
        addConnections(sourceConnections);
        addConnections(targetConnections);
    }

}

}

   command是gef的内部实现,在命令中我们还要定义UNDO/redo的功能。gef将他们发入命令堆栈,以实现多次取消/重做的功能。我们可以看到,命令就是针对模型的一些相关操作。

  前面涉及到的第二个策略是针对连接线的增加和更改。

public class ShapeConnectionEditPolicy extends GraphicalNodeEditPolicy {

    @Override
    
protected Command getConnectionCompleteCommand(
            CreateConnectionRequest request) 
{
        ConnectionCreateCommand cmd 
= (ConnectionCreateCommand) request
                .getStartCommand();
        cmd.setTarget((ShapeModel) getHost().getModel());
        
return cmd;
    }


    @Override
    
protected Command getConnectionCreateCommand(CreateConnectionRequest request) {
        
        ShapeModel source 
= (ShapeModel) getHost().getModel();
        ConnectionCreateCommand cmd 
= new ConnectionCreateCommand(source);
        request.setStartCommand(cmd);
        
return cmd;
    }


    @Override
    
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;
    }


    @Override
    
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;
    }


}

  我们通过不同的request来找到不同的命令来执行相关的操作。比如我们要建立一个连接,gef将调用getConnectionCompleteCommand和getConnectionCreateCommand方法,即该策略被要求创建一个连接命令。如果这个方法返回null,表示这个连接不能从所给的模型元素开始。如果允许连接的话,将创建新的命令,并作为起始命令存储在请求中。当用户点击另一个可视图形时,会要求策略提供一个连接完成命令。这是一个根据起始命令创建的新命令,而起始命令中包含了连接结束点的信息。那么创建连接命令的类我们就可以预见它是一系列针对Connection模型的操作:

public class ConnectionCreateCommand extends Command {
private Connection connection;


private final ShapeModel source;

private ShapeModel target;


public ConnectionCreateCommand(ShapeModel source) {
    
if (source == null{
        
throw new IllegalArgumentException();
    }

    
this.source = source;
}



public void execute() {
    
// 建立新连接
    connection = new Connection(source, target);
}



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


//设置目的连接点
public void setTarget(ShapeModel target) {
    
if (target == null{
        
throw new IllegalArgumentException();
    }

    
this.target = target;
}


public void undo() {
    connection.disconnect();
}

}

 

   那么过程我们就可以基本连接起来了:接着上面的说,我们增加连接线是执行了相应的命令。对相应的模型进行操作。当模型改变时,我们模型就调用firePropertyChange(String property, Object oldValue,Object newValue) 方法来同时EditPart增加了连接,然后刷新视图,反映改变。 (红色部分,得过程及代码实现见二,三天的帖子)

 

    其他EditPart中安装的策略,和执行的命令原理是一样的,在这里我们不再赘述。

posted @ 2008-07-27 00:18    阅读(839)  评论(2编辑  收藏  举报