static void RemoveNodeShapes(Canvas nodeCanvas)
        {
            NodeCanvasData ncDInst = curNodesOnLayout[nodeCanvas];

            if (ncDInst.heirsPivot != null)
            {
                Border borderToDel = (Border)ncDInst.heirsPivot.Parent;
                workspaceCanvas.Children.Remove(borderToDel);
                borderToDel = null;
            }
            if (ncDInst.parentPivot != null)
            {
                workspaceCanvas.Children.Remove(ncDInst.parentPivot);
                ncDInst.parentPivot = null;
            }
            List <Polyline> relations = ncDInst.relations;

            if (relations != null && relations.Count > 0)
            {
                for (int i = 0; i < relations.Count; i++)
                {
                    if (relations[i] != null && relations[i].Points != null)
                    {
                        while (relations[i].Points.Count > 0)
                        {
                            relations[i].Points.Remove(relations[i].Points.Take(1).ToArray()[0]);
                        }
                    }
                    workspaceCanvas.Children.Remove(relations[i]);
                    relations[i] = null;
                }
            }
        }
        static void DelNodeFromParents(Canvas canvNodeToDel)
        {
            HashSet <Node> parentNodes = GetCanvasNodeData(canvNodeToDel).node.parents;

            if (parentNodes.Count > 0)
            {
                foreach (Node parent in parentNodes)
                {
                    if (parent.heirs.Count > 0)
                    {
                        foreach (Heir heir in parent.heirs)
                        {
                            if (heir.heirNode.canvas.Equals(canvNodeToDel))
                            {
                                parent.heirs.Remove(heir);
                                NodeCanvasData parentNCDInst = GetCanvasNodeData(parent.canvas);
                                parentNCDInst.isCanvasChanged = true;
                                workspaceCanvas.Children.Remove((Border)parentNCDInst.heirsTextBlocks[heir.heirNode.canvas].Parent);
                                parentNCDInst.heirsTextBlocks.Remove(heir.heirNode.canvas);
                                DelNodeFromParents(canvNodeToDel);
                                return;
                            }
                        }
                    }
                }
            }
        }
        //>>>
        //calls from MainWindow
        public static void ToPositionTheNodeCanvas()
        {
            CheckNodes();
            float          x       = mouseLastPos.X - nodeCanvOffsVector.X;
            float          y       = mouseLastPos.Y - nodeCanvOffsVector.Y;
            NodeCanvasData nCDinst = GetCanvasNodeData(curManipulatingCanvas);

            nCDinst.isCanvasChanged = IsNodeCanvasPosChanged(curManipulatingCanvas, new PointF(x, y));
            Canvas.SetLeft(curManipCanvBorder, x);
            Canvas.SetTop(curManipCanvBorder, y);

            foreach (Node parentNode in nCDinst.node.parents)
            {
                GetCanvasNodeData(parentNode.canvas).isCanvasChanged = true;
            }
        }
        public static Canvas CreateNodeHeir(Node parentNode, string branchText)
        {
            Node heirNode = parentNode.AddHeir("new heir's branch text", "new heir content");

            heirNode.AddParent(parentNode);

            Canvas parentCanvas     = parentNode.canvas;
            Border nodeCanvasBorder = (Border)parentCanvas.Parent;
            PointF heirCanvasPos    = new PointF((float)Canvas.GetLeft(nodeCanvasBorder), (float)(Canvas.GetTop(nodeCanvasBorder) + parentCanvas.Height + 70));
            Canvas heirCanvas       = InstantiateNodeCanvas(heirNode, heirCanvasPos);


            TextBlock branchTextBlock = InstantiateBranchTextBlock(branchText);

            NodeCanvasData parentNCDInst = GetCanvasNodeData(parentCanvas);

            parentNCDInst.heirsTextBlocks.Add(heirCanvas, branchTextBlock);
            parentNCDInst.isCanvasChanged = true;
            return(heirCanvas);
        }
        private static void nodeCanvas_RightMouseUp(object sender, MouseEventArgs e)
        {
            Canvas nodeCanvas = (Canvas)sender;

            switch (mWInst.workspaceCondition)
            {
            case MainWindow.WorkspaceConditions.fromParentToHeirRelationPositioniong:
                NodeCanvasData parentNCDInst = GetCanvasNodeData(curManipulatingCanvas);
                if (!parentNCDInst.heirsTextBlocks.ContainsKey(nodeCanvas))
                {
                    TextBlock branchTextBlock = InstantiateBranchTextBlock("branch text");
                    parentNCDInst.heirsTextBlocks.Add(nodeCanvas, branchTextBlock);
                    GetCanvasNodeData(nodeCanvas).node.AddParent(parentNCDInst.node);
                    parentNCDInst.node.AddHeir("branch text", GetCanvasNodeData(nodeCanvas).node);
                    mWInst.workspaceCondition = MainWindow.WorkspaceConditions.nothingHappens;
                    GetCanvasNodeData(curManipulatingCanvas).isCanvasChanged = true;
                    workspaceCanvas.Children.Remove(curDrawingPoyline);
                }
                break;

            default:
                break;
            }
        }
        //создание визуальных элементов узла
        static Canvas InstantiateNodeCanvas(Node node, PointF nodeCanvasPos)
        {
            //the border, that embrace node canvas
            Border nodeBorder = new Border()
            {
                CornerRadius = new CornerRadius(5), BorderThickness = new Thickness(1), BorderBrush = System.Windows.Media.Brushes.Black
            };

            //canvas, that visually represent corresponding node
            Canvas nodeCanvas = new Canvas();

            nodeCanvas.MouseLeftButtonDown += new MouseButtonEventHandler(nodeCanvas_LeftMouseDown);
            nodeCanvas.MouseLeftButtonUp   += new MouseButtonEventHandler(nodeCanvas_LeftMouseUp);
            nodeCanvas.MouseEnter          += new MouseEventHandler(nodeCanvas_MouseEnter);
            nodeCanvas.MouseLeave          += new MouseEventHandler(nodeCanvas_MouseLeave);
            nodeCanvas.MouseRightButtonUp  += new MouseButtonEventHandler(nodeCanvas_RightMouseUp);
            nodeCanvas.Width      = 200;
            nodeCanvas.Height     = 100;
            nodeCanvas.Margin     = new Thickness(1);
            nodeCanvas.Background = System.Windows.Media.Brushes.LightGray;
            workspaceCanvas.Children.Add(nodeBorder);
            Canvas.SetZIndex(nodeBorder, 30000);
            nodeBorder.Child = nodeCanvas;
            Canvas.SetTop(nodeBorder, nodeCanvasPos.Y);
            Canvas.SetLeft(nodeBorder, nodeCanvasPos.X);

            //text block, containing the text of the node
            TextBlock demoTextBlock = new TextBlock();

            demoTextBlock.Text         = "The first few lines of the node content";
            demoTextBlock.TextWrapping = TextWrapping.Wrap;
            nodeCanvas.Children.Add(demoTextBlock);
            demoTextBlock.Width                = 150;
            demoTextBlock.Height               = 35;
            demoTextBlock.Background           = System.Windows.Media.Brushes.White;
            demoTextBlock.MouseLeftButtonDown += new MouseButtonEventHandler(nodeTextBlock_LeftMouseDown);
            Canvas.SetLeft(demoTextBlock, 5);
            Canvas.SetTop(demoTextBlock, 5);

            //visual separation block
            nodeCanvas.Children.Add(new Line()
            {
                X1 = 0, Y1 = 50, X2 = 200, Y2 = 50, Stroke = System.Windows.Media.Brushes.Black
            });

            //defenition of the button, deleting canvas
            Button deleteNodeButton = new Button();

            deleteNodeButton.Width  = 35;
            deleteNodeButton.Height = 35;
            nodeCanvas.Children.Add(deleteNodeButton);
            deleteNodeButton.Click += new RoutedEventHandler(nodeDelButton_Click);
            Canvas.SetRight(deleteNodeButton, 5);
            Canvas.SetTop(deleteNodeButton, 5);
            //del button content
            Canvas delButContCanvas = new Canvas();

            delButContCanvas.Width  = deleteNodeButton.Width * .8f;
            delButContCanvas.Height = deleteNodeButton.Height * .8f;
            ImageBrush ib = new ImageBrush();

            ib.ImageSource = new BitmapImage(new Uri("C:/Users/Nikita/Source/Repos/StoryCreator/StoryCreator/Images/delIcon.png", UriKind.Absolute));
            delButContCanvas.Background = ib;
            deleteNodeButton.Content    = delButContCanvas;

            //defenition of the button, adding new node
            Button addHeirButton = new Button();

            addHeirButton.Width  = 35;
            addHeirButton.Height = 35;
            nodeCanvas.Children.Add(addHeirButton);
            addHeirButton.Click += new RoutedEventHandler(nodeAddHeirButton_Click);
            Canvas.SetLeft(addHeirButton, 5);
            Canvas.SetBottom(addHeirButton, 5);
            //add button content
            Canvas addHeirButContCanvas = new Canvas();

            addHeirButContCanvas.Width  = addHeirButton.Width * .8f;
            addHeirButContCanvas.Height = addHeirButton.Height * .8f;
            ImageBrush ib1 = new ImageBrush();

            ib1.ImageSource = new BitmapImage(new Uri("C:/Users/Nikita/Source/Repos/StoryCreator/StoryCreator/Images/addIcon.png", UriKind.Absolute));
            addHeirButContCanvas.Background = ib1;
            addHeirButton.Content           = addHeirButContCanvas;

            NodeCanvasData nCDInst = new NodeCanvasData(node);

            node.canvas = nodeCanvas;

            nCDInst.isCanvasChanged = true;
            curNodesOnLayout.Add(nodeCanvas, nCDInst);
            Canvas.SetZIndex(nodeCanvas, 30000);
            RepaintNodeShapes(nodeCanvas);

            return(nodeCanvas);
        }
        static void RepaintNodeShapes(Canvas nodeCanvas)
        {
            Border nodeCanvasBorder = (Border)nodeCanvas.Parent;

            RemoveNodeShapes(nodeCanvas);
            NodeCanvasData ncDInst = GetCanvasNodeData(nodeCanvas);
            Node           node    = ncDInst.node;

            Border rectBorder = new Border()
            {
                CornerRadius = new CornerRadius(2), BorderThickness = new Thickness(1), BorderBrush = System.Windows.Media.Brushes.Black
            };

            System.Windows.Shapes.Rectangle heirsPivotRect = new System.Windows.Shapes.Rectangle()
            {
                Stroke = new SolidColorBrush(Colors.Black), Fill = new SolidColorBrush(Colors.IndianRed), Width = 25, Height = 25
            };
            Canvas.SetLeft(rectBorder, Canvas.GetLeft(nodeCanvasBorder) + .5f * nodeCanvasBorder.ActualWidth - 12.5f);
            Canvas.SetTop(rectBorder, Canvas.GetTop(nodeCanvasBorder) + nodeCanvasBorder.ActualHeight);
            heirsPivotRect.MouseEnter           += new MouseEventHandler(canvasRedRect_MouseEnter);
            heirsPivotRect.MouseLeave           += new MouseEventHandler(canvasRedRect_MouseLeave);
            heirsPivotRect.MouseLeftButtonDown  += new MouseButtonEventHandler(canvasRedRect_LeftMouseDown);
            heirsPivotRect.MouseRightButtonDown += new MouseButtonEventHandler(canvasRedRect_RightMouseDown);
            rectBorder.Child = heirsPivotRect;
            workspaceCanvas.Children.Add(rectBorder);
            Canvas.SetZIndex(rectBorder, 10000);
            ncDInst.heirsPivot = heirsPivotRect;

            Ellipse parentPivotEllipse = new Ellipse()
            {
                Stroke = new SolidColorBrush(Colors.Black), Fill = new SolidColorBrush(Colors.CadetBlue), Width = 25, Height = 25
            };

            Canvas.SetLeft(parentPivotEllipse, Canvas.GetLeft(nodeCanvasBorder) + .5f * nodeCanvas.Width - 12.5f);
            Canvas.SetTop(parentPivotEllipse, Canvas.GetTop(nodeCanvasBorder) - 25);
            workspaceCanvas.Children.Add(parentPivotEllipse);
            Canvas.SetZIndex(parentPivotEllipse, 20000);
            ncDInst.parentPivot = parentPivotEllipse;

            if (node.heirs != null && node.heirs.Count > 0)
            {
                List <Canvas> heirsCanvases = new List <Canvas>();
                foreach (Heir heir in node.heirs)
                {
                    heirsCanvases.Add(curNodesOnLayout.Where(el => el.Value.node.Equals(heir.heirNode)).ToArray()[0].Key);
                }
                for (int i = 0; i < heirsCanvases.Count; i++)
                {
                    Border   heirCanvBorder = (Border)heirsCanvases[i].Parent;
                    Polyline newPLine;
                    PointF   p0, p1, p2, p3;
                    p1 = new PointF((float)(Canvas.GetLeft(nodeCanvasBorder) + .5f * nodeCanvasBorder.ActualWidth), (float)(Canvas.GetTop(nodeCanvasBorder) + nodeCanvasBorder.ActualHeight + ncDInst.heirsPivot.ActualHeight * .5f));
                    p2 = new PointF((float)(Canvas.GetLeft(heirCanvBorder) + .5f * (heirCanvBorder).ActualWidth), (float)(Canvas.GetTop(heirCanvBorder) - GetCanvasNodeData(heirsCanvases[i]).parentPivot.ActualHeight * .5f));
                    if (!nodeCanvasBorder.Equals(heirCanvBorder))
                    {
                        p0       = new PointF(p1.X, (float)Canvas.GetTop(nodeCanvasBorder));
                        p3       = new PointF(p2.X, (float)(Canvas.GetTop(heirCanvBorder) + (heirCanvBorder).ActualHeight));
                        newPLine = RelationsDrawer.ConstructPolyline(p0, p1, p2, p3);
                    }
                    else
                    {
                        p0       = new PointF(p1.X, p1.Y - 100f);
                        p3       = new PointF(p2.X, p2.Y + 100f);
                        newPLine = RelationsDrawer.ConstructPolyline(p0, p1, p2, p3, true);
                    }

                    int midIndex = (int)(newPLine.Points.Count * .5f);

                    AddArrowsToPolyline(newPLine);

                    newPLine.MouseEnter += new MouseEventHandler(relation_MouseEnter);
                    newPLine.MouseLeave += new MouseEventHandler(relation_MouseLeave);
                    System.Windows.Point textBlockPos = newPLine.Points.ToArray()[midIndex];

                    Border tmpBorder = (Border)GetBranchTextBlock(nodeCanvas, heirsCanvases[i]).Parent;
                    Canvas.SetLeft(tmpBorder, textBlockPos.X - tmpBorder.ActualWidth * .5f);
                    Canvas.SetTop(tmpBorder, textBlockPos.Y);

                    ncDInst.relations.Add(newPLine);
                    workspaceCanvas.Children.Add(newPLine);
                    Canvas.SetZIndex(newPLine, 0);
                }
            }
        }