Find other port for Text in GoMultiText

I have a GoMultiTextNode with a header text and one or more additional GoText objects. Except for the header text, they each have a left and right side port.
I essentially need to find the port on the opposite side of a particular text. However, I don’t know exactly which port I’m entering from as I got there through the link attached to it.
Is there a way I can find the index position of a port in a GoMultiTextNode so that I can then find the opposite port? Or can I traverse through the GoText to find the opposite port?
Thanks. Glenn.

In general I think you’ll need to iterate from zero to .ItemCount and compare GetLeftPort(i) [and/or GetRightPort(i)] with the port that you have. That way you can find the index, from which you can get either the item or the other port.
If you need to do this lookup often, you might want to cache the index on the port. You could even use the UserFlags property for this, if you aren’t using that for any other purpose. As with any cached value, you need to consider maintaining it if you call Insert… or Remove…

Thanks Walter.
I’m now maintaining the index in UserFlags and it works fine.
As an asside, is there any reason that GoText doesn’t also have a UserObject property? I’d like the GoMultiTextNode to hold reference to the parent object and each GoText (excluding the header text) to hold a reference to a child object. I am currently maintaining this list as an additional attribute in my GoMultiTextNode descendant.

Well, the IGoGraphPart.UserFlags and IGoGraphPart.UserObject properties were meant to be used like the Tag property in some controls. Their presence is just a convenience for the programmer, so that they don’t necessarily have to define subclasses of nodes and ports and links for quick implemention of simple applications.
But in the more general case, of course, you can define your own subclass of any GoObject class (or of GoDocument) to hold as much state via as many properties as you want. In this case, you could define a class inheriting from GoText to have additional properties–you just need to make sure you deal with issues regarding initializing, copying, deleting, serializing and maybe some other concerns.
Note also that GoMultiTextNode items don’t even have to be GoText objects. That’s illustrated by the RecordNode class in the Demo1 sample, where the items in the list can be RecordItem objects, which are GoGroups holding both an icon (a GoImage) and text (a GoText).
So the reason GoText doesn’t have a UserObject property is the same reason the other basic object classes don’t have it: each GoDiagram class tries to focus on providing the most useful functionality with the least clutter, so that applications can be better implemented with a cleaner design.
In fact I believe all of the predefined GoNode classes (including GoNode itself) could be reimplemented by any programmer using the basic GoDiagram classes. Just looking at the source code for GoMultiTextNode, for example, I don’t see anything that you couldn’t write yourself. (Well, perhaps at the cost of reduced performance or duplicated code.) This is one way in which GoDiagram can provide all of the features and conveniences that competing products have, while offering the opportunity to do almost anything else if you are willing to implement a little extra code.

I find them very convenient and always use the UserObject property to hold a reference to the domain object that the graphical object is presenting.

This is the real issue for me. If all of the GoObjects supported UserObject then I could implement almost all of the functionality I need without having to add additional properties to descendants and the corresponding init, copy, delete, serializing adjustments. I have descendant objects that adjust the presentation of GoObject types but other than GoText don’t need any additional properties.

It is all a trade off and I understand your position.
Thanks. Glenn.

You need to deal with the issues of initialization, copying, deleting, and serializing when you use the UserObject property, too. For copying, that means an override of CopyObject; for serializing, that means making your domain object serializable.
Making you define a subclass to add your own property has the advantage of reducing memory usage in all the other uses of that class. Furthermore your property/field definition can and should be type specific, which improves compile-time checking and run-time speed.
Yes, it’s all a trade-off.
And you don’t have to add a field to associate a GoObject with one of your domain objects–you could use a Hashtable.