committed by
GitHub
11 changed files with 410 additions and 30 deletions
@ -0,0 +1,15 @@ |
|||
// 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; |
|||
|
|||
namespace Avalonia.Input |
|||
{ |
|||
/// <summary>
|
|||
/// Designates a control as handling its own keyboard navigation.
|
|||
/// </summary>
|
|||
public interface ICustomKeyboardNavigation |
|||
{ |
|||
(bool handled, IInputElement next) GetNext(IInputElement element, NavigationDirection direction); |
|||
} |
|||
} |
|||
@ -0,0 +1,214 @@ |
|||
// 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_Custom |
|||
{ |
|||
[Fact] |
|||
public void Tab_Should_Custom_Navigate_Within_Children() |
|||
{ |
|||
Button current; |
|||
Button next; |
|||
var target = new CustomNavigatingStackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
(current = new Button { Content = "Button 1" }), |
|||
new Button { Content = "Button 2" }, |
|||
(next = new Button { Content = "Button 3" }), |
|||
}, |
|||
NextControl = next, |
|||
}; |
|||
|
|||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Next); |
|||
|
|||
Assert.Same(next, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Right_Should_Custom_Navigate_Within_Children() |
|||
{ |
|||
Button current; |
|||
Button next; |
|||
var target = new CustomNavigatingStackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
(current = new Button { Content = "Button 1" }), |
|||
new Button { Content = "Button 2" }, |
|||
(next = new Button { Content = "Button 3" }), |
|||
}, |
|||
NextControl = next, |
|||
}; |
|||
|
|||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Right); |
|||
|
|||
Assert.Same(next, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Tab_Should_Custom_Navigate_From_Outside() |
|||
{ |
|||
Button current; |
|||
Button next; |
|||
var target = new CustomNavigatingStackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
new Button { Content = "Button 1" }, |
|||
new Button { Content = "Button 2" }, |
|||
(next = new Button { Content = "Button 3" }), |
|||
}, |
|||
NextControl = next, |
|||
}; |
|||
|
|||
var root = new StackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
(current = new Button { Content = "Outside" }), |
|||
target, |
|||
} |
|||
}; |
|||
|
|||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Next); |
|||
|
|||
Assert.Same(next, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Tab_Should_Custom_Navigate_From_Outside_When_Wrapping() |
|||
{ |
|||
Button current; |
|||
Button next; |
|||
var target = new CustomNavigatingStackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
new Button { Content = "Button 1" }, |
|||
new Button { Content = "Button 2" }, |
|||
(next = new Button { Content = "Button 3" }), |
|||
}, |
|||
NextControl = next, |
|||
}; |
|||
|
|||
var root = new StackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
target, |
|||
(current = new Button { Content = "Outside" }), |
|||
} |
|||
}; |
|||
|
|||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Next); |
|||
|
|||
Assert.Same(next, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ShiftTab_Should_Custom_Navigate_From_Outside() |
|||
{ |
|||
Button current; |
|||
Button next; |
|||
var target = new CustomNavigatingStackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
new Button { Content = "Button 1" }, |
|||
new Button { Content = "Button 2" }, |
|||
(next = new Button { Content = "Button 3" }), |
|||
}, |
|||
NextControl = next, |
|||
}; |
|||
|
|||
var root = new StackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
(current = new Button { Content = "Outside" }), |
|||
target, |
|||
} |
|||
}; |
|||
|
|||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Previous); |
|||
|
|||
Assert.Same(next, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Right_Should_Custom_Navigate_From_Outside() |
|||
{ |
|||
Button current; |
|||
Button next; |
|||
var target = new CustomNavigatingStackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
new Button { Content = "Button 1" }, |
|||
new Button { Content = "Button 2" }, |
|||
(next = new Button { Content = "Button 3" }), |
|||
}, |
|||
NextControl = next, |
|||
}; |
|||
|
|||
var root = new StackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
(current = new Button { Content = "Outside" }), |
|||
target, |
|||
}, |
|||
[KeyboardNavigation.DirectionalNavigationProperty] = KeyboardNavigationMode.Continue, |
|||
}; |
|||
|
|||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Right); |
|||
|
|||
Assert.Same(next, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Tab_Should_Navigate_Outside_When_Null_Returned_As_Next() |
|||
{ |
|||
Button current; |
|||
Button next; |
|||
var target = new CustomNavigatingStackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
new Button { Content = "Button 1" }, |
|||
(current = new Button { Content = "Button 2" }), |
|||
new Button { Content = "Button 3" }, |
|||
}, |
|||
}; |
|||
|
|||
var root = new StackPanel |
|||
{ |
|||
Children = |
|||
{ |
|||
target, |
|||
(next = new Button { Content = "Outside" }), |
|||
} |
|||
}; |
|||
|
|||
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Next); |
|||
|
|||
Assert.Same(next, result); |
|||
} |
|||
|
|||
private class CustomNavigatingStackPanel : StackPanel, ICustomKeyboardNavigation |
|||
{ |
|||
public bool CustomNavigates { get; set; } = true; |
|||
public IInputElement NextControl { get; set; } |
|||
|
|||
public (bool handled, IInputElement next) GetNext(IInputElement element, NavigationDirection direction) |
|||
{ |
|||
return (CustomNavigates, NextControl); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue