Browse Source

FlyoutBase updates

pull/5682/head
amwx 5 years ago
parent
commit
8786250eb2
  1. 47
      src/Avalonia.Controls/Flyouts/FlyoutBase.cs
  2. 9
      src/Avalonia.Controls/Flyouts/FlyoutPlacementMode.cs

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

@ -3,6 +3,7 @@ using System.ComponentModel;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Layout;
using Avalonia.Logging;
#nullable enable
@ -133,8 +134,12 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Hides the Flyout
/// </summary>
/// <param name="canCancel">Whether or not this closing action can be cancelled</param>
public void Hide(bool canCancel = true)
public void Hide()
{
HideCore();
}
protected virtual void HideCore(bool canCancel = true)
{
if (!IsOpen)
{
@ -181,7 +186,7 @@ namespace Avalonia.Controls.Primitives
}
else // Close before opening a new one
{
Hide(false);
HideCore(false);
}
}
@ -232,17 +237,27 @@ namespace Avalonia.Controls.Primitives
{
if (args is RawPointerEventArgs pArgs && pArgs.Type == RawPointerEventType.Move)
{
// In ShowMode = TransientWithDismissOnPointerMoveAway, the Flyout is kept
// shown as long as the pointer is within a certain px distance from the
// flyout itself. I'm not sure what WinUI uses, but I'm defaulting to
// 100px, which seems about right
// enlargedPopupRect is the Flyout bounds enlarged 100px
// For windowed popups, enlargedPopupRect is in screen coordinates,
// for overlay popups, its in OverlayLayer coordinates
if (enlargedPopupRect == null)
{
// Only do this once when the Flyout opens & cache the result
if (_popup?.Host is PopupRoot root)
{
// Get the popup root bounds and convert to screen coordinates
var tmp = root.Bounds.Inflate(100);
var scPt = root.PointToScreen(tmp.TopLeft);
enlargedPopupRect = new Rect(scPt.X, scPt.Y, tmp.Width, tmp.Height);
}
else if (_popup?.Host is OverlayPopupHost host)
{
// Overlay popups are in Window client coordinates, just use that
// Overlay popups are in OverlayLayer coordinates, just use that
enlargedPopupRect = host.Bounds.Inflate(100);
}
@ -251,10 +266,15 @@ namespace Avalonia.Controls.Primitives
if (_popup?.Host is PopupRoot)
{
// As long as the pointer stays within the enlargedPopupRect
// the flyout stays open. If it leaves, close it
// Despite working in screen coordinates, leaving the TopLevel
// window will not close this (as pointer events stop), which
// does match UWP
var pt = pArgs.Root.PointToScreen(pArgs.Position);
if (!enlargedPopupRect?.Contains(new Point(pt.X, pt.Y)) ?? false)
{
Hide(false);
HideCore(false);
enlargedPopupRect = null;
transientDisposable?.Dispose();
transientDisposable = null;
@ -262,9 +282,11 @@ namespace Avalonia.Controls.Primitives
}
else if (_popup?.Host is OverlayPopupHost)
{
// Same as above here, but just different coordinate space
// so we don't need to translate
if (!enlargedPopupRect?.Contains(pArgs.Position) ?? false)
{
Hide(false);
HideCore(false);
enlargedPopupRect = null;
transientDisposable?.Dispose();
transientDisposable = null;
@ -316,7 +338,7 @@ namespace Avalonia.Controls.Primitives
private void OnPopupClosed(object sender, EventArgs e)
{
Hide();
HideCore();
}
private void PositionPopup(bool showAtPointer)
@ -418,12 +440,6 @@ namespace Avalonia.Controls.Primitives
_popup.PlacementAnchor = PopupPositioning.PopupAnchor.BottomLeft;
break;
case FlyoutPlacementMode.Full:
//Not sure how the get this to work
//Popup should display at max size in the middle of the VisualRoot/Window of the Target
throw new NotSupportedException("FlyoutPlacementMode.Full is not supported at this time");
//break;
//includes Auto (not sure what determines that)...
default:
//This is just FlyoutPlacementMode.Top behavior (above & centered)
@ -457,6 +473,11 @@ namespace Avalonia.Controls.Primitives
{
if (c.ContextFlyout != null)
{
if (c.ContextMenu != null)
{
Logger.TryGet(LogEventLevel.Verbose, "FlyoutBase")?.Log(c, "ContextMenu and ContextFlyout are both set, defaulting to ContextMenu");
return;
}
c.ContextFlyout.ShowAt(c, true);
}
}

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

@ -22,10 +22,11 @@
/// </summary>
Right = 3,
/// <summary>
/// Preferred location is centered on the screen
/// </summary>
Full = 4,
//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

Loading…
Cancel
Save