Node location bound to Port of another Node

I have

  • node1 with a port (rectangle)
  • node2 which is also a rectangle of same size as port of node1
now I want node2 to overlap port of node1 and when node1 moves node2 should always move with node1 as if it is port of node1, this should be consistent when a lyout is done or when user moves node1 manually

Well, you can implement most of what you want by using a custom DraggingTool that overrides ComputeEffectiveCollection to return a collection of all of the Parts that should be moved together. It also helps with control-drag-copying behavior if you set DraggingTool.CopiesEffectiveCollection to true, if you want such behavior.

For the Copy and Delete commands, you can use a custom CommandHandler that overrides the Copy() and Delete() methods. [Again, I don’t know if you want such customization on these commands.]

However, these customizations do not help with having diagram layouts treat those collections of nodes (and links?) as if they were a single node. For that you need to customize the layout by overriding MakeNetwork to simplify the LayoutNetwork by removing the LayoutVertexes and LayoutEdges corresponding to the dependent parts, and correspondingly making the main node’s LayoutVertex bigger. Then you also need to override LayoutNodes method to make sure those dependent Nodes are positioned the way that you want relative to the “parent” Node, since the LayoutNetwork no longer knows about those dependent Nodes.

All of this can be a bit tricky because there are so many choices that you can legitimately make.

Here’s an example of overriding DraggingTool.ComputeEffectiveCollection.

public override Dictionary<Part, DraggingTool.Info> ComputeEffectiveCollection(IEnumerable<Part> parts) { if (this.IsShiftKeyDown()) { return base.ComputeEffectiveCollection(parts); } else { var map = new Dictionary<Part, DraggingTool.Info>(); if (parts == null) return map; foreach (var n in parts) { GatherConnecteds(map, n); } return map; } }</p><p> private void GatherConnecteds(Dictionary<Part, DraggingTool.Info> map, Part part) { var node = part as Node; if (node == null) return; if (map.ContainsKey(node)) return; // record the original Node location, for relative positioning and for cancellation map[node] = new DraggingTool.Info() { Point = node.Location }; // now recursively collect all connected Nodes and the Links to them foreach (var link in node.LinksConnected) { map[link] = new DraggingTool.Info(); GatherConnecteds(map, link.GetOtherNode(node)); } }

Basically this returns a collection of all of the Parts that are linked, even indirectly, with the selected Parts. So when the user moves a Node, all Nodes and Links that have a link chain connecting with that Node are moved too.

However, when the user holds down the Shift key, only the selected Parts are moved.

So you’ll want to change the implementation so that it includes dependent nodes. You also have to decide whether when the user moves a dependent node whether the “parent” node should also move. (Note that that is not the case in the Incremental Tree sample – moving a parent moves the whole subtree, but moving a child does not move the parent.)

I don’t think there are any good examples of overriding …Layout.MakeNetwork that do basically what you want. But there are two examples where such overrides do modify the network: the Fishbone and the Genogram samples.

Thanks Walter, Is there any documentation that explains what is LayoutVertex, LayoutEdge etc. any why and when one would use them.

Well, those aren’t the actual class names – there are “Network”, “Vertex”, and “Edge” classes for each of the Layout classes that make use of a GenericNetwork. You can certainly get some documentation on the individual properties added to each “Vertex” and “Edge” class for each kind of layout. But I guess we don’t have thorough documentation on how to override the layout methods beyond the API documentation.