// ----------------------------------------------------------------------- // // Copyright 2015 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Controls { using System; using System.Collections.Generic; using System.Linq; using Perspex.Input; using Perspex.Interactivity; /// /// Handles access keys within a /// public class MenuItemAccessKeyHandler : IAccessKeyHandler { /// /// The registered access keys. /// private List> registered = new List>(); /// /// The window to which the handler belongs. /// private IInputRoot owner; /// /// Gets or sets the window's main menu. /// /// /// This property is ignored as a menu item cannot have a main menu. /// public IMainMenu MainMenu { get; set; } /// /// Sets the owner of the access key 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); } /// /// Registers an input element to be associated with an access key. /// /// The access key. /// The input element. public void Register(char accessKey, IInputElement element) { var existing = this.registered.FirstOrDefault(x => x.Item2 == element); if (existing != null) { this.registered.Remove(existing); } this.registered.Add(Tuple.Create(accessKey.ToString().ToUpper(), element)); } /// /// Unregisters the access keys associated with the input element. /// /// The input element. public void Unregister(IInputElement element) { foreach (var i in this.registered.Where(x => x.Item2 == element).ToList()) { this.registered.Remove(i); } } /// /// Handles a key being pressed in the menu. /// /// The event sender. /// The event args. protected virtual void OnKeyDown(object sender, KeyEventArgs e) { if (!string.IsNullOrWhiteSpace(e.Text)) { var text = e.Text.ToUpper(); var focus = this.registered .Where(x => x.Item1 == text && x.Item2.IsEffectivelyVisible) .FirstOrDefault()?.Item2; if (focus != null) { focus.RaiseEvent(new RoutedEventArgs(AccessKeyHandler.AccessKeyPressedEvent)); } e.Handled = true; } } } }