GEF理解系列八

这一节,我们继续来看一下连接线。

一、带箭头的连接线

带箭头本身其实通常来说都不是模型需要的,只是为了看起来方便而已。呵呵。这里我们就做这样的假设。所以要实现一个带箭头的连接线,只要让连线figure加一个箭头就可以了。
之前我们建了一个抽象的连接模型,但是一直只有一个子类。这里它终于又要派上用场了。
我们再建一个连接线模型:ArrowConnectionModel,让它也继承AbstractConnectionModel。这就够了,模型就建好了。然后我们再建一个ArrowConnectionEditPart,继承AbstractConnectionModelEditPart,这就是ArrowConnectionModel的EditPart类。
为了让连接带箭头,我们就不能再用缺省的连接线了,所以我们重写ArrowConnectionEditPart的createFigure()方法如下:
 protected IFigure createFigure() {
       PolylineConnection connection = super.createFigure() ;
       PolygonDecoration decoration = new PolygonDecoration();
       connection.setTargetDecoration(decoration);
       return connection;
 }
因为我们是要装饰target端,所以选择setTargetDecoration方法,也可以装饰source端。这都无所谓。
最后在EditPartFactory里追加这一对模型与控件器:
if(model instanceof ArrowConnectionModel){
   ArrowConnectionEditPart editPart = new ArrowConnectionEditPart();
   editPart.setModel(model);
   return editPart;
}
这样我们整个带箭头的连接线模型就建好了。最后为了能创建这个模型,我们需要在调色板上追加创建工具。还是修改Editor的getPaletteRoot()方法,追加一个:
....
   ConnectionCreationToolEntry arrowConnection = new ConnectionCreationToolEntry(
    "plain", "this is arrow connection", new SimpleFactory(
      ArrowConnectionModel.class), Activator
      .getImageDescriptor("icons/arrowLine.gif"), Activator
      .getImageDescriptor("icons/arrowLine.gif"));
  
  selectionGroup.add(arrowConnection);
....
运行结果 :

arrowLine

图一

二、增加连接线的路由点

现在,我们所有的连线都是直来直去的,不会打弯。这样的一个坏处就是,线会在图上画过。所以为了能更改连接线的路径,我们需要让连接线支持路由点。首先先不考虑其他的,我们单纯创建一个带路由点的线。

背景知识

要想让线支持路由,我们就需要为PolylineConnection设置新的ConnectionRouter对象,因为缺省的是ConnectionRouter.NULL;我们可以找一个ConnectionRouter的子类。这里我们设置为:BendpointConnectionRouter。

所以下面要怎么支持路由点,就由这个BendpointConnectionRouter说了算了。我们看一下BendpointConnectionRouter的源码,看看它是怎么取得和设置路由点的:

首先在方法:setConstraint(Connection connection, Object constraint)的实现里,以connection为键值,将所有这个connection的constraint放到一个Map里去了。

然后看方法:route(Connection conn);这就是用来具体设置路由点的。可以看到它先以connection为键,从Map里取出所有的constraint,然后把这个constraint强制为一个List,最后从List里的取出的对象再强制为一个BendPoint对象。

从上面,我们基础可以猜测,在以BendpointConnectionRouter为连接路由的情况下,我们应该怎么设置路由点了。如下:

  List list = new ArrayList();
  list.add(new AbsoluteBendpoint(10,30));
  connection.setRoutingConstraint(list);

其中,AbsoluteBendpoint为BendPoint类的一个子类。

实现

由了上面的背景知识,要实现就不难了。不过首先我们修改一下模型。为了记录连接线的路由点,我们需要加一个属性。这里我们都以AbstractConnectionModel来做,因为我们可以假设所有的线都需要支持路由点。我假设我们都已经较熟练了,所以这次我们写得全面一些:

首先我们让我们AbstractConnectionModel继承AbstractModel,因为我们要涉及到了事件通知了。

其次,在AbstractConnectionModel里追加以下内容用以支持增加、移除和移动路由点:

  public static final String P_CONSTRAINT = "p_constraint";
 private List<Bendpoint> constraints = new ArrayList<Bendpoint>();

 public List<Bendpoint> getConstraints() {
  return constraints;
 }

 public void addConstraint(int index, Bendpoint bendpoint) {
  if (!constraints.contains(bendpoint)) {
   constraints.add(index, bendpoint);
   firePropertyChange(P_CONSTRAINT, null, bendpoint);
  }
 }
 
 public void setConstraint(int index, Bendpoint bendpoint) {
  if (!constraints.contains(bendpoint)) {
   constraints.set(index, bendpoint);
   firePropertyChange(P_CONSTRAINT, null, bendpoint);
  }
 }

 public void removeConstraint(int index) {
  Bendpoint bendpoint = constraints.get(index);
  constraints.remove(index);
  firePropertyChange(P_CONSTRAINT, bendpoint, null);
 }

有一点需要注意的:为了保证操作后的路由点显示正确,我们在操作时需要保证操作结点的顺序。所以看上面三个处理方法中,都是基于index来实现的。

接下来还是实现Policy和Command。这下我们应该可以很快就找到我们的Policy了:BendpointEditPolicy。而且我们也应该知道它应该安在哪了:AbstractConnectionModelEditPart。如下:

installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE, new ConnectionBendpointEditPolicy());

最后就是实现Policy里的三个命令。这里我就不一一写了。样子都差不多。就举一个增加的例子:

public class CreateBendPointCommand extends Command {

 private AbstractConnectionModel model;

 private AbsoluteBendpoint point;
 
 private int index;

 public CreateBendPointCommand(AbstractConnectionModel model, Point point, int index) {
  super();
  this.model = model;
  this.point = new AbsoluteBendpoint(point);
  this.index = index;
 }

 @Override
 public void execute() {
  model.addConstraint(index,point);
 }

 @Override
 public void undo() {
  model.removeConstraint(index);
 }
}

最后完成我们的Policy:

  @Override
 protected Command getCreateBendpointCommand(BendpointRequest request) {
  CreateBendPointCommand command = new CreateBendPointCommand(
    (AbstractConnectionModel) request.getSource().getModel(),request.getLocation(),
    request.getIndex());
  return command;
 }

 @Override
 protected Command getDeleteBendpointCommand(BendpointRequest request) {
  RemoveBendPointCommand command = new RemoveBendPointCommand(
    (AbstractConnectionModel) request.getSource().getModel(),
    request.getLocation(),request.getIndex());
  return command;
 }

 @Override
 protected Command getMoveBendpointCommand(BendpointRequest request) {
  MoveBendPointCommand command = new MoveBendPointCommand(
    (AbstractConnectionModel) request.getSource().getModel(),
    request.getIndex(), request.getLocation());
  return command;
 }

 

按照背景知识里的说法,为了支持路由,我们需要给连接线设置一个ConnectionRouter。所以个性createFigure()方法如下:

 @Override
 protected IFigure createFigure() {
  PolylineConnection connection = new PolylineConnection();
  connection.setConnectionRouter(new BendpointConnectionRouter());
  return connection;
 }

好,我们可以试一下现在的效果: 已经可以用鼠标拖出一个一个的路由点了。只是放开后又恢复了。这次好像我们已经写了监听啊。咋回事呢?玩我的吧?发出事件写了是没错的,不过还没完成事件监听和处理。下面我们就要完成我们的事件处理。

修改AbstractConnectionModelEditPart,让它实现PropertyChangeListener监听,然后在propertyChange()方法可以这样写:

 public void propertyChange(PropertyChangeEvent evt) {
  if(evt.getPropertyName().equals(AbstractConnectionModel.P_CONSTRAINT)){
   refreshConnectionRoutes();
  }
 }

注意,这个refreshConnectionRoutes()是我自己写的。editPart本身并不带。好了,现在的任务就是怎么完成这个方法了。终于到最后一步了,死了也值了,哈哈哈哈。

我是这样完成的:

 private void refreshConnectionRoutes() {
  List<Bendpoint> constraints = ((AbstractConnectionModel)getModel()).getConstraints();
  ((PolylineConnection)getFigure()).setRoutingConstraint(constraints);
 }

 再试一下!!!!!唉呀,怎么回来啊,还是没出来。跟踪一下:它根本就没进我的propertyChange()方法里来嘛。知道了,是因为我没有把监听加上。在AbstractConnectionModelEditPart,追加以下内容即可(老东西,照着写就行了):

 @Override
 public void activate() {
  super.activate();
  ((AbstractConnectionModel)getModel()).addPropertyChangeListener(this);
 }
 @Override
 public void deactivate() {
  ((AbstractConnectionModel)getModel()).removePropertyChangeListener(this);
  super.deactivate();
 }

好了,这下肯定会出来了。我保证!!!效果图如下:

bendpoint

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值