public Drawing.Point[] GetConnectionBezier(ParentChildConnection <Node <T> > connection)
        {
            var lineseg = this.GetConnectionLine(connection);

            var parent_attach_point = lineseg.Start;
            var child_attach_point  = lineseg.End;

            double scale = this.Options.LevelSeparation / 2.0;
            var    dif   = child_attach_point.Subtract(parent_attach_point).Multiply(scale);


            var handle_displacement = TreeLayout <T> .IsVertical(this.Options.Direction)
                                          ? new Drawing.Point(0, dif.Y)
                                          : new Drawing.Point(dif.X, 0);

            var h1 = parent_attach_point.Add(handle_displacement);
            var h2 = child_attach_point.Add(handle_displacement * (-1));

            return(new[] { parent_attach_point, h1, h2, child_attach_point });
        }
        private static Node <T> get_leftmost(Node <T> node, int level, int maxlevel)
        {
            if (level >= maxlevel)
            {
                return(node);
            }
            if (node.ChildCount == 0)
            {
                return(null);
            }

            foreach (var child in node.EnumChildren())
            {
                var leftmostDescendant = TreeLayout <T> .get_leftmost(child, level + 1, maxlevel);

                if (leftmostDescendant != null)
                {
                    return(leftmostDescendant);
                }
            }

            return(null);
        }
        private void apportion(Node <T> node, int level)
        {
            /*------------------------------------------------------
             * Clean up the positioning of small sibling subtrees.
             * Subtrees of a node are formed independently and
             * placed as close together as possible. By requiring
             * that the subtrees be rigid at the time they are put
             * together, we avoid the undesirable effects that can
             * accrue from positioning nodes rather than subtrees.
             *----------------------------------------------------*/

            var first_child = node.FirstChild;
            var first_child_left_neighbor = first_child.left_neighbor;
            int j = 1;

            for (int k = this.Options.MaximumDepth - level;
                 first_child != null && first_child_left_neighbor != null && j <= k;)
            {
                double modifier_sum_right = 0;
                double modifier_sum_left  = 0;
                var    right_ancestor     = first_child;
                var    left_ancestor      = first_child_left_neighbor;
                for (int l = 0; l < j; l++)
                {
                    right_ancestor      = right_ancestor.Parent;
                    left_ancestor       = left_ancestor.Parent;
                    modifier_sum_right += right_ancestor.modifier;
                    modifier_sum_left  += left_ancestor.modifier;
                }

                double total_gap = (first_child_left_neighbor.prelim_x + modifier_sum_left +
                                    this.GetNodeSize(first_child_left_neighbor) + this.Options.SubtreeSeparation) -
                                   (first_child.prelim_x + modifier_sum_right);
                if (total_gap > 0)
                {
                    var subtree_aux  = node;
                    int num_subtrees = 0;
                    for (; subtree_aux != null && subtree_aux != left_ancestor; subtree_aux = subtree_aux.LeftSibling)
                    {
                        num_subtrees++;
                    }

                    if (subtree_aux != null)
                    {
                        var    subtree_move_aux = node;
                        double single_gap       = total_gap / num_subtrees;
                        for (; subtree_move_aux != left_ancestor; subtree_move_aux = subtree_move_aux.LeftSibling)
                        {
                            subtree_move_aux.prelim_x += total_gap;
                            subtree_move_aux.modifier += total_gap;
                            total_gap -= single_gap;
                        }
                    }
                }
                j++;

                if (first_child.ChildCount == 0)
                {
                    first_child = TreeLayout <T> .get_leftmost(node, 0, j);
                }
                else
                {
                    first_child = first_child.FirstChild;
                }

                if (first_child != null)
                {
                    first_child_left_neighbor = first_child.left_neighbor;
                }
            }
        }