LinkTemplate, adornments, nodes and delete

3 littles questions about LinkTemplate :

1. How to change the handle adornment of the link (the two magenta rectangles and the diamond) :

2. Do you a built in method to get in the linkTemplate the two nodes linked between the link ?

3. Is this possible to delete an existing link when I release with the mouse a side on the background (like the image below).

In the second case, fromNode, toNode with the LinkDrawn, LinkRelinked events seem to be a good way.

The magenta rectangles are the LinkingBaseTool.temporaryFromPort and LinkingBaseTool.temporaryToPort. See http://gojs.net/latest/extensions/Templates.js, in the function setupLinkingToolTemporaryNodesAndLink.

The blue diamonds at the ends of relinkable Links are the RelinkingTool.fromHandleArchetype and RelinkingTool.toHandleArchetype. Again, see http://gojs.net/latest/extensions/Templates.js, but this time in the function setupRelinkingToolHandles.

Yes, the DiagramEvent.subject of the “LinkDrawn” and “LinkRelinked” events is the new Link or reconnected Link, from which you can get the Link.fromNode or Link.fromPort and Link.toNode or Link.toPort.

If you want to delete the link that the user is trying to reconnect when there is no valid port near the mouse point, yes, that is easy to implement:

      $(go.Diagram, "myDiagramDiv",
        {
          "relinkingTool.doNoRelink": function(existinglink, toend) {
            this.diagram.remove(existinglink);
            this.transactionResult = this.name;
          },
          . . . })

I don’t understand what you need to do. You should not be modifying anything in a binding conversion function.

Drop the last message. I have a strange behavior with this code :

  linkingTool.temporaryFromNode = this.getTemporaryNodeTemplate();
  linkingTool.temporaryFromPort = this.getTemporaryPortTemplate();
  linkingTool.temporaryToNode = this.getTemporaryNodeTemplate();
  linkingTool.temporaryToPort = this.getTemporaryPortTemplate();

 getTemporaryPortTemplate() {
    return this.go(go.Shape, 'Rectangle', {
      portId: '',
      fill: null,
      stroke: '#00FF00',
      strokeWidth: 2,
      desiredSize: new go.Size(1, 1),
   });
 }

 getTemporaryNodeTemplate() {
    const node = this.go(go.Node, {
      selectable: false,
      layerName: 'Tool',
    });
    node.add(this.getTemporaryPortTemplate());
    return node;
 }

I loose the bezier curve and shape is not resize like the default code :

The temporaryFromPort needs to be part of the temporaryFromNode, and the same for temporaryToPort and temporaryToNode.

The way that you have it there, the port is not part of a node because you construct the port twice.

Walter I have a little issue.

The fromPort of the link is aligned on the right and the toPort on the left. So the handle is aligned on this spot :

If I set an alignmentFocus to Spot.Right in the From HandleArcheType template and Left for the To, the issue is corrected :

But if I rotate the module it’s a disaster :

I can’t change the port alignment, so how to deal with the handleArcheType to center the shape on the port ?

You should define your temporary Nodes so that they position the port correctly even after rotation, if that is what you are doing with the ports themselves.

From what I see of what you defined above, it appears that the port occupies the whole Node. Whereas that’s clearly not the case with your template node ports.

Humm I dont understand.

By default I set the template with a spot for the From et the To

  relinkingTool.fromHandleArchetype = this.getRelinkPortTemplate(0, go.Spot.Right);
  relinkingTool.toHandleArchetype = this.getRelinkPortTemplate(-1, go.Spot.Left);

  getRelinkPortTemplate(segmentIndex, spot) {
    return this.go(go.Shape, 'Circle', {
      alignmentFocus: spot,
      fill: 'lightblue',
      stroke: '#FF0000',
      desiredSize: new go.Size(8, 8),
      cursor: 'pointer',
     segmentIndex,
   });
 }

This is this spot you want I change the position ? How to change this position only for the selected node, I dont see any method for this on the API ?

Another thing, I have changed my previous code for temporaryFromPort and temporaryFromNode like this :

  const fromPortTemplate = this.getTemporaryPortTemplate();
  const toPortTemplate = this.getTemporaryPortTemplate();

  linkingTool.temporaryFromPort = fromPortTemplate;
  linkingTool.temporaryFromNode = this.getTemporaryNodePortTemplate(fromPortTemplate);
  linkingTool.temporaryToPort = toPortTemplate;
  linkingTool.temporaryToNode = this.getTemporaryNodePortTemplate(toPortTemplate);

 getTemporaryPortTemplate() {
   return this.go(go.Shape, 'Circle', {
     portId: '',
     fill: null,
     stroke: '#00FF00',
     strokeWidth: 2,
     desiredSize: new go.Size(1, 1),
   });
 }

 getTemporaryNodePortTemplate(portTemplate) {
   const node = this.go(go.Node, {
     selectable: false,
     layerName: 'Tool',
   });

   node.add(portTemplate);
  return node;
}

When I create a new link, it’s perfect :

But when I move the link to another port, it’s the “magenta” rectangle :

New links are drawn by the LinkingTool, link reconnections are done by the RelinkingTool. So both tools need customization.

Ok perfect Walter !

I have allways dont understand what you mean by “should define your temporary Nodes so that they position the port correctly even after rotation”. I have seen a “PartRotated” event but I dont understand how I can change the position of the HandleArcheType template… Can you explain a little more ?

The default behavior of LinkingBaseTool.copyPortProperties is to make the temporary node and link just like the port object. That includes setting the angle of the temporary port match the document angle of the existing port.

If you haven’t set the angles of the ports in your nodes, then this doesn’t matter. If so, sorry to confuse things.

Walter I’am sorry but I continue to dont understand :) I repeat from the start :

  • My modules has ports on the left (from) and on the right (to). The “circle” is the port. Circles on the left, has configured with a fromLinkable and fromSpot to the left. Circles on the right with a toLinkable and a toSpot to the right.

    I have set a template on fromHandleArchetype and toHandleArchetype. The template function take as parameter the port alignment (left for left ports, etc.). Below you can see the template result (a circle with a blue stroke and a white fill).

  • Now I rotate, the module (angle = 90), the previous right ports are now on the bottom, the left on the top, I dont change any port properties, I juste rotate the node.

  • But this time, when I select the link, the toHandleArchetype position is incorrect :

  • If I set in the port the currentAngle (here -90), the toHandleArchetype position is correct but not the link (it must start on the bottom) :

It’s difficult to use an API without understand why the behavior is like this. Here I dont understand why I need to change the angle, when and how.

I don’t understand the problem. When I modify the angle of the nodes in the Dynamic Ports sample, the temporary ports are positioned correctly:

Maybe there’s a difference in how the ports are defined.

With the default template and If I remove the alignmentFocus that work :

My code was :

toolManager.relinkingTool.fromHandleArchetype = this.getRelinkPortTemplate(0, go.Spot.Right);
toolManager.relinkingTool.toHandleArchetype = this.getRelinkPortTemplate(-1, go.Spot.Left);

getRelinkPortTemplate(segmentIndex, spot) {
  return this.go(go.Shape, 'Circle', {
    alignmentFocus: spot, /* if I comment this that work */
    fill: '#FFFFFF',
    stroke: '0000FF',
    strokeWidth: 2,
    desiredSize: new go.Size(6, 6),
    cursor: 'pointer',
    segmentIndex,
  });
}

But in this case how to change the default origin of the shape to align it with the port circle ?

First, why aren’t you getting a JavaScript syntax error with:
{ ..., segmentIndex, } ?

Second, instead of setting alignmentFocus, I think you should set segmentOffset. Maybe something like:
{ segmentOffset: new go.Point(6, 0), ... }.

Because it’s an ES6 feature (ECMAScript 6: New Features: Overview and Comparison).

Not this values but that’s work !!! How you want I find this property without your help :)

Thanks a lot Walter !