Can't select or move my custom node

Hi,

I’ve created a custom node (only draws a rectangle at the moment) but when I add it to a goview I can’t select or move it. I know I must be missing something simple, can anyone help.

Regards,

Martin
Here’s the code:

public class StateNode : GoNode
{
    private Brush brush = Brushes.WhiteSmoke;
    private Pen pen = Pens.Black;
    private String text = String.Empty;
    public StateNode()
    {
          this.Size = new SizeF(50, 50);
          this.Resizable = true;
          this.Movable = true;
          this.Selectable = true;
          this.ResizesRealtime = true;
    }

    public Brush Brush
    {
          get { return this.brush; }
          set { this.brush = value; }
    }

    public Pen Pen
    {
          get { return this.pen; }
          set { this.pen = value; }
    }

    public String Text
    {
          get { return text; }
          set { text = value; }
    }


    public override void Paint(System.Drawing.Graphics g, GoView view)
    {
          //base.Paint(g, view);
          GraphicsPath path = MakePath();
          if (this.Brush != null)
          {
              g.FillPath(this.Brush, path);
          }
          if (this.Pen != null)
          {
              g.DrawPath(this.Pen, path);
          }
          if (this.Text != null)
          {
              g.DrawString(this.Text, new Font("Arial", 10, FontStyle.Regular), Brushes.Black, new PointF(0, 0));
          }
    }

    public GraphicsPath MakePath()
    {
          GraphicsPath path = new GraphicsPath(FillMode.Winding);
          RectangleF r = this.Bounds;
          path.AddRectangle(r);

          path.CloseAllFigures();

          return path;
          //return base.MakePath();
    }
}

That’s because your GoNode doesn’t actually contain any GoObjects, so there’s nothing to handle picking, for it to be selected.
Here’s an alternative definition that I think is compatible with what you were trying to do:
[Serializable]
public class StateNode : GoIconicNode {
public StateNode() {
// create a GoRectangle as the Icon and a GoText Label and a port
Initialize(null, null, String.Empty);
// position the text label at the top-left inside corner of the Icon
this.LabelOffset = new SizeF(0, 0);
}
protected override GoObject CreateIcon(ResourceManager res, String iconname) {
GoRectangle r = new GoRectangle();
r.Selectable = false;
r.ResizesRealtime = true;
r.Size = new SizeF(50, 50);
r.Brush = Brushes.WhiteSmoke;
r.Pen = Pens.Black;
return r;
}
private GoShape Shape {
get { return this.Icon as GoShape; }
}
public Brush Brush {
get { return this.Shape.Brush; }
set { this.Shape.Brush = value; }
}
public Pen Pen {
get { return this.Shape.Pen; }
set { this.Shape.Pen = value; }
}
}
I don’t know if you will eventually want a port on your node or not. GoIconicNode does have one. If you don’t, just override CreatePort to return null.
With only a little bit more code you could implement this so that it didn’t depend on GoIconicNode, but on GoNode. If you didn’t need any ports, you could inherit from GoGroup.

Hi Walter,

Thanks for that, it works fine. I guess my problem is I’m not quite sure what to use as my base class, and what methods I should override. I’ll describe my shape requirements here and perhaps you can point me in the right direction.

The shape will initially be a rectangle which can contain some text and will have four ports, top, bottom, left and right. In my current demo I’m using a GoTextNode. However depending on properties set on the node I have to display another rectangle with a circle in it on the outside edge of the current node. The user can select which edge. This then changes the number of ports available on the given edge.
So if user chooses the left edge, the current left port is to be disabled and connections will only be accepted to the box with the circle. This will have an unlimited number of connections.
This rule applies to all edges.

Thanks in advance for any help you can provide.

Regards,

Martin

This sounds like a simple variation on the DecoratedTextNode example class that is in the Demo1 sample in version 2.5.
It defines a subclass of GoTextNode that supports an additional TextNodeDecoration, a class that is just a GoGroup containing a GoImage and a GoText. In your case you’ll want to replace the GoImage with a GoRectangle and the GoText with a GoEllipse.
And you’ll want to generalize DecoratedTextNode to support up to four of those decorations, one on each side. I guess the natural thing is to have four fields instead of the one in DecoratedTextNode. You will need to extend the override of LayoutChildren to position each of those decorations where you want them, and also to move the corresponding port (e.g. GoTextNode.LeftPort) to where you want that port to be in the decoration.
The purpose of the LayoutChildren method is to position and size each group’s child objects. GoTextNode.LayoutChildren sizes the background object to fit around the text and positions the four ports in the middle of each side. (Or if GoTextNode.AutoResizes is false, the text is sized to fit in the background object.) When you add children, such as the four decorations, you need to extend LayoutChildren to size/position each of those decorations appropriately. And since you mention wanting to change where links connect to, and where users can start dragging a new link, you’ll need to move the ports correspondingly.

Walter,

Thanks for the pointers, my shape is working great at the moment. I have two problems now that I need to resolve. If a decorator is set on a side, I have to add extra ports to the decorator area. I already have one as I just move the relevant GoTextNode port out, but I would like two more.
Secondly how can I set restrictions on these ports to limit the number of connections and specify wheter they accept incoming, allow outgoing connections.

Regards,

Martin

If you want extra ports, just create them and Add them, and put the code to position them in your override of LayoutChildren.
To limit the number of connections, it’s easiest to use a subclass of GoPort that implements the MaxLinks property and overrides of CanLinkFrom and CanLinkTo, as shown in the LimitedNode example classes of Demo1. (Presumably you don’t want the code in the LimitedNodePort class that changes the color of the port according to the number of connected links, nor the code for the port-specific context menus.) It isn’t necessary to use a subclass of GoPort, but it’s the most natural. You might want to override GoTextNode.CreatePort, so that the four standard ports are instances of your class.
To specify whether they accept incoming or outgoing links, set GoPort.IsValidFrom and IsValidTo properties.

Thanks Walter, I was doing as you described but I was getting funny display issues. Turned out my override of LayoutChildren was incorrect and I wasn’t setting a size on the GoPort so it was filling the decorator area , calling port.Size = new SizeF(4, 4); fixed this.
Again thanks for all the help, support is top notch.

Regards,

Martin