|
@@ -1,4 +1,5 @@
|
|
using System;
|
|
using System;
|
|
|
|
+using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using System.Linq;
|
|
using Avalonia.Input.Navigation;
|
|
using Avalonia.Input.Navigation;
|
|
using Avalonia.VisualTree;
|
|
using Avalonia.VisualTree;
|
|
@@ -48,43 +49,24 @@ namespace Avalonia.Input
|
|
{
|
|
{
|
|
element = element ?? throw new ArgumentNullException(nameof(element));
|
|
element = element ?? throw new ArgumentNullException(nameof(element));
|
|
|
|
|
|
- var customHandler = element.GetSelfAndVisualAncestors()
|
|
|
|
- .OfType<ICustomKeyboardNavigation>()
|
|
|
|
- .FirstOrDefault();
|
|
|
|
|
|
+ // If there's a custom keyboard navigation handler as an ancestor, use that.
|
|
|
|
+ var custom = element.FindAncestorOfType<ICustomKeyboardNavigation>(true);
|
|
|
|
+ if (custom is object && HandlePreCustomNavigation(custom, element, direction, out var ce))
|
|
|
|
+ return ce;
|
|
|
|
|
|
- if (customHandler != null)
|
|
|
|
- {
|
|
|
|
- var (handled, next) = customHandler.GetNext(element, direction);
|
|
|
|
-
|
|
|
|
- if (handled)
|
|
|
|
- {
|
|
|
|
- if (next != null)
|
|
|
|
- {
|
|
|
|
- return next;
|
|
|
|
- }
|
|
|
|
- else if (direction == NavigationDirection.Next || direction == NavigationDirection.Previous)
|
|
|
|
- {
|
|
|
|
- var e = (IInputElement)customHandler;
|
|
|
|
- return direction switch
|
|
|
|
- {
|
|
|
|
- NavigationDirection.Next => TabNavigation.GetNextTab(e, false),
|
|
|
|
- NavigationDirection.Previous => TabNavigation.GetPrevTab(e, null, false),
|
|
|
|
- _ => throw new NotSupportedException(),
|
|
|
|
- };
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return direction switch
|
|
|
|
|
|
+ var result = direction switch
|
|
{
|
|
{
|
|
NavigationDirection.Next => TabNavigation.GetNextTab(element, false),
|
|
NavigationDirection.Next => TabNavigation.GetNextTab(element, false),
|
|
NavigationDirection.Previous => TabNavigation.GetPrevTab(element, null, false),
|
|
NavigationDirection.Previous => TabNavigation.GetPrevTab(element, null, false),
|
|
_ => throw new NotSupportedException(),
|
|
_ => throw new NotSupportedException(),
|
|
};
|
|
};
|
|
|
|
+
|
|
|
|
+ // If there wasn't a custom navigation handler as an ancestor of the current element,
|
|
|
|
+ // but there is one as an ancestor of the new element, use that.
|
|
|
|
+ if (custom is null && HandlePostCustomNavigation(element, result, direction, out ce))
|
|
|
|
+ return ce;
|
|
|
|
+
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
@@ -94,7 +76,7 @@ namespace Avalonia.Input
|
|
/// <param name="direction">The direction to move.</param>
|
|
/// <param name="direction">The direction to move.</param>
|
|
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
|
|
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
|
|
public void Move(
|
|
public void Move(
|
|
- IInputElement element,
|
|
|
|
|
|
+ IInputElement element,
|
|
NavigationDirection direction,
|
|
NavigationDirection direction,
|
|
KeyModifiers keyModifiers = KeyModifiers.None)
|
|
KeyModifiers keyModifiers = KeyModifiers.None)
|
|
{
|
|
{
|
|
@@ -128,5 +110,70 @@ namespace Avalonia.Input
|
|
e.Handled = true;
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ private static bool HandlePreCustomNavigation(
|
|
|
|
+ ICustomKeyboardNavigation customHandler,
|
|
|
|
+ IInputElement element,
|
|
|
|
+ NavigationDirection direction,
|
|
|
|
+ [NotNullWhen(true)] out IInputElement? result)
|
|
|
|
+ {
|
|
|
|
+ if (customHandler != null)
|
|
|
|
+ {
|
|
|
|
+ var (handled, next) = customHandler.GetNext(element, direction);
|
|
|
|
+
|
|
|
|
+ if (handled)
|
|
|
|
+ {
|
|
|
|
+ if (next != null)
|
|
|
|
+ {
|
|
|
|
+ result = next;
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ else if (direction == NavigationDirection.Next || direction == NavigationDirection.Previous)
|
|
|
|
+ {
|
|
|
|
+ var r = direction switch
|
|
|
|
+ {
|
|
|
|
+ NavigationDirection.Next => TabNavigation.GetNextTabOutside(customHandler),
|
|
|
|
+ NavigationDirection.Previous => TabNavigation.GetPrevTabOutside(customHandler),
|
|
|
|
+ _ => throw new NotSupportedException(),
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ if (r is object)
|
|
|
|
+ {
|
|
|
|
+ result = r;
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ result = null;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static bool HandlePostCustomNavigation(
|
|
|
|
+ IInputElement element,
|
|
|
|
+ IInputElement? newElement,
|
|
|
|
+ NavigationDirection direction,
|
|
|
|
+ [NotNullWhen(true)] out IInputElement? result)
|
|
|
|
+ {
|
|
|
|
+ if (newElement is object)
|
|
|
|
+ {
|
|
|
|
+ var customHandler = newElement.FindAncestorOfType<ICustomKeyboardNavigation>(true);
|
|
|
|
+
|
|
|
|
+ if (customHandler is object)
|
|
|
|
+ {
|
|
|
|
+ var (handled, next) = customHandler.GetNext(element, direction);
|
|
|
|
+
|
|
|
|
+ if (handled && next is object)
|
|
|
|
+ {
|
|
|
|
+ result = next;
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ result = null;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|