Example #1
0
        /// <summary>
        /// Updates DesiredSize of the Border.  Called by parent UIElement.  This is the first pass of layout.
        /// </summary>
        /// <remarks>
        /// Border determines its desired size it needs from the specified border the child: its sizing
        /// properties, margin, and requested size.
        /// </remarks>
        /// <param name="constraint">Constraint size is an "upper limit" that the return value should not exceed.</param>
        /// <returns>The Decorator's desired size.</returns>
        protected override Size MeasureOverride(Size constraint)
        {
            var child       = Child;
            var desiredSize = new Size();
            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));
            }

            // Compute the total size required
            var borderSize  = ThicknessUtil.CollapseThickness(borders);
            var paddingSize = ThicknessUtil.CollapseThickness(Padding);

            // If we have a child
            if (child != null)
            {
                // Combine into total decorating size
                var combined = new Size(borderSize.Width + paddingSize.Width, borderSize.Height + paddingSize.Height);

                // Remove size of border only from child's reference size.
                var childConstraint = new Size(Math.Max(0.0, constraint.Width - combined.Width),
                                               Math.Max(0.0, constraint.Height - combined.Height));


                child.Measure(childConstraint);
                var childSize = child.DesiredSize;

                // Now use the returned size to drive our size, by adding back the margins, etc.
                desiredSize.Width  = childSize.Width + combined.Width;
                desiredSize.Height = childSize.Height + combined.Height;
            }
            else
            {
                // Combine into total decorating size
                desiredSize = new Size(borderSize.Width + paddingSize.Width, borderSize.Height + paddingSize.Height);
            }

            return(desiredSize);
        }
Example #2
0
        private void SimpleRender(DrawingContext dc)
        {
            var useLayoutRounding = UseLayoutRounding;
            var dpi = DpiUtil.GetDpi(this);

            Brush brush;
            var   borderStyle = BorderStyle;

            var borders      = BorderThickness;
            var cornerRadius = CornerRadius;

            var outerCornerRadius = cornerRadius.TopLeft; // Already validated that all corners have the same radius
            var roundedCorners    = !DoubleUtil.IsZero(outerCornerRadius);

            var width  = RenderSize.Width;
            var height = RenderSize.Height;

            // Draw border
            if (!ThicknessUtil.IsZero(borders) && (brush = BorderBrush) != null)
            {
                var pen          = GetPen(brush, borderStyle, borders.Left, dpi.DpiScaleX, useLayoutRounding);
                var penThickness = pen.Thickness;

                double x    = penThickness * 0.5;
                var    rect = new Rect(x, x, width - penThickness, height - penThickness);

                if (roundedCorners)
                {
                    dc.DrawRoundedRectangle(null, pen, rect, outerCornerRadius, outerCornerRadius);
                }
                else
                {
                    dc.DrawRectangle(null, pen, rect);
                }
            }

            // Draw background in rectangle inside border.
            if ((brush = Background) != null)
            {
                // Intialize background
                Point ptTL, ptBR;

                if (useLayoutRounding)
                {
                    ptTL = new Point(UIElementUtil.RoundLayoutValue(borders.Left, dpi.DpiScaleX),
                                     UIElementUtil.RoundLayoutValue(borders.Top, dpi.DpiScaleY));
                    ptBR = new Point(width - UIElementUtil.RoundLayoutValue(borders.Right, dpi.DpiScaleX),
                                     height - UIElementUtil.RoundLayoutValue(borders.Bottom, dpi.DpiScaleY));
                }
                else
                {
                    ptTL = new Point(borders.Left, borders.Top);
                    ptBR = new Point(width - borders.Right, height - borders.Bottom);
                }

                // Do not draw background if the borders are so large that they overlap.
                if (ptBR.X > ptTL.X && ptBR.Y > ptTL.Y)
                {
                    if (roundedCorners)
                    {
                        // Determine the inner edge radius
                        var innerCornerRadius = Math.Max(0.0, outerCornerRadius - borders.Top * 0.5);
                        dc.DrawRoundedRectangle(brush, null, new Rect(ptTL, ptBR), innerCornerRadius, innerCornerRadius);
                    }
                    else
                    {
                        dc.DrawRectangle(brush, null, new Rect(ptTL, ptBR));
                    }
                }
            }
        }
Example #3
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);
        }
Example #4
0
 private static bool IsThicknessValid(object value)
 {
     return(ThicknessUtil.IsValid((Thickness)value, false, false, false, false));
 }