GEF功能增强之连接助手

GEF图形编辑器中,通常会有连接线的存在,如果没有,这篇文章你有兴趣也可以看看。

要连接两个图元,通常我们的作法是:选择palette中的connectionTool,然后选择一个图,再拖去鼠标到另一个图元上去。

 

我看的有editor会有一些快捷方式,支持我称之为连接助手的功能:选择一个图元,在图元的右下角会长出一些功能图元,选择其中一个(例如connection的功能),就可以直接拖动到其他图上,从而完成连接的操作。看附件图。

GEF功能增强之连接助手

这样的一个方便之处就是省了在palette上的切换的操作,当然推而广之,可以将某一类模型具体的所有操作都添加到这个功能区域,从而实现把操作集成到这个模型对象上。

 

实现这样的功能首先之一是:怎么让功能图显示出来。

 

首先要明确一点:这些功能图不是本身图元的一部分,所以不要所它直接画在宿主图上。我们可以参考handler,例如当选中一个图元的时候,会出现一个selection的handler,它会围绕着图元出现,但不属于这个图元,如果知道gef中层的概念的话就知道,handler是放在handler层,类似的还有feedback放在feedback层。

 

所以参考selectionHandler,我们也可以实现一个类似的handler,所以剩下的就是怎么实现handler的问题了。

 

在LayoutEditPolicy里有一个createChildEditPolicy(EditPart),是用来给child添加装饰用的。看它的子类实现就可以看到,ConstrainedLayoutEditPolicy里返回了一个ResizableEditPolicy,里面有一个createSelectionHandles()方法,打个断点就可以看到,当选择这个editpart的时候会调到这个方法。

 

所以简单一点的实现就是给你的Editpart安装一个LayoutEditPolicy的实现,重写它的createChildEditPolicy()方法,返回一个自定义的ResizableEditPolicy。

 

在这个自定义的ResizableEditPolicy里重写createSelectionHandles()方法,例如:

	@Override
	protected EditPolicy createChildEditPolicy(EditPart child) {
		return new ConnectionHelperEditPolicy();
	}

 

public class ConnectionHelperEditPolicy extends ResizableEditPolicy {
	@Override
	protected List createSelectionHandles() {
		List selectionHandles = super.createSelectionHandles();
		if (getHost() instanceof ***EditorPart) {
			selectionHandles.add(new ConnectionHelperHandler(
					(GraphicalEditPart) getHost()));
			selectionHandles.add(new ArrowConnectionHelperHandler(
					(GraphicalEditPart) getHost()));
		}
		return selectionHandles;
	}
}

 

这样,当你选中图元的时候,除了selectionHandles,还会多出两个handle,就像附件图里看到的。

 

后面的就是怎么实现这两个HelperHandler了。这里我合成一个讲,因为我的类子里,这两个大同小异,只不过一个是带前头的连线,一个不带箭头。

 

每一个handle都是Handle类的一个实现,GEF里已经提供了一大堆的实现,你可以根据需要选择继承某个类。这里我选择继承SquareHandle。

 

这里有几个需要实现的东西:

 

1.Locator

 

提供一个定位器显然是需要的,否则这个handle就不知道要安在哪了。

 

2.实现paintFigure()方法

 

如果你的继承SquareHandle,默认会是一个方框,如果你觉得不合适,那就需要自己实现这个方法了,就像附件图里。

 

3.实现createDragTracker()方法

 

这个方法返回一个DragTracker,就是当你拖动鼠标时的处理类。

 

4.其他功能

 

   1):可以增加一些美观性的东西,例如鼠标滑过时视觉加深,鼠标滑出时变淡。

   2):如果你的Editor支持放大缩小功能,那你还得处理缩放时的动作,否则当有缩放时,你的handle的位置可能就不对了。

 

 

提醒:看附件图中可以知道,这两个handle的位置已经超出图元的范围,所以当你拖运鼠标时提供的startLocation就是不对的了,已经超出图的范围了。所以我们需要在DragTracker里按某个算法提供自己的StartLocation。例如:

 

	protected Point getStartLocation() {
		return ((GraphicalEditPart) target).getFigure().getBounds()
				.getLocation();
	}

	protected boolean handleButtonDown(int button) {
		Point startLocation = getStartLocation();
		getCurrentInput().setMouseLocation(startLocation.x, startLocation.y);
		return super.handleButtonDown(button);
	}

 

实话说,我不知道是不是必须这样给出位置,还是有其他更好的定位初始位置的方法。

 

最后完成上面的实现后,你就可以通过拖动图中不动的handle来分别实现有箭头连接或无箭头连接。看下图,palette中的connectionTool并没有被选中,但已经可以创建连接线了(鼠标没有被截出来),从高亮可以看出现在是在画有前头图

 

GEF功能增强之连接助手

 

 

你可能感兴趣的:(算法)