Ejemplo n.º 1
0
        /// <summary>
        /// Border computes the position of its single child and applies its child's alignments to the child.
        /// </summary>
        /// <param name="finalSize">The size reserved for this element by the parent</param>
        /// <returns>The actual ink area of the element, typically the same as finalSize</returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            var borders = BorderThickness;

            if (UseLayoutRounding)
            {
                var dpi = DpiUtil.GetDpi(this);
                borders = new Thickness(UIElementUtil.RoundLayoutValue(borders.Left, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Top, dpi.DpiScaleY),
                                        UIElementUtil.RoundLayoutValue(borders.Right, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Bottom, dpi.DpiScaleY));
            }

            var boundRect = new Rect(finalSize);
            var innerRect = RectUtil.Deflate(boundRect, borders);

            //  arrange child
            var child = Child;

            if (child != null)
            {
                Rect childRect = RectUtil.Deflate(innerRect, Padding);
                child.Arrange(childRect);
            }

            var radius = CornerRadius;

            useComplexRender        = !CornerRadiusUtil.IsUniform(radius) || !ThicknessUtil.IsUniform(borders);
            backgroundGeometryCache = upperLeftCache = upperRightCache = lowerRightCache = lowerLeftCache = null;

            if (useComplexRender)
            {
                //  calculate border / background rendering geometry
                if (!DoubleUtil.IsZero(boundRect.Width) && !DoubleUtil.IsZero(boundRect.Height))
                {
                    var outerRadii = new Radii(boundRect, radius, borders, true);

                    // Upper-right corner
                    var radiusX = boundRect.TopRight.X - outerRadii.TopRight.X;
                    var radiusY = outerRadii.RightTop.Y - boundRect.TopRight.Y;
                    if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
                    {
                        upperRightCache = GenerateRoundedGeometry(outerRadii.TopRight, outerRadii.RightTop, new Size(radiusX, radiusY));
                    }

                    // Lower-right corner
                    radiusX = boundRect.BottomRight.X - outerRadii.BottomRight.X;
                    radiusY = boundRect.BottomRight.Y - outerRadii.RightBottom.Y;
                    if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
                    {
                        lowerRightCache = GenerateRoundedGeometry(outerRadii.RightBottom, outerRadii.BottomRight, new Size(radiusX, radiusY));
                    }

                    // Lower-left corner
                    radiusX = outerRadii.BottomLeft.X - boundRect.BottomLeft.X;
                    radiusY = boundRect.BottomLeft.Y - outerRadii.LeftBottom.Y;
                    if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
                    {
                        lowerLeftCache = GenerateRoundedGeometry(outerRadii.BottomLeft, outerRadii.LeftBottom, new Size(radiusX, radiusY));
                    }

                    // Upper-left corner
                    radiusX = outerRadii.TopLeft.X - boundRect.TopLeft.X;
                    radiusY = outerRadii.LeftTop.Y - boundRect.TopLeft.Y;
                    if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
                    {
                        upperLeftCache = GenerateRoundedGeometry(outerRadii.LeftTop, outerRadii.TopLeft, new Size(radiusX, radiusY));
                    }
                }

                if (!DoubleUtil.IsZero(innerRect.Width) && !DoubleUtil.IsZero(innerRect.Height))
                {
                    var innerRadii         = new Radii(innerRect, radius, borders, false);
                    var backgroundGeometry = new StreamGeometry();

                    using (StreamGeometryContext sc = backgroundGeometry.Open())
                    {
                        //  create the border geometry
                        sc.BeginFigure(innerRadii.TopLeft, true /* is filled */, true /* is closed */);

                        // Top line
                        sc.LineTo(innerRadii.TopRight, true /* is stroked */, false /* is smooth join */);

                        // Upper-right corners
                        var radiusX = innerRect.TopRight.X - innerRadii.TopRight.X;
                        var radiusY = innerRadii.RightTop.Y - innerRect.TopRight.Y;
                        if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
                        {
                            sc.ArcTo(innerRadii.RightTop, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
                        }

                        // Right line
                        sc.LineTo(innerRadii.RightBottom, true /* is stroked */, false /* is smooth join */);

                        // Lower-right corners
                        radiusX = innerRect.BottomRight.X - innerRadii.BottomRight.X;
                        radiusY = innerRect.BottomRight.Y - innerRadii.RightBottom.Y;
                        if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
                        {
                            sc.ArcTo(innerRadii.BottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
                        }

                        // Bottom line
                        sc.LineTo(innerRadii.BottomLeft, true /* is stroked */, false /* is smooth join */);

                        // Lower-left corners
                        radiusX = innerRadii.BottomLeft.X - innerRect.BottomLeft.X;
                        radiusY = innerRect.BottomLeft.Y - innerRadii.LeftBottom.Y;
                        if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
                        {
                            sc.ArcTo(innerRadii.LeftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
                        }

                        // Left line
                        sc.LineTo(innerRadii.LeftTop, true /* is stroked */, false /* is smooth join */);

                        // Upper-left corners
                        radiusX = innerRadii.TopLeft.X - innerRect.TopLeft.X;
                        radiusY = innerRadii.LeftTop.Y - innerRect.TopLeft.Y;
                        if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY))
                        {
                            sc.ArcTo(innerRadii.TopLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
                        }
                    }

                    backgroundGeometry.Freeze();
                    backgroundGeometryCache = backgroundGeometry;
                }
            }

            return(finalSize);
        }
Ejemplo n.º 2
0
 private static bool IsCornerRadiusValid(object value)
 {
     return(CornerRadiusUtil.IsValid((CornerRadius)value, false, false, false, false));
 }