Strange Behaviour

Hi,

I have two nodes a start node and a stop node. I want the start node to allow only outgoing connections and the stop node to only allow incoming connections. The start node seems to be okay when I try to link to it from another node. However the stop node allows linking from it to any node, even the start node which is set to disallow this. I’ve included the code below. Am I missing something really obvious?

Regards,

Martin

public class StartNode : GoNode
{
    private GoEllipse circle = null;
    private GoTriangle triangle = null;
    private GoPort topPort = null;
    private GoPort bottomPort = null;
    private GoPort rightPort = null;

    public StartNode()
    {
          Initialize();
    }

    private void Initialize()
     {         &nbsp ; 
          this.Resizable = false;

          circle = new GoEllipse();
          circle.Pen = Pens.Black;
          circle.Brush = Brushes.WhiteSmoke;
          circle.Selectable = false;
          circle.Movable = false;
          circle.Resizable = false;
          Add(circle);

          triangle = new GoTriangle();
          triangle.Pen = Pens.Black;
          triangle.Brush = Brushes.Green;
          triangle.Selectable = false;
          triangle.Movable = false;
          triangle.Resizable = false;
          Add(triangle);

          topPort = new GoPort();
          topPort.Style = GoPortStyle.Rectangle;
          topPort.IsValidTo = false;
          Add(topPort);

          bottomPort = new GoPort();
          bottomPort.IsValidTo = false;
          bottomPort.Style = GoPortStyle.Rectangle;
          Add(bottomPort);

          rightPort = new GoPort();
          rightPort.IsValidTo = false;
          rightPort.Style = GoPortStyle.Rectangle;
          Add(rightPort);

    }

    public override void LayoutChildren(GoObject childchanged)
    {
          if (Initializing) return;
          base.LayoutChildren(childchanged);

          if (triangle != null && circle != null)
          {
              triangle.A = new PointF(circle.Center.X + circle.Width / 3, circle.Center.Y );
              triangle.B = new PointF(circle.Center.X - circle.Width / 4, circle.Center.Y - circle.Height / 4);
              triangle.C = new PointF(circle.Center.X - circle.Width / 4, circle.Center.Y + circle.Height / 4);
              if (topPort != null)
              {
                  topPort.Size = new SizeF(4, 4);
                  PointF pt = new PointF(circle.Center.X, this.Top);
                  topPort.SetSpotLocation(TopCenter, pt);
              }
              if (bottomPort != null)
              {
                  bottomPort.Size = new SizeF(4, 4);
                  PointF pt = new PointF(circle.Center.X, this.Bottom);
                  bottomPort.SetSpotLocation(BottomCenter, pt);
              }
              if (rightPort != null)
              {
                  rightPort.Size = new SizeF(4, 4);
                  PointF pt = new PointF(this.Right, this.Top + this.Height/2);
                  rightPort.SetSpotLocation(MiddleRight, pt);
              }
          }
    }
}




public class StopNode : GoNode
{
    private GoEllipse circle = null;
    private GoRectangle rectangle = null;
    private GoPort topPort = null;
    private GoPort bottomPort = null;
    private GoPort leftPort = null;

    public StopNode()
    {
          Initialize();
    }

    private void Initialize()
    {
          this.Resizable = false;

          circle = new GoEllipse();
          circle.Pen = Pens.Black;
          circle.Brush = Brushes.WhiteSmoke;
          circle.Selectable = false;
          circle.Movable = false;
          circle.Resizable = false;
          Add(circle);

          rectangle = new GoRectangle();
          rectangle.Pen = Pens.Black;
          rectangle.Brush = Brushes.Red;
          rectangle.Selectable = false;
          rectangle.Movable = false;
          rectangle.Resizable = false;
          Add(rectangle);

          topPort = new GoPort();
          topPort.IsValidFrom = false;
          topPort.Style = GoPortStyle.Rectangle;
          Add(topPort);

          bottomPort = new GoPort();
          bottomPort.IsValidFrom = false;
          bottomPort.Style = GoPortStyle.Rectangle;
          Add(bottomPort);

          leftPort = new GoPort();
          leftPort.IsValidFrom = false;
          leftPort.Style = GoPortStyle.Rectangle;
          Add(leftPort);

    }

    public override void LayoutChildren(GoObject childchanged)
    {
          if (Initializing) return;
          base.LayoutChildren(childchanged);

          if (rectangle != null && circle != null)
          {
              rectangle.Bounds= new RectangleF(circle.Center.X - circle.Width / 4, circle.Center.Y - circle.Width / 4, circle.Width / 2, circle.Height / 2);
              if (topPort != null)
              {
                  topPort.Size = new SizeF(4, 4);
                  PointF pt = new PointF(circle.Center.X, this.Top);
                  topPort.SetSpotLocation(TopCenter, pt);
              }
              if (bottomPort != null)
              {
                  bottomPort.Size = new SizeF(4, 4);
                  PointF pt = new PointF(circle.Center.X, this.Bottom);
                  bottomPort.SetSpotLocation(BottomCenter, pt);
              }
              if (leftPort != null)
              {
                  leftPort.Size = new SizeF(4, 4);
                  PointF pt = new PointF(this.Left, this.Top + this.Height / 2);
                  leftPort.SetSpotLocation(MiddleLeft, pt);
              }
          }
    }
}

It seems to work just fine for me.
But perhaps you aren’t aware that users can draw links “backwards”, starting at the ToPort and going towards a FromPort. If you don’t like this functionality, you can do:
(goView1.FindMouseTool(typeof(GoToolLinkingNew), true) as GoToolLinkingNew).ForwardsOnly = true;
A few comments:
You might want to set the GoPort.FromSpot on the StartNode ports, and the GoPort.ToSpot on the StopNode ports, for those ports on the top or the bottom of those nodes.
You might also want to specify initial sizes for the shape; when I first created them, the nodes were too small.
You forgot to add the [Serializable] attribute.
You forgot to implement an override of CopyChildren, to make sure that copied nodes have the proper references in those fields that you added.
Pardon my comments if you had excerpted your code for exposition purposes. But I feel obliged to point out these common oversights for the benefit of other readers, even though you already knew about them.

Hi Walter,

Thanks for the comments, this is still at prototyping stage so code is not complete. What I want is not to allow backwards links from the StopNode only. In my app it has to be possible for the user to draw backwards links between other nodes.
Also another quick question it’s probably related. How do I prevent nodes of specific types from being linked together. e.g. stop user from connecting a StartNode and StopNode.

Many thanks for all your help.

Best Regards,

Martin

I think you could modify the GoToolLinkingNew tool to prevent drawing links backwards from particular nodes, but why would you want to? What harm is there in that? Why restrict the behavior in a manner that users might find arbitrary? (Remember, drawing links “backwards” does not change the direction of the link that results.)
To limit the possible connections that users can link (or relink), you can either override the IsValidLink method on either the GoPort or the linking tool. There’s an example in SubGraphApp, in the RestrictedLinkingTools file. You might find other examples by searching this forum too.

Ok Walter, I’m not sure if I understand. I need to prevent users drawing a link from StopNode to another node as a StopNode is the end of the flow. You can’t stop and then go back to/forward to somewhere else.
In the code I posted I would have expected that setting IsValidFrom = false would stop me using this port as a from port.
From what you’ve said it would seem the drawing the link backwards would set the starting node as the to node and the ending node as the from node. This would give me no directional information as everthing would seem to flow down.
Apologies if I’ve misunderstood, it’s getting late here now

Regards,

Martin

Yes, setting GoPort.IsValidFrom to false will prevent users from drawing links whose FromPort is that port. That port can only be the GoLink.ToPort for any link that is connected to that port.
Do you have GoLink.ToArrow set to true? If so, that would make it clear that drawing a link “backwards” does not mean that the direction of the link also goes “backwards”. It just means that the user starts the drawing gesture at the ToPort rather than at the FromPort.
Anyway, I am confident that you don’t need to do anything about this issue – the default behavior should work the way I think we all would want it to work.

Hi Walter,

Thanks for the help it works as expected when
(goView1.FindMouseTool(typeof(GoToolLinkingNew), true) as GoToolLinkingNew).ForwardsOnly = true;

Regards,

Martin