|
|
|
@ -6,6 +6,8 @@ using Avalonia.LogicalTree; |
|
|
|
using Avalonia.Rendering; |
|
|
|
using Avalonia.Threading; |
|
|
|
|
|
|
|
#nullable enable |
|
|
|
|
|
|
|
namespace Avalonia.Controls.Platform |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
@ -14,8 +16,8 @@ namespace Avalonia.Controls.Platform |
|
|
|
public class DefaultMenuInteractionHandler : IMenuInteractionHandler |
|
|
|
{ |
|
|
|
private readonly bool _isContextMenu; |
|
|
|
private IDisposable _inputManagerSubscription; |
|
|
|
private IRenderRoot _root; |
|
|
|
private IDisposable? _inputManagerSubscription; |
|
|
|
private IRenderRoot? _root; |
|
|
|
|
|
|
|
public DefaultMenuInteractionHandler(bool isContextMenu) |
|
|
|
: this(isContextMenu, Input.InputManager.Instance, DefaultDelayRun) |
|
|
|
@ -24,9 +26,11 @@ namespace Avalonia.Controls.Platform |
|
|
|
|
|
|
|
public DefaultMenuInteractionHandler( |
|
|
|
bool isContextMenu, |
|
|
|
IInputManager inputManager, |
|
|
|
IInputManager? inputManager, |
|
|
|
Action<Action, TimeSpan> delayRun) |
|
|
|
{ |
|
|
|
delayRun = delayRun ?? throw new ArgumentNullException(nameof(delayRun)); |
|
|
|
|
|
|
|
_isContextMenu = isContextMenu; |
|
|
|
InputManager = inputManager; |
|
|
|
DelayRun = delayRun; |
|
|
|
@ -92,7 +96,7 @@ namespace Avalonia.Controls.Platform |
|
|
|
root.Deactivated -= WindowDeactivated; |
|
|
|
} |
|
|
|
|
|
|
|
_inputManagerSubscription.Dispose(); |
|
|
|
_inputManagerSubscription!.Dispose(); |
|
|
|
|
|
|
|
Menu = null; |
|
|
|
_root = null; |
|
|
|
@ -100,9 +104,9 @@ namespace Avalonia.Controls.Platform |
|
|
|
|
|
|
|
protected Action<Action, TimeSpan> DelayRun { get; } |
|
|
|
|
|
|
|
protected IInputManager InputManager { get; } |
|
|
|
protected IInputManager? InputManager { get; } |
|
|
|
|
|
|
|
protected IMenu Menu { get; private set; } |
|
|
|
protected IMenu? Menu { get; private set; } |
|
|
|
|
|
|
|
protected static TimeSpan MenuShowDelay { get; } = TimeSpan.FromMilliseconds(400); |
|
|
|
|
|
|
|
@ -131,7 +135,7 @@ namespace Avalonia.Controls.Platform |
|
|
|
KeyDown(GetMenuItem(e.Source as IControl), e); |
|
|
|
} |
|
|
|
|
|
|
|
protected internal virtual void KeyDown(IMenuItem item, KeyEventArgs e) |
|
|
|
protected internal virtual void KeyDown(IMenuItem? item, KeyEventArgs e) |
|
|
|
{ |
|
|
|
switch (e.Key) |
|
|
|
{ |
|
|
|
@ -200,7 +204,7 @@ namespace Avalonia.Controls.Platform |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
Menu.Close(); |
|
|
|
Menu!.Close(); |
|
|
|
} |
|
|
|
|
|
|
|
e.Handled = true; |
|
|
|
@ -213,12 +217,12 @@ namespace Avalonia.Controls.Platform |
|
|
|
{ |
|
|
|
if (item == null && _isContextMenu) |
|
|
|
{ |
|
|
|
if (Menu.MoveSelection(direction.Value, true) == true) |
|
|
|
if (Menu!.MoveSelection(direction.Value, true) == true) |
|
|
|
{ |
|
|
|
e.Handled = true; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (item.Parent?.MoveSelection(direction.Value, true) == true) |
|
|
|
else if (item?.Parent?.MoveSelection(direction.Value, true) == true) |
|
|
|
{ |
|
|
|
// If the the parent is an IMenu which successfully moved its selection,
|
|
|
|
// and the current menu is open then close the current menu and open the
|
|
|
|
@ -408,7 +412,7 @@ namespace Avalonia.Controls.Platform |
|
|
|
|
|
|
|
protected void CloseMenu(IMenuItem item) |
|
|
|
{ |
|
|
|
var current = (IMenuElement)item; |
|
|
|
var current = (IMenuElement?)item; |
|
|
|
|
|
|
|
while (current != null && !(current is IMenu)) |
|
|
|
{ |
|
|
|
@ -456,7 +460,7 @@ namespace Avalonia.Controls.Platform |
|
|
|
|
|
|
|
protected void SelectItemAndAncestors(IMenuItem item) |
|
|
|
{ |
|
|
|
var current = item; |
|
|
|
var current = (IMenuItem?)item; |
|
|
|
|
|
|
|
while (current?.Parent != null) |
|
|
|
{ |
|
|
|
@ -465,7 +469,7 @@ namespace Avalonia.Controls.Platform |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected static IMenuItem GetMenuItem(IControl item) |
|
|
|
protected static IMenuItem? GetMenuItem(IControl? item) |
|
|
|
{ |
|
|
|
while (true) |
|
|
|
{ |
|
|
|
|