Ejemplo n.º 1
0
        /// <summary>
        /// Determine the size of the union of the bounds of the positioned and rotated child elements.
        /// </summary>
        /// <param name="availableSize"></param>
        /// <returns></returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            Part part = Diagram.FindAncestor <Part>(this);

            if (part == null)
            {
                return(new Size());
            }

            if (!part.IsMeasuringArranging)
            {
                return(new Size());
            }

            Link link = part as Link;

            if (link == null)
            {
                Adornment ad = part as Adornment;
                if (ad != null)
                {
                    link = ad.AdornedPart as Link;
                }
                if (link == null)
                {
                    return(new Size());
                }
            }

            //Diagram.Debug(" LinkPanelM- " + (link.Data != null ? link.Data.ToString() : ""));

            Shape stroke = this.Path; // may be null

            link.Path = stroke;       // the Link caches what the Path really is

            Route route       = link.Route;
            Rect  routeBounds = route.RouteBounds; // in model coordinates
            Rect  linkBounds  = routeBounds;       // includes all labels

            childrenBounds = new List <Rect>();    // in local coordinates
            if (stroke != null)
            {
                stroke.Measure(Geo.Unlimited);
                Size sz = stroke.DesiredSize;
                linkBounds.Width  = Math.Max(linkBounds.Width, sz.Width);
                linkBounds.Height = Math.Max(linkBounds.Height, sz.Height);
                childrenBounds.Add(new Rect(0, 0, linkBounds.Width, linkBounds.Height));
            }

            IList <Point> pts     = (List <Point>)route.Points;
            int           nPoints = pts.Count;

            foreach (UIElement e in this.Children)
            {
                if (e == stroke)
                {
                    continue;       // already measured the stroke, above
                }
                e.Measure(Geo.Unlimited);
                //if (e.GetType().Name.Contains("Expander")) Diagram.Debug(e.ToString() + " measured: " + Diagram.Str(e.DesiredSize));
                if (nPoints < 2)
                {
                    continue;
                }
                Size   sz    = e.DesiredSize;
                int    index = GetIndex(e);
                double frac  = ComputeFraction(GetFraction(e));
                Spot   align = GetAlignment(e);
                if (align.IsNoSpot)
                {
                    align = Spot.Center;
                }
                LabelOrientation orient = GetOrientation(e);
                Point            eltpt;                   // local coordinates
                if (index < -nPoints || index >= nPoints) // beyond range? assume at the MidPoint, with the MidAngle
                {
                    Point mid = route.MidPoint;
                    if (this.Implementation == LinkPanelImplementation.Stretch)
                    {
                        Point p0 = pts[0];
                        Point pn = pts[nPoints - 1];
                        sz.Width = Math.Sqrt(Geo.DistanceSquared(pn, p0));
                    }
                    double segangle = route.MidAngle;
                    // maybe rotate the label
                    double labelangle = 0;
                    if (orient != LabelOrientation.None)
                    {
                        labelangle = ComputeAngle(e, orient, segangle);
                        link.SetAngle(e, labelangle, align);
                    }
                    // maybe the alignment point is away from the line
                    eltpt = new Point(mid.X - routeBounds.X, mid.Y - routeBounds.Y); // local coordinates
                    Point offset = ComputeOffset(e, index, segangle, sz, labelangle);
                    eltpt = Geo.Add(eltpt, offset);
                }
                else // on a particular segment, given by Index, at a point given by Fraction
                // negative index means start from last point, going "backwards"
                {
                    Point a, b;
                    if (index >= 0)
                    {
                        a = pts[index];
                        b = (index < nPoints - 1) ? pts[index + 1] : a;
                    }
                    else
                    {
                        int i = nPoints + index; // remember that index is negative here
                        a = pts[i];
                        b = (i > 0) ? pts[i - 1] : a;
                    }
                    // compute the fractional point along the line, in local coordinates
                    eltpt = new Point(a.X + (b.X - a.X) * frac - routeBounds.X, a.Y + (b.Y - a.Y) * frac - routeBounds.Y);
                    double segangle = (index >= 0 ? Geo.GetAngle(a, b) : Geo.GetAngle(b, a));
                    // maybe rotate the label
                    double labelangle = 0;
                    if (orient != LabelOrientation.None)
                    {
                        labelangle = ComputeAngle(e, orient, segangle);
                        link.SetAngle(e, labelangle, align);
                    }
                    // maybe the alignment point is away from the line
                    Point offset = ComputeOffset(e, index, segangle, sz, labelangle);
                    eltpt = Geo.Add(eltpt, offset);
                }
                Rect cb = align.RectForPoint(eltpt, sz);
                childrenBounds.Add(cb);                                                                      // local coordinates
                linkBounds.Union(new Rect(cb.X + routeBounds.X, cb.Y + routeBounds.Y, cb.Width, cb.Height)); // model coordinates
            }

            // if this panel is the "whole" link, update the link's Bounds
            if (link.VisualElement == this)
            {
                //Diagram.Debug(" LinkPanelM+ " + (link.Data != null ? link.Data.ToString() : "") + " " + Diagram.Str(routeBounds) + Diagram.Str(linkBounds));
                link.Bounds = new Rect(routeBounds.X, routeBounds.Y, linkBounds.Width, linkBounds.Height);
            }

            return(new Size(routeBounds.Width, routeBounds.Height));
        }