// ----------------------------------------------------------------------- // // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Input { using System; using System.Collections.Generic; using System.Linq; using Perspex.Interactivity; using Perspex.VisualTree; using Splat; public class FocusManager : IFocusManager { private Dictionary focusScopes = new Dictionary(); public static IFocusManager Instance { get { return Locator.Current.GetService(); } } public IInputElement Current { get { return KeyboardDevice.Instance.FocusedElement; } } public IFocusScope Scope { get; private set; } /// /// Focuses a control. /// /// The control to focus. /// /// Whether the control was focused by a keypress (e.g. the Tab key). /// public void Focus(IInputElement control, bool keyboardNavigated = false) { if (control != null) { var scope = control.GetSelfAndVisualAncestors() .OfType() .FirstOrDefault(); if (scope != null) { this.SetFocusedElement(scope, control, keyboardNavigated); } } else { this.SetFocusedElement(this.Scope, null); } } /// /// Sets the currently focused element in the specified scope. /// /// The focus scope. /// The element to focus. May be null. /// /// Whether the control was focused by a keypress (e.g. the Tab key). /// /// /// If the specified scope is the current then the keyboard focus /// will change. /// public void SetFocusedElement( IFocusScope scope, IInputElement element, bool keyboardNavigated = false) { Contract.Requires(scope != null); this.focusScopes[scope] = element; if (this.Scope == scope) { KeyboardDevice.Instance.SetFocusedElement(element, keyboardNavigated); } } /// /// Notifies the focus manager of a change in focus scope. /// /// The new focus scope. public void SetFocusScope(IFocusScope scope) { Contract.Requires(scope != null); IInputElement e; if (!this.focusScopes.TryGetValue(scope, out e)) { // TODO: Make this do something useful, i.e. select the first focusable // control, select a control that the user has specified to have default // focus etc. e = scope as IInputElement; this.focusScopes.Add(scope, e); } this.Scope = scope; this.Focus(e); } } }