Drawing a polygon for a link

Hi all,

i am just evaluation GoDiagram and want to draw a polygon around a
GoLabeledLink. My first attempt was to override the Paint method with
calculating and painting the polygon. For two things it does not work
very well. First the InvalidateRect is smaller then my polygon and some
edges are cut off until i force a redraw manually. Secondly i would
like to compute the polygon only when the stroke changes and not when
the link needs to be painted. So (before starting implementation) i
would like to check my idea :-) Is it a good way to do:

  1. Compute polygon when stroke changes (in ComputeMove, ComputeResize, Changed?)

  2. Compute InvalidateRect after updated polygon (in ComputeBounds)

  3. Paint polygon in paint method

Will this work or did i miss anything?

Thanks in advance for any help :-)


First, you can get your Paint override to work without leaving “droppings” behind by also overriding ExpandPaintBounds to include the bounds of your polygon. It’s the “paint bounds” area that gets invalidated, not the GoObject.Bounds.
Second, to optimize your polygon calculations not to be as frequent as each call to Paint: is your polygon dependent only on the path of the link’s stroke? In other words, do you need to calculate a new polygon when and only when any point changes in the GoLabeledLink.RealLink?
If so, it might be best to define a class inheriting from GoLink that caches your extra data (a GraphicsPath?). If you override MakePath(), that might be a good time to reconstruct your data. Of course you will also have overrides of Paint and ExpandPaintBounds.
Finally you can get your GoLabeledLink to use your new GoLink-inheriting class, by either setting GoLabeledLink.RealLink, or by overriding CreateRealLink. As an example of defining a labeled link that uses a customized GoLink class, you can see in the StateCharter sample application how the Transition and TransitionLink classes are defined.

Thanks walter for your quick and helful reply. I got through most of
your tips and they are working fine :-) But i failed at one point. My
app does not get to MakePath of my GoLink descendant (a breakpoint has
no effect). I have no idea what i have to do.

The polygon has to be recalculated sometimes if if the sroke does not
change. E.g the width of the polygonal arrow represents a flow of a
material and a large flow is drawn as a wide arrow. So the polygon
needs to be recalculated if the flow changes. I think it can be done
with an event (or if possible the GoLink can be observer of my
flowobject). Will this be possible?

Oops, sorry about that. I forgot that MakePath need not be called if the shape optimizes its painting by not using GraphicsPaths, which GoStroke does.
You could try overriding CalculateStroke instead. Again, be sure to call the base method first. And put your polygon-calculating code in a separate method that can be called when you set the property representing the “flow” value. Something like:
public float Flow {
get { return myFlow; }
set {
float old = myFlow;
if (old != value) {
myFlow = value;
Changed(ChangedFlow, 0, null, MakeRect(old), 0, null, MakeRect(value));
if (!this.Initializing) UpdatePolygon();
private float myFlow = …;
public const int ChangedFlow = GoObject.LastChangedHint + …;
public override void CalculateStroke() {

I assume your polygon is more sophisticated than just a wide arrow, so that just setting the Pen’s width is insufficient.

Thx again. CalculateStroke works fine if i move a node. If i add a
point to the stroke CalculateStroke is not executed. But i am trying…

You are right setting pen’s width will not do. A single polygon may
represent not just one material flow but many (e.g. black outline with
different coloured “subarrow-sections”). If there are two or more links
going of a node they should be drawn as a splitting polygonal arrow.
Advanced math stuff … ;-)

Sorry, it wasn’t clear to me under what circumstances you wanted to know that you needed to update your polygon(s).
You can override the GoObject.Changed method (instead of CalculateStroke) and afterwards check for various subhints, such as ChangedModifiedPoint, ChangedAddPoint, ChangedRemovePoint, ChangedAllPoints, ChangedCurviness, or ChangedStyle.

Walter, thank you very much! Now everything works fine.
Best regards and have a good weekend.