Browse Source

Restore focus when menu item clicked.

pull/58/head
Steven Kirk 11 years ago
parent
commit
9ae44342e5
  1. 12
      Perspex.Controls/Menu.cs
  2. 11
      Perspex.Controls/PopupRoot.cs
  3. 41
      Perspex.Input/FocusManager.cs
  4. 2
      Perspex.Input/MouseDevice.cs
  5. 1
      Perspex.SceneGraph/Perspex.SceneGraph.csproj
  6. 22
      Perspex.SceneGraph/VisualTree/IHostedVisualTreeRoot.cs

12
Perspex.Controls/Menu.cs

@ -132,16 +132,6 @@ namespace Perspex.Controls
this.subscription.Dispose(); this.subscription.Dispose();
} }
/// <summary>
/// Called when the <see cref="Menu"/> loses focus.
/// </summary>
/// <param name="e">The event args.</param>
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
//this.Close();
}
/// <summary> /// <summary>
/// Called when a key is pressed within the menu. /// Called when a key is pressed within the menu.
/// </summary> /// </summary>
@ -205,6 +195,8 @@ namespace Perspex.Controls
private void OnMenuClick(RoutedEventArgs e) private void OnMenuClick(RoutedEventArgs e)
{ {
this.Close(); this.Close();
FocusManager.Instance.Focus(null);
e.Handled = true;
} }
/// <summary> /// <summary>

11
Perspex.Controls/PopupRoot.cs

@ -11,11 +11,12 @@ namespace Perspex.Controls
using Perspex.Media; using Perspex.Media;
using Perspex.Platform; using Perspex.Platform;
using Splat; using Splat;
using Perspex.VisualTree;
/// <summary> /// <summary>
/// The root window of a <see cref="Popup"/>. /// The root window of a <see cref="Popup"/>.
/// </summary> /// </summary>
public class PopupRoot : TopLevel, IInteractive public class PopupRoot : TopLevel, IInteractive, IHostedVisualTreeRoot
{ {
/// <summary> /// <summary>
/// Initializes static members of the <see cref="PopupRoot"/> class. /// Initializes static members of the <see cref="PopupRoot"/> class.
@ -64,6 +65,14 @@ namespace Perspex.Controls
get { return this.Parent; } get { return this.Parent; }
} }
/// <summary>
/// Gets the control that is hosting the popup root.
/// </summary>
IVisual IHostedVisualTreeRoot.Host
{
get { return this.Parent; }
}
/// <summary> /// <summary>
/// Sets the position of the popup in screen coordinates. /// Sets the position of the popup in screen coordinates.
/// </summary> /// </summary>

41
Perspex.Input/FocusManager.cs

@ -59,19 +59,29 @@ namespace Perspex.Input
{ {
if (control != null) if (control != null)
{ {
var scope = control.GetSelfAndVisualAncestors() var scope = GetFocusScopeAncestors(control)
.OfType<IFocusScope>() .FirstOrDefault();
.FirstOrDefault() ?? this.Scope;
if (scope != null) if (scope != null)
{ {
this.Scope = scope; this.Scope = scope;
this.SetFocusedElement(scope, control, keyboardNavigated); this.SetFocusedElement(scope, control, keyboardNavigated);
System.Diagnostics.Debug.WriteLine("Focused " + control.GetType().Name);
} }
} }
else else if (this.Current != null)
{ {
this.SetFocusedElement(this.Scope, null); // If control is null, set focus to the topmost focus scope.
foreach (var scope in GetFocusScopeAncestors(this.Current).Reverse().ToList())
{
IInputElement element;
if (this.focusScopes.TryGetValue(scope, out element))
{
this.Focus(element, keyboardNavigated);
break;
}
}
} }
} }
@ -124,5 +134,26 @@ namespace Perspex.Input
this.Scope = scope; this.Scope = scope;
this.Focus(e); this.Focus(e);
} }
/// <summary>
/// Gets the focus scope ancestors of the specified control, traversing popups.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>The focus scopes.</returns>
private static IEnumerable<IFocusScope> GetFocusScopeAncestors(IInputElement control)
{
while (control != null)
{
var scope = control as IFocusScope;
if (scope != null)
{
yield return scope;
}
control = control.GetVisualParent<IInputElement>() ??
((control as IHostedVisualTreeRoot)?.Host as IInputElement);
}
}
} }
} }

2
Perspex.Input/MouseDevice.cs

@ -143,7 +143,7 @@ namespace Perspex.Input
IInputElement focusable = this.GetFocusable(hit); IInputElement focusable = this.GetFocusable(hit);
if (focusable != null && focusable.Focusable) if (focusable != null && focusable.Focusable && focusable.IsEffectivelyVisible)
{ {
focusable.Focus(); focusable.Focus();
} }

1
Perspex.SceneGraph/Perspex.SceneGraph.csproj

@ -101,6 +101,7 @@
<Compile Include="Thickness.cs" /> <Compile Include="Thickness.cs" />
<Compile Include="Vector.cs" /> <Compile Include="Vector.cs" />
<Compile Include="Visual.cs" /> <Compile Include="Visual.cs" />
<Compile Include="VisualTree\IHostedVisualTreeRoot.cs" />
<Compile Include="VisualTree\IVisualTreeHost.cs" /> <Compile Include="VisualTree\IVisualTreeHost.cs" />
<Compile Include="VisualTree\TransformedBounds.cs" /> <Compile Include="VisualTree\TransformedBounds.cs" />
<Compile Include="VisualTree\BoundsTracker.cs" /> <Compile Include="VisualTree\BoundsTracker.cs" />

22
Perspex.SceneGraph/VisualTree/IHostedVisualTreeRoot.cs

@ -0,0 +1,22 @@
// -----------------------------------------------------------------------
// <copyright file="IVisualTreeHost.cs" company="Steven Kirk">
// Copyright 2015 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.VisualTree
{
/// <summary>
/// Interface for controls that are at the root of a hosted visual tree, such as popups.
/// </summary>
public interface IHostedVisualTreeRoot
{
/// <summary>
/// Gets the visual tree host.
/// </summary>
/// <value>
/// The visual tree host.
/// </value>
IVisual Host { get; }
}
}
Loading…
Cancel
Save