Browse Source

Merge branch 'master' into issue3294

pull/3753/head
Benedikt Stebner 6 years ago
committed by GitHub
parent
commit
37bf6f73df
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/Avalonia.Base/Threading/DispatcherPriority.cs
  2. 12
      src/Avalonia.Controls/TreeViewItem.cs
  3. 14
      src/Avalonia.Input/FocusManager.cs
  4. 6
      src/Avalonia.Input/IFocusManager.cs
  5. 2
      src/Avalonia.Input/IKeyboardDevice.cs
  6. 6
      src/Avalonia.Input/IKeyboardNavigationHandler.cs
  7. 4
      src/Avalonia.Input/KeyboardDevice.cs
  8. 8
      src/Avalonia.Input/KeyboardNavigationHandler.cs
  9. 2
      src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs
  10. 2
      src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs
  11. 29
      tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
  12. 4
      tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs

2
src/Avalonia.Base/Threading/DispatcherPriority.cs

@ -17,7 +17,7 @@ namespace Avalonia.Threading
SystemIdle = 1,
/// <summary>
/// The job will be processed when the application sis idle.
/// The job will be processed when the application is idle.
/// </summary>
ApplicationIdle = 2,

12
src/Avalonia.Controls/TreeViewItem.cs

@ -51,6 +51,7 @@ namespace Avalonia.Controls
SelectableMixin.Attach<TreeViewItem>(IsSelectedProperty);
FocusableProperty.OverrideDefaultValue<TreeViewItem>(true);
ItemsPanelProperty.OverrideDefaultValue<TreeViewItem>(DefaultPanel);
ParentProperty.Changed.AddClassHandler<TreeViewItem>((o, e) => o.OnParentChanged(e));
RequestBringIntoViewEvent.AddClassHandler<TreeViewItem>((x, e) => x.OnRequestBringIntoView(e));
}
@ -179,5 +180,16 @@ namespace Avalonia.Controls
return logical != null ? result : @default;
}
private void OnParentChanged(AvaloniaPropertyChangedEventArgs e)
{
if (!((ILogical)this).IsAttachedToLogicalTree && e.NewValue is null)
{
// If we're not attached to the logical tree, then OnDetachedFromLogicalTree isn't going to be
// called when the item is removed. This results in the item not being removed from the index,
// causing #3551. In this case, update the index when Parent is changed to null.
ItemContainerGenerator.UpdateIndex();
}
}
}
}

14
src/Avalonia.Input/FocusManager.cs

@ -53,11 +53,11 @@ namespace Avalonia.Input
/// </summary>
/// <param name="control">The control to focus.</param>
/// <param name="method">The method by which focus was changed.</param>
/// <param name="modifiers">Any input modifiers active at the time of focus.</param>
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
public void Focus(
IInputElement control,
NavigationMethod method = NavigationMethod.Unspecified,
InputModifiers modifiers = InputModifiers.None)
KeyModifiers keyModifiers = KeyModifiers.None)
{
if (control != null)
{
@ -67,7 +67,7 @@ namespace Avalonia.Input
if (scope != null)
{
Scope = scope;
SetFocusedElement(scope, control, method, modifiers);
SetFocusedElement(scope, control, method, keyModifiers);
}
}
else if (Current != null)
@ -95,7 +95,7 @@ namespace Avalonia.Input
/// <param name="scope">The focus scope.</param>
/// <param name="element">The element to focus. May be null.</param>
/// <param name="method">The method by which focus was changed.</param>
/// <param name="modifiers">Any input modifiers active at the time of focus.</param>
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
/// <remarks>
/// If the specified scope is the current <see cref="Scope"/> then the keyboard focus
/// will change.
@ -104,7 +104,7 @@ namespace Avalonia.Input
IFocusScope scope,
IInputElement element,
NavigationMethod method = NavigationMethod.Unspecified,
InputModifiers modifiers = InputModifiers.None)
KeyModifiers keyModifiers = KeyModifiers.None)
{
Contract.Requires<ArgumentNullException>(scope != null);
@ -123,7 +123,7 @@ namespace Avalonia.Input
if (Scope == scope)
{
KeyboardDevice.Instance?.SetFocusedElement(element, method, modifiers);
KeyboardDevice.Instance?.SetFocusedElement(element, method, keyModifiers);
}
}
@ -195,7 +195,7 @@ namespace Avalonia.Input
{
if (element is IInputElement inputElement && CanFocus(inputElement))
{
Instance?.Focus(inputElement, NavigationMethod.Pointer, ev.InputModifiers);
Instance?.Focus(inputElement, NavigationMethod.Pointer, ev.KeyModifiers);
break;
}

6
src/Avalonia.Input/IFocusManager.cs

@ -20,11 +20,11 @@ namespace Avalonia.Input
/// </summary>
/// <param name="control">The control to focus.</param>
/// <param name="method">The method by which focus was changed.</param>
/// <param name="modifiers">Any input modifiers active at the time of focus.</param>
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
void Focus(
IInputElement control,
IInputElement control,
NavigationMethod method = NavigationMethod.Unspecified,
InputModifiers modifiers = InputModifiers.None);
KeyModifiers keyModifiers = KeyModifiers.None);
/// <summary>
/// Notifies the focus manager of a change in focus scope.

2
src/Avalonia.Input/IKeyboardDevice.cs

@ -63,6 +63,6 @@ namespace Avalonia.Input
void SetFocusedElement(
IInputElement element,
NavigationMethod method,
InputModifiers modifiers);
KeyModifiers modifiers);
}
}

6
src/Avalonia.Input/IKeyboardNavigationHandler.cs

@ -19,10 +19,10 @@ namespace Avalonia.Input
/// </summary>
/// <param name="element">The current element.</param>
/// <param name="direction">The direction to move.</param>
/// <param name="modifiers">Any input modifiers active at the time of focus.</param>
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
void Move(
IInputElement element,
NavigationDirection direction,
InputModifiers modifiers = InputModifiers.None);
KeyModifiers keyModifiers = KeyModifiers.None);
}
}
}

4
src/Avalonia.Input/KeyboardDevice.cs

@ -35,7 +35,7 @@ namespace Avalonia.Input
public void SetFocusedElement(
IInputElement element,
NavigationMethod method,
InputModifiers modifiers)
KeyModifiers keyModifiers)
{
if (element != FocusedElement)
{
@ -53,7 +53,7 @@ namespace Avalonia.Input
{
RoutedEvent = InputElement.GotFocusEvent,
NavigationMethod = method,
InputModifiers = modifiers,
KeyModifiers = keyModifiers,
});
}
}

8
src/Avalonia.Input/KeyboardNavigationHandler.cs

@ -91,11 +91,11 @@ namespace Avalonia.Input
/// </summary>
/// <param name="element">The current element.</param>
/// <param name="direction">The direction to move.</param>
/// <param name="modifiers">Any input modifiers active at the time of focus.</param>
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
public void Move(
IInputElement element,
NavigationDirection direction,
InputModifiers modifiers = InputModifiers.None)
KeyModifiers keyModifiers = KeyModifiers.None)
{
Contract.Requires<ArgumentNullException>(element != null);
@ -106,7 +106,7 @@ namespace Avalonia.Input
var method = direction == NavigationDirection.Next ||
direction == NavigationDirection.Previous ?
NavigationMethod.Tab : NavigationMethod.Directional;
FocusManager.Instance.Focus(next, method, modifiers);
FocusManager.Instance.Focus(next, method, keyModifiers);
}
}
@ -123,7 +123,7 @@ namespace Avalonia.Input
{
var direction = (e.KeyModifiers & KeyModifiers.Shift) == 0 ?
NavigationDirection.Next : NavigationDirection.Previous;
Move(current, direction, e.Modifiers);
Move(current, direction, e.KeyModifiers);
e.Handled = true;
}
}

2
src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs

@ -45,7 +45,7 @@ namespace Avalonia.Win32.Embedding
focused = focused.VisualParent;
if (focused == _root)
KeyboardDevice.Instance.SetFocusedElement(null, NavigationMethod.Unspecified, InputModifiers.None);
KeyboardDevice.Instance.SetFocusedElement(null, NavigationMethod.Unspecified, KeyModifiers.None);
}
private void PlatformImpl_LostFocus()

2
src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs

@ -44,7 +44,7 @@ namespace Avalonia.Win32.Input
public void WindowActivated(Window window)
{
SetFocusedElement(window, NavigationMethod.Unspecified, InputModifiers.None);
SetFocusedElement(window, NavigationMethod.Unspecified, KeyModifiers.None);
}
public string StringFromVirtualKey(uint virtualKey)

29
tests/Avalonia.Controls.UnitTests/TreeViewTests.cs

@ -1002,6 +1002,35 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(1, child2Node.Presenter.Panel.Children.Count);
}
[Fact]
public void Clearing_TreeView_Items_Clears_Index()
{
// Issue #3551
var tree = CreateTestTreeData();
var target = new TreeView
{
Template = CreateTreeViewTemplate(),
Items = tree,
};
var root = new TestRoot();
root.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target);
var rootNode = tree[0];
var container = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(rootNode);
Assert.NotNull(container);
root.Child = null;
tree.Clear();
Assert.Empty(target.ItemContainerGenerator.Index.Containers);
}
private void ApplyTemplates(TreeView tree)
{
tree.ApplyTemplate();

4
tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs

@ -35,7 +35,7 @@ namespace Avalonia.Input.UnitTests
target.SetFocusedElement(
focused.Object,
NavigationMethod.Unspecified,
InputModifiers.None);
KeyModifiers.None);
target.ProcessRawEvent(
new RawKeyEventArgs(
@ -75,7 +75,7 @@ namespace Avalonia.Input.UnitTests
target.SetFocusedElement(
focused.Object,
NavigationMethod.Unspecified,
InputModifiers.None);
KeyModifiers.None);
target.ProcessRawEvent(
new RawTextInputEventArgs(

Loading…
Cancel
Save