分类:
2009-10-12 23:53:54
----------------------------------------------------------- 转载请注明出处: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. 对于选择对象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()); } 因为单击节点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变化了,也就是位置变化了。 到此平移结束了。
本文系本站原创,欢迎转载!选择对象事件的DragTracer---SelectEditPartTracker:
平移对象事件的DragTracer---DrageEditPartTracker: