Browse Source

Added KeyboardNavigationMode.Contained.

pull/72/merge
Steven Kirk 11 years ago
parent
commit
2472bf26cc
  1. 6
      Perspex.Input/KeyboardNavigationHandler.cs
  2. 32
      Perspex.Input/KeyboardNavigationMode.cs
  3. 13
      Tests/Perspex.Input.UnitTests/GlobalSuppressions.cs
  4. 160
      Tests/Perspex.Input.UnitTests/KeyboardNavigationTests_Tab.cs
  5. 3
      Tests/Perspex.Input.UnitTests/Perspex.Input.UnitTests.csproj

6
Perspex.Input/KeyboardNavigationHandler.cs

@ -65,6 +65,8 @@ namespace Perspex.Input
case KeyboardNavigationMode.Cycle: case KeyboardNavigationMode.Cycle:
return GetNextInContainer(element, container) ?? return GetNextInContainer(element, container) ??
GetDescendents(container).FirstOrDefault(); GetDescendents(container).FirstOrDefault();
case KeyboardNavigationMode.Contained:
return GetNextInContainer(element, container);
default: default:
return GetFirstInNextContainer(container); return GetFirstInNextContainer(container);
} }
@ -98,6 +100,8 @@ namespace Perspex.Input
case KeyboardNavigationMode.Cycle: case KeyboardNavigationMode.Cycle:
return GetPreviousInContainer(element, container) ?? return GetPreviousInContainer(element, container) ??
GetDescendents(container).LastOrDefault(); GetDescendents(container).LastOrDefault();
case KeyboardNavigationMode.Contained:
return GetPreviousInContainer(element, container);
default: default:
return GetLastInPreviousContainer(container); return GetLastInPreviousContainer(container);
} }
@ -164,7 +168,7 @@ namespace Perspex.Input
{ {
var mode = KeyboardNavigation.GetTabNavigation((InputElement)element); var mode = KeyboardNavigation.GetTabNavigation((InputElement)element);
if (mode == KeyboardNavigationMode.Never) if (mode == KeyboardNavigationMode.None)
{ {
yield break; yield break;
} }

32
Perspex.Input/KeyboardNavigationMode.cs

@ -6,11 +6,41 @@
namespace Perspex.Input namespace Perspex.Input
{ {
/// <summary>
/// Defines the mode of keyboard traversal within a container when the tab or arrow keys are
/// pressed.
/// </summary>
public enum KeyboardNavigationMode public enum KeyboardNavigationMode
{ {
/// <summary>
/// Items in the container will be cycled through, and focus will be moved to the
/// previous/next container after the first/last control in the container.
/// </summary>
Continue, Continue,
/// <summary>
/// Items in the container will be cycled through, and moving past the first or last
/// control in the container will cause the last/first control to be focused.
/// </summary>
Cycle, Cycle,
/// <summary>
/// Items in the container will be cycled through and focus will stop moving when the edge
/// of the container is reached.
/// </summary>
Contained,
/// <summary>
/// When focus is moved into the container, the control described by the
/// <see cref="KeyboardNavigation.TabOnceActiveElementProperty"/> attached property on the
/// container will be focused. When focus moves away from this control, focus will move to
/// the previous/next container.
/// </summary>
Once, Once,
Never,
/// <summary>
/// The container's children will not be focused when using the tab key.
/// </summary>
None,
} }
} }

13
Tests/Perspex.Input.UnitTests/GlobalSuppressions.cs

@ -0,0 +1,13 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.MaintainabilityRules",
"SA1401:Fields must be private",
Justification = "PerspexProperty fields should not be private.")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.DocumentationRules",
"SA1600:Elements must be documented",
Justification = "Tests should be self-documenting")]

160
Tests/Perspex.Input.UnitTests/KeyboardNavigationTests.cs → Tests/Perspex.Input.UnitTests/KeyboardNavigationTests_Tab.cs

@ -1,5 +1,5 @@
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// <copyright file="KeyboardNavigationTests.cs" company="Steven Kirk"> // <copyright file="KeyboardNavigationTests_Tab.cs" company="Steven Kirk">
// Copyright 2015 MIT Licence. See licence.md for more information. // Copyright 2015 MIT Licence. See licence.md for more information.
// </copyright> // </copyright>
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@ -9,7 +9,7 @@ namespace Perspex.Input.UnitTests
using Perspex.Controls; using Perspex.Controls;
using Xunit; using Xunit;
public class KeyboardNavigationTests public class KeyboardNavigationTests_Tab
{ {
[Fact] [Fact]
public void GetNextInTabOrder_Continue_Returns_Next_Control_In_Container() public void GetNextInTabOrder_Continue_Returns_Next_Control_In_Container()
@ -294,6 +294,82 @@ namespace Perspex.Input.UnitTests
Assert.Equal(next, result); Assert.Equal(next, result);
} }
[Fact]
public void GetNextInTabOrder_Contained_Returns_Next_Control_In_Container()
{
StackPanel container;
Button current;
Button next;
var top = new StackPanel
{
Children = new Controls
{
(container = new StackPanel
{
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Contained,
Children = new Controls
{
new Button { Name = "Button1" },
(current = new Button { Name = "Button2" }),
(next = new Button { Name = "Button3" }),
}
}),
new StackPanel
{
Children = new Controls
{
new Button { Name = "Button4" },
new Button { Name = "Button5" },
new Button { Name = "Button6" },
}
},
}
};
var result = KeyboardNavigationHandler.GetNextInTabOrder(current);
Assert.Equal(next, result);
}
[Fact]
public void GetNextInTabOrder_Contained_Stops_At_End()
{
StackPanel container;
Button current;
Button next;
var top = new StackPanel
{
Children = new Controls
{
(container = new StackPanel
{
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Contained,
Children = new Controls
{
(next = new Button { Name = "Button1" }),
new Button { Name = "Button2" },
(current = new Button { Name = "Button3" }),
}
}),
new StackPanel
{
Children = new Controls
{
new Button { Name = "Button4" },
new Button { Name = "Button5" },
new Button { Name = "Button6" },
}
},
}
};
var result = KeyboardNavigationHandler.GetNextInTabOrder(current);
Assert.Null(result);
}
[Fact] [Fact]
public void GetNextInTabOrder_Once_Moves_To_Next_Container() public void GetNextInTabOrder_Once_Moves_To_Next_Container()
{ {
@ -385,7 +461,7 @@ namespace Perspex.Input.UnitTests
{ {
(container = new StackPanel (container = new StackPanel
{ {
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Never, [KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.None,
Children = new Controls Children = new Controls
{ {
new Button { Name = "Button1" }, new Button { Name = "Button1" },
@ -423,7 +499,7 @@ namespace Perspex.Input.UnitTests
{ {
(container = new StackPanel (container = new StackPanel
{ {
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Never, [KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.None,
Children = new Controls Children = new Controls
{ {
new Button { Name = "Button1" }, new Button { Name = "Button1" },
@ -715,6 +791,82 @@ namespace Perspex.Input.UnitTests
Assert.Equal(next, result); Assert.Equal(next, result);
} }
[Fact]
public void GetPreviousInTabOrder_Contained_Returns_Previous_Control_In_Container()
{
StackPanel container;
Button current;
Button next;
var top = new StackPanel
{
Children = new Controls
{
(container = new StackPanel
{
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Contained,
Children = new Controls
{
(next = new Button { Name = "Button1" }),
(current = new Button { Name = "Button2" }),
new Button { Name = "Button3" },
}
}),
new StackPanel
{
Children = new Controls
{
new Button { Name = "Button4" },
new Button { Name = "Button5" },
new Button { Name = "Button6" },
}
},
}
};
var result = KeyboardNavigationHandler.GetPreviousInTabOrder(current);
Assert.Equal(next, result);
}
[Fact]
public void GetPreviousInTabOrder_Contained_Stops_At_Beginning()
{
StackPanel container;
Button current;
Button next;
var top = new StackPanel
{
Children = new Controls
{
(container = new StackPanel
{
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Contained,
Children = new Controls
{
(current = new Button { Name = "Button1" }),
new Button { Name = "Button2" },
(next = new Button { Name = "Button3" }),
}
}),
new StackPanel
{
Children = new Controls
{
new Button { Name = "Button4" },
new Button { Name = "Button5" },
new Button { Name = "Button6" },
}
},
}
};
var result = KeyboardNavigationHandler.GetPreviousInTabOrder(current);
Assert.Null(result);
}
[Fact] [Fact]
public void GetPreviousInTabOrder_Once_Moves_To_Previous_Container() public void GetPreviousInTabOrder_Once_Moves_To_Previous_Container()
{ {

3
Tests/Perspex.Input.UnitTests/Perspex.Input.UnitTests.csproj

@ -59,7 +59,8 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="KeyboardNavigationTests.cs" /> <Compile Include="GlobalSuppressions.cs" />
<Compile Include="KeyboardNavigationTests_Tab.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

Loading…
Cancel
Save