Multilabels for one link

Hello everyone,
I have a problem with multilabels (more than one label) for one link.
I have seen how I can make them in the FAQs (Theme: We need links with more labels than GoLabeledLink provides.).

Everything goes fine until I want to change the number of labels dynamically. The number of labels is controlled by the FromPort.
If I change the FromPort a new string is insert but the old one is still there. That is not the result that I have desired.

The only reason, that I see is: I handle the “Remove” function wrong. But how can I make it right?

Please help me.

Following my code:

class Link : GoLabeledLink
{

public const int ChangedLabel = 12408;
GoText [] multilabel;


public GoText[] MultiLabel
{
get
{
return multilabel;
}
set
{
GoText[] old = multilabel;
if (old != value)
{
if (old != null)
{
for (int index = 0; index < multilabel.Length; index++)
{
if (null != multilabel[index])
{
base.Remove(multilabel[index]);
multilabel[index] = null;
}
}
multilabel = null;
}
multilabel = value;
if (value != null)
{
for (int index = 0; index < multilabel.Length; index++)
{
if (null != multilabel[index])
{
Add(multilabel[index]);
}
}
}
Changed(ChangedLabel, 0, old, NullRect, 0, value, NullRect);
}
}

public override void OnPortChanged(IGoPort port, int subhint, int oldI, object oldVal,
RectangleF oldRect, int newI, object newVal, RectangleF newRect)
{
base.OnPortChanged(port, subhint, oldI, oldVal, oldRect, newI, newVal, newRect);

if(subhint == GoLink.ChangedFromPort)
{
GoPort Port = newVal as GoPort;
if (null != Port)
{
if (null != this.FromPort)
{
GoPort fromPort = this.FromPort.GoObject as GoPort;
if (null != fromPort)
{
int countInterfaces = fromPort.Interfaces.Length;
GoText[] label = new GoText[countInterfaces];
for (int index = 0; index < countInterfaces; index++)
{
label[index] = new GoText();
label[index].Text = “Text”;
}
LinkLabel = label;
}
}
}
}
}
}

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;
}
}

Hello,
OK, I understand, too many code
I try to explain my problem different.
My links have multiline labels.
Because of GoLabeledLinks which can only have a single line label, I create an array of GoText and add each element to the object.
In some ways the array length of the label is variable at runtime (if FromPort is changed).
If the array length is changed, I would like to remove the label from the object and create a new one which I add to the object.
But the remove function has no effect. The old label is already displayed in the view and the new one is there, too.
Have you got any answer, why the old one is still displayed?

Wait–the “label” on a GoLabeledLink can be practically any object at all. It doesn’t have to be a single line GoText. It could be a multiline GoText, or it could be a GoListGroup of a bunch of GoText objects, or it could be a GoPort, or it could be any GoNode!
So you should be able to change the GoText.Text string, or add or remove GoObjects to a GoGroup, or whatever.
But to answer your immediate question, label.Remove() or link.Remove(label) ought to work.
And your code doesn’t seem to set the MultiLabel property, but the LinkLabel property, whatever that is.

Hi Walter,
oh no, I’m so stupid. Thanks for your supply.