예제 #1
0
 public void ConfigurePosition(IVisual target, PlacementMode placement, Point offset,
                               PopupAnchor anchor = PopupAnchor.None, PopupGravity gravity = PopupGravity.None,
                               PopupPositionerConstraintAdjustment constraintAdjustment = PopupPositionerConstraintAdjustment.All,
                               Rect?rect = null)
 {
     _positionerParameters.ConfigurePosition((TopLevel)_overlayLayer.GetVisualRoot(), target, placement, offset, anchor,
                                             gravity, constraintAdjustment, rect);
     UpdatePosition();
 }
        private Rect Calculate(Size translatedSize,
                               Rect anchorRect, PopupAnchor anchor, PopupGravity gravity,
                               PopupPositionerConstraintAdjustment constraintAdjustment, Point offset)
        {
            var parentGeometry = _popup.ParentClientAreaScreenGeometry;

            anchorRect = anchorRect.Translate(parentGeometry.TopLeft);

            Rect GetBounds()
            {
                var screens = _popup.Screens;

                var targetScreen = screens.FirstOrDefault(s => s.Bounds.Contains(anchorRect.TopLeft))
                                   ?? screens.FirstOrDefault(s => s.Bounds.Intersects(anchorRect))
                                   ?? screens.FirstOrDefault(s => s.Bounds.Contains(parentGeometry.TopLeft))
                                   ?? screens.FirstOrDefault(s => s.Bounds.Intersects(parentGeometry))
                                   ?? screens.FirstOrDefault();

                if (targetScreen != null && targetScreen.WorkingArea.IsEmpty)
                {
                    return(targetScreen.Bounds);
                }

                return(targetScreen?.WorkingArea
                       ?? new Rect(0, 0, double.MaxValue, double.MaxValue));
            }

            var bounds = GetBounds();

            bool FitsInBounds(Rect rc, PopupAnchor edge = PopupAnchor.AllMask)
            {
                if ((edge & PopupAnchor.Left) != 0 &&
                    rc.X < bounds.X)
                {
                    return(false);
                }

                if ((edge & PopupAnchor.Top) != 0 &&
                    rc.Y < bounds.Y)
                {
                    return(false);
                }

                if ((edge & PopupAnchor.Right) != 0 &&
                    rc.Right > bounds.Right)
                {
                    return(false);
                }

                if ((edge & PopupAnchor.Bottom) != 0 &&
                    rc.Bottom > bounds.Bottom)
                {
                    return(false);
                }

                return(true);
            }
예제 #3
0
        public void ConfigurePosition(IVisual target, PlacementMode placement, Point offset,
                                      PopupAnchor anchor   = PopupAnchor.None,
                                      PopupGravity gravity = PopupGravity.None,
                                      PopupPositionerConstraintAdjustment constraintAdjustment = PopupPositionerConstraintAdjustment.All,
                                      Rect?rect = null)
        {
            _positionerParameters.ConfigurePosition(_parent, target,
                                                    placement, offset, anchor, gravity, constraintAdjustment, rect);

            if (_positionerParameters.Size != default)
            {
                UpdatePosition();
            }
        }
예제 #4
0
        private void Update(Size translatedSize, Size originalSize,
                            Rect anchorRect, PopupPositioningEdge anchor, PopupPositioningEdge gravity,
                            PopupPositionerConstraintAdjustment constraintAdjustment, Point offset)
        {
            var parentGeometry = _popup.ParentClientAreaScreenGeometry;

            anchorRect = anchorRect.Translate(parentGeometry.TopLeft);

            Rect GetBounds()
            {
                var screens = _popup.Screens;

                var targetScreen = screens.FirstOrDefault(s => s.Bounds.Contains(anchorRect.TopLeft))
                                   ?? screens.FirstOrDefault(s => s.Bounds.Intersects(anchorRect))
                                   ?? screens.FirstOrDefault(s => s.Bounds.Contains(parentGeometry.TopLeft))
                                   ?? screens.FirstOrDefault(s => s.Bounds.Intersects(parentGeometry))
                                   ?? screens.FirstOrDefault();

                return(targetScreen?.WorkingArea
                       ?? new Rect(0, 0, double.MaxValue, double.MaxValue));
            }

            var bounds = GetBounds();

            bool FitsInBounds(Rect rc, PopupPositioningEdge edge = PopupPositioningEdge.AllMask)
            {
                if ((edge & PopupPositioningEdge.Left) != 0 &&
                    rc.X < bounds.X)
                {
                    return(false);
                }

                if ((edge & PopupPositioningEdge.Top) != 0 &&
                    rc.Y < bounds.Y)
                {
                    return(false);
                }

                if ((edge & PopupPositioningEdge.Right) != 0 &&
                    rc.Right > bounds.Right)
                {
                    return(false);
                }

                if ((edge & PopupPositioningEdge.Bottom) != 0 &&
                    rc.Bottom > bounds.Bottom)
                {
                    return(false);
                }

                return(true);
            }

            Rect GetUnconstrained(PopupPositioningEdge a, PopupPositioningEdge g) =>
            new Rect(Gravitate(GetAnchorPoint(anchorRect, a), translatedSize, g) + offset, translatedSize);


            var geo = GetUnconstrained(anchor, gravity);

            // If flipping geometry and anchor is allowed and helps, use the flipped one,
            // otherwise leave it as is
            if (!FitsInBounds(geo, PopupPositioningEdge.HorizontalMask) &&
                (constraintAdjustment & PopupPositionerConstraintAdjustment.FlipX) != 0)
            {
                var flipped = GetUnconstrained(anchor.FlipX(), gravity.FlipX());
                if (FitsInBounds(flipped, PopupPositioningEdge.HorizontalMask))
                {
                    geo = geo.WithX(flipped.X);
                }
            }

            // If sliding is allowed, try moving the rect into the bounds
            if ((constraintAdjustment & PopupPositionerConstraintAdjustment.SlideX) != 0)
            {
                geo = geo.WithX(Math.Max(geo.X, bounds.X));
                if (geo.Right > bounds.Right)
                {
                    geo = geo.WithX(bounds.Right - geo.Width);
                }
            }

            // If flipping geometry and anchor is allowed and helps, use the flipped one,
            // otherwise leave it as is
            if (!FitsInBounds(geo, PopupPositioningEdge.VerticalMask) &&
                (constraintAdjustment & PopupPositionerConstraintAdjustment.FlipY) != 0)
            {
                var flipped = GetUnconstrained(anchor.FlipY(), gravity.FlipY());
                if (FitsInBounds(flipped, PopupPositioningEdge.VerticalMask))
                {
                    geo = geo.WithY(flipped.Y);
                }
            }

            // If sliding is allowed, try moving the rect into the bounds
            if ((constraintAdjustment & PopupPositionerConstraintAdjustment.SlideY) != 0)
            {
                geo = geo.WithY(Math.Max(geo.Y, bounds.Y));
                if (geo.Bottom > bounds.Bottom)
                {
                    geo = geo.WithY(bounds.Bottom - geo.Height);
                }
            }

            _popup.MoveAndResize(geo.TopLeft, originalSize);
        }