Add GoLabel Event Fire

Hey Guys (Walter)! I’m trying to figure out how to fire the reposition the new link label onto the link when it is added in. It is called when the diagram is drawn, but I have no idea how to call it outside of that. The Overridden function is LayoutChildren in my Link class that extends GoLabeledLink

        public override void LayoutChildren(GoObject childchanged)
        {
            if (this.Initializing)
                return;
            base.LayoutChildren(childchanged);
            foreach (GoObject child in this)
            {
                //Oooo this is what positions the bloody link ZOMG!
                IGoLinkLabel l = child as IGoLinkLabel;
                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);
            }
        }

This code is almost verbatim from the FlowLink class in the Processor document. I want to call this repositioning everytime the label is changed. So what I do is I kill the original link label and I add a new one, but the new one is way off somewhere else on the document. Thanks a lot for your help!

LayoutChildren is called automatically whenever any child’s Bounds changes. (It’s called by GoGroup.OnChildBoundsChanged.)

But you can call it any time you want by just calling LayoutChildren(null).

Hey walter I tried that but it keeps on not positioning my linklabel. How would I just use the PositionLabel function on a new label I made on the GoDocument. I tried using

            Label = new LinkLabel();
            Label.Text = ccode;
            LayoutChildren(Label);
            Add(Label);

but the current label is not positioned correctly. Thanks Walter!

You have to Add the label to be a child of the GoLabeledLink before LayoutChildren can have any effect on it.

I’m really sorry Walter, but I have no idea how to do that.

Exchange the last two statements in the code that you posted last.

I must be doing something wrong because I did this

            this.Label = new LinkLabel();
            this.Label.Text = ccode;

            if (Label.Text.Equals(""))
            {
                Label.Visible = false;
            }
            this.Add(Label);
            this.LayoutChildren(Label);

And I still don’t get the PositionLinkLabel to be correct , but it is called. Also Label is a defined in my link class as this

        public LinkLabel Label
        {
            get
            {
                return lbl;
            }
            set
            {
                LinkLabel old = lbl;
                if (old != value)
                {
                    lbl = value;
                }
            }
        }

What could I be doing wrong?

Actually, LayoutChildren is also called automatically when a child is Add’ed or Remove’d.

So just doing:
[code]LinkLabel lab = new LinkLabel();
lab.Text = ccode;
if (ccode == "") lab.Visible = false;
Add(lab);[/code]
should be sufficient.
In any case, if the code is the same as in the Processor example, then it should be working fine. What exactly is the problem, anyway? Do you need to set some of the LinkLabel properties before you Add it?

Here’s a link to a swf of my problem

http://www.brownandstreza.com/images/LabelAddProblem.swf.html

When I draw the graph initially on open I get my labels in the correct position, but when I recode my links and re-add the labels they end up in the top of the document and not on the link itself.

Is GoLabeledLink.Initializing false when you call Add with a new LinkLabel?

Are you using the LinkLabel class from the Processor sample application? Do its properties have the same default values?

I am using the LinkLabel from the Processor here is the code for it’s constructor

      public LinkLabel() {
      this.Alignment = GoObject.Middle;
      this.Bordered = true;
      this.Copyable = false;
      this.Deletable = true;
      this.Movable = true;
      this.Editable = false;
      this.TextColor = Color.DarkGreen;
      this.TransparentBackground = false;
    }

I made the movable true, and the editable false. Otherwise this should be verbatim from the processor example. Also here is my entire code for changing the link color and the label after the new code is selected.

        public void SetLinkStyle()
        {
            Pen p = new Pen(ReturnColor(), 2);
            this.Pen = p;
            this.ToArrow = true;
            this.HighlightPen = new Pen(Color.White, 6);
            this.Highlight = true;

            if (Added == true)
              {
                Remove(Label);
            }

            Label = new LinkLabel();
            Label.Text = ccode;
            if (Label.Text.Equals(""))
            {
                Label.Visible = false;
            }
            Add(Label);
            LayoutChildren(Label);

            Added = true;
        }

I couldn’t figure out how to just refresh the current label so that’s why I just remove it and add a new one. Also I just stepped through the whole process of adding a new Label and the initializing is always set to false.

So at most you will have just one label for each link, right?

I suggest you just use the GoLabeledLink.MidLabel property if you want easy access to that LinkLabel. And your override of LayoutChildren need not call the base method. since it would just set the position in the normal manner, which would be re-set by the code in PositionLinkLabel.
Another reason for avoiding the definition of child-reference fields in your subclasses is so that you don't need to update them in an override of CopyChildren or in an override of Remove. If you did have a "Label" field/property, you would need to override CopyChildren to make sure the copied link's "Label" referred to the copied LinkLabel rather than to the original one.

Walter removing and adding it in seemed like a horrid way to do it after talking to you so I just instantiated the linklabel in the constructor and now my code does this


            LabelLink.Visible = true;
            LabelLink.Text = ccode;
            if (LabelLink.Text.Equals(""))
            {
                LabelLink.Visible = false;
            }
            Add(LabelLink);

And it totally just works. I just use the label already there and not remove/add it in later to get the single label per link I need. Thanks Walter!