I’m not sure what you are trying to do, but here is a link class I have used to display a large and varying number of labels for a link, simplified from the FlowLink class in the Processor sample. This uses the LinkLabel class that is also in the Processor sample, but that I have copied here for completeness.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using Northwoods.Go;
namespace App {
[Serializable]
public class TestLink : GoLabeledLink {
public TestLink() {
this.ToArrow = true;
this.Orthogonal = true;
LinkLabel t = new LinkLabel();
t.Text = “0”;
t.Segment = 0;
Add(t);
t = new LinkLabel();
t.Text = “1”;
t.Segment = 1;
t.TextColor = Color.Red;
t.ConnectionColor = Color.Red;
Add(t);
t = new LinkLabel();
t.Text = “2”;
t.Segment = 2;
t.BackgroundColor = Color.DarkGreen;
t.TextColor = Color.LightGreen;
t.ConnectionColor = Color.DarkGreen;
Add(t);
t = new LinkLabel();
t.Text = “3”;
t.Segment = 3;
t.TextColor = Color.Blue;
Add(t);
t = new LinkLabel();
t.Text = “4”;
t.Segment = 4;
t.ConnectionColor = Color.Empty;
Add(t);
}
public override void LayoutChildren(GoObject childchanged) {
if (this.Initializing)
return;
base.LayoutChildren(childchanged);
foreach (GoObject child in this) {
IGoLinkLabel l = child as IGoLinkLabel;
if (l != null)
PositionLinkLabel(l, childchanged);
}
}
private void PositionLinkLabel(IGoLinkLabel l, GoObject childchanged) {
if (l == null) return;
if (l == childchanged) {
PointF center = childchanged.Center;
GoStroke s = this.RealLink;
float closestdist = 10e20f;
PointF closestpt = new PointF();
int closestseg = -1;
int numpts = s.PointsCount;
for (int i = 0; i < numpts - 1; i++) {
PointF start = s.GetPoint(i);
PointF end = s.GetPoint(i + 1);
PointF R;
GoStroke.NearestPointOnLine(start, end, center, out R);
float dist = ((R.X-center.X)(R.X-center.X) + (R.Y-center.Y)(R.Y-center.Y));
if (dist < closestdist) {
closestdist = dist;
closestpt = R;
closestseg = i;
}
}
if (closestseg > -1) {
l.Offset = new SizeF(center.X-closestpt.X, center.Y-closestpt.Y);
l.Segment = closestseg;
PointF A = s.GetPoint(closestseg);
PointF B = s.GetPoint(closestseg+1);
PointF R = closestpt;
double rdist = Math.Sqrt((A.X-R.X)(A.X-R.X) + (A.Y-R.Y)(A.Y-R.Y));
double sdist = Math.Sqrt((A.X-B.X)(A.X-B.X) + (A.Y-B.Y)(A.Y-B.Y));
if (sdist <= 0)
l.SegmentPercentage = 0;
else
l.SegmentPercentage = (float)(rdist*100/sdist);
}
} else {
SizeF off = l.Offset;
PointF cp = l.LinkLabelConnectionPoint;
((GoObject)l).Center = new PointF(cp.X + off.Width, cp.Y + off.Height);
}
}
}
public interface IGoLinkLabel {
///
/// Gets the point on the parent link where the line from this label connects
/// with the link stroke.
///
///
///
///
PointF LinkLabelConnectionPoint { get; }
///
/// Gets or sets the offset of the center of this label relative to the
/// .
///
///
///
SizeF Offset { get; set; }
///
/// Gets or sets the index of the segment where the should be.
///
///
///
int Segment { get; set; }
///
/// Gets or sets the percentage along the segment where the should be.
///
///
///
float SegmentPercentage { get; set; }
}
///
/// This implements a simple text label that works with
/// to provide independently movable labels that are “connected” with the link by a thin
/// drawn line to the nearest point on the link.
///
///
/// This needs to work with a subclass that overrides
/// to either position this LinkLabel or
/// to update the LinkLabel’s , , and
/// .
/// To use this class, just an instance to your
/// subclass that implements LayoutChildren
/// and PositionLinkLabel as shown in the TestLink class.
///
[Serializable]
public class LinkLabel : GoText, IGoLinkLabel {
///
/// By default these labels have an opaque background and a simple border,
/// and will not be copied when selected on their own.
///
public LinkLabel() {
this.TransparentBackground = false;
this.Alignment = GoObject.Middle;
this.Bordered = true;
this.Copyable = false;
}
///
/// Draw a line connecting the center of this label with the
/// .
///
///
///
///
/// The color of the line is determined by .
///
public override void Paint(Graphics g, GoView view) {
GoLabeledLink l = this.LabeledLink;
Color c = this.ConnectionColor;
if (l != null && c != Color.Empty) {
Pen pen = new Pen©;
PointF cp = this.LinkLabelConnectionPoint;
PointF center = this.Center;
GoShape.DrawLine(g, view, pen, center.X, center.Y, cp.X, cp.Y);
pen.Dispose();
}
base.Paint(g, view);
}
///
/// Include the line drawn from this label to the .
///
///
///
///
public override RectangleF ExpandPaintBounds(RectangleF rect, GoView view) {
Color c = this.ConnectionColor;
rect = base.ExpandPaintBounds(rect, view);
if (c != Color.Empty) {
PointF cp = this.LinkLabelConnectionPoint;
rect = RectangleF.Union(rect, new RectangleF(cp.X, cp.Y, 1, 1));
}
return rect;
}
///
/// Gets the point on the parent link where the line from this label connects
/// with the link stroke.
///
///
///
public PointF LinkLabelConnectionPoint {
get {
GoLabeledLink l = this.LabeledLink;
if (l != null && l.RealLink != null) {
GoLink rl = l.RealLink;
int numpts = rl.PointsCount;
if (numpts < 2) return this.Center;
int s = this.Segment;
if (s >= numpts-1)
s = numpts-2;
if (s < 0)
s = 0;
PointF A = rl.GetPoint(s);
PointF B = rl.GetPoint(s+1);
float segdst = this.SegmentPercentage;
return new PointF(A.X + ((B.X-A.X)*segdst)/100,
A.Y + ((B.Y-A.Y)*segdst)/100);
} else {
return this.Center;
}
}
}
///
/// A Convenience property, for getting the parent as a GoLabeledLink.
///
public GoLabeledLink LabeledLink {
get { return this.Parent as GoLabeledLink; }
}
///
/// Gets or sets the offset of the center of this label relative to the
/// .
///
///
///
public SizeF Offset {
get { return myOffset; }
set {
SizeF old = myOffset;
if (old != value) {
myOffset = value;
Changed(ChangedOffset, 0, null, MakeRect(old), 0, null, MakeRect(value));
}
}
}
///
/// Gets or sets the index of the segment where the should be.
///
///
///
public int Segment {
get { return mySegment; }
set {
int old = mySegment;
if (old != value) {
mySegment = value;
Changed(ChangedSegment, old, null, NullRect, value, null, NullRect);
}
}
}
///
/// Gets or sets the percentage along the segment where the should be.
///
///
///
public float SegmentPercentage {
get { return mySegmentPercentage; }
set {
float old = mySegmentPercentage;
if (old != value) {
mySegmentPercentage = value;
Changed(ChangedSegmentPercentage, 0, null, MakeRect(old), 0, null, MakeRect(value));
}
}
}
///
/// Gets or sets the color used to draw a line between this label and the link.
///
///
/// This defaults to Color.Gray.
/// A value of Color.Empty causes no line to be drawn.
///
public Color ConnectionColor {
get { return myConnectionColor; }
set {
Color old = myConnectionColor;
if (old != value) {
myConnectionColor = value;
Changed(ChangedConnectionColor, 0, old, NullRect, 0, value, NullRect);
}
}
}
public override void ChangeValue(GoChangedEventArgs e, bool undo) {
switch (e.SubHint) {
case ChangedOffset:
this.Offset = e.GetSize(undo);
return;
case ChangedSegment:
this.Segment = e.GetInt(undo);
return;
case ChangedSegmentPercentage:
this.SegmentPercentage = e.GetFloat(undo);
return;
case ChangedConnectionColor:
this.ConnectionColor = (Color)e.GetValue(undo);
return;
default:
base.ChangeValue(e, undo);
return;
}
}
public const int ChangedOffset = 3214;
public const int ChangedSegment = 3215;
public const int ChangedSegmentPercentage = 3216;
public const int ChangedConnectionColor = 3217;
private SizeF myOffset = new SizeF(0, 0);
private int mySegment = 3;
private float mySegmentPercentage = 50;
private Color myConnectionColor = Color.Gray;
}
}