专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »编程综合 » 点击这里:GEF 进阶 第 2部分: Router »正文

点击这里:GEF 进阶 第 2部分: Router

来源: 发布时间:星期六, 2009年12月19日 浏览:0次 评论:0
  ConnectionRouter(连线路由器)

  图形的间连线路线是由连线路由器来决定在Shapes Examples中使用了最短路径路由器这个路由器会帮我们绕开图形的间障碍选择条最短路径进行连接如图1所示:


图1. ShortestPathConnectionRouter效果图


  我们看到左右两边图形连线绕过了中间图形在两处发生了转折这就是使用了最短路径路由器效果连线路由器可以安装到Connection Layer(连接层有关层概念我们在本系列下篇中讲述)也可以针对某条连接所以只要你愿意每条连线都可以有区别路由器如果你没有为某条连线指定个路由器那么缺省会使用连接层路由器Draw2D自带了些路由器实现除了图1 ShortestPathConnectionRouter还有ManhattanConnectionRouter等路由器实现如果这些自带路由器不能满足我们需要我们所要做就是实现ConnectionRouter接口实现个自定义路由器ConnectionRouter接口并不复杂如下所示:

  Object getConstra(Connection connection);

  void Constra(Connection connection, Object constra);

  void invalidate(Connection connection);

  void route(Connection connection);

  void remove(Connection connection);

  Constra 和getConstra用来设置/得到连接上Constra(约束)所谓Constra是指加在某个连线上些参数我们可以看到constra个Object类型区别路由器可能对constra有区别要求对于 ShortestPathConnectionRouter来说constra需要是个List对象里面包含了所有转折点

  invalidate 思路方法可以将个连线置为无效这样在下次布局操作时无效连接将被重新路由remove思路方法是将连线从路由器中删除也就是路由器不会再负责这条连线布局般只有在删除条连线时候才会我们可以在里面做些清除工作比如释放和连线相关cacheroute思路方法是路由操作真正发生地方我们般只需要实现route思路方法就可以了如果你还想做些其他操作可以考虑实现其他思路方法同样般是不推荐直接实现 ConnectionRouter接口我们可以继承AbstractRouter类这个类提供了些简单或者空实现还提供了两个额外思路方法 getStartPo和getEndPo方便我们得到连线两个端点

  SingleBendpoConnectionRouter

  我们将实现个自定义路由器叫做SingleBendpoConnectionRouter它采用种走直角方式连接两个图形如图2所示:


图2. SingleBendpoConnectionRouter效果图


  也许这种路由器并没有太多通用性但是我们只是作为个例子演示路由器实现了解了基本思路方法的后再去实现更复杂更实用路由器也就大同小异了

  路由器实现前提

  显然我们无法凭空计算出线路走向条连线具体路线和很多原因有关比如锚点、图形位置和大小图形的间相互关系等等所以我们需要能够访问到这些必须信息在Connection接口中我们有getTargetAnchor和getSourceAnchor可以让我们得到锚点而在ConnectionAnchor接口中(参见本系列第部分)我们有getOwner这样思路方法可以得到图形这些必要思路方法为我们实现路由器提供了可能

  实现route思路方法

  route思路方法代码如下:


 public void route(Connection conn) { 
 // 清空连线所有点 
 PoList pos = conn.getPos; 
 pos.removeAllPos; 
  
 // 得到目标和源参考点 
 Po sourceRef = conn.getSourceAnchor.getReferencePo; 
 Po targetRef = conn.getTargetAnchor.getReferencePo; 
 A_POINT.Location(sourceRef.x, targetRef.y); 
  
 // 得到起始点和结束点 
 Po startPo = conn.getSourceAnchor.getLocation(A_POINT); 
 Po endPo = conn.getTargetAnchor.getLocation(A_POINT); 
  
 // 添加起始点 
 A_POINT.Location(startPo); 
 conn.translateToRelative(A_POINT); 
 pos.addPo(A_POINT); 
  
 // 添加转折点 
 A_POINT.Location(sourceRef.x, targetRef.y); 
 conn.translateToRelative(A_POINT); 
 pos.addPo(A_POINT); 
  
 // 添加结束点 
 A_POINT.Location(endPo); 
 conn.translateToRelative(A_POINT); 
 pos.addPo(A_POINT); 
  
 // 设置连线经过所有点 
 conn.Pos(pos); 
 } 


  条连线实际上是通过系列点来描述而route思路方法实际任务也就是计算出这些点位置所以我们开始就得到了这条连线点序列(PoList对象)然后清空它重新计算这些点在我们这个路由器设计里条连线由 3个点组成:分别是起始点转折点和结束点它们构成了两条垂直直线起始点和结束点(也就是锚点)我们都已经了解如何得到了中间转折点也很容易得出我们就不解释了要指出我们需要把它们坐标转换为相对坐标再添加同时在添加完成的后我们还需要Pos思路方法这样才会生效

  所以说实现个路由器过程是很简单复杂的处在于路由算法但这已经不属于GEF范畴所以我们就不讨论它了

  改变连接层路由器

  我们只是实现了路由器还没有把这个路由器设置为缺省路由器所以我们还要做点小修改在DiagramEditPart createFigure思路方法里将ShortestPathConnectionRouter替换为 SingleBendpoConnectionRouter即可

  待改进地方

  我们自定义路由器很简单但是它也有点小问题当两个图形在垂直或水平方向有重叠时连线看上去有点不正常如图3所示:


图3. 点小bug


  这只是由于我们路由器算法不是很完善没有考虑到所有情况而已你可以尝试修改下route算法改正这个问题我们这里就不详细演示了

  为连线指定路由器

  我们目前是将路由器安装到了连接层于是所有连线都会使用同个路由器有些时候为了让布局更加灵活我们需要为条或多条连线指定个区别路由器由于Connection接口中提供了ConnectionRouter思路方法因此这是可以实现

  修改model

  为了让连线知道它要使用何种路由器我们需要修改连线model把当前路由器种类存进去我们在Connection.java里面加上个routerId成员同时再定义些表示区别路由器常量:


// router id constant 
public  final  SHORTEST_PATH_ROUTER = 0; 
public  final  MANHATTAN_ROUTER = 1; 
public  final  SINGLE_BENDPOINT_ROUTER = 2; 
 
private  routerId; 
 
public  getRouterId { 
  routerId; 
} 
 
public void RouterId( routerId) { 
 this.routerId = routerId; 
} 




  添加属性

  为了能够随时修改连线路由器我们为连线添加个router属性由于这些内容不在本文讨论范围中所以不描述了完成的后我们可以在属性视图中看到连线路由器属性和可选值:


图4. Router属性


  查看原图(大图)

  于是我们就可以让多种连线方式共存了对于复杂图形来说这样可以尽量避免连线重叠增加布局美观程度


图5. 使用多种路由器


  结束语

  GEF中几乎切东西都可以定制本文介绍是连线路由器定制我们可以把这些内容和上部分自定义锚点结合起来构建更为灵活布局不过不要忘记了Draw2D自带那些路由器实在找不到合适可以考虑使用自定义路由器



0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: