Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Create a Custom Shape Node for Diagram (Read 3399 times)
SiConsulting Matteo
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 7
Joined: Jun 10th, 2020
Create a Custom Shape Node for Diagram
Jun 10th, 2020 at 10:57am
Print Post  
Hi,

I need to create a Custom Shape node for my diagram but I don't draw the custom node in my diagram and I don't know why.

I have a class Custom Shape where I add a new attribute (Kilometrica):

Code (C++)
Select All
  class CustomShapeNode : ShapeNode
    {
        public string Type = "CustomShapeNode";
        public int Kilometrica = 0;

        public CustomShapeNode() : base() { }

        protected override void SaveToXml(XmlElement xmlElement, XmlPersistContext context)
        {
            base.SaveToXml(xmlElement, context);
            context.WriteInt(this.Kilometrica, "Kilomerica", xmlElement);
        }
        protected override void LoadFromXml(XmlElement xmlElement, XmlPersistContext context)
        {
            base.LoadFromXml(xmlElement, context);
            this.Kilometrica = context.ReadInt("Kilomerica", xmlElement);
        }
    }
 



Then in my Form:

Code (C++)
Select All
protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
....
            ShapeNode nodeShape = new MindFusion.Diagramming.ShapeNode();

            nodeShape.Image = Image.FromFile("immagine.png");
            nodeShape.Text = "Shape Node";
            nodeShape.Transparent = true;
            nodeShape.ImageAlign = ImageAlign.Fit;
            nodeShape.Shape = Shape.FromId("Tipo Prova Shape Node");
            nodeListView1.AddNode(nodeShape);


            CustomShapeNode nodeShape1 = new CustomShapeNode();
            nodeShape1.Image = Image.FromFile("immagine.png");
            nodeShape1.Text = "Custom Shape Node";
            nodeShape1.Transparent = true;
            nodeShape1.ImageAlign = ImageAlign.Fit;
            nodeShape1.Shape = Shape.FromId("2");
            nodeShape1.Kilometrica = 100;
            nodeListView1.AddNode(nodeShape1);
...
 


Now if I try drawing CustomShapeNode with drap and drop but It fails instead the first Node Shape It is right behaviours.


  

Immage_1.PNG ( 50 KB | 116 Downloads )
Immage_1.PNG
Immage_2.PNG ( 52 KB | 124 Downloads )
Immage_2.PNG
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3147
Joined: Oct 19th, 2005
Re: Create a Custom Shape Node for Diagram
Reply #1 - Jun 10th, 2020 at 1:03pm
Print Post  
Hi,

Try overriding the Clone(bool clipboard) method or adding a copy constructor. Default Clone implementation calls copy constructor via reflection.

Regards,
Slavcho
Mindfusion
  
Back to top
 
IP Logged
 
SiConsulting Matteo
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 7
Joined: Jun 10th, 2020
Re: Create a Custom Shape Node for Diagram
Reply #2 - Jun 10th, 2020 at 2:36pm
Print Post  
Hi Slavcho,

I need to create a class that it is a shape custom and custom DiagramNode because I must change a Shape of node and I add new attributes in my node.
In the left panel of my form, I have a node List View object where I have the list of custom nodes.

How could I do this ?

I add a clone method like this:
Code
Select All
  class CustomShapeNode : ShapeNode
    {
        public string Type = "CustomShapeNode";
        public int Kilometrica = 0;

        public CustomShapeNode() : base() { }

        public override DiagramItem Clone(bool clipboard)
        {
            return base.Clone(clipboard);
        }

        protected override void SaveToXml(XmlElement xmlElement, XmlPersistContext context)
        {
            base.SaveToXml(xmlElement, context);
            context.WriteInt(this.Kilometrica, "Kilomerica", xmlElement);
        }
        protected override void LoadFromXml(XmlElement xmlElement, XmlPersistContext context)
        {
            base.LoadFromXml(xmlElement, context);
            this.Kilometrica = context.ReadInt("Kilomerica", xmlElement);
        }
    }
 


  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3147
Joined: Oct 19th, 2005
Re: Create a Custom Shape Node for Diagram
Reply #3 - Jun 10th, 2020 at 3:05pm
Print Post  
Hi,

Just returning base.Clone will fail because your class does not implement a copy constructor, which default Clone tries to call by reflection. Instead, create a CustomShapeNode instance, copy your property values and return the instance. Or alternatively implement a CustomShapeNode (CustomShapeNode prototype) copy constructor.

Regards,
Slavcho
  
Back to top
 
IP Logged
 
SiConsulting Matteo
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 7
Joined: Jun 10th, 2020
Re: Create a Custom Shape Node for Diagram
Reply #4 - Jun 11th, 2020 at 6:57am
Print Post  
Thank you Slavcho

I add a constructor. Now I have i right behaviour.

  
Back to top
 
IP Logged
 
SiConsulting Matteo
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 7
Joined: Jun 10th, 2020
Re: Create a Custom Shape Node for Diagram
Reply #5 - Jun 12th, 2020 at 1:00pm
Print Post  
Hi Slavcho,
I need help me again.

Now I add myNode with CustomShape but I need to create a custom link.

I try this :
Code
Select All
class CustomLink : DiagramLink
    {


        public CustomLink(Diagram parent) : base(parent)
        {
            MyProperty = "go there";

        }

        public override void Draw(MindFusion.Drawing.IGraphics graphics,RenderOptions options)
        {
            base.Draw(graphics, options);

        }

        protected override void SaveToXml(XmlElement xmlElement, XmlPersistContext context)
        {
            base.SaveToXml(xmlElement, context);
            context.WriteString(MyProperty, "MyProperty", xmlElement);
        }

        protected override void LoadFromXml(XmlElement xmlElement, XmlPersistContext context)
        {
            base.LoadFromXml(xmlElement, context);
            MyProperty = context.ReadString("MyProperty", xmlElement);
        }

        public string MyProperty { get; set; }
 



In my form :
Code
Select All
  public Form1()
        {
            InitializeComponent();


            // non permette il disegno del link sullo stesso nodo
            diagram1.AllowSelfLoops = false;

            diagramView1.SmoothingMode = SmoothingMode.AntiAlias;
            // disattiva in modo automatico il comportamento con il mouse della creazione del nodo e permette il disegno del solo link
            //diagramView1.Behavior = Behavior.DrawLinks;
            Diagram.RegisterItemClass(typeof(CustomLink), "CustomLink", 100);

            diagramView1.Behavior = Behavior.Custom;
            diagramView1.CustomLinkType = typeof(CustomLink);
            //diagramView1.CustomNodeType = typeof(CustomShapeNode);

            diagram1.ShapeHandlesStyle = HandlesStyle.Invisible;
            diagram1.DynamicLinks = true;
}
 


This event handler to draw custom shape link:
Code
Select All
private void diagram_DrawLink(object sender, DrawLinkEventArgs e)
        {
            if (e.Shadow)
            {
                // We are not drawing arrows shadows
                return;
            }
            int Larghezza = 105; // larghezza del rettangolo link
            PointF a = e.Points[0];
            PointF b = e.Points[e.Points.Count - 1];

            if (a.Equals(b))
            {
                // 0-length arrow, skip drawing
                return;
            }
            int threshold = 5;
            if (a.X == b.X && a.Y != b.Y)
            {
                threshold = 0;
            }
            else if (a.X != b.X && a.Y == b.Y)
            {
                threshold = 0;
            }

            PointF center = new PointF (Math.Abs(a.X - b.X)/2 + a.X + threshold, Math.Abs(a.Y -b.Y)/2+ a.Y + threshold);
            e.Graphics.DrawString(e.Link.Text, new Font(new FontFamily("Arial"), 12), new System.Drawing.SolidBrush(Color.Black), center.X, center.Y);

            // The fill color of the origin
            Color oc =
                Color.Black;
            // The fill color of the destination. The destination
            // can be null if the arrow is not yet created
            Color dc =
                Color.Black;

            // In order to display a rectangle instead of a simple line,
            // we need to find four points. For this purpose we
            // perform the following transformations
            float an = 0, r = 0;
            PointF p1 = PointF.Empty;
            PointF p2 = PointF.Empty;
            PointF p3 = PointF.Empty;
            PointF p4 = PointF.Empty;

            // Find two points around the origin control point
            Convert.DekartToPolar(a, b, ref an, ref r);
            Convert.PolarToDekart(a, an + Larghezza, 1.2f, ref p1);
            Convert.PolarToDekart(a, an - Larghezza, 1.2f, ref p2);

            // At this point in 'r' we have the length of the arrow
            // expressed in the current graphics unit (millimeters by default),
            // and in 'an' we have the angle, between the arrow line and
            // one of the coordinate axis
            float length = r;
            float angle = an;

            // Find two points around the destination control point
            Convert.DekartToPolar(b, a, ref an, ref r);
            Convert.PolarToDekart(b, an + Larghezza, 1.2f, ref p3);
            Convert.PolarToDekart(b, an - Larghezza, 1.2f, ref p4);

            PointF[] pts = new PointF[]
                {
                    p1, p2, p3, p4, p1
                };

            // Create the graphics path containing the arrow rectangle
            GraphicsPath path = new GraphicsPath(FillMode.Winding);
            path.AddLines(pts);

            // Solid fill the arrow with white color, or the color
            // of the destination box, if the arrow's type is gradient
            System.Drawing.Brush solid = new System.Drawing.SolidBrush(
                dc );
            e.Graphics.FillPath(solid, path);
            solid.Dispose();
            path.Dispose();
}
 



My problems are :
1) In behaviours custom the mouse draws a shape and I don't want this.
2) I would like have a link in black solid rectangle without arrow and In this link I want that It is possible to write a text like  the default link.

Do you know how I can do it in a simple way?

I add a image of how It should be.

  

immagine.PNG ( 21 KB | 113 Downloads )
immagine.PNG
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3147
Joined: Oct 19th, 2005
Re: Create a Custom Shape Node for Diagram
Reply #6 - Jun 12th, 2020 at 1:40pm
Print Post  
Hi,

1. Try deriving from DrawLinksBehavior class, override its CreateLink method to return your link instance, and assign to DiagramView.CustomBehavior.

2. Try setting link.Pen to a very thick pen, and link.HeadShape to null. I don't think you'd need any custom drawing for that.

Regards,
Slavcho
  
Back to top
 
IP Logged
 
SiConsulting Matteo
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 7
Joined: Jun 10th, 2020
Re: Create a Custom Shape Node for Diagram
Reply #7 - Jun 12th, 2020 at 2:08pm
Print Post  
Sorry Slavcho,

I wrote wrong :
1) I'm in custom mode, The diagram draws a node wrong i.e. a solid rectangle with a mouse event, because the library wants the behavious create node ("diagramView1.CustomNodeType").
I would want the behaviuos like Drawlinks "diagramView1.Behavior = Behavior.DrawLinks" with only the CustomLink.
2) I try your advice.
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3147
Joined: Oct 19th, 2005
Re: Create a Custom Shape Node for Diagram
Reply #8 - Jun 12th, 2020 at 3:32pm
Print Post  
Hi,

That's what I understood the first time, my answer is still what you should do Smiley For example see https://mindfusion.eu/Forum/YaBB.pl?num=1272511552/10#10

Otherwise just setting Behavior to Custom corresponds to a LinkShapesBehavior -derived class that draws both nodes and links.

Regards,
Slavcho
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint