// Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; using Perspex.Input.Navigation; namespace Perspex.Input { /// /// 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 (_owner != null) { throw new InvalidOperationException("AccessKeyHandler owner has already been set."); } _owner = owner; _owner.AddHandler(InputElement.KeyDownEvent, 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. /// Any input modifiers active at the time of focus. public void Move( IInputElement element, FocusNavigationDirection direction, InputModifiers modifiers = InputModifiers.None) { Contract.Requires(element != null); var next = GetNext(element, direction); if (next != null) { var method = direction == FocusNavigationDirection.Next || direction == FocusNavigationDirection.Previous ? NavigationMethod.Tab : NavigationMethod.Directional; FocusManager.Instance.Focus(next, method, modifiers); } } /// /// 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 = (e.Modifiers & InputModifiers.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) { Move(current, direction.Value, e.Modifiers); e.Handled = true; } } } } }