File: Element\Element_StyleSheets.cs
Web Access
Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls)
#nullable disable
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Maui.Controls.StyleSheets;
 
namespace Microsoft.Maui.Controls
{
	public partial class Element : IStyleSelectable
	{
		/// <inheritdoc/>
		IEnumerable<IStyleSelectable> IStyleSelectable.Children => LogicalChildrenInternal;
 
		/// <inheritdoc/>
		IList<string> IStyleSelectable.Classes => null;
 
		/// <inheritdoc/>
		string IStyleSelectable.Id => StyleId;
 
		string[] _styleSelectableNameAndBaseNames;
 
		/// <inheritdoc/>
		string[] IStyleSelectable.NameAndBases
		{
			get
			{
				if (_styleSelectableNameAndBaseNames == null)
				{
					var list = new List<string>();
					var t = GetType();
					while (t != typeof(BindableObject))
					{
						list.Add(t.Name);
						t = t.BaseType;
					}
					_styleSelectableNameAndBaseNames = list.ToArray();
				}
				return _styleSelectableNameAndBaseNames;
			}
		}
 
		/// <inheritdoc/>
		IStyleSelectable IStyleSelectable.Parent => Parent;
 
		//on parent set, or on parent stylesheet changed, reapply all
		internal void ApplyStyleSheets()
		{
			var sheets = new List<StyleSheet>();
			Element parent = this;
			while (parent != null)
			{
				var resourceProvider = parent as IResourcesProvider;
				var vpSheets = resourceProvider?.GetStyleSheets();
				if (vpSheets != null)
					sheets.AddRange(vpSheets);
				parent = parent.Parent;
			}
 
			ApplyStyleSheets(sheets, this);
		}
 
		void ApplyStyleSheets(List<StyleSheet> sheets, IVisualTreeElement element)
		{
			for (var i = (sheets?.Count ?? 0) - 1; i >= 0; i--)
			{
				if (element is BindableObject bo)
					//FIXME: is it ok to ignore specificty here ?
					((IStyle)sheets[i]).Apply(bo, new SetterSpecificity());
			}
 
			foreach (var child in element.GetVisualChildren())
			{
				var mergedSheets = sheets;
				var resourceProvider = child as IResourcesProvider;
				var childSheets = resourceProvider?.GetStyleSheets();
				if (childSheets?.Any() ?? false)
				{
					mergedSheets = new List<StyleSheet>(childSheets);
					mergedSheets.AddRange(sheets);
				}
				ApplyStyleSheets(mergedSheets, child);
			}
		}
	}
}