Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Scale / resize nodes inside Container Node, while Container Node is resizing (Read 3563 times)
PiotrMakowiec
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 12
Joined: Jul 26th, 2017
Scale / resize nodes inside Container Node, while Container Node is resizing
Jul 31st, 2017 at 1:51pm
Print Post  
Hi Smiley I've got a problem with scaling and resizing nodes which are added to Container Node. I am trying to do that while NodeModifying is happening, but always that nodes are multiplied to many times.

My code:
Code
Select All
      public DiagramNode SelectedContainer { get; set; }

      private double firstContainerWidth;
      private double firstContainerHeight;

      public MainWindow()
      {
         InitializeComponent();

         ShapeList.ItemsSource = Shape.Shapes.Cast<Shape>()
            .Select(x => new ShapeNode
            {
               Shape = x,
               Bounds = new Rect(0, 0, 40, 40)
            });
      }

      private void CreateGroupButton_Click(object sender, RoutedEventArgs e)
      {
         if (FlowChart.Selection.Nodes.Count > 1)
         {
            var groupNode = SetGroupNode();

            CreateGroup(groupNode, FlowChart.Selection.Nodes);
            groupNode.SubordinateGroup.AutoDeleteItems = true;
            FlowChart.Selection.Change(groupNode);
         }
      }

      private void CreateGroup(ContainerNode containerNode, DiagramNodeCollection children)
      {
         foreach (var child in children)
         {
            containerNode.Add(child);
         }
      }

      private ContainerNode SetGroupNode()
      {
         var containerNode = FlowChart.Factory.CreateContainerNode(0, 0, 1, 1);
         containerNode.ZBottom(false);
         containerNode.AutoShrink = true;
         containerNode.Foldable = false;
         containerNode.Caption = string.Empty;
         containerNode.CaptionHeight = 0.0;
         containerNode.HandlesStyle = HandlesStyle.DashFrame;
         containerNode.AllowRemoveChildren = false;
         containerNode.AllowAddChildren = false;
         containerNode.Pen = new Pen(new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)), 0.0);
         containerNode.EnabledHandles = AdjustmentHandles.All;

         return containerNode;
      }

      private void FlowChart_NodeModifying(object sender, NodeValidationEventArgs e)
      {

         if (e.Node.GetType() == typeof(ContainerNode))
         {
            Debug.WriteLine("Selected Node:" + SelectedContainer.ActualHeight + " x " + SelectedContainer.ActualWidth);
            Debug.WriteLine("Clicked:" + firstContainerHeight + " x " + firstContainerWidth);


            var container = e.Node as ContainerNode;

            var nodes = container.SubordinateGroup.AttachedNodes;

            foreach (DiagramNode diagramNode in nodes)
            {

               Rect r = diagramNode.Bounds;

               r.Scale(Scale(), Scale());
               diagramNode.SetBounds(r, false, false);
            }


         }
      }

      private double Scale()
      {
         var containerAspect = SelectedContainer.ActualWidth / SelectedContainer.ActualHeight;
         var childAspect = firstContainerWidth / firstContainerHeight;

         double scaleFactor = 1;
         if (containerAspect > childAspect)
         {
            scaleFactor = SelectedContainer.ActualHeight / firstContainerHeight;
         }
         else
         {
            scaleFactor = SelectedContainer.ActualWidth / firstContainerWidth;
         }

         return scaleFactor;
      }

      private void FlowChart_NodeSelected(object sender, NodeEventArgs e)
      {
         SelectedContainer = e.Node;
      }

      private void FlowChart_NodeClicked(object sender, NodeEventArgs e)
      {
         firstContainerHeight = e.Node.ActualHeight;
         firstContainerWidth = e.Node.ActualWidth;
      }
 



I wonder if you know how to do that, maybe even easier built in functions.

Thanks for help Cheesy
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3147
Joined: Oct 19th, 2005
Re: Scale / resize nodes inside Container Node, while Container Node is resizing
Reply #1 - Jul 31st, 2017 at 6:07pm
Print Post  
Hi,

I think problem is you should scale by original Bounds of node instead of current one here -

Code
Select All
Rect r = diagramNode.Bounds;
r.Scale(Scale(), Scale()); 



since you probably want to preserve this ratio -

originalContainerSize / newContainerSize == originalChildSize / newChildSize;

The control keeps original rectangles during interaction but unfortunately they are stored in internal fields. Instead, you could iterate the group's children in FlowChart_NodeClicked and save your own values, e.g. in a Dictionary<node,rect>, or by assigning to an attached property.

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


I Love MindFusion!

Posts: 12
Joined: Jul 26th, 2017
Re: Scale / resize nodes inside Container Node, while Container Node is resizing
Reply #2 - Jul 31st, 2017 at 11:15pm
Print Post  
Thank you so much, now changing size works well, but after that I have met another issue, strictly speaking when I am changing also X and Y values in the shapes it doesn't have any influence. I think it can be because of the nodes are in container. I wonder if you have any idea how to fix this problem also.

Thank you one more time  Smiley

Code
Select All
 private void FlowChart_NodeModifying(object sender, NodeValidationEventArgs e)
        {
            if (e.Node.GetType() == typeof(MindFusion.Diagramming.Wpf.ContainerNode))
            {
                var container = e.Node as MindFusion.Diagramming.Wpf.ContainerNode;

               // Debug.WriteLine("Container first: " + childrenShapeRect[container].X + " x " + childrenShapeRect[container].Y);
               // Debug.WriteLine("Container after: " + container.Bounds.X + " x " + container.Bounds.Y);

                var scale = Scale(container);
                var nodes = container.SubordinateGroup.AttachedNodes;

                foreach (DiagramNode diagramNode in nodes)
                {
                    var rect = childrenShapeRect[diagramNode];



                    var x = (container.ActualWidth - (childrenSize[container].Width * scale.X) / 2);
                    var y = (container.ActualHeight - (childrenSize[container].Height * scale.Y) / 2);

                    rect.Scale(scale.X, scale.Y);

                    var newRectangle = new Rect(new Point(x, y), new Size(rect.Width, rect.Height));

                    Debug.WriteLine(rect.X + " x " + rect.Y);

                    diagramNode.SetBounds(newRectangle, false, false);
                    //diagramNode.Repaint(true);
                }
            }
        }
 

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


tech.support

Posts: 3147
Joined: Oct 19th, 2005
Re: Scale / resize nodes inside Container Node, while Container Node is resizing
Reply #3 - Aug 1st, 2017 at 10:03am
Print Post  
That's right, the container sets its children's positions a bit after your code. I think you will be able to inject your code without the container interfering in a custom behavior class, e.g. if normally using LinkShapes behavior, try a custom one like this -

Code
Select All
class ResizableGroupsBehavior: LinkShapesBehavior
{
	protected internal ResizableGroupsBehavior(Diagram diagram) : base(diagram)
	{
	}

	protected override void OnMouseMove(Point mousePosition)
	{
		base.OnMouseMove(mousePosition);

		var ist = Diagram.Interaction;
		if (ist != null && ist.Action == Action.Modify && ist.CurrentItem is ContainerNode)
		{
			// resize children here
		}
	}
} 



One of the AttachTo overloads makes child nodes resizable with group parent, I guess we could add respective ContainerNode.Add overload to let you do the same with containers out of the box.

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


tech.support

Posts: 3147
Joined: Oct 19th, 2005
Re: Scale / resize nodes inside Container Node, while Container Node is resizing
Reply #4 - Aug 1st, 2017 at 11:22am
Print Post  
This build will resize children automatically if you add them as below -
https://mindfusion.eu/_beta/ctr_resize.zip

Code
Select All
var ctr = diagram.Factory.CreateContainerNode(20, 20, 200, 200);
var node = diagram.Factory.CreateShapeNode(50, 50, 100, 100);
ctr.Add(node, AttachToNode.Proportional);
ctr.EnabledHandles = AdjustmentHandles.All;
ctr.HandlesStyle = HandlesStyle.DashFrame; 



We'll need to extend it for the official release, e.g. a property to specify default AttachToNode type for interactively added child nodes. At this time you could maybe remove interactively added child nodes from ContainerChildAdded event handler and add them anew as above to make them resizable.

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


I Love MindFusion!

Posts: 12
Joined: Jul 26th, 2017
Re: Scale / resize nodes inside Container Node, while Container Node is resizing
Reply #5 - Aug 1st, 2017 at 2:15pm
Print Post  
Thank you for your help.
When I am adding nodes created by factory it works very well, but unfortunately I need to drag shapes from the shape list, next, select and press group button which creates container node with children (selected shapes) which are scalable when container node is resizing. Do you think that staff is possible to do?

yesterday code almost works, but in the first step of resizing  one of the shape inside the container node is moving a little bit :/

Code
Select All
private void FlowChart_NodeModifying(object sender, NodeValidationEventArgs e)
      {

         if (e.Node.GetType() == typeof(ContainerNode))
         {
            var container = e.Node as ContainerNode;

            // Debug.WriteLine("Container first: " + childrenShapeRect[container].X + " x " + childrenShapeRect[container].Y);
            // Debug.WriteLine("Container after: " + container.Bounds.X + " x " + container.Bounds.Y);


            if (IsNodeResized(container))
            {
               if (container != null)
               {
                  var scale = Scale(container);
                  var nodes = container.SubordinateGroup.AttachedNodes;

                  var containerPoint = new Point(container.Bounds.X, container.Bounds.Y);

                  foreach (DiagramNode diagramNode in nodes)
                  {
                     var rect = childrenShapeRect[diagramNode];



                     var x = containerPoint.X + scale.X * (childrenShapeRect[diagramNode].X - containerPoint.X); //childrenShapeRect contains Bounds of every nodes in group
                     var y = containerPoint.Y + scale.Y * (childrenShapeRect[diagramNode].Y - containerPoint.Y); // containerPoint indicate the start point of container node


                     rect.Scale(scale.X, scale.Y);

                     var newRectangle = new Rect(new Size(rect.Width, rect.Height));

                     Debug.WriteLine(rect.X + " x " + rect.Y);

                     diagramNode.SetBounds(newRectangle, false, false);
                     diagramNode.Move(x, y);
                     container.Move(x, y);
                     //diagramNode.Repaint(false);
                  }
               }
            }
         }
      }

 



I'm going to check more deeply your previous advise.
Thanks Smiley
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3147
Joined: Oct 19th, 2005
Re: Scale / resize nodes inside Container Node, while Container Node is resizing
Reply #6 - Aug 2nd, 2017 at 1:20pm
Print Post  
It should be possible with existing nodes too, but if adding many of them you'd need to ensure the container is large enough to fit them before starting. Otherwise each added child might resize the container to fit it, and the current children will resize too. That's something we'll also need to handle in our code when dropping new children in such containers interactively.
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint