| | | 1 | | namespace Allyaria.Theming.ThemeTypes; |
| | | 2 | | |
| | | 3 | | /// <summary> |
| | | 4 | | /// Represents a collection of <see cref="ThemeState" /> objects grouped by <see cref="ThemeType" />, forming a |
| | | 5 | | /// hierarchical layer in the Allyaria theming structure. |
| | | 6 | | /// </summary> |
| | | 7 | | /// <remarks> |
| | | 8 | | /// <para> |
| | | 9 | | /// Each <see cref="ThemeVariant" /> corresponds to a specific set of theme variants (e.g., Light, Dark, |
| | | 10 | | /// HighContrastLight, HighContrastDark) under a particular <see cref="ComponentType" />. It recursively builds CSS |
| | | 11 | | /// output and applies updates for its child <see cref="ThemeState" /> instances. |
| | | 12 | | /// </para> |
| | | 13 | | /// <para> |
| | | 14 | | /// This class participates in the theming resolution chain alongside <see cref="ThemeComponent" />, |
| | | 15 | | /// <see cref="ThemeState" />, and <see cref="ThemeUpdater" />. |
| | | 16 | | /// </para> |
| | | 17 | | /// </remarks> |
| | | 18 | | internal sealed class ThemeVariant |
| | | 19 | | { |
| | | 20 | | /// <summary> |
| | | 21 | | /// A dictionary mapping <see cref="ThemeType" /> values to their respective <see cref="ThemeState" /> definitions. |
| | | 22 | | /// </summary> |
| | 114 | 23 | | private readonly Dictionary<ThemeType, ThemeState> _children = new(); |
| | | 24 | | |
| | | 25 | | /// <summary> |
| | | 26 | | /// Builds CSS for this theme variant and its child <see cref="ThemeState" /> instances using the provided context. |
| | | 27 | | /// </summary> |
| | | 28 | | /// <param name="builder">The <see cref="CssBuilder" /> used to accumulate CSS declarations.</param> |
| | | 29 | | /// <param name="navigator"> |
| | | 30 | | /// The <see cref="ThemeNavigator" /> describing the scope of components, themes, and states to include. |
| | | 31 | | /// </param> |
| | | 32 | | /// <param name="varPrefix">An optional variable prefix used when generating CSS variable declarations.</param> |
| | | 33 | | /// <returns>A <see cref="CssBuilder" /> instance containing the concatenated CSS output for this variant.</returns> |
| | | 34 | | internal CssBuilder BuildCss(CssBuilder builder, ThemeNavigator navigator, string? varPrefix = "") |
| | | 35 | | { |
| | 33 | 36 | | if (navigator.ThemeTypes.Count is 0) |
| | | 37 | | { |
| | 26 | 38 | | foreach (var child in _children) |
| | | 39 | | { |
| | 8 | 40 | | builder = child.Value.BuildCss( |
| | 8 | 41 | | builder: builder, |
| | 8 | 42 | | navigator: navigator, |
| | 8 | 43 | | varPrefix: SetPrefix(varPrefix: varPrefix, type: child.Key) |
| | 8 | 44 | | ); |
| | | 45 | | } |
| | | 46 | | } |
| | | 47 | | else |
| | | 48 | | { |
| | 114 | 49 | | foreach (var key in navigator.ThemeTypes) |
| | | 50 | | { |
| | 29 | 51 | | builder = Get(key: key)?.BuildCss( |
| | 29 | 52 | | builder: builder, |
| | 29 | 53 | | navigator: navigator, |
| | 29 | 54 | | varPrefix: SetPrefix(varPrefix: varPrefix, type: key) |
| | 29 | 55 | | ) ?? builder; |
| | | 56 | | } |
| | | 57 | | } |
| | | 58 | | |
| | 33 | 59 | | return builder; |
| | | 60 | | } |
| | | 61 | | |
| | | 62 | | /// <summary> |
| | | 63 | | /// Retrieves a <see cref="ThemeState" /> associated with a given <see cref="ThemeType" />, if it exists. |
| | | 64 | | /// </summary> |
| | | 65 | | /// <param name="key">The <see cref="ThemeType" /> identifier to retrieve.</param> |
| | | 66 | | /// <returns>The corresponding <see cref="ThemeState" /> if found; otherwise, <see langword="null" />.</returns> |
| | 6578 | 67 | | private ThemeState? Get(ThemeType key) => _children.GetValueOrDefault(key: key); |
| | | 68 | | |
| | | 69 | | /// <summary> |
| | | 70 | | /// Applies a <see cref="ThemeUpdater" /> to update or create <see cref="ThemeState" /> entries for all matching |
| | | 71 | | /// <see cref="ThemeType" /> values in this variant. |
| | | 72 | | /// </summary> |
| | | 73 | | /// <param name="updater">The <see cref="ThemeUpdater" /> instance containing the update definition.</param> |
| | | 74 | | /// <returns>The current <see cref="ThemeVariant" /> instance, allowing fluent configuration.</returns> |
| | | 75 | | internal ThemeVariant Set(ThemeUpdater updater) |
| | | 76 | | { |
| | 24374 | 77 | | foreach (var key in updater.Navigator.ThemeTypes) |
| | | 78 | | { |
| | 6549 | 79 | | if (!_children.ContainsKey(key: key)) |
| | | 80 | | { |
| | 402 | 81 | | _children.Add(key: key, value: new ThemeState()); |
| | | 82 | | } |
| | | 83 | | |
| | 6549 | 84 | | Get(key: key)?.Set(updater: updater); |
| | | 85 | | } |
| | | 86 | | |
| | 5638 | 87 | | return this; |
| | | 88 | | } |
| | | 89 | | |
| | | 90 | | /// <summary>Generates a hierarchical CSS variable prefix string combining the provided prefix and theme type.</summ |
| | | 91 | | /// <param name="varPrefix">The existing variable prefix, if any.</param> |
| | | 92 | | /// <param name="type">The <see cref="ThemeType" /> to append to the prefix.</param> |
| | | 93 | | /// <returns>A normalized CSS-compatible prefix string.</returns> |
| | | 94 | | private static string SetPrefix(string? varPrefix, ThemeType type) |
| | | 95 | | { |
| | 34 | 96 | | var prefix = varPrefix?.ToCssName() ?? string.Empty; |
| | | 97 | | |
| | 34 | 98 | | return string.IsNullOrWhiteSpace(value: prefix) |
| | 34 | 99 | | ? string.Empty |
| | 34 | 100 | | : $"{prefix}-{type}".ToCssName(); |
| | | 101 | | } |
| | | 102 | | } |