GEF常见问题2:具有转折点的连接线
从直线连接转换到可以任意增减转折点的折线连接,因为模型里要增加新的元素,所以模型、editpart和图形部分都要有所修改,显得稍微有些烦琐,但其实很多代码是通用的。这个过程主要分为以下几个部分:
1、在模型里增加转折点对应的类(这些转折点在GEF里称作Bendpoint),在类里要具有两个Dimension类型用来记录Bendpoint相对连接线起止点的位置。在连接类里要维护一个Bendpoint列表,并提供访问方法,由于篇幅关系这里只列出连接类中的这几个方法。
getBendpoints().add(index, point);
firePropertyChange(PROP_BENDPOINT, null, null);
}
/**
* zhanghao: 为了在更新两个dimension后能发送事件,在MoveBendpointCommand要在用这个方法设置新坐标,
* 而不是直接用BendPoint里的方法。
*/
public void setBendpointRelativeDimensions(int index, Dimension d1, Dimension d2){
ConnectionBendpoint cbp=(ConnectionBendpoint)getBendpoints().get(index);
cbp.setRelativeDimensions(d1,d2);
firePropertyChange(PROP_BENDPOINT, null, null);
}
public void removeBendpoint(int index) {
getBendpoints().remove(index);
firePropertyChange(PROP_BENDPOINT, null, null);
}
2、在原来的连接方式里,由于连接线本身不需要刷新,所以现在要确保这个editpart实现了PropertyChangeListener接口,并像其他editpart一样覆盖了activate()和deactivate()这两个方法,以便接收Bendpoint发生改变的事件。
super.activate();
((Connection)getModel()).addPropertyChangeListener(this);
}
public void deactivate() {
super.deactivate();
((Connection)getModel()).removePropertyChangeListener(this);
}
public void propertyChange(PropertyChangeEvent event) {
String property = event.getPropertyName();
if(Connection.PROP_BENDPOINT.equals(property)){
refreshBendpoints();
}
}
为模型连接类对应的editpart里增加一个继承自BendpointEditPolicy的子类ConnectionBendPointEditPolicy,这个类的内容后面会说到。
installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE, new ConnectionBendPointEditPolicy());
}
直线连接的情况下,连接的刷新不需要我们负责,但增加了Bendpoint以后,必须在Bendpoint发生改变时刷新连接线的显示。所以在上面这个editpart的refreshVisuals()方法里需要增加一些代码,以便把模型里的Bendpoint转换为图形上的relativeBendpoint。
Connection conn = (Connection) getModel();
List modelConstraint = conn.getBendpoints();
List figureConstraint = new ArrayList();
for (int i = 0; i < modelConstraint.size(); i++) {
ConnectionBendpoint cbp = (ConnectionBendpoint) modelConstraint
.get(i);
RelativeBendpoint rbp = new RelativeBendpoint(getConnectionFigure());
rbp.setRelativeDimensions(cbp.getFirstRelativeDimension(), cbp
.getSecondRelativeDimension());
rbp.setWeight((i + 1) / ((float) modelConstraint.size() + 1));
figureConstraint.add(rbp);
}
getConnectionFigure().setRoutingConstraint(figureConstraint);
}
3、创建CreateBendpointCommand、MoveBendpointCommand和DeleteBendpointCommand这三个类,可以像Logic例子那样创建一个基类BendPointCommand让它们来继承。作为例子,BendpointCommand的内容如下。
protected int index;
protected Connection connection;
protected Dimension d1, d2;
public void setConnection(Connection connection) {
this.connection = connection;
}
public void redo() {
execute();
}
public void setRelativeDimensions(Dimension dim1, Dimension dim2) {
d1 = dim1;
d2 = dim2;
}
public void setIndex(int i) {
index = i;
}
}
4、在ConnectionBendPointEditPolicy里实现BendpointEditPolicy定义的创建、移动和删除Bendpoint的三个方法。
protected Command getCreateBendpointCommand(BendpointRequest request) {
CreateBendpointCommand cmd = new CreateBendpointCommand();
Point p = request.getLocation();
Connection conn = getConnection();
conn.translateToRelative(p);
Point ref1 = getConnection().getSourceAnchor().getReferencePoint();
Point ref2 = getConnection().getTargetAnchor().getReferencePoint();
conn.translateToRelative(ref1);
conn.translateToRelative(ref2);
cmd.setRelativeDimensions(p.getDifference(ref1), p.getDifference(ref2));
cmd.setConnection((com.example.model.Connection) request.getSource()
.getModel());
cmd.setIndex(request.getIndex());
return cmd;
}
protected Command getDeleteBendpointCommand(BendpointRequest request) {
BendpointCommand cmd = new DeleteBendpointCommand();
Point p = request.getLocation();
cmd.setConnection((com.example.model.Connection) request.getSource().getModel());
cmd.setIndex(request.getIndex());
return cmd;
}
protected Command getMoveBendpointCommand(BendpointRequest request) {
MoveBendpointCommand cmd = new MoveBendpointCommand();
Point p = request.getLocation();
Connection conn = getConnection();
conn.translateToRelative(p);
Point ref1 = getConnection().getSourceAnchor().getReferencePoint();
Point ref2 = getConnection().getTargetAnchor().getReferencePoint();
conn.translateToRelative(ref1);
conn.translateToRelative(ref2);
cmd.setRelativeDimensions(p.getDifference(ref1), p.getDifference(ref2));
cmd.setConnection((com.example.model.Connection) request.getSource()
.getModel());
cmd.setIndex(request.getIndex());
return cmd;
}
}
修改完成后的编辑器如下图所示。
编辑器中的转折连接线
点此下载工程,此工程修改自GEF应用实例中的GefPractice,目标文件的扩展名改为.gefpracticebp。