Ejemplo n.º 1
0
        //tree specific properties

        /// <summary>
        /// Commits the position of the link to the corresponding Link.
        /// </summary>
        /// <remarks>
        /// This routes the Link's Route.
        /// </remarks>
        public override void CommitPosition()
        {
            Route s = this.Route;

            if (s == null)
            {
                return;
            }
            if (s.Routing == LinkRouting.AvoidsNodes)
            {
                return;
            }

            TreeLayout layout = this.Network.Layout;
            TreeVertex parent;
            TreeVertex child;

            switch (layout.Path)
            {
            case TreePath.Destination: parent = this.FromVertex; child = this.ToVertex; break;

            case TreePath.Source: parent = this.ToVertex; child = this.FromVertex; break;

            default: throw new InvalidOperationException("Unhandled Path value " + layout.Path.ToString());
            }
            if (parent == null || child == null)
            {
                return;
            }

            Point p = this.RelativePoint;

            if (p.X == 0 && p.Y == 0 && !parent.RouteFirstRow) // no rows
            {
                AdjustRouteForAngleChange(parent, child);
                return;
            }
            bool   firstrow     = (p.X == 0 && p.Y == 0 && parent.RouteFirstRow);
            Node   node         = parent.Node;
            Rect   nodebounds   = node.Bounds;
            double angle        = TreeLayout.OrthoAngle(parent);
            double layerspacing = TreeLayout.ComputeLayerSpacing(parent);
            double rowspacing   = parent.RowSpacing;

            s.UpdatePoints();
            bool  bezier = s.Curve == LinkCurve.Bezier;
            bool  ortho  = s.Orthogonal;
            int   idx;
            Point prev;
            Point next;
            Point last;

            if (ortho || bezier)
            {
                idx = 2;
                while (s.PointsCount > 4)
                {
                    s.RemovePoint(2);
                }
                prev = s.GetPoint(1);
                next = s.GetPoint(2);
            }
            else
            {
                idx = 1;
                while (s.PointsCount > 3)
                {
                    s.RemovePoint(1);
                }
                prev = s.GetPoint(0);
                next = s.GetPoint(s.PointsCount - 1);
            }
            last = s.GetPoint(s.PointsCount - 1);
            if (angle == 0)
            {
                double c;
                if (parent.Alignment == TreeAlignment.End)
                {
                    // route around at Y coordinate relative to the bottom of the parent node
                    c = nodebounds.Bottom + p.Y;
                    // try to keep the links straight from the parent node -- consider room from RowIndent and NodeIndent
                    if (p.Y == 0 && prev.Y > last.Y + parent.RowIndent)
                    {
                        c = Math.Min(c, Math.Max(prev.Y, c - TreeLayout.ComputeNodeIndent(parent)));
                    }
                }
                else if (parent.Alignment == TreeAlignment.Start)
                {
                    // route around at Y coordinate relative to the top of the parent node
                    c = nodebounds.Top + p.Y;
                    // try to keep the links straight from the parent node -- consider room from RowIndent and NodeIndent
                    if (p.Y == 0 && prev.Y < last.Y - parent.RowIndent)
                    {
                        c = Math.Max(c, Math.Min(prev.Y, c + TreeLayout.ComputeNodeIndent(parent)));
                    }
                }
                else if (parent.RouteAroundCentered || (parent.RouteAroundLastParent && parent.MaxGenerationCount == 1))
                {
                    c = nodebounds.Top - parent.SubtreeOffset.Y + p.Y;
                }
                else
                {
                    c = nodebounds.Y + nodebounds.Height / 2 + p.Y;
                }
                if (bezier) // curved segments
                {
                    if (!firstrow)
                    {
                        // add a straight curve at Y-coord C
                        s.InsertPoint(idx, new Point(prev.X, c)); idx++;
                        s.InsertPoint(idx, new Point(nodebounds.Right + layerspacing, c)); idx++;
                        s.InsertPoint(idx, new Point(nodebounds.Right + layerspacing + (p.X - rowspacing) / 3, c)); idx++;
                        s.InsertPoint(idx, new Point(nodebounds.Right + layerspacing + (p.X - rowspacing) * 2 / 3, c)); idx++;
                    }
                    else
                    {
                        s.InsertPoint(idx, new Point(nodebounds.Right + layerspacing + (p.X - rowspacing), c)); idx++;
                    }
                    s.InsertPoint(idx, new Point(nodebounds.Right + layerspacing + (p.X - rowspacing), c)); idx++;
                    s.InsertPoint(idx, new Point(next.X, c)); idx++;
                }
                else // straight line segments
                {
                    if (ortho)
                    {
                        s.InsertPoint(idx, new Point(nodebounds.Right + layerspacing / 2, prev.Y)); idx++;
                    }
                    s.InsertPoint(idx, new Point(nodebounds.Right + layerspacing / 2, c)); idx++;
                    s.InsertPoint(idx, new Point(nodebounds.Right + layerspacing + p.X - (ortho ? rowspacing / 2 : rowspacing), c)); idx++;
                    if (ortho)
                    {
                        s.InsertPoint(idx, new Point(s.GetPoint(idx - 1).X, next.Y)); idx++;
                    }
                }
            }
            else if (angle == 90)
            {
                double c;
                if (parent.Alignment == TreeAlignment.End)
                {
                    c = nodebounds.Right + p.X;
                    if (p.X == 0 && prev.X > last.X + parent.RowIndent)
                    {
                        c = Math.Min(c, Math.Max(prev.X, c - TreeLayout.ComputeNodeIndent(parent)));
                    }
                }
                else if (parent.Alignment == TreeAlignment.Start)
                {
                    c = nodebounds.Left + p.X;
                    if (p.X == 0 && prev.X < last.X - parent.RowIndent)
                    {
                        c = Math.Max(c, Math.Min(prev.X, c + TreeLayout.ComputeNodeIndent(parent)));
                    }
                }
                else if (parent.RouteAroundCentered || (parent.RouteAroundLastParent && parent.MaxGenerationCount == 1))
                {
                    c = nodebounds.Left - parent.SubtreeOffset.X + p.X;
                }
                else
                {
                    c = nodebounds.X + nodebounds.Width / 2 + p.X;
                }
                if (bezier)
                {
                    if (!firstrow)
                    {
                        s.InsertPoint(idx, new Point(c, prev.Y)); idx++;
                        s.InsertPoint(idx, new Point(c, nodebounds.Bottom + layerspacing)); idx++;
                        s.InsertPoint(idx, new Point(c, nodebounds.Bottom + layerspacing + (p.Y - rowspacing) / 3)); idx++;
                        s.InsertPoint(idx, new Point(c, nodebounds.Bottom + layerspacing + (p.Y - rowspacing) * 2 / 3)); idx++;
                    }
                    else
                    {
                        s.InsertPoint(idx, new Point(c, nodebounds.Bottom + layerspacing + (p.Y - rowspacing))); idx++;
                    }
                    s.InsertPoint(idx, new Point(c, nodebounds.Bottom + layerspacing + (p.Y - rowspacing))); idx++;
                    s.InsertPoint(idx, new Point(c, next.Y)); idx++;
                }
                else
                {
                    if (ortho)
                    {
                        s.InsertPoint(idx, new Point(prev.X, nodebounds.Bottom + layerspacing / 2)); idx++;
                    }
                    s.InsertPoint(idx, new Point(c, nodebounds.Bottom + layerspacing / 2)); idx++;
                    s.InsertPoint(idx, new Point(c, nodebounds.Bottom + layerspacing + p.Y - (ortho ? rowspacing / 2 : rowspacing))); idx++;
                    if (ortho)
                    {
                        s.InsertPoint(idx, new Point(next.X, s.GetPoint(idx - 1).Y)); idx++;
                    }
                }
            }
            else if (angle == 180)
            {
                double c;
                if (parent.Alignment == TreeAlignment.End)
                {
                    c = nodebounds.Bottom + p.Y;
                    if (p.Y == 0 && prev.Y > last.Y + parent.RowIndent)
                    {
                        c = Math.Min(c, Math.Max(prev.Y, c - TreeLayout.ComputeNodeIndent(parent)));
                    }
                }
                else if (parent.Alignment == TreeAlignment.Start)
                {
                    c = nodebounds.Top + p.Y;
                    if (p.Y == 0 && prev.Y < last.Y - parent.RowIndent)
                    {
                        c = Math.Max(c, Math.Min(prev.Y, c + TreeLayout.ComputeNodeIndent(parent)));
                    }
                }
                else if (parent.RouteAroundCentered || (parent.RouteAroundLastParent && parent.MaxGenerationCount == 1))
                {
                    c = nodebounds.Top - parent.SubtreeOffset.Y + p.Y;
                }
                else
                {
                    c = nodebounds.Y + nodebounds.Height / 2 + p.Y;
                }
                if (bezier)
                {
                    if (!firstrow)
                    {
                        s.InsertPoint(idx, new Point(prev.X, c)); idx++;
                        s.InsertPoint(idx, new Point(nodebounds.Left - layerspacing, c)); idx++;
                        s.InsertPoint(idx, new Point(nodebounds.Left - layerspacing + (p.X + rowspacing) / 3, c)); idx++;
                        s.InsertPoint(idx, new Point(nodebounds.Left - layerspacing + (p.X + rowspacing) * 2 / 3, c)); idx++;
                    }
                    else
                    {
                        s.InsertPoint(idx, new Point(nodebounds.Left - layerspacing + (p.X + rowspacing), c)); idx++;
                    }
                    s.InsertPoint(idx, new Point(nodebounds.Left - layerspacing + (p.X + rowspacing), c)); idx++;
                    s.InsertPoint(idx, new Point(next.X, c)); idx++;
                }
                else
                {
                    if (ortho)
                    {
                        s.InsertPoint(idx, new Point(nodebounds.Left - layerspacing / 2, prev.Y)); idx++;
                    }
                    s.InsertPoint(idx, new Point(nodebounds.Left - layerspacing / 2, c)); idx++;
                    s.InsertPoint(idx, new Point(nodebounds.Left - layerspacing + p.X + (ortho ? rowspacing / 2 : rowspacing), c)); idx++;
                    if (ortho)
                    {
                        s.InsertPoint(idx, new Point(s.GetPoint(idx - 1).X, next.Y)); idx++;
                    }
                }
            }
            else if (angle == 270)
            {
                double c;
                if (parent.Alignment == TreeAlignment.End)
                {
                    c = nodebounds.Right + p.X;
                    if (p.X == 0 && prev.X > last.X + parent.RowIndent)
                    {
                        c = Math.Min(c, Math.Max(prev.X, c - TreeLayout.ComputeNodeIndent(parent)));
                    }
                }
                else if (parent.Alignment == TreeAlignment.Start)
                {
                    c = nodebounds.Left + p.X;
                    if (p.X == 0 && prev.X < last.X - parent.RowIndent)
                    {
                        c = Math.Max(c, Math.Min(prev.X, c + TreeLayout.ComputeNodeIndent(parent)));
                    }
                }
                else if (parent.RouteAroundCentered || (parent.RouteAroundLastParent && parent.MaxGenerationCount == 1))
                {
                    c = nodebounds.Left - parent.SubtreeOffset.X + p.X;
                }
                else
                {
                    c = nodebounds.X + nodebounds.Width / 2 + p.X;
                }
                if (bezier)
                {
                    if (!firstrow)
                    {
                        s.InsertPoint(idx, new Point(c, prev.Y)); idx++;
                        s.InsertPoint(idx, new Point(c, nodebounds.Top - layerspacing)); idx++;
                        s.InsertPoint(idx, new Point(c, nodebounds.Top - layerspacing + (p.Y + rowspacing) / 3)); idx++;
                        s.InsertPoint(idx, new Point(c, nodebounds.Top - layerspacing + (p.Y + rowspacing) * 2 / 3)); idx++;
                    }
                    else
                    {
                        s.InsertPoint(idx, new Point(c, nodebounds.Top - layerspacing + (p.Y + rowspacing))); idx++;
                    }
                    s.InsertPoint(idx, new Point(c, nodebounds.Top - layerspacing + (p.Y + rowspacing))); idx++;
                    s.InsertPoint(idx, new Point(c, next.Y)); idx++;
                }
                else
                {
                    if (ortho)
                    {
                        s.InsertPoint(idx, new Point(prev.X, nodebounds.Top - layerspacing / 2)); idx++;
                    }
                    s.InsertPoint(idx, new Point(c, nodebounds.Top - layerspacing / 2)); idx++;
                    s.InsertPoint(idx, new Point(c, nodebounds.Top - layerspacing + p.Y + (ortho ? rowspacing / 2 : rowspacing))); idx++;
                    if (ortho)
                    {
                        s.InsertPoint(idx, new Point(next.X, s.GetPoint(idx - 1).Y)); idx++;
                    }
                }
            }
            else
            {
                throw new InvalidOperationException("Invalid angle " + angle.ToString(System.Globalization.CultureInfo.InvariantCulture));
            }
        }