Пример #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));
            }
        }
Пример #2
0
        private void AdjustRouteForAngleChange(TreeVertex parent, TreeVertex child)
        {
            double angle      = TreeLayout.OrthoAngle(parent);
            double childangle = TreeLayout.OrthoAngle(child);

            if (angle == childangle)
            {
                return;
            }
            double layerspacing = TreeLayout.ComputeLayerSpacing(parent);
            Rect   pb           = parent.Node.Bounds;
            Rect   cb           = child.Node.Bounds;

            // but maybe an Angle change causes the child node not to be adjacent to the layer
            // separating it with the parent node; only need to do anything if that's the case
            if ((angle == 0 && cb.Left - pb.Right < layerspacing + 1) ||
                (angle == 90 && cb.Top - pb.Bottom < layerspacing + 1) ||
                (angle == 180 && pb.Left - cb.Right < layerspacing + 1) ||
                (angle == 270 && pb.Top - cb.Bottom < layerspacing + 1))
            {
                return;
            }

            Route s = this.Route;

            s.UpdatePoints();
            bool bezier = s.Curve == LinkCurve.Bezier;
            bool ortho  = s.Orthogonal;

            if (angle == 0)
            {
                double x = pb.Right + layerspacing / 2;
                if (bezier) // curved segments
                {
                    if (s.PointsCount == 4)
                    {
                        double y = s.GetPoint(3).Y;
                        s.SetPoint(1, new Point(x - 20, s.GetPoint(1).Y));
                        s.InsertPoint(2, new Point(x - 20, y));
                        s.InsertPoint(3, new Point(x, y));
                        s.InsertPoint(4, new Point(x + 20, y));
                        s.SetPoint(5, new Point(s.GetPoint(5).X, y));
                    }
                }
                else if (ortho)
                {
                    if (s.PointsCount == 6)
                    {
                        s.SetPoint(2, new Point(x, s.GetPoint(2).Y));
                        s.SetPoint(3, new Point(x, s.GetPoint(3).Y));
                    }
                }
                else
                {
                    if (s.PointsCount == 4)
                    {
                        s.InsertPoint(2, new Point(x, s.GetPoint(2).Y));
                    }
                    else if (s.PointsCount == 3)
                    {
                        s.SetPoint(1, new Point(x, s.GetPoint(2).Y));
                    }
                    else if (s.PointsCount == 2)
                    {
                        s.InsertPoint(1, new Point(x, s.GetPoint(1).Y));
                    }
                }
            }
            else if (angle == 90)
            {
                double y = pb.Bottom + layerspacing / 2;
                if (bezier) // curved segments
                {
                    if (s.PointsCount == 4)
                    {
                        double x = s.GetPoint(3).X;
                        s.SetPoint(1, new Point(s.GetPoint(1).X, y - 20));
                        s.InsertPoint(2, new Point(x, y - 20));
                        s.InsertPoint(3, new Point(x, y));
                        s.InsertPoint(4, new Point(x, y + 20));
                        s.SetPoint(5, new Point(x, s.GetPoint(5).Y));
                    }
                }
                else if (ortho)
                {
                    if (s.PointsCount == 6)
                    {
                        s.SetPoint(2, new Point(s.GetPoint(2).X, y));
                        s.SetPoint(3, new Point(s.GetPoint(3).X, y));
                    }
                }
                else
                {
                    if (s.PointsCount == 4)
                    {
                        s.InsertPoint(2, new Point(s.GetPoint(2).X, y));
                    }
                    else if (s.PointsCount == 3)
                    {
                        s.SetPoint(1, new Point(s.GetPoint(2).X, y));
                    }
                    else if (s.PointsCount == 2)
                    {
                        s.InsertPoint(1, new Point(s.GetPoint(1).X, y));
                    }
                }
            }
            else if (angle == 180)
            {
                double x = pb.Left - layerspacing / 2;
                if (bezier) // curved segments
                {
                    if (s.PointsCount == 4)
                    {
                        double y = s.GetPoint(3).Y;
                        s.SetPoint(1, new Point(x + 20, s.GetPoint(1).Y));
                        s.InsertPoint(2, new Point(x + 20, y));
                        s.InsertPoint(3, new Point(x, y));
                        s.InsertPoint(4, new Point(x - 20, y));
                        s.SetPoint(5, new Point(s.GetPoint(5).X, y));
                    }
                }
                else if (ortho)
                {
                    if (s.PointsCount == 6)
                    {
                        s.SetPoint(2, new Point(x, s.GetPoint(2).Y));
                        s.SetPoint(3, new Point(x, s.GetPoint(3).Y));
                    }
                }
                else
                {
                    if (s.PointsCount == 4)
                    {
                        s.InsertPoint(2, new Point(x, s.GetPoint(2).Y));
                    }
                    else if (s.PointsCount == 3)
                    {
                        s.SetPoint(1, new Point(x, s.GetPoint(2).Y));
                    }
                    else if (s.PointsCount == 2)
                    {
                        s.InsertPoint(1, new Point(x, s.GetPoint(1).Y));
                    }
                }
            }
            else if (angle == 270)
            {
                double y = pb.Top - layerspacing / 2;
                if (bezier) // curved segments
                {
                    if (s.PointsCount == 4)
                    {
                        double x = s.GetPoint(3).X;
                        s.SetPoint(1, new Point(s.GetPoint(1).X, y + 20));
                        s.InsertPoint(2, new Point(x, y + 20));
                        s.InsertPoint(3, new Point(x, y));
                        s.InsertPoint(4, new Point(x, y - 20));
                        s.SetPoint(5, new Point(x, s.GetPoint(5).Y));
                    }
                }
                else if (ortho)
                {
                    if (s.PointsCount == 6)
                    {
                        s.SetPoint(2, new Point(s.GetPoint(2).X, y));
                        s.SetPoint(3, new Point(s.GetPoint(3).X, y));
                    }
                }
                else
                {
                    if (s.PointsCount == 4)
                    {
                        s.InsertPoint(2, new Point(s.GetPoint(2).X, y));
                    }
                    else if (s.PointsCount == 3)
                    {
                        s.SetPoint(1, new Point(s.GetPoint(2).X, y));
                    }
                    else if (s.PointsCount == 2)
                    {
                        s.InsertPoint(1, new Point(s.GetPoint(1).X, y));
                    }
                }
            }
        }