Using more than one Link type

Hi,

I’ve a flowchart and have used makePort to add spots to the "T"op, "L"eft, "B"ottom and "R"ight. All works well and the flowchart looks great.

I’ve now got comments associated with specific elements and need to ‘highlight’ the link to the comment as the number/size of comments may increase.

  • So out of the box I have scenario (1)
  • but what I'd like it to have a 'different' link that I could style and control such that it was more in line with (2) - note that the text 'sticks to vertical link of target' should be 'line' i.e. the user could move the comment up and down and the line would remain straight unto the comment is moved too far up/down.
  • Option (3) would be nice but I'm not sure that the boxes can be forced to be aligned soNot quite sure where to start...

This is the Comment Template:
   <font face="Courier New, Courier, mono" size="2">     myDiagram.nodeTemplateMap.add("Comment",</font>

$$(go.Node, “Auto”, nodeStyle(), {
selectionChanged: onSelectionChanged
,visible: isAdmin
},
new go.Binding(“location”, “loc”, go.Point.parse).makeTwoWay(go.Point.stringify),
{
//doubleClick: nodeDoubleClick
click: nodeDoubleClick
}, $$(go.Shape, “Rectangle”, {
fill: commentBGColor
, stroke: commentBorder
, strokeWidth: defaultBorder
}),
<span =“apple-tab-span”="" style=“white-space:pre”>
$$(go.Panel, “Table”,
{ defaultAlignment: go.Spot.Left },
$$(go.TextBlock, { row: 0, column: 0, margin: 4, textAlign: “left”, editable: false, font: commentNoteFont, stroke: commentFontColor}, “Note:”),
$$(go.TextBlock, { row: 1, column: 0, margin: 4, /maxSize: new go.Size(200, NaN),/ wrap: go.TextBlock.WrapFit, textAlign: “left”, editable: false, font: commentFont, stroke: commentFontColor }, new go.Binding(“text”, “text”))
)
,
// two named ports, one on each side:
//REQUIRED:
// not the default like (no arrowhead required)
// require straight line to ‘defined’ spot on left or right side (i.e. replace TopLeft with 0,10 or similar?)
makePort(“TL”, go.Spot.TopLeft, false, true)
, makePort(“TR”, go.Spot.TopRight, false, true)
));

This is the makePort function

function makePort(name, spot, output, input) {
// the port is basically just a small circle that has a white stroke when it is made visible
return $$(go.Shape, “Circle”, {
fill: “transparent”
,stroke: null
,desiredSize: new go.Size(6, 6)
,alignment: spot
,alignmentFocus: spot
,portId: name
,fromSpot: spot
,toSpot: spot
,fromLinkable: output
,toLinkable: input
,cursor: “pointer”
});
}

You didn’t include your Link template for “Comment” links, so I think that’s the first thing you need to define.

In that link template, you do not need the Shape that has the “toArrow” set on it. You can set the strokeWidth of the main path Shape to be 4 or whatever. And you can set or bind the Link.fromSpot and Link.toSpot to be where you want.

Furthermore if you declare that the node Shape is the default port, you do not need to create separate port elements named “TL” and “TR”.

myDiagram.linkTemplateMap.add(“Comment”,
$$(go.Link,
{ toSpot: new go.Spot(0, 0.001), fromSpot: new go.Spot(1, 0.001) },
$$(go.Shape, { strokeWidth: 4 })
));

And in your node templates you need to set:
$$(go.Shape, . . . , { portId: “” }, . . . )

Apologies Walter,

I’m not sure what to do with the portId

I’ve removed the reference to the TL and TR on the Comment node and added , portId: “Comment” (although I’m not certain what this is supposed to be doing?)

myDiagram.nodeTemplateMap.add(“Comment”,

$$(go.Node, “Auto”, nodeStyle(), {
selectionChanged: onSelectionChanged
,visible: isAdmin
},
new go.Binding(“location”, “loc”, go.Point.parse).makeTwoWay(go.Point.stringify),
{
//doubleClick: nodeDoubleClick
click: nodeDoubleClick
}, $$(go.Shape, “Rectangle”, {
fill: commentBGColor
, stroke: commentBorder
, strokeWidth: defaultBorder
, portId: “Comment”
}),
<span =“apple-tab-span”="" style=“white-space:pre”>
$$(go.Panel, “Table”,
{ defaultAlignment: go.Spot.Left },
$$(go.TextBlock, { row: 0, column: 0, margin: 4, textAlign: “left”, editable: false, font: commentNoteFont, stroke: commentFontColor}, “Note:”),
$$(go.TextBlock, { row: 1, column: 0, margin: 4, /maxSize: new go.Size(200, NaN),/ wrap: go.TextBlock.WrapFit, textAlign: “left”, editable: false, font: commentFont, stroke: commentFontColor }, new go.Binding(“text”, “text”))
)
//, makePort(“TL”, go.Spot.TopLeft, false, true)
//, makePort(“TR”, go.Spot.TopRight, false, true)
));

I’ve also added the LinkTemplate (It makes sense to add this but I’m just uncertain on utilising it… )

myDiagram.linkTemplateMap.add(“Comment”,
$$(go.Link, // the whole link panel
{
toSpot: new go.Spot(0, 0.001)
, fromSpot: new go.Spot(1, 0.001)
}
, $$(go.Shape, { strokeWidth: 10 })
)
);

Did you have a question?

The reason for setting portId: “” (the empty string) on the Shape in the Node is to allow the link data not to specify the fromPortId or the toPortId. But you don’t have to do what I suggest there – it just depends on what behavior that you want.

Apologies - the question was really that it wasn’t working and I can’t see why.

I’ve copied the relevant sections here and think that I’m missing some sort of binding between the CommentLink and the port created in makePortComment?

If there’s an example somewhere in the site feel free to point me and I can dissect, all I can see is a screenshot to indicate this is feasible such as

            myDiagram.linkTemplateMap.add("CommentLink",
                $$(go.Link, // the whole link panel
                    {
                        routing: go.Link.Normal, curve: go.Link.Normal, corner: 0, toShortLength: 0, relinkableFrom: isAdmin, relinkableTo: isAdmin, reshapable: isAdmin, selectable: true
                    }
                    , $$(go.Shape, { strokeWidth: 1 })
                )
            );

            function makePortComment(name, spot, output, input) {
                // the port is basically just a small circle that has a white stroke when it is made visible
                return $$(go.Shape, "Circle", {
                    fill: "red"
                    ,stroke: null
                    ,desiredSize: new go.Size(6, 6)
                    ,alignment: spot
                    ,alignmentFocus: spot
                    ,portId: name // if name="" this will be the default
                    ,fromSpot: spot
                    ,toSpot: spot
                    ,fromLinkable: output
                    ,toLinkable: input 
                    ,cursor: "pointer" 
<span ="Apple-tab-span" style="white-space:pre">					</span>//??define the type of link {category} to make this link {i.e. CommentLink}
                });
            }

            myDiagram.nodeTemplateMap.add("Comment",
            $$(go.Node, "Auto", nodeStyle(), 
                new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
<span ="Apple-tab-span" style="white-space:pre">				</span>$$(go.Shape, "Rectangle", {
<span ="Apple-tab-span" style="white-space:pre">					</span>portId: ""
                }),

                $$(go.Panel, "Table",
                { defaultAlignment: go.Spot.Left },
                  $$(go.TextBlock, { row: 0, column: 0 }, "Note:"),
                  $$(go.TextBlock, { row: 1, column: 0 }, new go.Binding("text", "text"))
                )
                , makePortComment("", go.Spot.LeftCenter, true, true)
                , makePortComment("R", go.Spot.LeftCenter, true, true)
<span ="Apple-tab-span" style="white-space:pre">				</span>//??define the type of link {category} to make this link {i.e. CommentLink}
            ));

When I specifically add the categroy into the LinkData:

                {"from":-23, "to":-60, "fromPort":"B", "toPort":"T"},
                {"from":-60, "to":-28, "fromPort":"B", "toPort":"T"},
                {"from":-1, "to":-41, "fromPort":"R", "toPort":"", "category":"CommentLink"},
                {"from":-8, "to":-53, "fromPort":"R", "toPort":"", "category":"CommentLink"},
                {"from":-26, "to":-55, "fromPort":"R", "toPort":"", "category":"CommentLink"},
                {"from":-25, "to":-54, "fromPort":"L", "toPort":"R", "category":"CommentLink"},
                {"from":-50, "to":-59, "fromPort":"R", "toPort":"", "category":"CommentLink"}

the link renders as expected - but I want the editor to simply connect in/out of a comment and the link be forced the CommentLink type?

So the question is

is it possible to have the editor simple link nodes together and the type of link be forced?

I guess I can bind a JS event to test the incoming/outgoing and force an attribute somehow - but would ideally use something OOTB if there is a way?

Thanks again

Incidentally, I can see that I can bind on the shape and update the color (as an example) but can’t see how I can either assign a different template or update the link params as they would be in a template)

[code]

                , $$(go.Shape
                , new go.Binding("stroke", "toNode", function (n) { return checkLinkTo(n); }).ofObject()

[/code]


[code]

      function checkLinkTo(n) {
            if (n.data.category != null && n.data.category == 'Comment') {
                return 'red';
            }
            else {
                return 'blue';
            }
        }

[/code]


the above work in that it changes the colour of lines as expected - but I want to apply different link styles altogether - is this possible?

Are you trying to automatically choose a link category (i.e. a named template in Diagram.linkTemplateMap) based on what the link is connecting to?

The simple but manual solution is to set the category property on the link data.

The automatic solution is to override the undocumented method Diagram.getCategoryForLinkData. Here is an override that does exactly what the standard behavior does:

myDiagram.getCategoryForLinkData = function(data) { var model = myDiagram.model; var cat = ''; if (model instanceof GraphLinksModel) { cat = model.getCategoryForLinkData(data); } else if (model instanceof TreeModel) { cat = model.getParentLinkCategoryForNodeData(data); } return cat; };

I haven’t had time to investigate a better solution for your whole situation.

Thanks again Walter. Using a little of the code you’ve got above I’ve

  • detected the port-in is on a comment
  • updated the obj.part.category to indicate the link category is CommentLink

This means the user has to click save/load to see the updated link but it works perfectly on reloading - given the flowcharts will be created at a rate of 1 every few months I’m sure this will be acceptable!

Thanks for your efforts and if you do come across a situation where the template is dynamically applied in the GUI at drag/link time do let me know :)

Thanks again.