How to make a link to start/end at specified point

Hello,

We have a graph with expandable group nodes and LayeredDigraphLayout. Initially it looks like 1) at the attached image. When user expands some node the layout becomes like in 2). But we want it to be like in 3). I.e. nodes to be still top aligned and link starts/ends from fixed point of a node but not from the center of the node. Additionally we don’t want to have any visible ports and would like to have node linking like in State Chart example, I mean user may start to drag a link from any point around a node border but when the link will be finished, it will start and end from our fixed points. What is the best way to achive this?

Thanks.

You need to adjust the LayeredDigraphVertex.Focus to be near the top of the vertex/node.

[code] public class CustomLayout : LayeredDigraphLayout {
public CustomLayout() {
this.Direction = 90;
}

public override LayeredDigraphNetwork MakeNetwork(IEnumerable<Node> nodes, IEnumerable<Link> links) {
  var net = base.MakeNetwork(nodes, links);
  foreach (var v in net.Vertexes) v.Focus = new Point(0, 0);
  return net;
}

}[/code]
The default vertex focus is at the center.

But remember that the above just controls where the layout will position the nodes. The actual link points are governed by the bounds of the ports and the FromSpot and ToSpot values. To make sure that each of the links connect just below the top of each node, you’ll probably want to set the go:Node.FromSpot=“1 0 0 15” and go:Node.ToSpot=“0 0 0 15”, or something like that.

By default the whole node is a port. If you set go:Node.LinkableFrom=“True” and go:Node.LinkableTo=“True”, the user will be able to drag from anywhere in the node in order to start drawing a new link. You probably don’t want that, so you probably want to put all four of these port properties on the Rectangle that you are using, and to set go:Node.PortId="" on that Rectangle. That means that links will connect to that Rectangle and the user can only draw links from/to that Rectangle.

If you only want the user to be able to draw a new link from along the edge of the Rectangle, put a transparent-filled Rectangle in front of that port Rectangle that is centered on the same Rectangle but is a bit smaller, thereby exposing the port only along the edges. Or you can do what the StateChart sample does – re-use the TextBlock as the non-port object that obscures most of the node from being a place to start drawing a new link.

Thanks a lot, your code really helped.
We have one more question related to that. Direction of our LayeredDigraphLayout is set to 0, and all linked nodes are aligned in one line as at the picture. But unlinked nodes are placed below them so initial layout without any links looks like if Direction is set to 90. Is there an option to layout unlinked nodes the same way as linked nodes? I mean if Direction is set to 0 all unlinked nodes should be placed at the same line after the linked nodes like here






Thank you in advance. BTW, we are finally buy the subscription, should I register somewhere to let you know that I am a supported customer?

Hmm, there doesn’t seem to be a LayeredDigraphLayout.Arrangement property like there is for TreeLayout. So I don’t think there’s a trivial solution for you. You might want to position them yourself.

Regarding your support question, we can tell from your (private) e-mail address in your profile, so you should use your work e-mail address there.

Hello Walter,

Unfortunately my boss bought the subscription so my e-mail is not at your customers base. Is there other way to let you know that my conscience is clear when I’m asking for support? :)

Regarding the topic, could you point me how I may reposition unlinked nodes after automatic layouter complete its work?

Well, since you already have a custom layout class, it’s probably easiest to customize it further.

You’ll want to override MakeNetwork to remove all of the singleton (i.e. unconnected) nodes from the network that the layout operates on. Something like:

public override LayeredDigraphNetwork MakeNetwork(IEnumerable<Node> nodes, IEnumerable<Link> links) { this.Singletons = nodes.Where(n => n.LinksConnected.Count() == 0).ToList(); return base.MakeNetwork(nodes.Where(n => n.LinksConnected.Count() > 0), links); } IEnumerable<Node> Singletons { get; set; }
Then change LayoutNodes to do its usual work and also programmatically put the Singletons where you want them. Something like:

protected override void LayoutNodes() { base.LayoutNodes(); Rect bounds = this.Diagram.Panel.ComputeBounds(this.Network.GetNodesAndLinks()); foreach (Node n in this.Singletons) { . . . n.Position = ...; . . . } this.Singletons = null; // release this layout's references to Nodes }