I’m programatically adding links to nodes as the user adds them, to draw a fully connected (complete) graph. In other words, every node connects to every other node.
If I fully connect the graph after all of the nodes are there, the links draw fine, but if I add the links on DocumentChanged, the links start from every other node but do not connect to the newly created node. The weird thing is, this used to work just fine until I added a palette and subgraph functionality. When the newly created node(s) is moved, the links immediately draw correctly.
I tried calling GoLink.CalculateStroke() after the programmatic link behavior but the weirdness persists. I should also mention that I’m subclassing GoLink, but I don’t think I’m changing anything that would affect this. Any ideas?
Thanks in advance, Tyler
The only reason to call CalculateStroke explicitly when creating links programmatically is if the link needs to be part of a document first so that it can route itself correctly. Normally that’s only the case when Orthogonal and AvoidsNodes are true – if so you would call CalculateStroke after adding the link to the document.
But if that’s not the case for your links, I can’t think of how you could be having a problem, since setting either GoLink.FromPort or .ToPort will automatically cause the link to be routed.
You haven’t set SuspendsUpdates or overridden some method that really ought to be calling its base method but isn’t?
Hmmm. Does the problem only happen when dropping a node that is dragged from the palette? If so, are you sure that any fields that you have defined in your classes are being copied correctly?
What hint(s) are you listening for in your GoDocument.Changed event handler that decides to create some links? Maybe the node isn’t completely initialized at the time you create and hook up a link.
Thanks for the quick reply!
I have a method that creates a new link by calling new and then setting the .ToPort and .FromPort, so I guess I don’t need to worry about CalculateStroke. In fact, the only thing I do in the subclass of GoLink is define a number of static Pen references to use based on an enum, simply to “type” the link.
The odd behavior occurs when both dragging and dropping from a Palette and when double-clicking on the GoView.
When a user double-clicks, I do a Document.AddCopy() and reference the GoPalette.Selection.Primary, and the GoInputEventArgs.DocPoint. When the user drags into the GoView, I use DocumentChanged and Hint==GoLayer.InsertedObject.
In both cases, I am relying on DocumentChanged to be called so that I can call my updateLinks() method, which iterates over every node in the Document, in a SubGraph or not, and creates links by the procedure given above.
It is really odd because as I change the position where I add nodes, the destination point for the newly created links seems to change somehow. I should also clarify / reiterate that all of the newly created links seem to go to some point in space, but some of them are bent at the end and others are fine. A simple drag of either node of a link will correct it, snapping it back into place, but any other newly created link will remain the same.
Could you describe your node class? I’m wondering, if you defined it yourself, whether LayoutChildren isn’t positioning and/or sizing the port correctly.
Of course, I’m still assuming that copying nodes is working correctly – i.e. that there aren’t any stale references to the original node or its parts in the copied node or its parts.
Also, what version are you using, and is this Windows Forms or Web Forms?
I’ll answer the easy questions first: I’m using the Winforms .NET C# version, 2.5. Also, I actually am using GoIconicNode, so I didn’t mess up anything there :-). The only thing I’ve subclassed is the GoLink class.
To set up the palette, I am using GoIconicNode.Initialize with an ImageList, some text, etc., and then adding it to the palette using Document.Add().
To get all of the GoIconicNodes out of the Document, I am using a static method to recursively enter collections and collect all GoIconicNodes. These are all doing a shallow copy to build a collection with all the nodes or links. By the way, is there an easier built-in way to get every node out of a Document, no matter how nested within a SubGraph it is? I have a feeling this might have something to do with the problem.
No, doing a recursive traversal is the only certain way to do it. GoSubGraph inherits from GoNode, by the way, so subgraphs are nodes too.
Alright. I’ll work on other things and come back to this later.
Does it work when there aren’t any subgraphs?
Does it work when you control-drag to make a copy of a node?
Even when there are no subgraphs, it still performs strangely. I haven’t tried doing control-drag copy, I’ll try that out tomorrow.
That’s very interesting behavior. I just implemented some behavior which I assume is similar to yours, invoked in a GoDocument.Changed event handler for GoLayer.ObjectInserted.
I think the problem has nothing to do with subgraphs but with copying. It happens in versions 2.3.1, 2.4.1, and 2.5.2, so it isn’t new. In fact, I bet it’s been doing that since before 1.0. It’s slightly surprising that no one has ever reported this problem, although I guess the circumstances are fairly specialized.
The problem is due to the routing (i.e. call to GoLink.CalculateStroke) being done during the first pass of copying, when the GoPort.PortObject which refers to the GoIconicNode.Icon, hasn’t been updated yet by the two-pass copying process.
So your idea of calling CalculateStroke is vaguely right, but it’s not happening late enough. It needs to happen after the whole copy process is done.
In 2.5 after you add the link to the document you can call:
This will work as long as GoDocument.RoutingTime is any one of the delayed routing options – just not GoRoutingTime.Immediate. (The default value is GoRoutingTime.Delayed.)
Thanks for the response. I’ll try that out as soon as I can.
Thanks Walter, this solution seems to work for us.