8 changed files with 9 additions and 1162 deletions
@ -1,242 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using Avalonia.VisualTree; |
|
||||
|
|
||||
namespace Avalonia.Input.Navigation |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// The implementation for default directional navigation.
|
|
||||
/// </summary>
|
|
||||
public static class DirectionalNavigation |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Gets the next control in the specified navigation direction.
|
|
||||
/// </summary>
|
|
||||
/// <param name="element">The element.</param>
|
|
||||
/// <param name="direction">The navigation direction.</param>
|
|
||||
/// <returns>
|
|
||||
/// The next element in the specified direction, or null if <paramref name="element"/>
|
|
||||
/// was the last in the requested direction.
|
|
||||
/// </returns>
|
|
||||
public static IInputElement GetNext( |
|
||||
IInputElement element, |
|
||||
NavigationDirection direction) |
|
||||
{ |
|
||||
Contract.Requires<ArgumentNullException>(element != null); |
|
||||
Contract.Requires<ArgumentException>( |
|
||||
direction != NavigationDirection.Next && |
|
||||
direction != NavigationDirection.Previous); |
|
||||
|
|
||||
var container = element.GetVisualParent<IInputElement>(); |
|
||||
|
|
||||
if (container != null) |
|
||||
{ |
|
||||
var mode = KeyboardNavigation.GetDirectionalNavigation((InputElement)container); |
|
||||
|
|
||||
switch (mode) |
|
||||
{ |
|
||||
case KeyboardNavigationMode.Continue: |
|
||||
return GetNextInContainer(element, container, direction) ?? |
|
||||
GetFirstInNextContainer(element, element, direction); |
|
||||
case KeyboardNavigationMode.Cycle: |
|
||||
return GetNextInContainer(element, container, direction) ?? |
|
||||
GetFocusableDescendant(container, direction); |
|
||||
case KeyboardNavigationMode.Contained: |
|
||||
return GetNextInContainer(element, container, direction); |
|
||||
default: |
|
||||
return null; |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
return GetFocusableDescendants(element).FirstOrDefault(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns a value indicting whether the specified direction is forward.
|
|
||||
/// </summary>
|
|
||||
/// <param name="direction">The direction.</param>
|
|
||||
/// <returns>True if the direction is forward.</returns>
|
|
||||
private static bool IsForward(NavigationDirection direction) |
|
||||
{ |
|
||||
return direction == NavigationDirection.Next || |
|
||||
direction == NavigationDirection.Last || |
|
||||
direction == NavigationDirection.Right || |
|
||||
direction == NavigationDirection.Down; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the first or last focusable descendant of the specified element.
|
|
||||
/// </summary>
|
|
||||
/// <param name="container">The element.</param>
|
|
||||
/// <param name="direction">The direction to search.</param>
|
|
||||
/// <returns>The element or null if not found.##</returns>
|
|
||||
private static IInputElement GetFocusableDescendant(IInputElement container, NavigationDirection direction) |
|
||||
{ |
|
||||
return IsForward(direction) ? |
|
||||
GetFocusableDescendants(container).FirstOrDefault() : |
|
||||
GetFocusableDescendants(container).LastOrDefault(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the focusable descendants of the specified element.
|
|
||||
/// </summary>
|
|
||||
/// <param name="element">The element.</param>
|
|
||||
/// <returns>The element's focusable descendants.</returns>
|
|
||||
private static IEnumerable<IInputElement> GetFocusableDescendants(IInputElement element) |
|
||||
{ |
|
||||
var children = element.GetVisualChildren().OfType<IInputElement>(); |
|
||||
|
|
||||
foreach (var child in children) |
|
||||
{ |
|
||||
if (child.CanFocus()) |
|
||||
{ |
|
||||
yield return child; |
|
||||
} |
|
||||
|
|
||||
if (child.CanFocusDescendants()) |
|
||||
{ |
|
||||
foreach (var descendant in GetFocusableDescendants(child)) |
|
||||
{ |
|
||||
yield return descendant; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the next item that should be focused in the specified container.
|
|
||||
/// </summary>
|
|
||||
/// <param name="element">The starting element/</param>
|
|
||||
/// <param name="container">The container.</param>
|
|
||||
/// <param name="direction">The direction.</param>
|
|
||||
/// <returns>The next element, or null if the element is the last.</returns>
|
|
||||
private static IInputElement GetNextInContainer( |
|
||||
IInputElement element, |
|
||||
IInputElement container, |
|
||||
NavigationDirection direction) |
|
||||
{ |
|
||||
if (direction == NavigationDirection.Down) |
|
||||
{ |
|
||||
var descendant = GetFocusableDescendants(element).FirstOrDefault(); |
|
||||
|
|
||||
if (descendant != null) |
|
||||
{ |
|
||||
return descendant; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (container != null) |
|
||||
{ |
|
||||
var navigable = container as INavigableContainer; |
|
||||
|
|
||||
if (navigable != null) |
|
||||
{ |
|
||||
while (element != null) |
|
||||
{ |
|
||||
element = navigable.GetControl(direction, element); |
|
||||
|
|
||||
if (element != null && element.CanFocus()) |
|
||||
{ |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
// TODO: Do a spatial search here if the container doesn't implement
|
|
||||
// INavigableContainer.
|
|
||||
element = null; |
|
||||
} |
|
||||
|
|
||||
if (element != null && direction == NavigationDirection.Up) |
|
||||
{ |
|
||||
var descendant = GetFocusableDescendants(element).LastOrDefault(); |
|
||||
|
|
||||
if (descendant != null) |
|
||||
{ |
|
||||
return descendant; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return element; |
|
||||
} |
|
||||
|
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the first item that should be focused in the next container.
|
|
||||
/// </summary>
|
|
||||
/// <param name="element">The element being navigated away from.</param>
|
|
||||
/// <param name="container">The container.</param>
|
|
||||
/// <param name="direction">The direction of the search.</param>
|
|
||||
/// <returns>The first element, or null if there are no more elements.</returns>
|
|
||||
private static IInputElement GetFirstInNextContainer( |
|
||||
IInputElement element, |
|
||||
IInputElement container, |
|
||||
NavigationDirection direction) |
|
||||
{ |
|
||||
var parent = container.GetVisualParent<IInputElement>(); |
|
||||
var isForward = IsForward(direction); |
|
||||
IInputElement next = null; |
|
||||
|
|
||||
if (parent != null) |
|
||||
{ |
|
||||
if (!isForward && parent.CanFocus()) |
|
||||
{ |
|
||||
return parent; |
|
||||
} |
|
||||
|
|
||||
var siblings = parent.GetVisualChildren() |
|
||||
.OfType<IInputElement>() |
|
||||
.Where(FocusExtensions.CanFocusDescendants); |
|
||||
var sibling = isForward ? |
|
||||
siblings.SkipWhile(x => x != container).Skip(1).FirstOrDefault() : |
|
||||
siblings.TakeWhile(x => x != container).LastOrDefault(); |
|
||||
|
|
||||
if (sibling != null) |
|
||||
{ |
|
||||
if (sibling is ICustomKeyboardNavigation custom) |
|
||||
{ |
|
||||
var (handled, customNext) = custom.GetNext(element, direction); |
|
||||
|
|
||||
if (handled) |
|
||||
{ |
|
||||
return customNext; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (sibling.CanFocus()) |
|
||||
{ |
|
||||
next = sibling; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
next = isForward ? |
|
||||
GetFocusableDescendants(sibling).FirstOrDefault() : |
|
||||
GetFocusableDescendants(sibling).LastOrDefault(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (next == null) |
|
||||
{ |
|
||||
next = GetFirstInNextContainer(element, parent, direction); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
next = isForward ? |
|
||||
GetFocusableDescendants(container).FirstOrDefault() : |
|
||||
GetFocusableDescendants(container).LastOrDefault(); |
|
||||
} |
|
||||
|
|
||||
return next; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,799 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using Avalonia.Controls; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Avalonia.Input.UnitTests |
|
||||
{ |
|
||||
public class KeyboardNavigationTests_Arrows |
|
||||
{ |
|
||||
[Fact] |
|
||||
public void Down_Continue_Returns_Down_Control_In_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
(current = new Button { Name = "Button2" }), |
|
||||
(next = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_Continue_Returns_First_Control_In_Down_Sibling_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
new Button { Name = "Button2" }, |
|
||||
(current = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
(next = new Button { Name = "Button4" }), |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_Continue_Returns_Down_Sibling() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
new Button { Name = "Button2" }, |
|
||||
(current = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
(next = new Button { Name = "Button4" }), |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_Continue_Returns_First_Control_In_Down_Uncle_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
new Button { Name = "Button2" }, |
|
||||
(current = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
(next = new Button { Name = "Button4" }), |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_Continue_Returns_Child_Of_Top_Level() |
|
||||
{ |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
(next = new Button { Name = "Button1" }), |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(top, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_Continue_Wraps() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
(next = new Button { Name = "Button1" }), |
|
||||
new Button { Name = "Button2" }, |
|
||||
new Button { Name = "Button3" }, |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
(current = new Button { Name = "Button6" }), |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_Cycle_Returns_Down_Control_In_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Cycle, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
(current = new Button { Name = "Button2" }), |
|
||||
(next = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_Cycle_Wraps_To_First() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Cycle, |
|
||||
Children = |
|
||||
{ |
|
||||
(next = new Button { Name = "Button1" }), |
|
||||
new Button { Name = "Button2" }, |
|
||||
(current = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_Contained_Returns_Down_Control_In_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
(current = new Button { Name = "Button2" }), |
|
||||
(next = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_Contained_Stops_At_End() |
|
||||
{ |
|
||||
Button current; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
new Button { Name = "Button2" }, |
|
||||
(current = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Null(result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Down_None_Does_Nothing() |
|
||||
{ |
|
||||
Button current; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.None, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
(current = new Button { Name = "Button2" }), |
|
||||
new Button { Name = "Button3" }, |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down); |
|
||||
|
|
||||
Assert.Null(result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Continue_Returns_Up_Control_In_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
(next = new Button { Name = "Button2" }), |
|
||||
(current = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Continue_Returns_Last_Control_In_Up_Sibling_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
new Button { Name = "Button2" }, |
|
||||
(next = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
(current = new Button { Name = "Button4" }), |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Continue_Returns_Last_Child_Of_Sibling() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
new Button { Name = "Button2" }, |
|
||||
(next = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
(current = new Button { Name = "Button4" }), |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Continue_Returns_Last_Control_In_Up_Nephew_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button1" }, |
|
||||
new Button { Name = "Button2" }, |
|
||||
(next = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
(current = new Button { Name = "Button4" }), |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Continue_Wraps() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
(current = new Button { Name = "Button1" }), |
|
||||
new Button { Name = "Button2" }, |
|
||||
new Button { Name = "Button3" }, |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
(next = new Button { Name = "Button6" }), |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Continue_Returns_Parent() |
|
||||
{ |
|
||||
Button current; |
|
||||
|
|
||||
var top = new Decorator |
|
||||
{ |
|
||||
Focusable = true, |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|
||||
Child = current = new Button |
|
||||
{ |
|
||||
Name = "Button", |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Equal(top, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Cycle_Returns_Up_Control_In_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Cycle, |
|
||||
Children = |
|
||||
{ |
|
||||
(next = new Button { Name = "Button1" }), |
|
||||
(current = new Button { Name = "Button2" }), |
|
||||
new Button { Name = "Button3" }, |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Cycle, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Cycle_Wraps_To_Last() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Cycle, |
|
||||
Children = |
|
||||
{ |
|
||||
(current = new Button { Name = "Button1" }), |
|
||||
new Button { Name = "Button2" }, |
|
||||
(next = new Button { Name = "Button3" }), |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Cycle, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Contained_Returns_Up_Control_In_Container() |
|
||||
{ |
|
||||
Button current; |
|
||||
Button next; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
(next = new Button { Name = "Button1" }), |
|
||||
(current = new Button { Name = "Button2" }), |
|
||||
new Button { Name = "Button3" }, |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Equal(next, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Contained_Stops_At_Beginning() |
|
||||
{ |
|
||||
Button current; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
Children = |
|
||||
{ |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
(current = new Button { Name = "Button1" }), |
|
||||
new Button { Name = "Button2" }, |
|
||||
new Button { Name = "Button3" }, |
|
||||
} |
|
||||
}, |
|
||||
new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
new Button { Name = "Button4" }, |
|
||||
new Button { Name = "Button5" }, |
|
||||
new Button { Name = "Button6" }, |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Null(result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Up_Contained_Doesnt_Return_Child_Control() |
|
||||
{ |
|
||||
Decorator current; |
|
||||
|
|
||||
var top = new StackPanel |
|
||||
{ |
|
||||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Contained, |
|
||||
Children = |
|
||||
{ |
|
||||
(current = new Decorator |
|
||||
{ |
|
||||
Focusable = true, |
|
||||
Child = new Button(), |
|
||||
}) |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Up); |
|
||||
|
|
||||
Assert.Null(result); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue