예제 #1
0
        /// <summary>
        /// Compute the offset to use in determining the position of a label.
        /// </summary>
        /// <param name="elt">the label being positioned, either a child element of the <see cref="LinkPanel"/>
        /// or the <see cref="Part.VisualElement"/> of a label <see cref="Node"/></param>
        /// <param name="index">the segment of the link, or a negative value if the label should be at the <see cref="Route.MidPoint"/></param>
        /// <param name="segangle">the angle of the <paramref name="index"/>th segment, or the <see cref="Route.MidAngle"/></param>
        /// <param name="sz">the size of the label</param>
        /// <param name="labelangle">the angle at which the label is rotated, from calling <see cref="ComputeAngle"/></param>
        /// <returns>an offset that is rotated according to the angle of the segment;
        /// this will be added to the midpoint of the link or to the fractional point along the segment</returns>
        protected virtual Point ComputeOffset(UIElement elt, int index, double segangle, Size sz, double labelangle)
        {
            Point off   = GetOffset(elt);
            Spot  align = GetAlignment(elt);

            if (align.IsNoSpot)
            {
                align = Spot.Center;
            }
            Point p = align.PointInRect(new Rect(0, 0, sz.Width, sz.Height));

            if (Double.IsNaN(off.X))
            {
                if (index >= 0)
                {
                    off.X = p.X + 3;
                }
                else
                {
                    off.X = -(p.X + 3);
                }
            }
            if (Double.IsNaN(off.Y))
            {
                //?? make this smarter to handle short end segments, especially if Orthogonal
                off.Y = -(p.Y + 3);
            }
            //?? make this better for larger non-square/circular labels that are not rotated
            return(Geo.RotatePoint(off, segangle));
        }
예제 #2
0
        private Size actualSize; // remember between MeasureAuto and ArrangeAuto

        /// <summary>
        /// Arranges the children according to the rules defined by NodePanelSizing.Auto.
        /// Resizes the first shape to fit around the other children and wraps text appropriately if requested.
        /// </summary>
        /// <param name="finalSize"></param>
        /// <returns></returns>
        private Size ArrangeAuto(Size finalSize)
        {
            finalSize = actualSize;
            Rect outer = new Rect(0, 0, finalSize.Width, finalSize.Height);
            Rect inner = outer;
            bool first = true;

            foreach (UIElement child in this.Children)
            {
                Part.ClearCachedValues(child);
                if (first) // first child is the background
                {
                    first = false;
                    child.Arrange(outer);
                    Spot spot1 = ComputeSpot1(child);
                    Spot spot2 = ComputeSpot2(child);
                    inner = new Rect(spot1.PointInRect(outer), spot2.PointInRect(outer));
                    //Diagram.Debug("NodePanel arrange1: " + Diagram.Str(outer) + Diagram.Str(inner));
                }
                else
                {
                    child.Arrange(inner);
                }
            }
            return(finalSize);
        }
예제 #3
0
        /// <summary>
        /// Measures the children according to the rules defined by NodePanelSizing.Fixed.
        /// </summary>
        /// <param name="finalSize"></param>
        /// <returns></returns>
        private Size ArrangeFixed(Size finalSize)
        {
            bool first = true;
            Rect outer = new Rect(0, 0, finalSize.Width, finalSize.Height);
            Rect inner = outer;

            foreach (UIElement child in this.Children)
            {
                Part.ClearCachedValues(child);
                if (finalSize == new Size(0, 0))
                {
                    child.Arrange(outer); continue;
                }                                                             //???
                if (first)
                {
                    first = false;
                    Spot spot1 = ComputeSpot1(child);
                    Spot spot2 = ComputeSpot2(child);
                    inner = new Rect(spot1.PointInRect(outer), spot2.PointInRect(outer));
                    child.Arrange(outer);
                }
                else // Alignments are auto-accounted for, so just arrange in whatever rect is given
                {
                    Rect r = inner;
                    // adjust R according to each child's HorizontalAlignment and VerticalAlignment
                    FrameworkElement elt = child as FrameworkElement;
                    if (elt != null)
                    {
                        Size sz = EffectiveDesiredSize(child);
                        if (sz.Width < inner.Width)
                        {
                            switch (elt.HorizontalAlignment)
                            {
                            case HorizontalAlignment.Left:
                                r.Width = sz.Width;
                                r.X     = inner.X;
                                break;

                            case HorizontalAlignment.Center:
                                r.Width = sz.Width;
                                r.X     = inner.X + inner.Width / 2 - sz.Width / 2;
                                break;

                            case HorizontalAlignment.Right:
                                r.Width = sz.Width;
                                r.X     = inner.X + inner.Width - sz.Width;
                                break;

                            default: // Stretch means use full inner.Width
                                break;
                            }
                        }
                        if (sz.Height < inner.Height)
                        {
                            switch (elt.VerticalAlignment)
                            {
                            case VerticalAlignment.Top:
                                r.Height = sz.Height;
                                r.Y      = inner.Y;
                                break;

                            case VerticalAlignment.Center:
                                r.Height = sz.Height;
                                r.Y      = inner.Y + inner.Height / 2 - sz.Height / 2;
                                break;

                            case VerticalAlignment.Bottom:
                                r.Height = sz.Height;
                                r.Y      = inner.Y + inner.Height - sz.Height;
                                break;

                            default: // Stretch means use full inner.Height
                                break;
                            }
                        }
                    }
                    child.Arrange(r);
                }
            }
            return(finalSize);
        }