Browse Source

Remove FlyoutPlacementMode and improve PlacementMode instead

pull/10492/head
Max Katz 3 years ago
parent
commit
aa2ad652e3
  1. 90
      src/Avalonia.Controls/Flyouts/FlyoutBase.cs
  2. 77
      src/Avalonia.Controls/Flyouts/FlyoutPlacementMode.cs
  3. 53
      src/Avalonia.Controls/PlacementMode.cs
  4. 45
      src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs

90
src/Avalonia.Controls/Flyouts/FlyoutBase.cs

@ -29,8 +29,8 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Defines the <see cref="Placement"/> property
/// </summary>
public static readonly StyledProperty<FlyoutPlacementMode> PlacementProperty =
AvaloniaProperty.Register<FlyoutBase, FlyoutPlacementMode>(nameof(Placement));
public static readonly StyledProperty<PlacementMode> PlacementProperty =
AvaloniaProperty.Register<FlyoutBase, PlacementMode>(nameof(Placement));
/// <summary>
/// Defines the <see cref="ShowMode"/> property
@ -87,7 +87,7 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Gets or sets the desired placement
/// </summary>
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)

77
src/Avalonia.Controls/Flyouts/FlyoutPlacementMode.cs

@ -1,77 +0,0 @@
namespace Avalonia.Controls
{
public enum FlyoutPlacementMode
{
/// <summary>
/// Preferred location is above the target element
/// </summary>
Top = 0,
/// <summary>
/// Preferred location is below the target element
/// </summary>
Bottom = 1,
/// <summary>
/// Preferred location is to the left of the target element
/// </summary>
Left = 2,
/// <summary>
/// Preferred location is to the right of the target element
/// </summary>
Right = 3,
//TODO
// <summary>
// Preferred location is centered on the screen
// </summary>
//Full = 4,
/// <summary>
/// Preferred location is above the target element, with the left edge of the flyout
/// aligned with the left edge of the target element
/// </summary>
TopEdgeAlignedLeft = 5,
/// <summary>
/// Preferred location is above the target element, with the right edge of flyout aligned with right edge of the target element.
/// </summary>
TopEdgeAlignedRight = 6,
/// <summary>
/// Preferred location is below the target element, with the left edge of flyout aligned with left edge of the target element.
/// </summary>
BottomEdgeAlignedLeft = 7,
/// <summary>
/// Preferred location is below the target element, with the right edge of flyout aligned with right edge of the target element.
/// </summary>
BottomEdgeAlignedRight = 8,
/// <summary>
/// Preferred location is to the left of the target element, with the top edge of flyout aligned with top edge of the target element.
/// </summary>
LeftEdgeAlignedTop = 9,
/// <summary>
/// Preferred location is to the left of the target element, with the bottom edge of flyout aligned with bottom edge of the target element.
/// </summary>
LeftEdgeAlignedBottom = 10,
/// <summary>
/// Preferred location is to the right of the target element, with the top edge of flyout aligned with top edge of the target element.
/// </summary>
RightEdgeAlignedTop = 11,
/// <summary>
/// Preferred location is to the right of the target element, with the bottom edge of flyout aligned with bottom edge of the target element.
/// </summary>
RightEdgeAlignedBottom = 12,
/// <summary>
/// Preferred location is determined automatically.
/// </summary>
Auto = 13
}
}

53
src/Avalonia.Controls/PlacementMode.cs

@ -13,28 +13,69 @@ namespace Avalonia.Controls
Pointer,
/// <summary>
/// The popup is placed at the bottom left of its target.
/// Preferred location is below the target element.
/// </summary>
Bottom,
/// <summary>
/// The popup is placed at the top right of its target.
/// Preferred location is to the right of the target element.
/// </summary>
Right,
/// <summary>
/// The popup is placed at the top left of its target.
/// Preferred location is to the left of the target element.
/// </summary>
Left,
/// <summary>
/// The popup is placed at the top left of its target.
/// Preferred location is above the target element.
/// </summary>
Top,
/// <summary>
/// The popup is placed according to <see cref="Popup.PlacementAnchor"/> and <see cref="Popup.PlacementGravity"/> rules.
/// </summary>
AnchorAndGravity,
/// <summary>
/// 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.
/// </summary>
TopEdgeAlignedLeft,
/// <summary>
/// Preferred location is above the target element, with the right edge of popup aligned with right edge of the target element.
/// </summary>
TopEdgeAlignedRight,
/// <summary>
/// Preferred location is below the target element, with the left edge of popup aligned with left edge of the target element.
/// </summary>
BottomEdgeAlignedLeft,
/// <summary>
/// Preferred location is below the target element, with the right edge of popup aligned with right edge of the target element.
/// </summary>
BottomEdgeAlignedRight,
/// <summary>
/// Preferred location is to the left of the target element, with the top edge of popup aligned with top edge of the target element.
/// </summary>
LeftEdgeAlignedTop,
/// <summary>
/// Preferred location is to the left of the target element, with the bottom edge of popup aligned with bottom edge of the target element.
/// </summary>
LeftEdgeAlignedBottom,
/// <summary>
/// Preferred location is to the right of the target element, with the top edge of popup aligned with top edge of the target element.
/// </summary>
RightEdgeAlignedTop,
/// <summary>
/// Preferred location is to the right of the target element, with the bottom edge of popup aligned with bottom edge of the target element.
/// </summary>
AnchorAndGravity
RightEdgeAlignedBottom
}
}

45
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

Loading…
Cancel
Save