-----------------------------------------------------------
本文系本站原创,欢迎转载!
转载请注明出处:http://sjj0412.cublog.cn/
-----------------------------------------------------------
上面刚讲到事件处理已经到了Tool层,而GEF的默认Tool就是SelectionTool,故今天来讲下SelectionTool及它映射出的其他几个Tool。
Class SelectionTool.
从上面我们看到各种事件处理函数:
mouseDown, mouseUP,mouseDrag等,但是你可能会说怎么不见key的相关函数啊,这个其实在它的父类TargetingTool.
我们先来看一个mouseDown。
Class SelectionTool
public void mouseDown(MouseEvent e, EditPartViewer viewer) {
super.mouseDown(e, viewer);
//这一步其实就是调用handleMouseDown。
if (getDragTracker() != null)
getDragTracker().mouseDown(e, viewer);
// DragTracker也是Tool,这种Tool主要用来针对具体事件跟踪处理的,这部分很重要,是拖曳,移动GEF图形节点的十分重要的
}
Class TargetingTool
public void mouseDown(MouseEvent me, EditPartViewer viewer) {
if (!isViewerImportant(viewer))
return;
setViewer(viewer);
getCurrentInput().setInput(me);
getCurrentInput().setMouseButton(me.button, true);
startX = me.x;
startY = me.y;
handleButtonDown(me.button);
//这个一般被重载了。
}
因为重载了,所以又是到了SelectionTool
Class SelectionTool
// handleButtonDown是真正的处理函数,同时也找到TargetEditPart,DragTracker,及向TargetEditPart发送相关request.
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);
if (handle != null) {
setDragTracker(handle.getDragTracker());
return true;
}
//找DragTracker的一种方法,比如改变大小的事件就是在这里找到DragTracker,为ResizeTracer,同时点击周围移动handle,找到时movehandle,这个handle返回DragEditPartTracker.
}
updateTargetRequest();
//这个是更新request,比如坐标值,request type的类型,不过在selectionTool, type不变都是selection,在ResizeTracer等tool里,其会随着state变化而变化。
((SelectionRequest)getTargetRequest()).setLastButtonPressed(button);
updateTargetUnderMouse();
//这个就是更新TargetEditPart,同时进行相关feedback调用
EditPart editpart = getTargetEditPart();
if (editpart != null) {
setDragTracker(editpart.getDragTracker(getTargetRequest()));
//这也是一种获取DragTracker的方法,想平移GEF图形节点的DragTracker就是这中方法找到的,对于一般的GraphicEditPart,其实DragEditPartTracer.
lockTargetEditPart(editpart);
return true;
}
return false;
}
protected boolean updateTargetUnderMouse() {
if (!isTargetLocked()) {
EditPart editPart = getCurrentViewer().findObjectAtExcluding(
getLocation(),
getExclusionSet(),
getTargetingConditional());
//获取鼠标所在GEF图形节点,其中getTargetingConditional()很重要,这个将在讲解DrageEditPartTracer时将。
if (editPart != null)
editPart = editPart.getTargetEditPart(getTargetRequest());
boolean changed = getTargetEditPart() != editPart;
setTargetEditPart(editPart);
//这个是更新TargetEditPart,同时调用feedBack相关的函数。
return changed;
} else
return false;
}
protected void setTargetEditPart(EditPart editpart) {
if (editpart != targetEditPart) {
if (targetEditPart != null)
handleExitingEditPart();
targetEditPart = editpart;
if (getTargetRequest() instanceof TargetRequest)
((TargetRequest)getTargetRequest()).setTargetEditPart(targetEditPart);
handleEnteredEditPart();
}
}
当我们选择一个对象的feedback就是handleEnteredEditPart调用的。
protected boolean handleEnteredEditPart() {
updateTargetRequest();
showTargetFeedback();
return true;
}
到此点击事件完成了。
其实SelectionTool从事件处理方面来说没起多大多大作用,既没有command相关的作用,也没有feedback相关的作用,因为SelectionTool的request的type是selection,但是你看下editpart的各个policy,基本没有处理selection类型的request,不论是policy的getCommand函数,还是showTargetFeedBack和showSourceFeedBack。那它的作用是什么呢?其实它可以看成是所有Tool层事件的入口,事件从它进入,然后根据不同情况选择不同真正起作用的Tool(比如DragEditPartTracer,ResizeTracer),从SelectionTool的各个事件函数都要调用getDragTracker().mouseDown(up/drag/…)(e, viewer);就可以看出,同时由于SelectionTool只有Target,对于像拖曳,改变大小这些涉及source和target的肯定不适合。
下面就开始将真正起作用的Tool,各种Tracer tool.
选择对象事件的DragTracer---SelectEditPartTracker:
对于选择对象mouseDown,移动(drag)对象都是DrageEditPartTracer,对于鼠标单击这一事件(选择对象),DrageEditPartTracer没有handleMouseDown函数,故调用的是SelectEditPartTracker的函数,所以对于选择事件,可以看成SelectEditPartTracker。
protected boolean handleButtonDown(int button) {
if ((button == 3 || button == 1)
&& isInState(STATE_INITIAL))
performConditionalSelection();
//这个起真正的作用,让graphicViewer选择editpart元件。
if (button != 1) {
setState(STATE_INVALID);
if (button == 3)
setState(STATE_TERMINAL);
handleInvalidInput();
} else
stateTransition(STATE_INITIAL, STATE_DRAG);
//左键选择节点后,就进入STATE_DRAG了。
return true;
}
public SelectEditPartTracker(EditPart owner) {
setSourceEditPart(owner);
}
protected void performConditionalSelection() {
if (getSourceEditPart().getSelected() == EditPart.SELECTED_NONE)
performSelection();
else if (getCurrentInput().getModifiers() == 0)
setFlag(FLAG_ENABLE_DIRECT_EDIT, true);
}
protected void performSelection() {
if (hasSelectionOccurred())
return;
setFlag(FLAG_SELECTION_PERFORMED, true);
EditPartViewer viewer = getCurrentViewer();
List selectedObjects = viewer.getSelectedEditParts();
if (getCurrentInput().isModKeyDown(SWT.MOD1)) {
if (selectedObjects.contains(getSourceEditPart()))
viewer.deselect(getSourceEditPart());
else
viewer.appendSelection(getSourceEditPart());
} else if (getCurrentInput().isShiftKeyDown())
viewer.appendSelection(getSourceEditPart());
else
viewer.select(getSourceEditPart());
}
这样viewer就选择了节点。
从上面我们可以看出,根本没有feedback相关的处理,那为什么当我们选择一个对象时会多出一个框呢?这个在下面提问解答部分单独的讨论一下。
当我们点击松开鼠标时
protected boolean handleButtonUp(int button) {
if (isInState(STATE_DRAG)) {
performSelection();
if (getFlag(FLAG_ENABLE_DIRECT_EDIT))
performDirectEdit();
//我们松开鼠标可以编辑节点就是因为这个。
if (button == 1 && getSourceEditPart().getSelected() != EditPart.SELECTED_NONE)
getCurrentViewer().reveal(getSourceEditPart());
setState(STATE_TERMINAL);
return true;
}
return false;
}
protected void performDirectEdit() {
DirectEditRequest req = new DirectEditRequest();
req.setLocation(getCurrentInput().getMouseLocation());
new DelayedDirectEditHelper(
getSourceEditPart().getViewer(),
req,
getSourceEditPart());
}
平移对象事件的DragTracer---DrageEditPartTracker:
因为单击节点editpart时,selectionTool的Target是节点editpart,故通过mouseDown获得的是节点editpart.getDragTracer();而节点editpart一般继承AbstractEditPart,这个类的getDragTracer返回DrageEditPartTracker,故其DragTracer为DrageEditPartTracker,如果是点击周围的Movehandle,则是通过。
Class AbstractGraphicalEditPart
public DragTracker getDragTracker(Request request) {
return new org.eclipse.gef.tools.DragEditPartsTracker(this);
}
拖曳时调用:
public void mouseDrag(MouseEvent me, EditPartViewer viewer) {
if (!isViewerImportant(viewer))
return;
setViewer(viewer);
boolean wasDragging = movedPastThreshold();
getCurrentInput().setInput(me);
handleDrag();
if (movedPastThreshold()) {
if (!wasDragging)
handleDragStarted();
handleDragInProgress();
}
}
protected boolean handleDragInProgress() {
if (isInDragInProgress()) {
updateTargetRequest();
//这里的request就是REQ_MOVE
if (updateTargetUnderMouse())
updateTargetRequest();
showTargetFeedback();
showSourceFeedback();
//feedback反馈。
setCurrentCommand(getCommand());
//使用命令,比如拖曳完成后要执行什么命令
}
return true;
}
//这个调用target的,其实拖曳时target是content的editpart。
protected void showTargetFeedback() {
if (getTargetEditPart() != null)
getTargetEditPart().showTargetFeedback(getTargetRequest());
setFlag(FLAG_TARGET_FEEDBACK, true);
}
//所有被选择的对象是sourceEditpart,
protected void showSourceFeedback() {
List editParts = getOperationSet();
//获取所有被选择的节点editpart
for (int i = 0; i < editParts.size(); i++) {
EditPart editPart = (EditPart) editParts.get(i);
editPart.showSourceFeedback(getTargetRequest());
}
setFlag(FLAG_SOURCE_FEEDBACK, true);
}
protected Command getCommand() {
CompoundCommand command = new CompoundCommand();
command.setDebugLabel("Drag Object Tracker");//$NON-NLS-1$
Iterator iter = getOperationSet().iterator();
Request request = getTargetRequest();
//这个request是REQ_MOVE
if (isCloneActive())
request.setType(REQ_CLONE);
else if (isMove())
request.setType(REQ_MOVE);
else
request.setType(REQ_ORPHAN);
if (!isCloneActive()) {
while (iter.hasNext()) {
EditPart editPart = (EditPart)iter.next();
command.add(editPart.getCommand(request));
}
}
if (!isMove() || isCloneActive()) {
if (!isCloneActive())
request.setType(REQ_ADD);
if (getTargetEditPart() == null)
command.add(UnexecutableCommand.INSTANCE);
else
command.add(getTargetEditPart().getCommand(getTargetRequest()));
//这个会调用policy的createChangeConstraintCommand
}
return command;
}
Class in policy
public Command getCommand(Request request) {
if (REQ_RESIZE_CHILDREN.equals(request.getType()))
return getResizeChildrenCommand((ChangeBoundsRequest)request);
if (REQ_ALIGN_CHILDREN.equals(request.getType()))
return getAlignChildrenCommand((AlignmentRequest)request);
return super.getCommand(request);
}
public Command getCommand(Request request) {
if (REQ_MOVE_CHILDREN.equals(request.getType()))
return getMoveChildrenCommand(request);
return null;
}
protected Command getMoveChildrenCommand(Request request) {
//By default, move and resize are treated the same for constrained layouts.
return getResizeChildrenCommand((ChangeBoundsRequest)request);
}
protected Command getResizeChildrenCommand(ChangeBoundsRequest request) {
CompoundCommand resize = new CompoundCommand();
Command c;
GraphicalEditPart child;
List children = request.getEditParts();
for (int i = 0; i < children.size(); i++) {
child = (GraphicalEditPart)children.get(i);
c = createChangeConstraintCommand(request, child,
translateToModelConstraint(
getConstraintFor(request, child)));
resize.add(c);
}
return resize.unwrap();
}
当mouseUp时会调用:
protected boolean handleButtonUp(int button) {
if (stateTransition(STATE_DRAG_IN_PROGRESS, STATE_TERMINAL)) {
eraseSourceFeedback();
eraseTargetFeedback();
performDrag();
return true;
}
return super.handleButtonUp(button);
}
protected void performDrag() {
executeCurrentCommand();
}
protected void executeCurrentCommand() {
Command curCommand = getCurrentCommand();
if (curCommand != null && curCommand.canExecute())
executeCommand(curCommand);
setCurrentCommand(null);
}
这个command其实就是createChangeConstraintCommand函数返回的command.
执行后,节点constraint变化了,也就是位置变化了。
到此平移结束了。