Link routing issue with invisible components

Hi, I have a setup that ends up looking like this and I can’t quite figure out why:

The link properties:

$go(go.Link,
  { 
    routing: go.Routing.AvoidsNodes, 
    curve: go.Curve.JumpOver, 
    corner: 10,
    reshapable: true,
    // resegmentable: true,
    relinkableFrom: true, relinkableTo: true,
    fromEndSegmentLength: 20,
    toEndSegmentLength: 20,
    toolTip: linkToolTiptemplate,
    contextMenu: linkMenu,
    layerName: "LinkLayer"
  },
  ...
)

The node properties:

$go(go.Node, "Spot",
  {
    toolTip: tooltiptemplate,
    locationObjectName: "BODY",
    locationSpot: go.Spot.Center,
    selectionAdorned: true,
    selectionObjectName: "BODY",
    toolTip: tooltiptemplate,
    shadowBlur: 20,
    isShadowed: true,
    selectionAdorned: true,  // use a Binding on the Shape.stroke to show selection
    contextMenu: activityNodeMenu,
    resizable: false,
    resizeObjectName: "SHAPE",
  },
  ...
)

The nodes have ports defined like this on all sides (this is the right-hand side one)

$go(go.Shape, "Circle",
  {
    desiredSize: new go.Size(1, 20),
    fromLinkable: true, toLinkable: true, cursor: "pointer",
    fromLinkableDuplicates: true, toLinkableDuplicates: true,
    portId: "rightPort", fromSpot: go.Spot.RightSide, toSpot: go.Spot.RightSide,
    alignment: go.Spot.RightCenter,
    margin: new go.Margin(0, 0, 0, 0),
    opacity: 0
  }
),

I also use AvoidsLinksRouter without any parameters and LayeredDigraphLayout with these parameters

new go.LayeredDigraphLayout({
            setsPortSpots: false,
            direction: direction,
            layerSpacing: layerSpacing,
            columnSpacing: columnSpacing,
            // layeringOption: go.LayeredDigraphLayout.LayerOptimalLinkLength, // the default
            aggressiveOption: go.LayeredDigraphAggressive.More,
            alignOption: go.LayeredDigraphAlign.All,
            // initializeOption: go.LayeredDigraphLayout.InitDepthFirstOut // the default,
            iterations: 10
          })

Triggering a relayout repetedly, it sometimes ends up looking like this instead, which is also a bit weird.

I suspect that it is something to do with the fact that the nodes have these invisible panels which show up on hover - but I am not sure how to go about fixing the link issue

Any help is appreciated

Yes, I think your guess is correct – are those panels that show up on hover in your node template? Then indeed both the layouts and the link routing will think that the node is bigger than it normally appears.

You could have those panels not be in the node’s visual tree but in the visual tree of an Adornment. Here’s an example:

Although that sample uses the “Selection” Adornment rather than a completely new Adornment that you would show on mouseHover.

I suggest that you look at how the Hover Buttons sample is implemented in this sample:

Thank you - yes the panels are part of the node template and that does seem to be the issue because if I change from AvoidNodes to Orthogonal these issues seem not to happen - although then edges go over nodes which is not what we want so I will have to explore the adornments approach.

Is there an example where you click and drag an adornment to create a link from the adorned node?

I also wonder if there is a explanation/workaround for this smaller issue as well - the nodes and the links to them are not quite aligned either vertically or horizontally after a relayout.


Yes, the Adornment Buttons sample, Selection Adornment Showing Buttons for Nodes | GoJS Diagramming Library, demonstrates a button from which the user can start dragging/drawing a new link, and another button from which the user can start dragging a new node that is already linked with the selected node.

However, like the Hover Buttons sample I mentioned above, the Adornment Buttons sample also uses selection as the mechanism/policy for when the Adornment appears. Bit I don’t think that should matter if you change the behavior to have the Adornment show on mouseEnter or mouseHover instead of when the Node is selected.

Remember also that hover events are normally not easy for users to trigger on touch devices.

Apologies Walter, having looked into it further, I removed these invisible panels just to test before trying to make them into an adornment, but the link are still taking weird routes with the same setup.



The real reason here seems to be the AvoidsNodes router which is unfortunate because it is otherwise useful.

Another thing I tried was to increase the columnSpacing and layerSpacing on the LayeredDigraphLayout - that does seem to have an effect but not quite what we want.

Does AvoidsNodes use the whole node or some object inside it like the selectionObjectName (does not seem to be that one)? The avoidable property is not available on the TextBlock it seems.
If not we might end up using Orthogonal anyway.

I did also find this post that states that AvoidsNodes does not include the two nodes that it is connecting, but that does not seem to be the case here - perhaps it has changed since then?

Any advice?

Which version of GoJS are you using?

Yes, there’s Node.avoidable (default true) and there’s Node.avoidableMargin. You might want to set Node.avoidableMargin to a value with a negative Margin.bottom value so as to ignore the TextBlock that sticks out in three directions.

Hmmm, if you want to ignore the TextBlock totally, maybe you want to use a custom subclass of Node that overrides Node.getAvoidableRect to return the Rect in document coordinates for the area that you would prefer links not go through.

For debugging, you could temporarily set the Node.background to a distinctive color, just so you can see what bounds the system thinks each node has. But the actual “avoidable Rect” area is normally slightly larger that the Node.actualBounds.

Yes, setting Node.avoidableMargin to a negative value seems to be the easiest solution to the original problem. Setting it to negative on all sides to account for the invisible panels and the bottom text seems to fix the problem without the need of converting the panels to adornments. I realize it’s probably better for them to be adornments but that’s for another day, I guess.

We are using GoJS 3.0 btw.

Thank you!