分类:
2009-10-13 00:03:04
上一篇提了几个问题,分别是
1.选择,平移,改变大小这些操作的source,target的editpart分别是什么?
2.选择,平移,改变大小操作出来的虚框是怎么出来的,这个是feedback产生的?如果是feedback产生的,由于平移,改变会执行showTargetFeedback和showSourceFeedback,那么这个虚框是Target产生,还是Source产生。
3.当我们拖曳时,尽管鼠标在source editpart上,为什么target editpart始终是content editpart呢?
下面就一个一个来回答:
1.
对于选择,source和target一样,source是在创建tracer时就赋值了,target是通过updateTargetUnderMouse得到的。
对于平移,改变大小操作,source是被选择了的editpart,target是content editpart,在我的例子中是DiamEditor.
2.
对于平移,改变大小操作的虚框是由showSourceFeedback。也就是被选择的节点的showSourceFeedback,但是如果节点没有绑定任何policy,也会显示出虚框,这是什么原因呢?这个说没有绑定任何policy应该是指没有显示绑定,以为,如果我们给content editpart绑定了继承于XYLayoutEditPolicy的policy,那么这个policy会所有节点editpart绑定一个ResizableEditPolicy.
protected void decorateChild(EditPart child) {
EditPolicy policy = createChildEditPolicy(child);
child.installEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE, policy);
}
protected EditPolicy createChildEditPolicy(EditPart child) {
return new ResizableEditPolicy();
}这个就为child创建了policy
这个ResizableEditPolicy就有对REQ_MOVE和REQ_RESIZE的feedback处理
public void showSourceFeedback(Request request) {
if (REQ_RESIZE.equals(request.getType()))
showChangeBoundsFeedback((ChangeBoundsRequest)request);
//这个是对于改变大小
else
super.showSourceFeedback(request);
//这个是对于平移
}
public void showSourceFeedback(Request request) {
if ((REQ_MOVE.equals(request.getType()) && isDragAllowed())
|| REQ_ADD.equals(request.getType())
|| REQ_CLONE.equals(request.getType()))
showChangeBoundsFeedback((ChangeBoundsRequest) request);
}
仔细看下,这个多一个isDragAllowed,也就是说平移时要判断是否允许drag.
最终都是到showChangeBoundsFeedback
protected void showChangeBoundsFeedback(ChangeBoundsRequest request) {
IFigure feedback = getDragSourceFeedbackFigure();
PrecisionRectangle rect = newPrecisionRectangle(getInitialFeedbackBounds().getCopy());
getHostFigure().translateToAbsolute(rect);
rect.translate(request.getMoveDelta());
rect.resize(request.getSizeDelta());
feedback.translateToRelative(rect);
feedback.setBounds(rect);
}
对于选择虚框不是由feedback产生的,是由target的policy(这个policy也是上面那个ResizableEditPolicy)在active时绑定listener,监听select事件产生。
public void activate() {
super.activate();
addSelectionListener();
//监听editpart的selection事件,从而调用shows
setSelectedState(getHost().getSelected());
setFocus(getHost().hasFocus());
}
protected void addSelectionListener() {
selectionListener = new EditPartListener.Stub() {
public void selectedStateChanged(EditPart part) {
setSelectedState(part.getSelected());
setFocus(part.hasFocus());
}
};
getHost().addEditPartListener(selectionListener);
}
当editpart选择发生变化时便会调用setSelectedState。
protected void setSelectedState(int type) {
if (state == type)
return;
state = type;
if (type == EditPart.SELECTED_PRIMARY)
showPrimarySelection();
else if (type == EditPart.SELECTED)
showSelection();
else
hideSelection();
}
showSelection就是我们选择一个editpart周围出现框的原因,其实是添加了相应的handle,这个也是一种figure,只不过这种figure,可以提供dragTracer,对于moveHandle,是DragEditPartTracer,对于Resize handle,则是resizeTracer,当我们选择节点边框拖动时,是相应的handle产生dragTracer。
4.targetEditpart,我们主要讨论Tracer Tool的target的targetEditpart:
对于ResizeTracer,由于他已固定了:
protected GraphicalEditPart getTargetEditPart() {
if (owner != null)
return (GraphicalEditPart)owner.getParent();
return null;
}
Owner是NodeEditor,所以其parent肯定是content editpart.
对于DragEditPartTracer:其由updateTargetUnderMouse这个函数决定,以为这个函数调用了setTargetEditPart。
protected boolean updateTargetUnderMouse() {
if (!isTargetLocked()) {
EditPart editPart = getCurrentViewer().findObjectAtExcluding(
getLocation(),
getExclusionSet(),
getTargetingConditional());
if (editPart != null)
editPart = editPart.getTargetEditPart(getTargetRequest());
boolean changed = getTargetEditPart() != editPart;
setTargetEditPart(editPart);
return changed;
} else
return false;
}
EditPart editPart = getCurrentViewer().findObjectAtExcluding(
getLocation(),
getExclusionSet(),
getTargetingConditional());
protected EditPartViewer.Conditional getTargetingConditional() {
return new EditPartViewer.Conditional() {
public boolean evaluate(EditPart editpart) {
return editpart.getTargetEditPart(getTargetRequest()) !=null;
}
};
}
public EditPart findObjectAtExcluding{
IFigure figure = getLightweightSystem()
.getRootFigure()
.findFigureAt(pt.x, pt.y, new ConditionalTreeSearch(exclude));
EditPart part = null;
while (part == null && figure != null) {
part = (EditPart)getVisualPartMap().get(figure);
figure = figure.getParent();
}
if (part == null)
return getContents();
return part;
}
public EditPart getTargetEditPart(Request request) {
EditPolicyIterator i = getEditPolicyIterator();
EditPart editPart;
while (i.hasNext()) {
editPart = i.next()
.getTargetEditPart(request);
if (editPart != null)
return editPart;
}
if (RequestConstants.REQ_SELECTION == request.getType()) {
if (isSelectable())
return this;
}
return null;
}
由于所有的Editpart的getTargetEditPart只能处理REQ_SELECTION,所以对于其他request都返回null(不考虑editpart的policy的影响,其实一般的policy的getTargetEditPart也返回null).所以像REQ_MOVE,REQ_RESIZE这些Request,findObjectAtExcluding都返回getContent,也就是content editpart.由于DragEditPartTracer的request是REQ_MOV,所以其TargetEditPart始终是content editpart。还有一个例子是:当在空白出进行拖曳操作时,dragTrace是MarqueeDragTracker,这里的request是REQ_SELECTION,故其target就是被选择的节点由于是空白地方.
对于selectionTool,没有source。当为resize时:Target为rootEditpart,当MOVE时是NodeEditPart.
总结:选择对象包括Marquee选择对象事件的Tracer Tool都是通过SelectionTool的TargetEditPart的getDragTracer得到:只不过RootEditPart返回MarqueeTracer,节点EditPart返回DraEditPartTracer.而Resize操作的是通过point热点返回的,((GraphicalViewer) viewer).findHandleAt(getLocation()),是ResizeTracer.
TracerTool都是在mouseDonw时确定的.
同时dragTracer的sourceEditPart都是通过getOperationSet获取到得editpart的list,这个函数就是返回被选择的节点的集合,而TargetEditPart是通过
UpdateUnderMouse更新的,当前鼠标下的EditPart必须接受REQ_Move才能是TargetEditPart,若没有满足条件的则TargetEditPart为ContentEditPart.