// -----------------------------------------------------------------------
//
// Copyright 2015 MIT Licence. See licence.md for more information.
//
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using System;
using Perspex.Input.Navigation;
///
/// Handles keyboard navigation for a window.
///
public class KeyboardNavigationHandler : IKeyboardNavigationHandler
{
///
/// The window to which the handler belongs.
///
private IInputRoot owner;
///
/// Sets the owner of the keyboard navigation handler.
///
/// The owner.
///
/// This method can only be called once, typically by the owner itself on creation.
///
public void SetOwner(IInputRoot owner)
{
Contract.Requires(owner != null);
if (this.owner != null)
{
throw new InvalidOperationException("AccessKeyHandler owner has already been set.");
}
this.owner = owner;
this.owner.AddHandler(InputElement.KeyDownEvent, this.OnKeyDown);
}
///
/// Gets the next control in the specified navigation direction.
///
/// The element.
/// The navigation direction.
///
/// The next element in the specified direction, or null if
/// was the last in therequested direction.
///
public static IInputElement GetNext(
IInputElement element,
FocusNavigationDirection direction)
{
Contract.Requires(element != null);
if (direction == FocusNavigationDirection.Next || direction == FocusNavigationDirection.Previous)
{
return TabNavigation.GetNextInTabOrder(element, direction);
}
else
{
return DirectionalNavigation.GetNext(element, direction);
}
}
///
/// Moves the focus in the specified direction.
///
/// The current element.
/// The direction to move.
public void Move(IInputElement element, FocusNavigationDirection direction)
{
Contract.Requires(element != null);
var next = GetNext(element, direction);
if (next != null)
{
FocusManager.Instance.Focus(next, true);
}
}
///
/// Handles the Tab key being pressed in the window.
///
/// The event sender.
/// The event args.
protected virtual void OnKeyDown(object sender, KeyEventArgs e)
{
var current = FocusManager.Instance.Current;
if (current != null)
{
FocusNavigationDirection? direction = null;
switch (e.Key)
{
case Key.Tab:
direction = (KeyboardDevice.Instance.Modifiers & ModifierKeys.Shift) == 0 ?
FocusNavigationDirection.Next : FocusNavigationDirection.Previous;
break;
case Key.Up:
direction = FocusNavigationDirection.Up;
break;
case Key.Down:
direction = FocusNavigationDirection.Down;
break;
case Key.Left:
direction = FocusNavigationDirection.Left;
break;
case Key.Right:
direction = FocusNavigationDirection.Right;
break;
}
if (direction.HasValue)
{
this.Move(current, direction.Value);
e.Handled = true;
}
}
}
}
}