View Issue Details

IDProjectCategoryView StatusLast Update
0001534NoesisGUIC# SDKpublic2020-06-26 16:38
Reporterdarthmaule2Assigned Tosfernandez 
PrioritynormalSeverityfeatureReproducibilityalways
Status resolvedResolutionno change required 
Product Version2.2.3 
Target VersionFixed in Version 
Summary0001534: Request a "ClipBorder" (a Border that clips)
DescriptionSomething like this:
https://wpfspark.wordpress.com/2011/06/08/clipborder-a-wpf-border-that-clips/

This is very useful for borders with rounded corners and ensuring the content does not go outside of the corner.
TagsNo tags attached.
PlatformAny

Activities

sfernandez

sfernandez

2020-06-26 16:38

manager   ~0006459

The implementation of such class would look like this:

    public class ClipBorder: Border
    {
        public ClipBorder()
        {
            _clipTransform = new MatrixTransform();
            _clipGeometry = new StreamGeometry() { Transform = _clipTransform };
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            Size renderSize = base.ArrangeOverride(finalSize);

            UIElement child = Child;
            if (child != null)
            {
                Thickness borders = BorderThickness;
                CornerRadius corners = CornerRadius;

                float left = (float)borders.Left;
                float top = (float)borders.Top;
                float right = (float)borders.Right;
                float bottom = (float)borders.Bottom;

                float leftH = left / 2.0F;
                float topH = top / 2.0F;
                float rightH = right / 2.0F;
                float bottomH = bottom / 2.0F;

                using (StreamGeometryContext context = _clipGeometry.Open())
                {
                    // Top-Left
                    Point p0 = new Point(left, corners.TopLeft + topH);
                    Point p1 = new Point(corners.TopLeft + leftH, top);

                    p0.Y = System.Math.Max(p0.Y, p1.Y);
                    p1.X = System.Math.Max(p0.X, p1.X);

                    context.BeginFigure(p0, true, true);
                    if (p0.X < p1.Y && p0.Y > p1.Y)
                    {
                        Size size = new Size(p1.X - p0.X, p0.Y - p1.Y);
                        context.ArcTo(p1, size, 0, false, SweepDirection.Clockwise, false, false);
                    }

                    // Top-Right
                    Point p2 = new Point(renderSize.Width - corners.TopRight - rightH, top);
                    Point p3 = new Point(renderSize.Width - right, corners.TopRight + topH);

                    p2.X = System.Math.Min(p2.X, p3.X);
                    p3.Y = System.Math.Max(p2.Y, p3.Y);

                    context.LineTo(p2, false, false);
                    if (p2.X < p3.X && p2.Y < p3.Y)
                    {
                        Size size = new Size(p3.X - p2.X, p3.Y - p2.Y);
                        context.ArcTo(p3, size, 0, false, SweepDirection.Clockwise, false, false);
                    }

                    // Bottom-Right
                    Point p4 = new Point(renderSize.Width - right, renderSize.Height - corners.BottomRight - bottomH);
                    Point p5 = new Point(renderSize.Width - corners.BottomRight - rightH, renderSize.Height - bottom);

                    p4.Y = System.Math.Min(p4.Y, p5.Y);
                    p5.X = System.Math.Min(p4.X, p5.X);

                    context.LineTo(p4, false, false);
                    if (p4.X > p5.X && p4.Y < p5.Y)
                    {
                        Size size = new Size(p4.X - p5.X, p5.Y - p4.Y);
                        context.ArcTo(p5, size, 0, false, SweepDirection.Clockwise, false, false);
                    }

                    // Bottom-Left
                    Point p6 = new Point(corners.BottomLeft + leftH, renderSize.Height - bottom);
                    Point p7 = new Point(left, renderSize.Height - corners.BottomLeft - bottomH);

                    p6.X = System.Math.Max(p6.X, p7.X);
                    p7.Y = System.Math.Min(p6.Y, p7.Y);

                    context.LineTo(p6, false, false);
                    if (p6.X > p7.X && p6.Y > p7.Y)
                    {
                        Size size = new Size(p6.X - p7.X, p6.Y - p7.Y);
                        context.ArcTo(p7, size, 0, false, SweepDirection.Clockwise, false, false);
                    }

                    // Close
                    context.LineTo(p0, false, false);
                }

                // Transform to child coordinates
                Matrix4 m4 = TransformToDescendant(child);
                _clipTransform.Matrix = new Matrix(m4[0][0], m4[0][1], m4[1][0], m4[1][1], m4[3][0], m4[3][1]);

                // Assign new Clip geometry to the child
                child.Clip = _clipGeometry;
            }

            return renderSize;
        }

        private MatrixTransform _clipTransform;
        private StreamGeometry _clipGeometry;
    }

Issue History

Date Modified Username Field Change
2019-08-08 18:45 darthmaule2 New Issue
2019-09-24 13:11 sfernandez Assigned To => sfernandez
2019-09-24 13:11 sfernandez Status new => assigned
2019-09-24 13:11 sfernandez Product Version 2.3.0 => 2.2.3
2019-09-24 13:11 sfernandez Target Version => 2.3.0
2020-06-26 16:38 sfernandez Status assigned => resolved
2020-06-26 16:38 sfernandez Resolution open => no change required
2020-06-26 16:38 sfernandez Note Added: 0006459