diff --git a/Perspex/Application.cs b/Perspex/Application.cs index 18a300c086..092f5f5ec2 100644 --- a/Perspex/Application.cs +++ b/Perspex/Application.cs @@ -17,6 +17,7 @@ namespace Perspex public Application() { Current = this; + this.FocusManager = new FocusManager(); this.InputManager = new InputManager(); } @@ -26,6 +27,12 @@ namespace Perspex private set; } + public IFocusManager FocusManager + { + get; + private set; + } + public InputManager InputManager { get; @@ -53,6 +60,7 @@ namespace Perspex public void RegisterServices() { Styler styler = new Styler(); + Locator.CurrentMutable.Register(() => this.FocusManager, typeof(IFocusManager)); Locator.CurrentMutable.Register(() => this.InputManager, typeof(IInputManager)); Locator.CurrentMutable.Register(() => styler, typeof(IStyler)); } diff --git a/Perspex/Controls/Button.cs b/Perspex/Controls/Button.cs index e4ae7ee9a1..36452bab3b 100644 --- a/Perspex/Controls/Button.cs +++ b/Perspex/Controls/Button.cs @@ -13,6 +13,11 @@ namespace Perspex.Controls public static readonly RoutedEvent ClickEvent = RoutedEvent.Register("Click", RoutingStrategy.Bubble); + static Button() + { + FocusableProperty.OverrideDefaultValue(typeof(Button), true); + } + public Button() { this.PointerPressed += (s, e) => diff --git a/Perspex/Controls/Control.cs b/Perspex/Controls/Control.cs index 53b99914b4..c2155b17a4 100644 --- a/Perspex/Controls/Control.cs +++ b/Perspex/Controls/Control.cs @@ -246,7 +246,7 @@ namespace Perspex.Controls public bool IsFocused { get { return this.GetValue(IsFocusedProperty); } - set { this.SetValue(IsFocusedProperty, value); } + internal set { this.SetValue(IsFocusedProperty, value); } } public string Id @@ -356,6 +356,12 @@ namespace Perspex.Controls set { this.SetValue(WidthProperty, value); } } + bool IFocusable.IsFocused + { + get { return this.GetValue(IsFocusedProperty); } + set { this.SetValue(IsFocusedProperty, value); } + } + ILogical ILogical.LogicalParent { get { return this.Parent; } @@ -385,7 +391,7 @@ namespace Perspex.Controls public void Focus() { - this.IsFocused = true; + Locator.Current.GetService().Focus(this); } public void InvalidateArrange() diff --git a/Perspex/Controls/TextBox.cs b/Perspex/Controls/TextBox.cs index f8d9eaef76..ba327f870d 100644 --- a/Perspex/Controls/TextBox.cs +++ b/Perspex/Controls/TextBox.cs @@ -19,10 +19,14 @@ namespace Perspex.Controls private TextBoxView textBoxView; + static TextBox() + { + FocusableProperty.OverrideDefaultValue(typeof(TextBox), true); + } + public TextBox() { this.GetObservable(TextProperty).Subscribe(_ => this.InvalidateVisual()); - FocusableProperty.OverrideDefaultValue(typeof(TextBox), true); } public int CaretIndex diff --git a/Perspex/Input/FocusManager.cs b/Perspex/Input/FocusManager.cs new file mode 100644 index 0000000000..58fc90ce65 --- /dev/null +++ b/Perspex/Input/FocusManager.cs @@ -0,0 +1,31 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Input +{ + public class FocusManager : IFocusManager + { + public IFocusable Current + { + get; + private set; + } + + public void Focus(IFocusable control) + { + if (this.Current != null) + { + this.Current.IsFocused = false; + } + + if (control != null) + { + control.IsFocused = true; + this.Current = control; + } + } + } +} diff --git a/Perspex/Input/IFocusManager.cs b/Perspex/Input/IFocusManager.cs new file mode 100644 index 0000000000..de8d5c1953 --- /dev/null +++ b/Perspex/Input/IFocusManager.cs @@ -0,0 +1,21 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Input +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + + public interface IFocusManager + { + IFocusable Current { get; } + + void Focus(IFocusable focusable); + } +} diff --git a/Perspex/Input/IFocusable.cs b/Perspex/Input/IFocusable.cs index 03ec8d3561..f8c81d8aef 100644 --- a/Perspex/Input/IFocusable.cs +++ b/Perspex/Input/IFocusable.cs @@ -10,7 +10,7 @@ namespace Perspex.Input { bool Focusable { get; } - bool IsFocused { get; } + bool IsFocused { get; set; } void Focus(); } diff --git a/Perspex/Input/InputManager.cs b/Perspex/Input/InputManager.cs index 4b2da523e3..1d203c1002 100644 --- a/Perspex/Input/InputManager.cs +++ b/Perspex/Input/InputManager.cs @@ -69,7 +69,9 @@ namespace Perspex.Input Interactive interactive = device.Captured ?? (hit as Interactive) ?? hit.GetVisualAncestor(); IFocusable focusable = device.Captured as IFocusable ?? - hit.GetVisualAncestorsAndSelf().OfType().FirstOrDefault(x => x.Focusable); + hit.GetVisualAncestorsAndSelf() + .OfType() + .FirstOrDefault(x => x.Focusable); if (interactive != null) { diff --git a/Perspex/Perspex.csproj b/Perspex/Perspex.csproj index ad9662ee7c..beee983b6c 100644 --- a/Perspex/Perspex.csproj +++ b/Perspex/Perspex.csproj @@ -84,6 +84,8 @@ + +