Browse Source

Improved tab focus handling a bit.

pull/39/head
Steven Kirk 11 years ago
parent
commit
3efc8e8920
  1. 13
      Perspex.Application/Application.cs
  2. 1
      Perspex.Controls/Primitives/TabStrip.cs
  3. 5
      Perspex.Controls/TabControl.cs
  4. 7
      Perspex.Controls/TextBox.cs
  5. 15
      Perspex.Input/IKeyboardNavigation.cs
  6. 10
      Perspex.Input/InputElement.cs
  7. 81
      Perspex.Input/KeyboardNavigation.cs
  8. 1
      Perspex.Input/Perspex.Input.csproj
  9. 13
      Perspex.SceneGraph/VisualTree/VisualExtensions.cs

13
Perspex.Application/Application.cs

@ -31,8 +31,6 @@ namespace Perspex
Current = this;
this.Styles = theme;
this.FocusManager = new FocusManager();
this.InputManager = new InputManager();
this.RegisterServices();
}
@ -72,6 +70,12 @@ namespace Perspex
private set;
}
public KeyboardNavigation KeyboardNavigation
{
get;
private set;
}
public Styles Styles
{
get;
@ -87,10 +91,15 @@ namespace Perspex
protected virtual void RegisterServices()
{
this.FocusManager = new FocusManager();
this.InputManager = new InputManager();
this.KeyboardNavigation = new KeyboardNavigation();
Locator.CurrentMutable.Register(() => this, typeof(IGlobalDataTemplates));
Locator.CurrentMutable.Register(() => this, typeof(IGlobalStyles));
Locator.CurrentMutable.Register(() => this.FocusManager, typeof(IFocusManager));
Locator.CurrentMutable.Register(() => this.InputManager, typeof(IInputManager));
Locator.CurrentMutable.Register(() => this.KeyboardNavigation, typeof(IKeyboardNavigation));
Locator.CurrentMutable.Register(() => this.styler, typeof(IStyler));
Locator.CurrentMutable.Register(() => new LayoutManager(), typeof(ILayoutManager));

1
Perspex.Controls/Primitives/TabStrip.cs

@ -21,6 +21,7 @@ namespace Perspex.Controls.Primitives
static TabStrip()
{
FocusableProperty.OverrideDefaultValue(typeof(TabStrip), false);
ItemsPanelProperty.OverrideDefaultValue(typeof(TabStrip), PanelTemplate);
}

5
Perspex.Controls/TabControl.cs

@ -26,6 +26,11 @@ namespace Perspex.Controls
private PerspexReadOnlyListView<ILogical> logicalChildren =
new PerspexReadOnlyListView<ILogical>();
static TabControl()
{
FocusableProperty.OverrideDefaultValue(typeof(TabControl), false);
}
public TabControl()
{
this.GetObservable(SelectedItemProperty).Subscribe(x =>

7
Perspex.Controls/TextBox.cs

@ -134,6 +134,7 @@ namespace Perspex.Controls
int caretIndex = this.CaretIndex;
bool movement = false;
bool textEntered = false;
bool handled = true;
var modifiers = e.Device.Modifiers;
switch (e.Key)
@ -213,6 +214,7 @@ namespace Perspex.Controls
else
{
base.OnKeyDown(e);
handled = false;
}
break;
@ -240,7 +242,10 @@ namespace Perspex.Controls
this.SelectionStart = this.SelectionEnd = this.CaretIndex;
}
e.Handled = true;
if (handled)
{
e.Handled = true;
}
}
protected override void OnPointerPressed(PointerPressEventArgs e)

15
Perspex.Input/IKeyboardNavigation.cs

@ -0,0 +1,15 @@
// -----------------------------------------------------------------------
// <copyright file="IKeyboardDevice.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
public interface IKeyboardNavigation
{
bool MoveNext(IInputElement element);
bool MovePrevious(IInputElement element);
}
}

10
Perspex.Input/InputElement.cs

@ -221,11 +221,17 @@ namespace Perspex.Input
if ((modifiers & ModifierKeys.Shift) == 0)
{
KeyboardNavigation.MoveNext(this);
if (KeyboardNavigation.Instance.MoveNext(this))
{
e.Handled = true;
}
}
else
{
KeyboardNavigation.MovePrevious(this);
if (KeyboardNavigation.Instance.MovePrevious(this))
{
e.Handled = true;
}
}
}
}

81
Perspex.Input/KeyboardNavigation.cs

@ -8,42 +8,79 @@ namespace Perspex.Input
{
using System.Linq;
using Perspex.VisualTree;
using Splat;
/// <summary>
/// TODO: This class is a temporary stop-gap just to add tab handling. Should be replaced
/// with something better thought out and testable etc.
/// </summary>
public static class KeyboardNavigation
public class KeyboardNavigation : IKeyboardNavigation
{
public static void MoveNext(IInputElement element)
public static IKeyboardNavigation Instance
{
var siblings = element.GetVisualSiblings().OfType<IInputElement>()
.Where(x => x.Focusable)
.SkipWhile(x => x != element)
.Skip(1);
get { return Locator.Current.GetService<IKeyboardNavigation>(); }
}
var next = siblings.FirstOrDefault();
public bool MoveNext(IInputElement element)
{
var parent = element.GetVisualParent();
var descendent = element.GetVisualDescendents()
.OfType<IInputElement>()
.Where(x => x.Focusable && x.IsEnabledCore)
.FirstOrDefault();
if (next != null)
if (descendent != null)
{
FocusManager.Instance.Focus(descendent, true);
return true;
}
else if (parent != null)
{
FocusManager.Instance.Focus(next, true);
var sibling = parent.GetVisualChildren()
.OfType<IInputElement>()
.Where(x => x.Focusable && x.IsEnabledCore)
.SkipWhile(x => x != element)
.Skip(1)
.FirstOrDefault();
if (sibling != null)
{
FocusManager.Instance.Focus(sibling, true);
return true;
}
}
return false;
}
public static void MovePrevious(IInputElement element)
public bool MovePrevious(IInputElement element)
{
var siblings = element.GetVisualSiblings().OfType<IInputElement>()
.Where(x => x.Focusable)
var parent = element.GetVisualParent();
var descendent = element.GetVisualDescendents()
.OfType<IInputElement>()
.Where(x => x.Focusable && x.IsEnabledCore)
.Reverse()
.SkipWhile(x => x != element)
.Skip(1);
.FirstOrDefault();
var next = siblings.FirstOrDefault();
if (next != null)
if (descendent != null)
{
FocusManager.Instance.Focus(next, true);
FocusManager.Instance.Focus(descendent, true);
return true;
}
else if (parent != null)
{
var previous = parent.GetVisualChildren()
.OfType<IInputElement>()
.Where(x => x.Focusable)
.Reverse()
.SkipWhile(x => x != element)
.Skip(1)
.FirstOrDefault();
if (previous != null)
{
FocusManager.Instance.Focus(previous, true);
return true;
}
}
return false;
}
}
}

1
Perspex.Input/Perspex.Input.csproj

@ -66,6 +66,7 @@
<Compile Include="IInputElement.cs" />
<Compile Include="IInputManager.cs" />
<Compile Include="IKeyboardDevice.cs" />
<Compile Include="IKeyboardNavigation.cs" />
<Compile Include="IMouseDevice.cs" />
<Compile Include="InputElement.cs" />
<Compile Include="InputExtensions.cs" />

13
Perspex.SceneGraph/VisualTree/VisualExtensions.cs

@ -102,18 +102,5 @@ namespace Perspex.VisualTree
{
return visual.VisualParent as T;
}
public static IEnumerable<IVisual> GetVisualSiblings(this IVisual visual)
{
IVisual parent = visual.VisualParent;
if (parent != null)
{
foreach (IVisual sibling in parent.VisualChildren)
{
yield return sibling;
}
}
}
}
}

Loading…
Cancel
Save