static int ChooseSeeds(IList <RectangleNode <T, P> > nodes, ref IRectangle <P> b0, ref int seed0)
        {
            double area = b0.Add(nodes[seed0].Rectangle).Area;

            for (int i = 2; i < nodes.Count; i++)
            {
                double area0 = b0.Add(nodes[i].Rectangle).Area;
                if (area0 > area)
                {
                    seed0 = i;
                    area  = area0;
                }
            }

            //Got the first seed seed0
            //Now looking for a seed for the second group
            int seed1 = 0; //the compiler forces me to init it

            //init seed1
            for (int i = 0; i < nodes.Count; i++)
            {
                if (i != seed0)
                {
                    seed1 = i;
                    break;
                }
            }

            area = nodes[seed0].Rectangle.Add(nodes[seed1].Rectangle).Area;
            //Now try to improve the second seed

            for (int i = 0; i < nodes.Count; i++)
            {
                if (i == seed0)
                {
                    continue;
                }
                double area1 = nodes[seed0].Rectangle.Add(nodes[i].Rectangle).Area;
                if (area1 > area)
                {
                    seed1 = i;
                    area  = area1;
                }
            }
            return(seed1);
        }
        static void DivideNodes(IList <RectangleNode <T, P> > nodes, int seed0, int seed1, List <RectangleNode <T, P> > gr0, List <RectangleNode <T, P> > gr1,
                                ref IRectangle <P> box0, ref IRectangle <P> box1, int groupSplitThreshold)
        {
            for (int i = 0; i < nodes.Count; i++)
            {
                if (i == seed0 || i == seed1)
                {
                    continue;
                }

// ReSharper disable InconsistentNaming
                var    box0_  = box0.Add(nodes[i].Rectangle);
                double delta0 = box0_.Area - box0.Area;

                var    box1_  = box1.Add(nodes[i].Rectangle);
                double delta1 = box1_.Area - box1.Area;
// ReSharper restore InconsistentNaming

                //keep the tree roughly balanced

                if (gr0.Count * groupSplitThreshold < gr1.Count)
                {
                    gr0.Add(nodes[i]);
                    box0 = box0_;
                }
                else if (gr1.Count * groupSplitThreshold < gr0.Count)
                {
                    gr1.Add(nodes[i]);
                    box1 = box1_;
                }
                else if (delta0 < delta1)
                {
                    gr0.Add(nodes[i]);
                    box0 = box0_;
                }
                else if (delta1 < delta0)
                {
                    gr1.Add(nodes[i]);
                    box1 = box1_;
                }
                else if (box0.Area < box1.Area)
                {
                    gr0.Add(nodes[i]);
                    box0 = box0_;
                }
                else
                {
                    gr1.Add(nodes[i]);
                    box1 = box1_;
                }
            }
        }
        private void UpdateIcon()
        {
            //special treatment for root
            if (FBackground.Parent is IDot && !FViewer.ShowRoot)
            {
                return;
            }

            FIcon.Clear();
            FIcon.Brush    = null;
            FIcon.Position = new PointF(3, 3);
            FIcon.Visible  = false;

            if (FDecoratable != null)
            {
                if (FDecoratable.Icon > NodeIcon.None)
                {
                    FIcon.Visible = true;

                    if (FDecoratable.Icon == NodeIcon.GUI || FDecoratable.Icon == NodeIcon.GUICode || FDecoratable.Icon == NodeIcon.GUIPatch)
                    {
                        FIcon.Pen  = FTextColor;
                        FIcon.Size = new SizeF(16, 12);
                    }
                    if (FDecoratable.Icon == NodeIcon.Patch || FDecoratable.Icon == NodeIcon.GUIPatch)
                    {
                        var n = FCanvas.CreateRectangle(null);
                        n.Pen      = FTextColor;
                        n.Size     = new SizeF(8, 2);
                        n.Position = new PointF(3, 2);
                        FIcon.Add(n);
                        n          = FCanvas.CreateRectangle(null);
                        n.Pen      = FTextColor;
                        n.Size     = new SizeF(8, 2);
                        n.Position = new PointF(6, 5);
                        FIcon.Add(n);
                        n          = FCanvas.CreateRectangle(null);
                        n.Pen      = FTextColor;
                        n.Size     = new SizeF(8, 2);
                        n.Position = new PointF(3, 8);
                        FIcon.Add(n);
                    }

                    if (FDecoratable.Icon == NodeIcon.Code || FDecoratable.Icon == NodeIcon.GUICode)
                    {
                        IPolygon line;
                        var      y = 3;
                        for (int i = 0; i < 4; i++)
                        {
                            line          = FCanvas.CreatePoly(null);
                            line.IsClosed = false;
                            line.Pen      = FTextColor;
                            line.Brush    = null;
                            line.Points.Add(new PointF(3, y));
                            if (i == 0)
                            {
                                line.Points.Add(new PointF(7, y));
                            }
                            else
                            {
                                line.Points.Add(new PointF(13, y));
                            }
                            FIcon.Add(line);
                            y += 2;
                        }
                    }

                    if (FDecoratable.Icon == NodeIcon.Comment)
                    {
                        IPolygon line;
                        line          = FCanvas.CreatePoly(null);
                        line.IsClosed = false;
                        line.Pen      = FTextColor;
                        line.Brush    = null;
                        line.Points.Add(new PointF(5, 12));
                        line.Points.Add(new PointF(7, 0));
                        FIcon.Add(line);

                        line          = FCanvas.CreatePoly(null);
                        line.IsClosed = false;
                        line.Pen      = FTextColor;
                        line.Brush    = null;
                        line.Points.Add(new PointF(7, 12));
                        line.Points.Add(new PointF(9, 0));
                        FIcon.Add(line);
                    }

                    if (FDecoratable.Icon == NodeIcon.IONode)
                    {
                        IPolygon line;
                        line          = FCanvas.CreatePoly(null);
                        line.IsClosed = false;
                        line.Pen      = FTextColor;
                        line.Brush    = null;
                        line.Points.Add(new PointF(2, 2));
                        line.Points.Add(new PointF(2, 10));
                        FIcon.Add(line);

                        ICircle circle;
                        circle = FCanvas.CreateCircle(null);
                        circle.PositionMode = PositionMode.Center;
                        circle.Pen          = FTextColor;
                        circle.Brush        = null;
                        circle.Position     = new PointF(8, 6);
                        circle.Radius       = 4;
                        FIcon.Add(circle);
                    }
                }
            }
        }
        public MapperHierarchyNode(ModelMapper mapper, ICanvas canvas, IGraphElement parent, HierarchyViewer viewer)
            : base()
        {
            Mapper  = mapper;
            FCanvas = canvas;
            FViewer = viewer;

            MouseClick       += FViewer.MouseClickHandler;
            MouseDoubleClick += FViewer.MouseDoubleClickHandler;
            Tag = mapper.Model;

            //graphelements
            FBackground = canvas.CreateRectangle(this);
            FPoly       = canvas.CreatePoly(this);
            FText       = canvas.CreateText(null, "");
            FIcon       = FCanvas.CreateRectangle(null);

            parent.Add(FBackground);
            FBackground.Add(FPoly);
            FBackground.Add(FText);
            FBackground.Add(FIcon);

            //compute level of depth
            IGraphElement p = FBackground;

            while (p.Parent != null)
            {
                FDepth++;
                p = p.Parent;
            }
            FDepth -= 1;

            //init static properties via Mapper
            if (Mapper.CanMap <ISelectable>())
            {
                FSelectable = Mapper.Map <ISelectable>();
                FSelectable.SelectionChanged += selectable_SelectionChanged;
                Selected = FSelectable.Selected;
            }

            if (Mapper.CanMap <IDecoratable>())
            {
                FDecoratable = Mapper.Map <IDecoratable>();
                FDecoratable.DecorationChanged += decorated_DecorationChanged;
            }

            if (Mapper.CanMap <ILinkSource>())
            {
                FLinkSource = Mapper.Map <ILinkSource>();

                FLinkSourceRectangle = FCanvas.CreateRectangle(null);
                FBackground.Add(FLinkSourceRectangle);
                FLinkOffset = FTextOffset;
            }

            if (Mapper.CanMap <ILinkSink>())
            {
                FLinkSink = Mapper.Map <ILinkSink>();

                FLinkSinkRectangle = FCanvas.CreateRectangle(null);
                FBackground.Add(FLinkSinkRectangle);
            }

            if (Mapper.CanMap <INamed>())
            {
                FNamed          = Mapper.Map <INamed>();
                FNamed.Renamed += named_Renamed;
                SetCaption(FNamed.Name);
            }

            if (Mapper.CanMap <IParent>())
            {
                var node = Mapper.Map <IParent>();
                if (node.Childs != null)
                {
                    // Keep Nodes and items in sync
                    FSynchronizer         = FSubTree.SyncWith(node.Childs, CreateChildNode);
                    FSynchronizer.Synced += synchronizer_Synced;
                }
            }

            //init dynamic properties via Mapper
            UpdateColors();
            UpdateIcon();
            UpdateLinkSink();
            UpdateLinkSource();
        }