Browse Source

Show keyboard focus adorner.

pull/39/head
Steven Kirk 12 years ago
parent
commit
6fa126f827
  1. 5
      Perspex.Base/Collections/PerspexList.cs
  2. 39
      Perspex.Controls/Control.cs
  3. 2
      Perspex.Controls/Primitives/AdornerLayer.cs
  4. 2
      Perspex.Controls/TextBox.cs
  5. 4
      Perspex.Diagnostics/DevTools.cs
  6. 8
      Perspex.Input/FocusManager.cs
  7. 19
      Perspex.Input/GotFocusEventArgs.cs
  8. 9
      Perspex.Input/IFocusManager.cs
  9. 2
      Perspex.Input/IInputElement.cs
  10. 18
      Perspex.Input/InputElement.cs
  11. 4
      Perspex.Input/KeyboardNavigation.cs
  12. 1
      Perspex.Input/Perspex.Input.csproj

5
Perspex.Base/Collections/PerspexList.cs

@ -37,6 +37,11 @@ namespace Perspex.Collections
this.inner = new List<T>(items);
}
public PerspexList(params T[] items)
{
this.inner = new List<T>(items);
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public event PropertyChangedEventHandler PropertyChanged;

39
Perspex.Controls/Control.cs

@ -11,6 +11,8 @@ namespace Perspex.Controls
using System.Linq;
using System.Reactive.Linq;
using Perspex.Collections;
using Perspex.Controls.Primitives;
using Perspex.Controls.Shapes;
using Perspex.Input;
using Perspex.Interactivity;
using Perspex.Media;
@ -41,6 +43,8 @@ namespace Perspex.Controls
private DataTemplates dataTemplates;
private Rectangle focusAdorner;
private string id;
private Styles styles;
@ -185,6 +189,41 @@ namespace Perspex.Controls
this.RaiseEvent(ev);
}
protected override void OnGotFocus(GotFocusEventArgs e)
{
base.OnGotFocus(e);
if (this.IsFocused && e.KeyboardNavigated)
{
var adornerLayer = AdornerLayer.GetAdornerLayer(this);
if (adornerLayer != null)
{
this.focusAdorner = new Rectangle
{
Stroke = Brushes.Black,
StrokeThickness = 1,
StrokeDashArray = new PerspexList<double>(1, 2),
Margin = new Thickness(3),
};
AdornerLayer.SetAdornedElement(this.focusAdorner, this);
adornerLayer.Children.Add(this.focusAdorner);
}
}
}
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
if (this.focusAdorner != null)
{
var adornerLayer = AdornerLayer.GetAdornerLayer(this);
adornerLayer.Children.Remove(this.focusAdorner);
this.focusAdorner = null;
}
}
protected static void PseudoClass(PerspexProperty<bool> property, string className)
{
PseudoClass(property, x => x, className);

2
Perspex.Controls/Primitives/AdornerLayer.cs

@ -51,7 +51,7 @@ namespace Perspex.Controls.Primitives
{
var transform = adorned.TransformToVisual(parent);
var position = new Point(0, 0) * transform;
child.Arrange(new Rect(position, child.DesiredSize.Value));
child.Arrange(new Rect(position, adorned.Bounds.Size));
}
else
{

2
Perspex.Controls/TextBox.cs

@ -114,7 +114,7 @@ namespace Perspex.Controls
this.presenter = this.GetTemplateChild<TextPresenter>("textPresenter");
}
protected override void OnGotFocus(RoutedEventArgs e)
protected override void OnGotFocus(GotFocusEventArgs e)
{
base.OnGotFocus(e);
this.presenter.ShowCaret();

4
Perspex.Diagnostics/DevTools.cs

@ -216,13 +216,9 @@ namespace Perspex.Diagnostics
if (layer != null)
{
var size = node.Control.GetObservable(Visual.BoundsProperty).Select(x => x.Size);
this.adorner = new Rectangle
{
Fill = new SolidColorBrush(0x80a0c5e8),
[!Layoutable.WidthProperty] = size.Select(x => (object)x.Width),
[!Layoutable.HeightProperty] = size.Select(x => (object)x.Height),
[AdornerLayer.AdornedElementProperty] = node.Control,
};

8
Perspex.Input/FocusManager.cs

@ -39,7 +39,10 @@ namespace Perspex.Input
/// Focuses a control.
/// </summary>
/// <param name="control">The control to focus.</param>
public void Focus(IInputElement control)
/// <param name="keyboardNavigated">
/// Whether the control was focused by a keypress (e.g. the Tab key).
/// </param>
public void Focus(IInputElement control, bool keyboardNavigated = false)
{
Contract.Requires<ArgumentNullException>(control != null);
@ -74,11 +77,12 @@ namespace Perspex.Input
if (next != null)
{
next.RaiseEvent(new RoutedEventArgs
next.RaiseEvent(new GotFocusEventArgs
{
RoutedEvent = InputElement.GotFocusEvent,
Source = next,
OriginalSource = next,
KeyboardNavigated = keyboardNavigated,
});
}
}

19
Perspex.Input/GotFocusEventArgs.cs

@ -0,0 +1,19 @@
// -----------------------------------------------------------------------
// <copyright file="GotFocusEventArgs.cs" company="Steven Kirk">
// Copyright 2015 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Input
{
using Perspex.Interactivity;
public class GotFocusEventArgs : RoutedEventArgs
{
/// <summary>
/// Gets or sets a value indicating whether the control was focused by a keypress (e.g.
/// the Tab key).
/// </summary>
public bool KeyboardNavigated { get; set; }
}
}

9
Perspex.Input/IFocusManager.cs

@ -18,7 +18,14 @@ namespace Perspex.Input
IFocusScope Scope { get; }
void Focus(IInputElement focusable);
/// <summary>
/// Focuses a control.
/// </summary>
/// <param name="control">The control to focus.</param>
/// <param name="keyboardNavigated">
/// Whether the control was focused by a keypress (e.g. the Tab key).
/// </param>
void Focus(IInputElement focusable, bool keyboardNavigated = false);
/// <summary>
/// Notifies the focus manager of a change in focus scope.

2
Perspex.Input/IInputElement.cs

@ -37,6 +37,8 @@ namespace Perspex.Input
bool IsPointerOver { get; }
bool IsTabFocused { get; }
void Focus();
IInputElement InputHitTest(Point p);

18
Perspex.Input/InputElement.cs

@ -23,7 +23,7 @@ namespace Perspex.Input
PerspexProperty.Register<InputElement, bool>("IsEnabledCore", true);
public static readonly PerspexProperty<bool> IsFocusedProperty =
PerspexProperty.Register<InputElement, bool>("IsFocused", false);
PerspexProperty.Register<InputElement, bool>("IsFocused");
public static readonly PerspexProperty<bool> IsHitTestVisibleProperty =
PerspexProperty.Register<InputElement, bool>("IsHitTestVisible", true);
@ -31,8 +31,11 @@ namespace Perspex.Input
public static readonly PerspexProperty<bool> IsPointerOverProperty =
PerspexProperty.Register<InputElement, bool>("IsPointerOver");
public static readonly RoutedEvent<RoutedEventArgs> GotFocusEvent =
RoutedEvent.Register<InputElement, RoutedEventArgs>("GotFocus", RoutingStrategies.Bubble);
public static readonly PerspexProperty<bool> IsTabFocusedProperty =
PerspexProperty.Register<InputElement, bool>("IsTabFocused");
public static readonly RoutedEvent<GotFocusEventArgs> GotFocusEvent =
RoutedEvent.Register<InputElement, GotFocusEventArgs>("GotFocus", RoutingStrategies.Bubble);
public static readonly RoutedEvent<RoutedEventArgs> LostFocusEvent =
RoutedEvent.Register<InputElement, RoutedEventArgs>("LostFocus", RoutingStrategies.Bubble);
@ -172,6 +175,11 @@ namespace Perspex.Input
get { return this.IsEnabledCore; }
}
bool IInputElement.IsTabFocused
{
get { return this.GetValue(IsTabFocusedProperty); }
}
protected bool IsEnabledCore
{
get { return this.GetValue(IsEnabledCoreProperty); }
@ -193,14 +201,16 @@ namespace Perspex.Input
this.UpdateIsEnabledCore();
}
protected virtual void OnGotFocus(RoutedEventArgs e)
protected virtual void OnGotFocus(GotFocusEventArgs e)
{
this.IsFocused = e.OriginalSource == this;
this.SetValue(IsTabFocusedProperty, e.KeyboardNavigated);
}
protected virtual void OnLostFocus(RoutedEventArgs e)
{
this.IsFocused = false;
this.SetValue(IsTabFocusedProperty, false);
}
protected virtual void OnKeyDown(KeyEventArgs e)

4
Perspex.Input/KeyboardNavigation.cs

@ -26,7 +26,7 @@ namespace Perspex.Input
if (next != null)
{
FocusManager.Instance.Focus(next);
FocusManager.Instance.Focus(next, true);
}
}
@ -42,7 +42,7 @@ namespace Perspex.Input
if (next != null)
{
FocusManager.Instance.Focus(next);
FocusManager.Instance.Focus(next, true);
}
}
}

1
Perspex.Input/Perspex.Input.csproj

@ -74,6 +74,7 @@
<Compile Include="Key.cs" />
<Compile Include="KeyboardDevice.cs" />
<Compile Include="KeyboardNavigation.cs" />
<Compile Include="GotFocusEventArgs.cs" />
<Compile Include="Platform\IPlatformSettings.cs" />
<Compile Include="PointerPressEventArgs.cs" />
<Compile Include="PointerWheelEventArgs.cs" />

Loading…
Cancel
Save