Browse Source

Use nested styles in Button template.

And related fixes to make this work.
pull/8024/head
Steven Kirk 5 years ago
parent
commit
82835ef957
  1. 2
      src/Avalonia.Base/Styling/NestingSelector.cs
  2. 8
      src/Avalonia.Base/Styling/Style.cs
  3. 80
      src/Avalonia.Themes.Fluent/Controls/Button.xaml
  4. 68
      tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Nesting.cs

2
src/Avalonia.Base/Styling/NestingSelector.cs

@ -17,7 +17,7 @@ namespace Avalonia.Styling
{
if (parent is Style s && s.Selector is Selector selector)
{
return selector.Match(control, null, subscribe);
return selector.Match(control, (parent as Style)?.Parent, subscribe);
}
throw new InvalidOperationException(

8
src/Avalonia.Base/Styling/Style.cs

@ -120,15 +120,19 @@ namespace Avalonia.Styling
instance.Start();
}
var result = match.Result;
if (_children is not null)
{
foreach (var child in _children)
{
child.TryAttach(target, host);
var childResult = child.TryAttach(target, host);
if (childResult > result)
result = childResult;
}
}
return match.Result;
return result;
}
public bool TryGetResource(object key, out object? result)

80
src/Avalonia.Themes.Fluent/Controls/Button.xaml

@ -7,9 +7,11 @@
</StackPanel>
</Border>
</Design.PreviewWith>
<Styles.Resources>
<Thickness x:Key="ButtonPadding">8,5,8,6</Thickness>
</Styles.Resources>
<Style Selector="Button">
<Setter Property="Background" Value="{DynamicResource ButtonBackground}" />
<!--<Setter Property="BackgroundSizing" Value="OuterBorderEdge" />-->
@ -37,43 +39,54 @@
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</ControlTemplate>
</Setter>
</Style>
<!-- PointerOverState -->
<Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPointerOver}" />
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" />
</Style>
<Style.Children>
<Style Selector="&amp;:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPointerOver}" />
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" />
</Style>
<Style Selector="Button:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPressed}" />
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" />
</Style>
<Style Selector="&amp;:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPressed}" />
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" />
</Style>
<Style Selector="Button:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" />
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
</Style>
<Style Selector="&amp;:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" />
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
</Style>
<Style Selector="Button.accent /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackground}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrush}" />
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForeground}" />
</Style>
<Style Selector="&amp;.accent">
<Style.Children>
<Style Selector="&amp; /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackground}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrush}" />
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForeground}" />
</Style>
<Style Selector="Button.accent:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPointerOver}" />
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForegroundPointerOver}" />
</Style>
<Style Selector="&amp;:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPointerOver}" />
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForegroundPointerOver}" />
</Style>
<Style Selector="Button.accent:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPressed}" />
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForegroundPressed}" />
<Style Selector="&amp;:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPressed}" />
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForegroundPressed}" />
</Style>
<Style Selector="&amp;:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushDisabled}" />
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForegroundDisabled}" />
</Style>
</Style.Children>
</Style>
</Style.Children>
</Style>
<Style Selector="Button, RepeatButton, ToggleButton, DropDownButton">
@ -89,9 +102,4 @@
<Setter Property="RenderTransform" Value="scale(0.98)" />
</Style>
<Style Selector="Button.accent:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushDisabled}" />
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForegroundDisabled}" />
</Style>
</Styles>

68
tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Nesting.cs

@ -9,7 +9,7 @@ namespace Avalonia.Base.UnitTests.Styling
public class SelectorTests_Nesting
{
[Fact]
public void Nesting_Class_Doesnt_Match_Parent_Selector()
public void Nesting_Class_Doesnt_Match_Parent_OfType_Selector()
{
var control = new Control2();
Style nested;
@ -26,7 +26,7 @@ namespace Avalonia.Base.UnitTests.Styling
}
[Fact]
public void Or_Nesting_Class_Doesnt_Match_Parent_Selector()
public void Or_Nesting_Class_Doesnt_Match_Parent_OfType_Selector()
{
var control = new Control2();
Style nested;
@ -45,7 +45,7 @@ namespace Avalonia.Base.UnitTests.Styling
}
[Fact]
public void Or_Nesting_Child_OfType_Does_Not_Match_Parent_Selector()
public void Or_Nesting_Child_OfType_Doesnt_Match_Parent_OfType_Selector()
{
var control = new Control1();
var panel = new DockPanel { Children = { control } };
@ -64,6 +64,34 @@ namespace Avalonia.Base.UnitTests.Styling
Assert.Equal(SelectorMatchResult.NeverThisInstance, match.Result);
}
[Fact]
public void Double_Nesting_Class_Doesnt_Match_Grandparent_OfType_Selector()
{
var control = new Control2
{
Classes = { "foo", "bar" },
};
Style parent;
Style nested;
var grandparent = new Style(x => x.OfType<Control1>())
{
Children =
{
(parent = new Style(x => x.Nesting().Class("foo"))
{
Children =
{
(nested = new Style(x => x.Nesting().Class("bar")))
}
})
}
};
var match = nested.Selector.Match(control, parent);
Assert.Equal(SelectorMatchResult.NeverThisType, match.Result);
}
[Fact]
public void Nesting_Class_Matches()
{
@ -87,6 +115,40 @@ namespace Avalonia.Base.UnitTests.Styling
Assert.False(sink.Active);
}
[Fact]
public void Double_Nesting_Class_Matches()
{
var control = new Control1
{
Classes = { "foo", "bar" },
};
Style parent;
Style nested;
var grandparent = new Style(x => x.OfType<Control1>())
{
Children =
{
(parent = new Style(x => x.Nesting().Class("foo"))
{
Children =
{
(nested = new Style(x => x.Nesting().Class("bar")))
}
})
}
};
var match = nested.Selector.Match(control, parent);
Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
var sink = new ActivatorSink(match.Activator);
Assert.True(sink.Active);
control.Classes.Remove("foo");
Assert.False(sink.Active);
}
[Fact]
public void Or_Nesting_Class_Matches()
{

Loading…
Cancel
Save