背景:
在默认的gef中,这两个鼠标工具都是不默认选中连线的. 但是多选节点,进行复制粘贴等操作时,总希望连续也是跟随节点的操作. 选中连线是基础.
其实很简单,但又涉及到一点gef机制的探索,所以就立文记录下.
解决:
MarqueeToolEntry
进入源码看下豁然开朗.它用常量给出了自己的选中状态.并保存到marqueeBehavior中.通过ToolEntry.getToolProperty()获取状态. 而且提供了setToolProperty()的方法. 所以无需求甚解就可以解决.
// 4.0 创建一个GEF提供的 "Marquee多选"工具并将其放到toolGroup中
toolEntry = new MarqueeToolEntry(); //修改区域选择tool支持选中关联连线
toolEntry.setToolProperty(
MarqueeSelectionTool.PROPERTY_MARQUEE_BEHAVIOR,
MarqueeSelectionTool.BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS);
然后用户用的多的是SelectionToolEntry,并且它同样也提供多选. 所以SelectionToolEntry也得同样支持,否则用户跟你没完. 当然实际上MarqueeToolEntry可以废除了.
SelectionToolEntry
进入源码大失所望, 仿照上面的代码试试 也是无效. 看来得 求甚解才能解了.
不迈关子直接上源码阅读结果. 以下是当前的理解,可能有偏差. 如果机会和能力 我会写一篇关于Tool(基类是abstractTool)的机制文章.
toolEntry只是为了创建工具箱 更重要的是ToolEntry的下面方法获取的Tool
public Tool createTool() {
if (toolClass == null)
return null;
Tool tool;
try {
tool = (Tool) toolClass.newInstance();
} catch (IllegalAccessException iae) {
return null;
} catch (InstantiationException ie) {
return null;
}
tool.setProperties(getToolProperties()); //tool获取了toolEntry的属性 toolEntry只是桥接
return tool;
}
而tool真正负责相应操作 直接处理事件
MarqueeSelectionTool功能相对简单所以直接处理
SelectionTool是selectionToolEntry对应的工具. 它的功能相对复杂.它是在相应mouseDown的事件.直接确定鼠标位置下面是handle还是EditPart 然后从handle(或editPart)获取Tracker. tracker用于响应处理. 所以SelectionTool 才支持 多选,选中线,选中节点等复杂功能. 上源码:
protected boolean handleButtonDown(int button) {
if (!stateTransition(STATE_INITIAL, STATE_DRAG)) {
resetHover();
return true;
}
resetHover();
EditPartViewer viewer = getCurrentViewer();
Point p = getLocation();
if (getDragTracker() != null)
getDragTracker().deactivate();
if (viewer instanceof GraphicalViewer) {
Handle handle = ((GraphicalViewer) viewer).findHandleAt(p); //handle为什么可以相应操作的源头 因为它优先提供了tracker
if (handle != null) { //当然这不是我们这次关注的重点
setDragTracker(handle.getDragTracker());
return true;
}
}
updateTargetRequest();
((SelectionRequest) getTargetRequest()).setLastButtonPressed(button);
updateTargetUnderMouse();
EditPart editpart = getTargetEditPart();
if (editpart != null) {
setDragTracker(editpart.getDragTracker(getTargetRequest())); //根据不同的editpart获取不同的DragTracker
lockTargetEditPart(editpart);
return true;
}
return false;
}
我大概统计了下:
选中对象 | 操作 | Tracker |
---|---|---|
背景(ContentEditPart) | 多选 | MarqueeDragTracker(眼熟吧) |
节点(NodeEditPart) | 选中节点/拖动 | DragEditPartsTracker |
线(LineEditPart) | 选中线/拖动 | SelectEditPartTracker |
甚解了 回去解决原来的问题. 方法很简单.
找到ContentEditPart 然后修改getDragTracker方法 将MarqueeDragTracker设置成可以选中线
不同的环境代码可能不同这是我的代码:
@Override
protected void configureGraphicalViewer() {
super.configureGraphicalViewer();
viewer = getGraphicalViewer();
viewer.setEditPartFactory(new PartFactory());
ScalableFreeformRootEditPart rootEditPart = new ScalableFreeformRootEditPart(){
@Override
public DragTracker getDragTracker(Request req) {
MarqueeDragTracker dt= new MarqueeDragTracker();
dt.setMarqueeBehavior(MarqueeSelectionTool.BEHAVIOR_NODES_CONTAINED_AND_RELATED_CONNECTIONS);
return dt;
}
};
viewer.setRootEditPart(rootEditPart);