| File: StyleSheets\StyleSheet.cs | Web Access |
| Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls) |
#nullable disable using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Xml; using Microsoft.Maui.Controls.Xaml; namespace Microsoft.Maui.Controls.StyleSheets { /// <include file="../../../docs/Microsoft.Maui.Controls.StyleSheets/StyleSheet.xml" path="Type[@FullName='Microsoft.Maui.Controls.StyleSheets.StyleSheet']/Docs/*" /> public sealed class StyleSheet : IStyle { StyleSheet() { } internal IDictionary<Selector, Style> Styles { get; set; } = new Dictionary<Selector, Style>(); //used by code generated by XamlC. Has to stay public /// <include file="../../../docs/Microsoft.Maui.Controls.StyleSheets/StyleSheet.xml" path="//Member[@MemberName='FromResource']/Docs/*" /> [EditorBrowsable(EditorBrowsableState.Never)] public static StyleSheet FromResource(string resourcePath, Assembly assembly, IXmlLineInfo lineInfo = null) { var styleSheet = new StyleSheet(); var resString = GetResource(resourcePath, assembly, styleSheet, lineInfo); using (var textReader = new StringReader(resString)) using (var cssReader = new CssReader(textReader)) Parse(styleSheet, cssReader); return styleSheet; } //used by code generated by XamlC. Has to stay public /// <include file="../../../docs/Microsoft.Maui.Controls.StyleSheets/StyleSheet.xml" path="//Member[@MemberName='FromString']/Docs/*" /> [EditorBrowsable(EditorBrowsableState.Never)] public static StyleSheet FromString(string stylesheet) { if (stylesheet == null) throw new ArgumentNullException(nameof(stylesheet)); using (var reader = new StringReader(stylesheet)) return FromReader(reader); } /// <include file="../../../docs/Microsoft.Maui.Controls.StyleSheets/StyleSheet.xml" path="//Member[@MemberName='FromReader']/Docs/*" /> public static StyleSheet FromReader(TextReader reader) { if (reader == null) throw new ArgumentNullException(nameof(reader)); var sheet = new StyleSheet(); using (var cssReader = new CssReader(reader)) Parse(sheet, cssReader); return sheet; } [MethodImpl(MethodImplOptions.AggressiveInlining)] static void Parse(StyleSheet sheet, CssReader reader) { Style style = null; var selector = Selector.All; int p; bool inStyle = false; reader.SkipWhiteSpaces(); while ((p = reader.Peek()) > 0) { switch ((char)p) { case '@': throw new NotSupportedException("AT-rules not supported"); case '{': reader.Read(); style = Style.Parse(reader, '}'); inStyle = true; break; case '}': reader.Read(); if (!inStyle) throw new Exception(); inStyle = false; sheet.Styles.Add(selector, style); style = null; selector = Selector.All; break; default: selector = Selector.Parse(reader, '{'); break; } } } Type IStyle.TargetType => typeof(VisualElement); void IStyle.Apply(BindableObject bindable, SetterSpecificity setterspecificity) { if (!(bindable is Element styleable)) return; Apply(styleable); } void Apply(Element styleable) { if (!(styleable is VisualElement visualStylable)) return; foreach (var kvp in Styles) { var selector = kvp.Key; var style = kvp.Value; if (!selector.Matches(styleable)) continue; style.Apply(visualStylable, Selector.SelectorSpecificity.FromSelector(selector)); } } void IStyle.UnApply(BindableObject bindable) => throw new NotImplementedException(); private static string GetResource(string resourcePath, Assembly assembly, object target, IXmlLineInfo lineInfo) { var resourceLoadingResponse = Maui.Controls.Internals.ResourceLoader.ResourceProvider2?.Invoke(new Maui.Controls.Internals.ResourceLoader.ResourceLoadingQuery { AssemblyName = assembly.GetName(), ResourcePath = resourcePath, Instance = target }); var alternateResource = resourceLoadingResponse?.ResourceContent; if (alternateResource != null) return alternateResource; var resourceId = XamlResourceIdAttribute.GetResourceIdForPath(assembly, resourcePath); if (resourceId == null) throw new XamlParseException($"Resource '{resourcePath}' not found.", lineInfo); using (var stream = assembly.GetManifestResourceStream(resourceId)) { if (stream == null) throw new XamlParseException($"No resource found for '{resourceId}'.", lineInfo); using (var reader = new StreamReader(stream)) return reader.ReadToEnd(); } } } }