GEF理解系列六(1)
这一节我们主要讲结点和连接的删除,另外就是连接的重定向。
一、连接线的选中与重定向因为和系列五还有点扯,所以先讲一下连接的重定向。
在上一节中,我们创建了一个用来新建连接的Policy:HelloWorldGraphicalNodeEditPolicy,它还有两个方法在上一节中一直没有提到:
????? @Override
????? protected Command getReconnectSourceCommand(ReconnectRequest request) {
??????????? // TODO Auto-generated method stub
??????????? return null;
????? }
?
????? @Override
????? protected Command getReconnectTargetCommand(ReconnectRequest request) {
??????????? // TODO Auto-generated method stub
??????????? return null;
????? }
看方法名就可以知道这两个方法就是用来返回重定向源和重定向目标的了。所以要完成重定向其实很简单,就是写两个command了。回想一下我们新建一个连接的过程:首先是有一个连接对象,然后给这个对象设置源和目标,最后把它附着到这个源和目标上的。这就完成了一个连接的创建。
?
以重定向源举例。如果要重定向源,那么首先应该是先离开原来的源,把目标源设置为新的源,最后附着到这个新的源的。代码大约就是:
connection.deattachSource();
connection.setSrc(newSrc);
connection.attachSource();
重定向目标结点过程也一样。这里就不复述了。最后完成上面的两个方法即可。列举代码如下:
?
ReconnectSourceCommand: ?
public class ReconnectSourceCommand extends Command {
?
????? private AbstractConnectionModel connection;
?
????? private HelloWorldModel src;
?
????? private HelloWorldModel old;
?
????? public ReconnectSourceCommand(AbstractConnectionModel connection,
????????????????? HelloWorldModel newSource) {
??????????? super();
??????????? this.connection = connection;
??????????? this.src = newSource;
????? }
?
????? @Override
????? public void execute() {
??????????? old = connection.getSrc();
??????????? connection.deattachSource();
??????????? connection.setSrc(src);
??????????? connection.attachSource();
????? }
?
????? @Override
????? public void undo() {
??????????? src = connection.getSrc();
??????????? connection.deattachSource();
??????????? connection.setSrc(old);
??????????? connection.attachSource();
????? }
}
重连方法:
????? @Override
????? protected Command getReconnectSourceCommand(ReconnectRequest request) {
??????????? ReconnectSourceCommand command = new ReconnectSourceCommand(
??????????????????????? (AbstractConnectionModel) request.getConnectionEditPart()
??????????????????????????????????? .getModel(), (HelloWorldModel) getHost().getModel());
??????????? return command;
????? }
?
????? @Override
????? protected Command getReconnectTargetCommand(ReconnectRequest request) {
??????????? ReconnectTargetCommand command = new ReconnectTargetCommand(
??????????????????????? (AbstractConnectionModel) request.getConnectionEditPart()
??????????????????????????????????? .getModel(), (HelloWorldModel) getHost().getModel());
??????????? return command;
????? }
这样就完成了重连了。
?
这里有一个失误,我还没讲怎么选中一条连接线呢。到目前为止,连接线都是不能选中的。呵呵,所以现在重定向命令已经完成,但是重定向操作还是不能做。那这里就顺便讲一下怎么选中一个连接线。
?
有点明白的观众一般此时会心里大喊:那是不是还是装Policy啊?对的,GEF中要想做点事,您都得做这个。那Policy安在哪呢?这个也很简单,因为是要选择Connection,和其他人无关,所以这个Policy肯定是要安在Connection的模型上。
?
这里因为我觉得所有的连接线都需要能够被选中。所以我就把这个Policy安装在:AbstractConnectionModel对应的EditPart上。不过因为我们还没有给AbstractConnectionModel定义EditPart。所以我们顺便定义一个。然后让所以其他connection的EditPart继承它就行了。代码就不举了。最后安装Policy。要支持连接线的选中,我们需要安装一个EditPolicy.CONNECTION_ENDPOINTS_ROLE,这里我们不需要写继承类,如下:
installEditPolicy(EditPolicy.CONNECTION_ENDPOINTS_ROLE, new ConnectionEndpointEditPolicy());
?
好了,连接线可以被选中了。因为我们已经完成了重定向功能,所以应该也可以被重定向了。试一下:
图一
?
?
二、结点的删除结点要被删除,还写Policy和command。这点跑不掉。看看现在已有的Policy里,都没有要返回一个删除命令的。所以肯定还得再写一个新Policy,然后把它安装到某个EditPart上去。
?
不过这里我有一点困惑的是:ContainerEditPolicy可以返回一个创建命令,怎么没有一个删除命令吗?我总觉得他们是一对的。可能是因为理解的还不深吧(后来理解,还是跟文件系统一样,删除是选中文件删除,不在是文件夹下操作)。不管怎么样,我们还是不得不去找一个支持删除的Policy,然后把它安装在一个EditPart上。
?
我们可以找到这个删除Policy为:ComponentEditPolicy。还有一个疑问就是:这个Policy应该安装在将被删除的模型EditPart上。这也很令我困惑(还是参考Windows文件系统:增加的时候是由父管理,这很好理解;删除的时候就变了自己删除自己呢!反正记住就行了)。
?
好了,我们写了一个ComponentEditPolicy类:HelloWorldComponentEditPolicy。然后把它安装到HelloWorldEditPart上去:
installEditPolicy(EditPolicy.COMPONENT_ROLE, new HelloWorldComponentEditPolicy());
还是和之前一样,先完成命令,再回过头来完成Policy。
?
早先我们讲增加的时候就讲了:一个HelloWorld要想被显示,它就得被加到content上去。那么我就想了,那要不想显示呢?它是不是就从content上移除啊?先试一下。
?
依据上面的想法,我们就猜想Command里至少应该有两个对象:一个将要被删除的,另一个就是content对象了。
command代码如下:
public class DeleteHelloWorldCommand extends Command {
?
????? private DiagramRootContent content;
????? private HelloWorldModel model;
????? public DeleteHelloWorldCommand(DiagramRootContent content,
????????????????? HelloWorldModel model) {
??????????? super();
??????????? this.content = content;
??????????? this.model = model;
????? }
????? @Override
????? public void execute() {
??????????? content.removeChild(model);
????? }
????? @Override
????? public void undo() {
??????????? content.addChild(model);
????? }
}
最后再完成Policy,如下:
????? @Override
????? protected Command getDeleteCommand(GroupRequest request) {
??????????? DeleteHelloWorldCommand command = new DeleteHelloWorldCommand(
??????????????????????? (DiagramRootContent) getHost().getParent().getModel(),
??????????????????????? (HelloWorldModel) getHost().getModel());
??????????? return command;
????? }
我们前面提到过:getHost()代表Policy所安装在的对象,所以这里就是HelloWorldEditPart。因此要得到helloworld模型和它的父模型,像上面这样写就行了。
试一下,成功了。呵呵。这里我们不用写监听事件,因为在前面写增加子节点时已经完成了。
????????????? 图:删除前 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?图:删除后 ?
?
?