Chinaunix首页 | 论坛 | 博客
  • 博客访问: 515563
  • 博文数量: 95
  • 博客积分: 5168
  • 博客等级: 大校
  • 技术积分: 1271
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-28 23:31
文章分类

全部博文(95)

文章存档

2013年(2)

2012年(3)

2011年(1)

2010年(8)

2009年(81)

分类:

2009-10-13 00:09:29

       当我们点击tool栏的创建连接时,Tool就会是ConnectionCreationTool,

 

 

当我们选择一个节点单击时:

protected boolean handleButtonDown(int button) {

    if (button == 1 && stateTransition(STATE_CONNECTION_STARTED, STATE_TERMINAL))

       return handleCreateConnection();

//这个是指连线执行,即选择了连线的两端原件。

 

    super.handleButtonDown(button);

//这个是选择连线开始端时调用:

    if (isInState(STATE_CONNECTION_STARTED))

       //Fake a drag to cause feedback to be displayed immediately on mouse down.

       handleDrag();

    return true;

}

 

protected boolean handleButtonDown(int button) {

    if (isInState(STATE_INITIAL) && button == 1) {

       updateTargetRequest();

       updateTargetUnderMouse();

       setConnectionSource(getTargetEditPart());

       Command command = getCommand();

       ((CreateConnectionRequest)getTargetRequest()).setSourceEditPart(

           getTargetEditPart());

//设置requstsourceTarget

       if (command != null) {

           setState(STATE_CONNECTION_STARTED);

           setCurrentCommand(command);

           viewer = getCurrentViewer();

       }

    }

 

    if (isInState(STATE_INITIAL) && button != 1) {

       setState(STATE_INVALID);

       handleInvalidInput();

    }

    return true;

}

//这个函数将state设置为STATE_CONNECTION_STARTED,并并将requestsource设置为TargetEditPart,这个就是点击时的节点。

同时执行

 

getCommand(REQ_CONNECTION_START)//

 

 

这个其实会调用editpart(作为connectsource)getCommand(REQ_CONNECTION_START),

public abstract class TargetTooling{

protected Command getCommand() {

    if (getTargetEditPart() == null)

       return null;

        return getTargetEditPart().

           getCommand(getTargetRequest());

}

}

然后会调用

 

public abstract class GraphicalNodeEditPolicy

    extends GraphicalEditPolicy

{

public Command getCommand(Request request) {

    if (REQ_CONNECTION_START.equals(request.getType()))

       return getConnectionCreateCommand((CreateConnectionRequest)request);

    if (REQ_CONNECTION_END.equals(request.getType()))

       return getConnectionCompleteCommand((CreateConnectionRequest)request);

    if (REQ_RECONNECT_TARGET.equals(request.getType()))

       return getReconnectTargetCommand((ReconnectRequest)request);

    if (REQ_RECONNECT_SOURCE.equals(request.getType()))

       return getReconnectSourceCommand((ReconnectRequest)request);

 

    return null;                                       

}

 

 

}

然后就会fake一次handleDrag,其实以后鼠标运动也是调用这个函数,直到再次单击鼠标.

protected boolean handleDrag() {

    if (isInState(STATE_CONNECTION_STARTED))

       return handleMove();

    return false;

}

 

protected boolean handleMove() {

    if (isInState(STATE_CONNECTION_STARTED) && viewer != getCurrentViewer())

       return false;

    if (isInState(STATE_CONNECTION_STARTED | STATE_INITIAL

           | STATE_ACCESSIBLE_DRAG_IN_PROGRESS)) {

       updateTargetRequest();

//这时requestREQ_CONNECTION_END

       updateTargetUnderMouse();

       showSourceFeedback();

       showTargetFeedback();

//feedback,其实只有showSourceFeedback()是真正画线的,showTargetFeedback可能无用。

       setCurrentCommand(getCommand());//这个没有多大用。

    }

    return true;

}

下面我们看看showSourceFeedback()如何画线的:

protected void showSourceFeedback() {

    if (connectionSource != null) {

       connectionSource.showSourceFeedback(getSourceRequest());

    }

    setFlag(FLAG_SOURCE_FEEDBACK, true);

}

connectionSource就是connect的开始editpartNodeEditpart结构)。

 

上面执行的就是NodeEditpartshowSourceFeedback(REQ_CONNECTION_END);

然后就到NodeEditPart,其实会执行policyshowSourceFeedback,即一般是GraphicalNodeEditPolicyshowSourceFeedback

 

public void showSourceFeedback(Request request) {

    if (REQ_CONNECTION_END.equals(request.getType()))

       showCreationFeedback((CreateConnectionRequest)request);

}

protected void showCreationFeedback(CreateConnectionRequest request) {

    FeedbackHelper helper = getFeedbackHelper(request);

    Point p = new Point(request.getLocation());

    helper.update(getTargetConnectionAnchor(request), p);

}

 

protected FeedbackHelper getFeedbackHelper(CreateConnectionRequest request) {

    if (feedbackHelper == null) {

       feedbackHelper = new FeedbackHelper();

       Point p = request.getLocation();

       connectionFeedback = createDummyConnection(request);

       connectionFeedback.setConnectionRouter(getDummyConnectionRouter(request));

       connectionFeedback.setSourceAnchor(getSourceConnectionAnchor(request));

       feedbackHelper.setConnection(connectionFeedback);

       addFeedback(connectionFeedback);

       feedbackHelper.update(null, p);

    }

    return feedbackHelper;

}

getFeedbackHelper第一次调用会创建一个feedbackHelper类实例,这个其实就是一个包含connection的类,用来管理这个connect

然后update,每次鼠标move都是会执行一次。

protected ConnectionAnchor getTargetConnectionAnchor(CreateConnectionRequest request) {

    EditPart target = request.getTargetEditPart();

//获取connect的末端节点editpart,如果不是NodeEditPart,则可知返回null.

    return target instanceof NodeEditPart

       ? ((NodeEditPart) target).getTargetConnectionAnchor(request)

       : null;

}

public void update(ConnectionAnchor anchor, Point p) {

    if (anchor != null)

       setAnchor(anchor);

    else {

       dummyAnchor.setLocation(p);

       setAnchor(dummyAnchor);

    }

}

从上面可知,当末端节点是NodeEditPart,则调用这个editpartgetTargetConnectionAnchor,否则用当前鼠标值作为末端anchor,这样connect的两个anchor都定了,连线的开始断点是定的,是第一次点击时鼠标所在editpart返回的anchor

 

当第二次单击鼠标完成画线。

protected boolean handleCreateConnection() {

    eraseSourceFeedback();

    Command endCommand = getCommand();

// REQ_CONNECTION_END command

    setCurrentCommand(endCommand);

    executeCurrentCommand();

    return true;

}

//上面红色部分就会执行editpart端的getConnectionCompleteCommand

if (REQ_CONNECTION_END.equals(request.getType()))

return getConnectionCompleteCommand((CreateConnectionRequest)request);

 

protected Command getConnectionCompleteCommand(CreateConnectionRequest request) {

        CreateConnectionCommand command = (CreateConnectionCommand) request.getStartCommand();

        command.setTarget((Node) getHost().getModel());

        return command;

    }

这个就是将target也赋给command,这样当command执行时就会将connect放到sourceEditparttargetEditpart相关项中,这样就好了。

大家可能为想requestTargetEditPart在哪赋值的吧:

这个是在updateTargetUnderMouse

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);

//targetEditpart赋给request

       return changed;

    } else

       return false;

}

 

 

到现在思路能清楚了:

  下面我从应用的角度来说下,我们对可以画线的节点的相关函数进行解释:

 一个节点要想能被连线连接:必须绑定GraphicalNodeEditPolicy相关的policy,必须继承NodeEditPart,也就是必须包含如下函数:

public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {

    System.out.println("in source editpart");

    return new ChopboxAnchor(getFigure());

    }

//这个是editpartpolicy(一般是GraphicalNodeEditPolicy)showSourceFeedBack时用到,只调用一次,且被放到feedHelp里的dummyConnect的开始端点,当第一次单击鼠标时执行。

    public ConnectionAnchor getSourceConnectionAnchor(Request request) {

    System.out.println("in source");

        return new ChopboxAnchor(getFigure());

    }

 

//这个是真正画线的时候由GEF画图系统调用

public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {

    System.out.println("in target editpart");

    return new ChopboxAnchor(getFigure());

    }

 

    public ConnectionAnchor getTargetConnectionAnchor(Request request) {

    System.out.println("intarget");

        return new ChopboxAnchor(getFigure());

    }

//这个是sourceEditPartpolicyshowSourceFeedBack函数从request取出TargetEditpart,然后调用TargetEditpart. getTargetConnectionAnchor时会调用的,这个返回值用来update feedbackHelpconnection的另一端点,单击后鼠标运动时调用。

 

    protected List getModelSourceConnections() {

        return ((Node) this.getModel()).getOutgoingConnections();

    }

 

    protected List getModelTargetConnections() {

        return ((Node) this.getModel()).getIncomingConnections();

    }

//上面两个是gef在绘制图形的时候,调用每个节点editpartgetModelTargetConnectionsgetModelSourceConnections来画线时用到的。

 

GraphicalNodeEditPolicy

public class NodeGraphicalNodeEditPolicy extends GraphicalNodeEditPolicy {

 

    protected Command getConnectionCompleteCommand(CreateConnectionRequest request) {

        CreateConnectionCommand command = (CreateConnectionCommand) request.getStartCommand();

        command.setTarget((Node) getHost().getModel());

        return command;

    }

//这个是当单击了一次到单击第二次之间调用:

    protected Command getConnectionCreateCommand(CreateConnectionRequest request) {

        CreateConnectionCommand command = new CreateConnectionCommand();

        command.setSource((Node) getHost().getModel());

        request.setStartCommand(command);

        return command;

    }

//这个是开始移动到第一次单击开始连线之间调用:

  

 protected Command getReconnectSourceCommand(ReconnectRequest request) {

       ReconnectSourceCommand cmd = new ReconnectSourceCommand();

       cmd.setConnection((Connection)request.getConnectionEditPart().getModel());

       cmd.setSource((Node)getHost().getModel());

       return cmd;

    }

 

    protected Command getReconnectTargetCommand(ReconnectRequest request) {

        return null;

    }

}

 

阅读(1864) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~