Browse Source

Merge branch 'master' into fix-validation-not-found-member

pull/4150/head
Dariusz Komosiński 6 years ago
committed by GitHub
parent
commit
6405df5d69
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      samples/ControlCatalog/Pages/ButtonPage.xaml
  2. 4
      src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
  3. 27
      src/Avalonia.Controls/Primitives/HeaderedContentControl.cs
  4. 1
      src/Avalonia.Controls/TreeViewItem.cs
  5. 33
      src/Avalonia.Input/KeyboardNavigation.cs
  6. 39
      src/Avalonia.Input/Navigation/TabNavigation.cs
  7. 10
      src/Avalonia.Layout/LayoutManager.cs
  8. 4
      src/Avalonia.Themes.Default/ToggleSwitch.xaml
  9. 7
      src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml
  10. 7
      src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml
  11. 30
      src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml
  12. 30
      src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml
  13. 4
      src/Avalonia.Themes.Fluent/ToggleSwitch.xaml
  14. 17
      src/Avalonia.Themes.Fluent/TreeView.xaml
  15. 246
      src/Avalonia.Themes.Fluent/TreeViewItem.xaml
  16. 29
      tests/Avalonia.Input.UnitTests/KeyboardNavigationTests_Tab.cs

1
samples/ControlCatalog/Pages/ButtonPage.xaml

@ -35,6 +35,7 @@
<Button BorderBrush="{DynamicResource ThemeAccentBrush}">Border Color</Button>
<Button BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="4">Thick Border</Button>
<Button BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="4" IsEnabled="False">Disabled</Button>
<Button BorderBrush="{DynamicResource ThemeAccentBrush}" KeyboardNavigation.IsTabStop="False">IsTabStop=False</Button>
</StackPanel>
</StackPanel>
</StackPanel>

4
src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs

@ -333,6 +333,10 @@ namespace Avalonia.Controls.Platform
{
item.Parent.SelectedItem = null;
}
else if (!item.IsPointerOverSubMenu)
{
item.IsSubMenuOpen = false;
}
}
}

27
src/Avalonia.Controls/Primitives/HeaderedContentControl.cs

@ -1,8 +1,9 @@
using Avalonia.Controls.Mixins;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.LogicalTree;
#nullable enable
namespace Avalonia.Controls.Primitives
{
/// <summary>
@ -13,36 +14,36 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Defines the <see cref="Header"/> property.
/// </summary>
public static readonly StyledProperty<object> HeaderProperty =
AvaloniaProperty.Register<HeaderedContentControl, object>(nameof(Header));
public static readonly StyledProperty<object?> HeaderProperty =
AvaloniaProperty.Register<HeaderedContentControl, object?>(nameof(Header));
/// <summary>
/// Defines the <see cref="HeaderTemplate"/> property.
/// </summary>
public static readonly StyledProperty<IDataTemplate> HeaderTemplateProperty =
AvaloniaProperty.Register<HeaderedContentControl, IDataTemplate>(nameof(HeaderTemplate));
public static readonly StyledProperty<IDataTemplate?> HeaderTemplateProperty =
AvaloniaProperty.Register<HeaderedContentControl, IDataTemplate?>(nameof(HeaderTemplate));
/// <summary>
/// Initializes static members of the <see cref="ContentControl"/> class.
/// </summary>
static HeaderedContentControl()
{
ContentProperty.Changed.AddClassHandler<HeaderedContentControl>((x, e) => x.HeaderChanged(e));
HeaderProperty.Changed.AddClassHandler<HeaderedContentControl>((x, e) => x.HeaderChanged(e));
}
/// <summary>
/// Gets or sets the header content.
/// </summary>
public object Header
public object? Header
{
get { return GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
get => GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
/// <summary>
/// Gets the header presenter from the control's template.
/// </summary>
public IContentPresenter HeaderPresenter
public IContentPresenter? HeaderPresenter
{
get;
private set;
@ -51,10 +52,10 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Gets or sets the data template used to display the header content of the control.
/// </summary>
public IDataTemplate HeaderTemplate
public IDataTemplate? HeaderTemplate
{
get { return GetValue(HeaderTemplateProperty); }
set { SetValue(HeaderTemplateProperty, value); }
get => GetValue(HeaderTemplateProperty);
set => SetValue(HeaderTemplateProperty, value);
}
/// <inheritdoc/>

1
src/Avalonia.Controls/TreeViewItem.cs

@ -49,6 +49,7 @@ namespace Avalonia.Controls
static TreeViewItem()
{
SelectableMixin.Attach<TreeViewItem>(IsSelectedProperty);
PressedMixin.Attach<TreeViewItem>();
FocusableProperty.OverrideDefaultValue<TreeViewItem>(true);
ItemsPanelProperty.OverrideDefaultValue<TreeViewItem>(DefaultPanel);
ParentProperty.Changed.AddClassHandler<TreeViewItem>((o, e) => o.OnParentChanged(e));

33
src/Avalonia.Input/KeyboardNavigation.cs

@ -30,6 +30,19 @@ namespace Avalonia.Input
"TabOnceActiveElement",
typeof(KeyboardNavigation));
/// <summary>
/// Defines the IsTabStop attached property.
/// </summary>
/// <remarks>
/// The IsTabStop attached property determines whether the control is focusable by tab navigation.
/// </remarks>
public static readonly AttachedProperty<bool> IsTabStopProperty =
AvaloniaProperty.RegisterAttached<InputElement, bool>(
"IsTabStop",
typeof(KeyboardNavigation),
true);
/// <summary>
/// Gets the <see cref="TabNavigationProperty"/> for a container.
/// </summary>
@ -69,5 +82,25 @@ namespace Avalonia.Input
{
element.SetValue(TabOnceActiveElementProperty, value);
}
/// <summary>
/// Sets the <see cref="IsTabStopProperty"/> for a container.
/// </summary>
/// <param name="element">The container.</param>
/// <param name="value">Value indicating whether the container is a tab stop.</param>
public static void SetIsTabStop(InputElement element, bool value)
{
element.SetValue(IsTabStopProperty, value);
}
/// <summary>
/// Gets the <see cref="IsTabStopProperty"/> for a container.
/// </summary>
/// <param name="element">The container.</param>
/// <returns>Whether the container is a tab stop.</returns>
public static bool GetIsTabStop(InputElement element)
{
return element.GetValue(IsTabStopProperty);
}
}
}

39
src/Avalonia.Input/Navigation/TabNavigation.cs

@ -77,7 +77,8 @@ namespace Avalonia.Input.Navigation
/// <param name="element">The element.</param>
/// <param name="direction">The tab direction. Must be Next or Previous.</param>
/// <returns>The element's focusable descendants.</returns>
private static IEnumerable<IInputElement> GetFocusableDescendants(IInputElement element, NavigationDirection direction)
private static IEnumerable<IInputElement> GetFocusableDescendants(IInputElement element,
NavigationDirection direction)
{
var mode = KeyboardNavigation.GetTabNavigation((InputElement)element);
@ -113,7 +114,7 @@ namespace Avalonia.Input.Navigation
}
else
{
if (child.CanFocus())
if (child.CanFocus() && KeyboardNavigation.GetIsTabStop((InputElement)child))
{
yield return child;
}
@ -122,7 +123,10 @@ namespace Avalonia.Input.Navigation
{
foreach (var descendant in GetFocusableDescendants(child, direction))
{
yield return descendant;
if (KeyboardNavigation.GetIsTabStop((InputElement)descendant))
{
yield return descendant;
}
}
}
}
@ -167,7 +171,9 @@ namespace Avalonia.Input.Navigation
{
element = navigable.GetControl(direction, element, false);
if (element != null && element.CanFocus())
if (element != null &&
element.CanFocus() &&
KeyboardNavigation.GetIsTabStop((InputElement) element))
{
break;
}
@ -233,26 +239,22 @@ namespace Avalonia.Input.Navigation
return customNext.next;
}
if (sibling.CanFocus())
if (sibling.CanFocus() && KeyboardNavigation.GetIsTabStop((InputElement) sibling))
{
return sibling;
}
else
next = direction == NavigationDirection.Next ?
GetFocusableDescendants(sibling, direction).FirstOrDefault() :
GetFocusableDescendants(sibling, direction).LastOrDefault();
if (next != null)
{
next = direction == NavigationDirection.Next ?
GetFocusableDescendants(sibling, direction).FirstOrDefault() :
GetFocusableDescendants(sibling, direction).LastOrDefault();
if(next != null)
{
return next;
}
return next;
}
}
if (next == null)
{
next = GetFirstInNextContainer(element, parent, direction);
}
next = GetFirstInNextContainer(element, parent, direction);
}
else
{
@ -264,7 +266,8 @@ namespace Avalonia.Input.Navigation
return next;
}
private static (bool handled, IInputElement next) GetCustomNext(IInputElement element, NavigationDirection direction)
private static (bool handled, IInputElement next) GetCustomNext(IInputElement element,
NavigationDirection direction)
{
if (element is ICustomKeyboardNavigation custom)
{

10
src/Avalonia.Layout/LayoutManager.cs

@ -23,10 +23,10 @@ namespace Avalonia.Layout
_executeLayoutPass = ExecuteLayoutPass;
}
public event EventHandler? LayoutUpdated;
public virtual event EventHandler? LayoutUpdated;
/// <inheritdoc/>
public void InvalidateMeasure(ILayoutable control)
public virtual void InvalidateMeasure(ILayoutable control)
{
control = control ?? throw new ArgumentNullException(nameof(control));
Dispatcher.UIThread.VerifyAccess();
@ -47,7 +47,7 @@ namespace Avalonia.Layout
}
/// <inheritdoc/>
public void InvalidateArrange(ILayoutable control)
public virtual void InvalidateArrange(ILayoutable control)
{
control = control ?? throw new ArgumentNullException(nameof(control));
Dispatcher.UIThread.VerifyAccess();
@ -67,7 +67,7 @@ namespace Avalonia.Layout
}
/// <inheritdoc/>
public void ExecuteLayoutPass()
public virtual void ExecuteLayoutPass()
{
const int MaxPasses = 3;
@ -131,7 +131,7 @@ namespace Avalonia.Layout
}
/// <inheritdoc/>
public void ExecuteInitialLayoutPass(ILayoutRoot root)
public virtual void ExecuteInitialLayoutPass(ILayoutRoot root)
{
try
{

4
src/Avalonia.Themes.Default/ToggleSwitch.xaml

@ -3,8 +3,8 @@
xmlns:sys="clr-namespace:System;assembly=netstandard">
<Styles.Resources>
<Thickness x:Key="ToggleSwitchTopHeaderMargin">0,0,0,6</Thickness>
<x:Double x:Key="ToggleSwitchPreContentMargin">6</x:Double>
<x:Double x:Key="ToggleSwitchPostContentMargin">6</x:Double>
<GridLength x:Key="ToggleSwitchPreContentMargin">6</GridLength>
<GridLength x:Key="ToggleSwitchPostContentMargin">6</GridLength>
<x:Double x:Key="ToggleSwitchThemeMinWidth">154</x:Double>
<x:Double x:Key="KnobOnPosition">20</x:Double>
<x:Double x:Key="KnobOffPosition">0</x:Double>

7
src/Avalonia.Themes.Fluent/Accents/BaseDark.xaml

@ -140,7 +140,12 @@
<SolidColorBrush x:Key="SystemControlTransientBorderBrush" Color="#000000" Opacity="0.36" />
<SolidColorBrush x:Key="SystemControlHighlightListLowRevealBackgroundBrush" Color="{StaticResource SystemListMediumColor}" />
<SolidColorBrush x:Key="SystemControlHighlightListMediumRevealBackgroundBrush" Color="{StaticResource SystemListMediumColor}" />
<SolidColorBrush x:Key="SystemControlHighlightAccentRevealBackgroundBrush" Color="{StaticResource SystemAccentColor}" />
<SolidColorBrush x:Key="SystemControlHighlightAccentRevealBackgroundBrush" Color="{DynamicResource SystemAccentColor}" />
<SolidColorBrush x:Key="SystemControlHighlightAccent3RevealBackgroundBrush" Color="{DynamicResource SystemAccentColor}" Opacity="0.6" />
<SolidColorBrush x:Key="SystemControlHighlightAccent2RevealBackgroundBrush" Color="{DynamicResource SystemAccentColor}" Opacity="0.8" />
<SolidColorBrush x:Key="SystemControlBackgroundChromeWhiteRevealBorderBrush" Color="{StaticResource SystemChromeWhiteColor}" />
<SolidColorBrush x:Key="SystemControlHighlightAltTransparentRevealBorderBrush" Color="Transparent" />
<SolidColorBrush x:Key="SystemControlBackgroundTransparentRevealBorderBrush" Color="Transparent" />
<!-- TODO implement AcrylicBrush -->
<!--<AcrylicBrush x:Key="SystemControlTransientBackgroundBrush" BackgroundSource="HostBackdrop" TintColor="{StaticResource SystemChromeAltHighColor}" TintOpacity="0.8" FallbackColor="{StaticResource SystemChromeMediumLowColor}" />-->
<SolidColorBrush x:Key="SystemControlTransientBackgroundBrush" Color="{StaticResource SystemChromeMediumLowColor}" />

7
src/Avalonia.Themes.Fluent/Accents/BaseLight.xaml

@ -140,7 +140,12 @@
<SolidColorBrush x:Key="SystemControlTransientBorderBrush" Color="#000000" Opacity="0.14" />
<SolidColorBrush x:Key="SystemControlHighlightListLowRevealBackgroundBrush" Color="{StaticResource SystemListMediumColor}" />
<SolidColorBrush x:Key="SystemControlHighlightListMediumRevealBackgroundBrush" Color="{StaticResource SystemListMediumColor}" />
<SolidColorBrush x:Key="SystemControlHighlightAccentRevealBackgroundBrush" Color="{StaticResource SystemAccentColor}" />
<SolidColorBrush x:Key="SystemControlHighlightAccentRevealBackgroundBrush" Color="{DynamicResource SystemAccentColor}" />
<SolidColorBrush x:Key="SystemControlHighlightAccent3RevealBackgroundBrush" Color="{DynamicResource SystemAccentColor}" Opacity="0.6" />
<SolidColorBrush x:Key="SystemControlHighlightAccent2RevealBackgroundBrush" Color="{DynamicResource SystemAccentColor}" Opacity="0.8" />
<SolidColorBrush x:Key="SystemControlBackgroundChromeWhiteRevealBorderBrush" Color="{StaticResource SystemChromeWhiteColor}" />
<SolidColorBrush x:Key="SystemControlHighlightAltTransparentRevealBorderBrush" Color="Transparent" />
<SolidColorBrush x:Key="SystemControlBackgroundTransparentRevealBorderBrush" Color="Transparent" />
<!-- TODO implement AcrylicBrush -->
<!--<AcrylicBrush x:Key="SystemControlTransientBackgroundBrush" BackgroundSource="HostBackdrop" TintColor="{StaticResource SystemChromeAltHighColor}" TintOpacity="0.8" FallbackColor="{StaticResource SystemChromeMediumLowColor}" />-->
<SolidColorBrush x:Key="SystemControlTransientBackgroundBrush" Color="{StaticResource SystemChromeMediumLowColor}" />

30
src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml

@ -789,5 +789,35 @@
<x:Double x:Key="ScrollBarButtonArrowIconFontSize">8</x:Double>
<x:String x:Key="ScrollBarExpandBeginTime">00:00:00.40</x:String>
<x:String x:Key="ScrollBarContractBeginTime">00:00:02.00</x:String>
<!-- Resources for TreeViewItem.xaml -->
<StaticResource x:Key="TreeViewItemBackground" ResourceKey="SystemControlTransparentRevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundPointerOver" ResourceKey="SystemControlHighlightListLowRevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundPressed" ResourceKey="SystemControlHighlightListMediumRevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundDisabled" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemBackgroundSelected" ResourceKey="SystemControlHighlightAccent3RevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundSelectedPointerOver" ResourceKey="SystemControlHighlightAccent2RevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundSelectedPressed" ResourceKey="SystemControlHighlightListMediumRevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundSelectedDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
<StaticResource x:Key="TreeViewItemForeground" ResourceKey="SystemControlForegroundBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundPointerOver" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundPressed" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
<StaticResource x:Key="TreeViewItemForegroundSelected" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundSelectedPointerOver" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundSelectedPressed" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundSelectedDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
<StaticResource x:Key="TreeViewItemBorderBrush" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushPointerOver" ResourceKey="SystemControlHighlightAltTransparentRevealBorderBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushPressed" ResourceKey="SystemControlHighlightAltTransparentRevealBorderBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushDisabled" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushSelected" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushSelectedPointerOver" ResourceKey="SystemControlBackgroundTransparentRevealBorderBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushSelectedPressed" ResourceKey="SystemControlBackgroundTransparentRevealBorderBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushSelectedDisabled" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemCheckBoxBackgroundSelected" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemCheckBoxBorderSelected" ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<StaticResource x:Key="TreeViewItemCheckGlyphSelected" ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<Thickness x:Key="TreeViewItemBorderThemeThickness">1</Thickness>
<x:Double x:Key="TreeViewItemMinHeight">32</x:Double>
</Style.Resources>
</Style>

30
src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml

@ -787,5 +787,35 @@
<x:Double x:Key="ScrollBarButtonArrowIconFontSize">8</x:Double>
<x:String x:Key="ScrollBarExpandBeginTime">00:00:00.40</x:String>
<x:String x:Key="ScrollBarContractBeginTime">00:00:02.00</x:String>
<!-- Resources for TreeViewItem.xaml -->
<StaticResource x:Key="TreeViewItemBackground" ResourceKey="SystemControlTransparentRevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundPointerOver" ResourceKey="SystemControlHighlightListLowRevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundPressed" ResourceKey="SystemControlHighlightListMediumRevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundDisabled" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemBackgroundSelected" ResourceKey="SystemControlHighlightAccent3RevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundSelectedPointerOver" ResourceKey="SystemControlHighlightAccent2RevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundSelectedPressed" ResourceKey="SystemControlHighlightListMediumRevealBackgroundBrush" />
<StaticResource x:Key="TreeViewItemBackgroundSelectedDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
<StaticResource x:Key="TreeViewItemForeground" ResourceKey="SystemControlForegroundBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundPointerOver" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundPressed" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
<StaticResource x:Key="TreeViewItemForegroundSelected" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundSelectedPointerOver" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundSelectedPressed" ResourceKey="SystemControlHighlightAltBaseHighBrush" />
<StaticResource x:Key="TreeViewItemForegroundSelectedDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
<StaticResource x:Key="TreeViewItemBorderBrush" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushPointerOver" ResourceKey="SystemControlHighlightAltTransparentRevealBorderBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushPressed" ResourceKey="SystemControlHighlightAltTransparentRevealBorderBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushDisabled" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushSelected" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushSelectedPointerOver" ResourceKey="SystemControlBackgroundTransparentRevealBorderBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushSelectedPressed" ResourceKey="SystemControlBackgroundTransparentRevealBorderBrush" />
<StaticResource x:Key="TreeViewItemBorderBrushSelectedDisabled" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemCheckBoxBackgroundSelected" ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="TreeViewItemCheckBoxBorderSelected" ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<StaticResource x:Key="TreeViewItemCheckGlyphSelected" ResourceKey="SystemControlForegroundBaseMediumHighBrush" />
<Thickness x:Key="TreeViewItemBorderThemeThickness">1</Thickness>
<x:Double x:Key="TreeViewItemMinHeight">32</x:Double>
</Style.Resources>
</Style>

4
src/Avalonia.Themes.Fluent/ToggleSwitch.xaml

@ -3,8 +3,8 @@
xmlns:sys="clr-namespace:System;assembly=netstandard">
<Styles.Resources>
<Thickness x:Key="ToggleSwitchTopHeaderMargin">0,0,0,6</Thickness>
<x:Double x:Key="ToggleSwitchPreContentMargin">6</x:Double>
<x:Double x:Key="ToggleSwitchPostContentMargin">6</x:Double>
<GridLength x:Key="ToggleSwitchPreContentMargin">6</GridLength>
<GridLength x:Key="ToggleSwitchPostContentMargin">6</GridLength>
<x:Double x:Key="ToggleSwitchThemeMinWidth">154</x:Double>
<x:Double x:Key="KnobOnPosition">20</x:Double>
<x:Double x:Key="KnobOffPosition">0</x:Double>

17
src/Avalonia.Themes.Fluent/TreeView.xaml

@ -1,10 +1,11 @@
<Style xmlns="https://github.com/avaloniaui" Selector="TreeView">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}"/>
<Setter Property="BorderThickness" Value="{DynamicResource ThemeBorderThickness}"/>
<Setter Property="Padding" Value="4"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Style xmlns="https://github.com/avaloniaui"
Selector="TreeView">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="Template">
<ControlTemplate>
<Border BorderBrush="{TemplateBinding BorderBrush}"
@ -15,7 +16,7 @@
<ItemsPresenter Name="PART_ItemsPresenter"
Items="{TemplateBinding Items}"
ItemsPanel="{TemplateBinding ItemsPanel}"
Margin="{TemplateBinding Padding}"/>
Margin="{TemplateBinding Padding}" />
</ScrollViewer>
</Border>
</ControlTemplate>

246
src/Avalonia.Themes.Fluent/TreeViewItem.xaml

@ -1,92 +1,180 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:Avalonia.Controls.Converters;assembly=Avalonia.Controls">
<Style Selector="TreeViewItem">
<Style.Resources>
<converters:MarginMultiplierConverter Indent="16" Left="True" x:Key="LeftMarginConverter" />
</Style.Resources>
<Setter Property="Padding" Value="2"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<ControlTemplate>
<StackPanel>
<Border Name="SelectionBorder"
Focusable="True"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
TemplatedControl.IsTemplateFocusTarget="True">
<Grid Name="PART_Header"
ColumnDefinitions="16, *"
Margin="{TemplateBinding Level, Mode=OneWay, Converter={StaticResource LeftMarginConverter}}" >
<ToggleButton Name="expander"
Focusable="False"
IsChecked="{TemplateBinding IsExpanded, Mode=TwoWay}"/>
<ContentPresenter Name="PART_HeaderPresenter"
Focusable="False"
Content="{TemplateBinding Header}"
HorizontalContentAlignment="{TemplateBinding HorizontalAlignment}"
Padding="{TemplateBinding Padding}"
Grid.Column="1"/>
</Grid>
</Border>
<ItemsPresenter Name="PART_ItemsPresenter"
IsVisible="{TemplateBinding IsExpanded}"
Items="{TemplateBinding Items}"
ItemsPanel="{TemplateBinding ItemsPanel}"/>
</StackPanel>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="TreeViewItem /template/ ToggleButton#expander">
<Setter Property="Template">
<ControlTemplate>
<Border Background="Transparent"
Width="14"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Path Fill="{DynamicResource ThemeForegroundBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 2 L 4 6 L 0 10 Z"/>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Design.PreviewWith>
<Border Padding="20"
MinWidth="300">
<TreeView>
<TreeViewItem Header="Level 1">
<TreeViewItem Header="Level 2.1">
<TreeViewItem Header="Level 3.1" />
<TreeViewItem Header="Level 3.2">
<TreeViewItem Header="Level 4" />
</TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="Level 2.2"
IsEnabled="False" />
</TreeViewItem>
</TreeView>
</Border>
</Design.PreviewWith>
<Style Selector="TreeViewItem /template/ ContentPresenter#PART_HeaderPresenter">
<Setter Property="Padding" Value="2"/>
</Style>
<Styles.Resources>
<x:Double x:Key="TreeViewItemIndent">16</x:Double>
<x:Double x:Key="TreeViewItemExpandCollapseChevronSize">12</x:Double>
<Thickness x:Key="TreeViewItemExpandCollapseChevronMargin">12, 0, 12, 0</Thickness>
<StreamGeometry x:Key="TreeViewItemCollapsedChevronPathData">M 1,0 10,10 l -9,10 -1,-1 L 8,10 -0,1 Z</StreamGeometry>
<StreamGeometry x:Key="TreeViewItemExpandedChevronPathData">M0,1 L10,10 20,1 19,0 10,8 1,0 Z</StreamGeometry>
<converters:MarginMultiplierConverter Indent="{StaticResource TreeViewItemIndent}"
Left="True"
x:Key="TreeViewItemLeftMarginConverter" />
</Styles.Resources>
<Style Selector="TreeViewItem /template/ Border#SelectionBorder:pointerover">
<Setter Property="Background" Value="{DynamicResource ThemeControlHighlightMidBrush}"/>
</Style>
<Style Selector="ToggleButton.ExpandCollapseChevron">
<Setter Property="Margin" Value="0" />
<Setter Property="Width" Value="{StaticResource TreeViewItemExpandCollapseChevronSize}" />
<Setter Property="Height" Value="{StaticResource TreeViewItemExpandCollapseChevronSize}" />
<Setter Property="Template">
<ControlTemplate>
<Border Background="Transparent"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Path x:Name="ChevronPath"
Fill="{DynamicResource TreeViewItemForeground}"
Stretch="Uniform"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="TreeViewItem:selected /template/ Border#SelectionBorder">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush4}"/>
</Style>
<Style Selector="TreeViewItem">
<Style.Resources />
<Setter Property="Padding" Value="0" />
<Setter Property="Background" Value="{DynamicResource TreeViewItemBackground}" />
<Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrush}" />
<Setter Property="BorderThickness" Value="{DynamicResource TreeViewItemBorderThemeThickness}" />
<Setter Property="Foreground" Value="{DynamicResource TreeViewItemForeground}" />
<Setter Property="MinHeight" Value="{DynamicResource TreeViewItemMinHeight}" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<ControlTemplate>
<StackPanel>
<Border Name="PART_LayoutRoot"
Classes="TreeViewItemLayoutRoot"
Focusable="True"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
MinHeight="{TemplateBinding MinHeight}"
TemplatedControl.IsTemplateFocusTarget="True">
<Grid Name="PART_Header"
ColumnDefinitions="Auto, *"
Margin="{TemplateBinding Level, Mode=OneWay, Converter={StaticResource TreeViewItemLeftMarginConverter}}">
<Panel Name="PART_ExpandCollapseChevronContainer"
Margin="{StaticResource TreeViewItemExpandCollapseChevronMargin}">
<ToggleButton Name="PART_ExpandCollapseChevron"
Classes="ExpandCollapseChevron"
Focusable="False"
IsChecked="{TemplateBinding IsExpanded, Mode=TwoWay}" />
</Panel>
<ContentPresenter Name="PART_HeaderPresenter"
Grid.Column="1"
Focusable="False"
Content="{TemplateBinding Header}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Margin="{TemplateBinding Padding}" />
</Grid>
</Border>
<ItemsPresenter Name="PART_ItemsPresenter"
IsVisible="{TemplateBinding IsExpanded}"
Items="{TemplateBinding Items}"
ItemsPanel="{TemplateBinding ItemsPanel}" />
</StackPanel>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="TreeViewItem:selected /template/ Border#SelectionBorder:focus">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush3}"/>
</Style>
<!-- PointerOver state -->
<Style Selector="TreeViewItem /template/ Border#PART_LayoutRoot:pointerover">
<Setter Property="Background" Value="{DynamicResource TreeViewItemBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrushPointerOver}" />
</Style>
<Style Selector="TreeViewItem /template/ Border#PART_LayoutRoot:pointerover > ContentPresenter#PART_HeaderPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundPointerOver}" />
</Style>
<Style Selector="TreeViewItem:selected /template/ Border#SelectionBorder:pointerover">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush3}"/>
</Style>
<!-- Pressed state -->
<Style Selector="TreeViewItem:pressed /template/ Border#PART_LayoutRoot:pointerover">
<Setter Property="Background" Value="{DynamicResource TreeViewItemBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrushPressed}" />
</Style>
<Style Selector="TreeViewItem:pressed /template/ Border#PART_LayoutRoot:pointerover > ContentPresenter#PART_HeaderPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundPressed}" />
</Style>
<Style Selector="TreeViewItem:selected /template/ Border#SelectionBorder:pointerover:focus">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush2}"/>
</Style>
<!-- Disabled state -->
<Style Selector="TreeViewItem:disabled /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="{DynamicResource TreeViewItemBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrushDisabled}" />
</Style>
<Style Selector="TreeViewItem:disabled /template/ Border#PART_LayoutRoot > ContentPresenter#PART_HeaderPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundDisabled}" />
</Style>
<Style Selector="TreeViewItem /template/ ToggleButton#expander:checked">
<Setter Property="RenderTransform">
<RotateTransform Angle="45"/>
</Setter>
</Style>
<!-- Selected state -->
<Style Selector="TreeViewItem:selected /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="{DynamicResource TreeViewItemBackgroundSelected}" />
<Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrushSelected}" />
</Style>
<Style Selector="TreeViewItem:selected /template/ Border#PART_LayoutRoot > ContentPresenter#PART_HeaderPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundSelected}" />
</Style>
<!-- Selected PointerOver state -->
<Style Selector="TreeViewItem:selected /template/ Border#PART_LayoutRoot:pointerover">
<Setter Property="Background" Value="{DynamicResource TreeViewItemBackgroundSelectedPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrushSelectedPointerOver}" />
</Style>
<Style Selector="TreeViewItem:selected /template/ Border#PART_LayoutRoot:pointerover > ContentPresenter#PART_HeaderPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundSelectedPointerOver}" />
</Style>
<!-- Selected Pressed state -->
<Style Selector="TreeViewItem:pressed:selected /template/ Border#PART_LayoutRoot:pointerover">
<Setter Property="Background" Value="{DynamicResource TreeViewItemBackgroundSelectedPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrushSelectedPressed}" />
</Style>
<Style Selector="TreeViewItem:pressed:selected /template/ Border#PART_LayoutRoot:pointerover > ContentPresenter#PART_HeaderPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundSelectedPressed}" />
</Style>
<!-- Disabled Selected state -->
<Style Selector="TreeViewItem:disabled:selected /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="{DynamicResource TreeViewItemBackgroundSelectedDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrushSelectedDisabled}" />
</Style>
<Style Selector="TreeViewItem:disabled:selected /template/ Border#PART_LayoutRoot > ContentPresenter#PART_HeaderPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundSelectedDisabled}" />
</Style>
<!-- ExpandCollapseChevron Group states -->
<Style Selector="ToggleButton.ExpandCollapseChevron /template/ Path#ChevronPath">
<Setter Property="Data" Value="{StaticResource TreeViewItemCollapsedChevronPathData}" />
</Style>
<Style Selector="ToggleButton.ExpandCollapseChevron:checked /template/ Path#ChevronPath">
<Setter Property="Data" Value="{StaticResource TreeViewItemExpandedChevronPathData}" />
</Style>
<Style Selector="TreeViewItem:empty /template/ ToggleButton#PART_ExpandCollapseChevron">
<Setter Property="IsVisible" Value="False" />
</Style>
<Style Selector="TreeViewItem:empty /template/ Panel#PART_ExpandCollapseChevronContainer">
<Setter Property="Width" Value="{StaticResource TreeViewItemExpandCollapseChevronSize}" />
</Style>
<Style Selector="TreeViewItem:empty /template/ ToggleButton#expander">
<Setter Property="IsVisible" Value="False"/>
</Style>
</Styles>

29
tests/Avalonia.Input.UnitTests/KeyboardNavigationTests_Tab.cs

@ -185,6 +185,35 @@ namespace Avalonia.Input.UnitTests
Assert.Equal(next, result);
}
[Fact]
public void Next_Skips_Non_TabStop_Siblings()
{
Button current;
Button next;
var top = new StackPanel
{
Children =
{
new StackPanel
{
Children =
{
new Button { Name = "Button1" },
new Button { Name = "Button2" },
(current = new Button { Name = "Button3" }),
new Button { Name="Button4", [KeyboardNavigation.IsTabStopProperty] = false }
}
},
(next = new Button { Name = "Button5" }),
}
};
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Next);
Assert.Equal(next, result);
}
[Fact]
public void Next_Continue_Returns_First_Control_In_Next_Uncle_Container()
{

Loading…
Cancel
Save