diff --git a/src/Controls/src/Core/StyleSheets/Selector.cs b/src/Controls/src/Core/StyleSheets/Selector.cs index 231fbc77d7f4..b3c8b79b2c4a 100644 --- a/src/Controls/src/Core/StyleSheets/Selector.cs +++ b/src/Controls/src/Core/StyleSheets/Selector.cs @@ -1,5 +1,6 @@ #nullable disable using System; +using System.Diagnostics; namespace Microsoft.Maui.Controls.StyleSheets { @@ -313,5 +314,65 @@ public override bool Matches(IStyleSelectable styleable) //return siblingIndex != -1; } } + + [DebuggerDisplay("{id} - {class} = {type}")] + public struct SelectorSpecificity + { + int id; + int @class; + int type; + + public int Id { get => id; } + public int Class { get => @class; } + public int Type { get => type; } + + public static SelectorSpecificity FromSelector(Selector selector) + { + switch(selector) + { + case Selector.Class c: + return new SelectorSpecificity { @class = 1 }; + case Selector.Id i: + return new SelectorSpecificity { id = 1 }; + case Selector.Element e: + return new SelectorSpecificity { type = 1 }; + case Selector.Base b: + return new SelectorSpecificity { type = 1 }; + case Selector.And a: + return FromSelector(a.Left) + FromSelector(a.Right); + case Selector.Or o: + return FromSelector(o.Left) + FromSelector(o.Right); + case Selector.Child c: + return FromSelector(c.Left) + FromSelector(c.Right); + case Selector.Descendent d: + return FromSelector(d.Left) + FromSelector(d.Right); + case Selector.Adjacent a: + return FromSelector(a.Left) + FromSelector(a.Right); + case Selector.Sibling s: + return FromSelector(s.Left) + FromSelector(s.Right); + default: + return default; + } + } + + public static SelectorSpecificity operator +(SelectorSpecificity left, SelectorSpecificity right) + { + return new SelectorSpecificity + { + id = left.id + right.id, + @class = left.@class + right.@class, + type = left.type + right.type + }; + } + public SelectorSpecificity Add(SelectorSpecificity other) + { + return new SelectorSpecificity + { + id = id + other.id, + @class = @class + other.@class, + type = type + other.type + }; + } + } } } diff --git a/src/Controls/src/Core/StyleSheets/Style.cs b/src/Controls/src/Core/StyleSheets/Style.cs index 2b14357b455f..8c8634ee4ea6 100644 --- a/src/Controls/src/Core/StyleSheets/Style.cs +++ b/src/Controls/src/Core/StyleSheets/Style.cs @@ -60,7 +60,7 @@ public static Style Parse(CssReader reader, char stopChar = '\0') return style; } - public void Apply(VisualElement styleable, bool inheriting = false) + public void Apply(VisualElement styleable, Selector.SelectorSpecificity selectorSpecificity = default, bool inheriting = false) { if (styleable == null) throw new ArgumentNullException(nameof(styleable)); @@ -71,15 +71,14 @@ public void Apply(VisualElement styleable, bool inheriting = false) if (property == null) continue; if (string.Equals(decl.Value, "initial", StringComparison.OrdinalIgnoreCase)) - //FIXME - styleable.ClearValue(property, new SetterSpecificity(SetterSpecificity.StyleImplicit, 0, 0, 0)); + styleable.SetValue(property, property.DefaultValue, new SetterSpecificity(SetterSpecificity.StyleImplicit, (byte)selectorSpecificity.Id, (byte)selectorSpecificity.Class, (byte)selectorSpecificity.Type)); else { object value; if (!convertedValues.TryGetValue(decl, out value)) convertedValues[decl] = (value = Convert(styleable, decl.Value, property)); //FIXME: compute distance - styleable.SetValue(property, value, new SetterSpecificity(SetterSpecificity.StyleImplicit, 0, 0, 0)); + styleable.SetValue(property, value, new SetterSpecificity(SetterSpecificity.StyleImplicit, (byte)selectorSpecificity.Id, (byte)selectorSpecificity.Class, (byte)selectorSpecificity.Type)); } } diff --git a/src/Controls/src/Core/StyleSheets/StyleSheet.cs b/src/Controls/src/Core/StyleSheets/StyleSheet.cs index 69bf4d6dbb55..5ed7218206fb 100644 --- a/src/Controls/src/Core/StyleSheets/StyleSheet.cs +++ b/src/Controls/src/Core/StyleSheets/StyleSheet.cs @@ -111,7 +111,8 @@ void Apply(Element styleable) var style = kvp.Value; if (!selector.Matches(styleable)) continue; - style.Apply(visualStylable); + + style.Apply(visualStylable, Selector.SelectorSpecificity.FromSelector(selector)); } } diff --git a/src/Controls/tests/Xaml.UnitTests/Issues/Maui18980.xaml b/src/Controls/tests/Xaml.UnitTests/Issues/Maui18980.xaml new file mode 100644 index 000000000000..f1b628671a9b --- /dev/null +++ b/src/Controls/tests/Xaml.UnitTests/Issues/Maui18980.xaml @@ -0,0 +1,11 @@ + + + + + + +