目标:创建连接
GEF的连接:
GEF中的连接也被当成模型来看待。连接这种模型拥有起点Source和终点Target,它们都被称为节点Node。
创建连接的步骤:
1. 创建连接模型ConnectionModel及其控制器EditPart
连接的控制器一般由org.eclipse.gef.editparts.AbstractConnectionEditPart派生。
不要忘记在PartFactory这个负责创建EditParts的工厂里把连接模型与控制器联系起来。
2. 修改节点模型及其EditPart
本例中连接的节点是HelloModel,所以HelloModel要增加两个List:sourceConnections与targetConnections。注意sourceConnections指当前model为起点(source)的所有连接,也就是出去的连接outgoingConnections,更标准的写法是modelSourceConnections,可以记为“以当前model为source的connections”。targetConnections正好相反。
节点模型的EditPart要实现NodeEditPart接口。简单理解的话,这个接口定义了连接的锚点Anchor。连接模型不是直接与节点相连,而是通过锚点与节点联系起来的。
一般使用org.eclipse.draw2d.ChopboxAnchor,如本例:
public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {
return new ChopboxAnchor(getFigure());
}
ChopboxAnchor定位在figure(传入参数)的边界上,其延长线与figure的中心相交。
此外,还有LabelAnchor(指向Label的图标icon的中心),EllipseAnchor(处理椭圆形边界的figure)和XYAnchor(可以自由定义Anchor的位置)。
NodeEditPart接口定义的锚点用于三个地方:a. 正常显示;b. 创建连接中途(此时还没有ConnectionEditPart)用来显示feedback;c. 重定向连接时用来显示feedback。b对应的request是CreateConnectionRequest,c对应的是ReconnectRequest,可以由此在下面的方法中区别处理。<这增进了一种思路,虽然不一定有实际用途>
public ConnectionAnchor getSourceConnectionAnchor(Request request) { // if/else ... }
最后要使ConnectionEditPart能够处理节点增删连接的事件,更新视图。
refreshSourceConnections()方法用来更新出去的连接,它需要调用getModelSourceConnections()方法,我们需要重载它,让它返回节点的所有source connections模型。(可类比getModelChildren方法对ContentsEditPart的作用)
refreshTargetConnections()方法用来处理进入的连接incoming connections。
protected List getModelTargetConnections() {
return ((HelloModel) getModel()).getModelTargetConnections();
}
3. 在palette上加上“连接”工具
4. 修改连接模型
在连接模型中增加起点Source与终点Target对象,并添加attachSource,detachSource,attachTarget与detachTarget方法。
5. 创建连接命令
重载了canExecute方法,限制自身连接。
6. 实现连接相关的Policy并安装
负责连接创建的policy是org.eclipse.gef.editpolicies.GraphicalNodeEditPolicy。需要重载如下方法:
// 创建连接。是Source节点的控制器调用的该方法。
protected Command getConnectionCreateCommand(CreateConnectionRequest request) {
// 生成一个创建连接的命令
CreateConnectionCommand command = new CreateConnectionCommand();
command.setConnection(request.getNewObject());
command.setSource(getHost().getModel());
// 创建连接的命令被记录下来
request.setStartCommand(command);
return command;
}
// 完成连接。是Target节点的控制器调用的该方法。
protected Command getConnectionCompleteCommand(CreateConnectionRequest request) {
// 从request中获得Source节点生成的创建连接的命令
CreateConnectionCommand command = (CreateConnectionCommand) request.getStartCommand();
command.setTarget(getHost().getModel());
// 返回完整的创建连接的命令,交给CommandStack执行。
return command;
}
生成创建连接命令与前面的例子不一样,因为这个操作涉及到了两个节点的控制器。
很明显,这个Policy要安装在节点控制器上(HelloEditPart),使用的Role是EditPolicy.GRAPHICAL_NODE_ROLE。
7. 修改DeleteCommand使得删除节点时相关连接也自动删除
8. 创建带箭头的连接
连接默认使用PolylineConnection作为figure(继承自AbstractConnectionEditPart)。我们可以给PolylineConnection加上装饰 PolygonDecoration——实心的三角箭头。
polylineConnection.setTargetDecoration(new PolygonDecoration());
也可以使用PolylineDecoration——三角箭头。
这两种装饰都可以通过setScale方法设置大小。