// -----------------------------------------------------------------------
//
// 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 Splat;
public class FocusManager : IFocusManager
{
private Dictionary focusScopes =
new Dictionary();
public static IFocusManager Instance
{
get { return Locator.Current.GetService(); }
}
public IInputElement Current
{
get;
private set;
}
public IFocusScope Scope
{
get;
private set;
}
///
/// Focuses a control.
///
/// The control to focus.
public void Focus(IInputElement control)
{
Contract.Requires(control != null);
var current = this.Current as IInteractive;
var next = control as IInteractive;
var scope = control.GetSelfAndVisualAncestors()
.OfType()
.FirstOrDefault();
if (scope != null && control != current)
{
this.focusScopes[scope] = control;
if (current != null)
{
current.RaiseEvent(new RoutedEventArgs
{
RoutedEvent = InputElement.LostFocusEvent,
Source = current,
OriginalSource = current,
});
}
this.Current = control;
IKeyboardDevice keyboard = Locator.Current.GetService();
if (keyboard != null)
{
keyboard.FocusedElement = control;
}
if (next != null)
{
next.RaiseEvent(new RoutedEventArgs
{
RoutedEvent = InputElement.GotFocusEvent,
Source = next,
OriginalSource = next,
});
}
}
}
///
/// Notifies the focus manager of a change in focus scope.
///
/// The new focus scope.
///
/// This should not be called by client code. It is called by an
/// when it activates, e.g. when a Window is activated.
///
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);
}
}
}