diff --git a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs index 9d4abec549..373386e259 100644 --- a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs +++ b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs @@ -29,8 +29,8 @@ namespace Avalonia.Controls.Primitives /// /// Defines the property /// - public static readonly StyledProperty PlacementProperty = - AvaloniaProperty.Register(nameof(Placement)); + public static readonly StyledProperty PlacementProperty = + AvaloniaProperty.Register(nameof(Placement)); /// /// Defines the property @@ -87,7 +87,7 @@ namespace Avalonia.Controls.Primitives /// /// Gets or sets the desired placement /// - public FlyoutPlacementMode Placement + public PlacementMode Placement { get => GetValue(PlacementProperty); set => SetValue(PlacementProperty, value); @@ -452,93 +452,11 @@ namespace Avalonia.Controls.Primitives } else { - Popup.PlacementMode = PlacementMode.AnchorAndGravity; + Popup.PlacementMode = Placement; Popup.PlacementConstraintAdjustment = PopupPositioning.PopupPositionerConstraintAdjustment.SlideX | PopupPositioning.PopupPositionerConstraintAdjustment.SlideY; } - - var trgtBnds = Target?.Bounds ?? default; - - switch (Placement) - { - case FlyoutPlacementMode.Top: //Above & centered - Popup.PlacementRect = new Rect(0, 0, trgtBnds.Width - 1, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.Top; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.Top; - break; - - case FlyoutPlacementMode.TopEdgeAlignedLeft: - Popup.PlacementRect = new Rect(0, 0, 0, 0); - Popup.PlacementGravity = PopupPositioning.PopupGravity.TopRight; - break; - - case FlyoutPlacementMode.TopEdgeAlignedRight: - Popup.PlacementRect = new Rect(trgtBnds.Width - 1, 0, 10, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.TopLeft; - break; - - case FlyoutPlacementMode.RightEdgeAlignedTop: - Popup.PlacementRect = new Rect(trgtBnds.Width - 1, 0, 1, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.BottomRight; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.Right; - break; - - case FlyoutPlacementMode.Right: //Right & centered - Popup.PlacementRect = new Rect(trgtBnds.Width - 1, 0, 1, trgtBnds.Height); - Popup.PlacementGravity = PopupPositioning.PopupGravity.Right; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.Right; - break; - - case FlyoutPlacementMode.RightEdgeAlignedBottom: - Popup.PlacementRect = new Rect(trgtBnds.Width - 1, trgtBnds.Height - 1, 1, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.TopRight; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.Right; - break; - - case FlyoutPlacementMode.Bottom: //Below & centered - Popup.PlacementRect = new Rect(0, trgtBnds.Height - 1, trgtBnds.Width, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.Bottom; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.Bottom; - break; - - case FlyoutPlacementMode.BottomEdgeAlignedLeft: - Popup.PlacementRect = new Rect(0, trgtBnds.Height - 1, 1, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.BottomRight; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.Bottom; - break; - - case FlyoutPlacementMode.BottomEdgeAlignedRight: - Popup.PlacementRect = new Rect(trgtBnds.Width - 1, trgtBnds.Height - 1, 1, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.BottomLeft; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.Bottom; - break; - - case FlyoutPlacementMode.LeftEdgeAlignedTop: - Popup.PlacementRect = new Rect(0, 0, 1, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.BottomLeft; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.Left; - break; - - case FlyoutPlacementMode.Left: //Left & centered - Popup.PlacementRect = new Rect(0, 0, 1, trgtBnds.Height); - Popup.PlacementGravity = PopupPositioning.PopupGravity.Left; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.Left; - break; - - case FlyoutPlacementMode.LeftEdgeAlignedBottom: - Popup.PlacementRect = new Rect(0, trgtBnds.Height - 1, 1, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.TopLeft; - Popup.PlacementAnchor = PopupPositioning.PopupAnchor.BottomLeft; - break; - - //includes Auto (not sure what determines that)... - default: - //This is just FlyoutPlacementMode.Top behavior (above & centered) - Popup.PlacementRect = new Rect(-sz.Width / 2, 0, sz.Width, 1); - Popup.PlacementGravity = PopupPositioning.PopupGravity.Top; - break; - } } private static void OnContextFlyoutPropertyChanged(AvaloniaPropertyChangedEventArgs args) diff --git a/src/Avalonia.Controls/Flyouts/FlyoutPlacementMode.cs b/src/Avalonia.Controls/Flyouts/FlyoutPlacementMode.cs deleted file mode 100644 index 2e77de3b3b..0000000000 --- a/src/Avalonia.Controls/Flyouts/FlyoutPlacementMode.cs +++ /dev/null @@ -1,77 +0,0 @@ -namespace Avalonia.Controls -{ - public enum FlyoutPlacementMode - { - /// - /// Preferred location is above the target element - /// - Top = 0, - - /// - /// Preferred location is below the target element - /// - Bottom = 1, - - /// - /// Preferred location is to the left of the target element - /// - Left = 2, - - /// - /// Preferred location is to the right of the target element - /// - Right = 3, - - //TODO - // - // Preferred location is centered on the screen - // - //Full = 4, - - /// - /// Preferred location is above the target element, with the left edge of the flyout - /// aligned with the left edge of the target element - /// - TopEdgeAlignedLeft = 5, - - /// - /// Preferred location is above the target element, with the right edge of flyout aligned with right edge of the target element. - /// - TopEdgeAlignedRight = 6, - - /// - /// Preferred location is below the target element, with the left edge of flyout aligned with left edge of the target element. - /// - BottomEdgeAlignedLeft = 7, - - /// - /// Preferred location is below the target element, with the right edge of flyout aligned with right edge of the target element. - /// - BottomEdgeAlignedRight = 8, - - /// - /// Preferred location is to the left of the target element, with the top edge of flyout aligned with top edge of the target element. - /// - LeftEdgeAlignedTop = 9, - - /// - /// Preferred location is to the left of the target element, with the bottom edge of flyout aligned with bottom edge of the target element. - /// - LeftEdgeAlignedBottom = 10, - - /// - /// Preferred location is to the right of the target element, with the top edge of flyout aligned with top edge of the target element. - /// - RightEdgeAlignedTop = 11, - - /// - /// Preferred location is to the right of the target element, with the bottom edge of flyout aligned with bottom edge of the target element. - /// - RightEdgeAlignedBottom = 12, - - /// - /// Preferred location is determined automatically. - /// - Auto = 13 - } -} diff --git a/src/Avalonia.Controls/PlacementMode.cs b/src/Avalonia.Controls/PlacementMode.cs index 68a4b9eecb..fa4f029cf3 100644 --- a/src/Avalonia.Controls/PlacementMode.cs +++ b/src/Avalonia.Controls/PlacementMode.cs @@ -13,28 +13,69 @@ namespace Avalonia.Controls Pointer, /// - /// The popup is placed at the bottom left of its target. + /// Preferred location is below the target element. /// Bottom, /// - /// The popup is placed at the top right of its target. + /// Preferred location is to the right of the target element. /// Right, /// - /// The popup is placed at the top left of its target. + /// Preferred location is to the left of the target element. /// Left, /// - /// The popup is placed at the top left of its target. + /// Preferred location is above the target element. /// Top, + + /// + /// The popup is placed according to and rules. + /// + AnchorAndGravity, /// - /// The popup is placed according to anchor and gravity rules + /// Preferred location is above the target element, with the left edge of the popup + /// aligned with the left edge of the target element. + /// + TopEdgeAlignedLeft, + + /// + /// Preferred location is above the target element, with the right edge of popup aligned with right edge of the target element. + /// + TopEdgeAlignedRight, + + /// + /// Preferred location is below the target element, with the left edge of popup aligned with left edge of the target element. + /// + BottomEdgeAlignedLeft, + + /// + /// Preferred location is below the target element, with the right edge of popup aligned with right edge of the target element. + /// + BottomEdgeAlignedRight, + + /// + /// Preferred location is to the left of the target element, with the top edge of popup aligned with top edge of the target element. + /// + LeftEdgeAlignedTop, + + /// + /// Preferred location is to the left of the target element, with the bottom edge of popup aligned with bottom edge of the target element. + /// + LeftEdgeAlignedBottom, + + /// + /// Preferred location is to the right of the target element, with the top edge of popup aligned with top edge of the target element. + /// + RightEdgeAlignedTop, + + /// + /// Preferred location is to the right of the target element, with the bottom edge of popup aligned with bottom edge of the target element. /// - AnchorAndGravity + RightEdgeAlignedBottom } } diff --git a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs index 2e70947457..0bb596d778 100644 --- a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs +++ b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs @@ -480,33 +480,26 @@ namespace Avalonia.Controls.Primitives.PopupPositioning var anchorRect = rect ?? bounds; positionerParameters.AnchorRectangle = anchorRect.Intersect(bounds).TransformToAABB(matrix.Value); - if (placement == PlacementMode.Right) + var parameters = placement switch { - positionerParameters.Anchor = PopupAnchor.TopRight; - positionerParameters.Gravity = PopupGravity.BottomRight; - } - else if (placement == PlacementMode.Bottom) - { - positionerParameters.Anchor = PopupAnchor.BottomLeft; - positionerParameters.Gravity = PopupGravity.BottomRight; - } - else if (placement == PlacementMode.Left) - { - positionerParameters.Anchor = PopupAnchor.TopLeft; - positionerParameters.Gravity = PopupGravity.BottomLeft; - } - else if (placement == PlacementMode.Top) - { - positionerParameters.Anchor = PopupAnchor.TopLeft; - positionerParameters.Gravity = PopupGravity.TopRight; - } - else if (placement == PlacementMode.AnchorAndGravity) - { - positionerParameters.Anchor = anchor; - positionerParameters.Gravity = gravity; - } - else - throw new InvalidOperationException("Invalid value for Popup.PlacementMode"); + PlacementMode.Bottom => (PopupAnchor.Bottom, PopupGravity.Bottom), + PlacementMode.Right => (PopupAnchor.Right, PopupGravity.Right), + PlacementMode.Left => (PopupAnchor.Left, PopupGravity.Left), + PlacementMode.Top => (PopupAnchor.Top, PopupGravity.Top), + PlacementMode.AnchorAndGravity => (anchor, gravity), + PlacementMode.TopEdgeAlignedRight => (PopupAnchor.TopRight, PopupGravity.TopLeft), + PlacementMode.TopEdgeAlignedLeft => (PopupAnchor.TopLeft, PopupGravity.TopRight), + PlacementMode.BottomEdgeAlignedLeft => (PopupAnchor.BottomLeft, PopupGravity.BottomRight), + PlacementMode.BottomEdgeAlignedRight => (PopupAnchor.BottomRight, PopupGravity.BottomLeft), + PlacementMode.LeftEdgeAlignedTop => (PopupAnchor.TopLeft, PopupGravity.BottomLeft), + PlacementMode.LeftEdgeAlignedBottom => (PopupAnchor.BottomLeft, PopupGravity.TopLeft), + PlacementMode.RightEdgeAlignedTop => (PopupAnchor.TopRight, PopupGravity.BottomRight), + PlacementMode.RightEdgeAlignedBottom => (PopupAnchor.BottomRight, PopupGravity.TopRight), + _ => throw new ArgumentOutOfRangeException(nameof(placement), placement, + "Invalid value for Popup.PlacementMode") + }; + positionerParameters.Anchor = parameters.Item1; + positionerParameters.Gravity = parameters.Item2; } // Invert coordinate system if FlowDirection is RTL