public void ConfigurePosition(IVisual target, PlacementMode placement, Point offset, PopupPositioningEdge anchor = PopupPositioningEdge.None, PopupPositioningEdge gravity = PopupPositioningEdge.None) { _positionerParameters.ConfigurePosition(_parent, target, placement, offset, anchor, gravity); if (_positionerParameters.Size != default) { UpdatePosition(); } }
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); }
public void ConfigurePosition(IVisual target, PlacementMode placement, Point offset, PopupPositioningEdge anchor = PopupPositioningEdge.None, PopupPositioningEdge gravity = PopupPositioningEdge.None) { _positionerParameters.ConfigurePosition((TopLevel)_overlayLayer.GetVisualRoot(), target, placement, offset, anchor, gravity); UpdatePosition(); }