From 82835ef95708edaf80a4ac2406179192d2db3d59 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 21 Apr 2022 09:53:28 +0200 Subject: [PATCH] Use nested styles in Button template. And related fixes to make this work. --- src/Avalonia.Base/Styling/NestingSelector.cs | 2 +- src/Avalonia.Base/Styling/Style.cs | 8 +- .../Controls/Button.xaml | 80 ++++++++++--------- .../Styling/SelectorTests_Nesting.cs | 68 +++++++++++++++- 4 files changed, 116 insertions(+), 42 deletions(-) diff --git a/src/Avalonia.Base/Styling/NestingSelector.cs b/src/Avalonia.Base/Styling/NestingSelector.cs index 1be54dea3c..741eb7e9ca 100644 --- a/src/Avalonia.Base/Styling/NestingSelector.cs +++ b/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( diff --git a/src/Avalonia.Base/Styling/Style.cs b/src/Avalonia.Base/Styling/Style.cs index 6020dfe25f..7a83322355 100644 --- a/src/Avalonia.Base/Styling/Style.cs +++ b/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) diff --git a/src/Avalonia.Themes.Fluent/Controls/Button.xaml b/src/Avalonia.Themes.Fluent/Controls/Button.xaml index f545206a2f..282f575605 100644 --- a/src/Avalonia.Themes.Fluent/Controls/Button.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/Button.xaml @@ -7,9 +7,11 @@ + 8,5,8,6 + - - + + - + - + - + - + - + + + + + - diff --git a/tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Nesting.cs b/tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Nesting.cs index eeb2fad996..f7e8793ede 100644 --- a/tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Nesting.cs +++ b/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()) + { + 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()) + { + 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() {