< Summary

Information
Class: Allyaria.Theming.Helpers.ThemeMapper
Assembly: Allyaria.Theming
File(s): /home/runner/work/allyaria/allyaria/src/Allyaria.Theming/Helpers/ThemeMapper.cs
Line coverage
100%
Covered lines: 88
Uncovered lines: 0
Coverable lines: 88
Total lines: 201
Line coverage: 100%
Branch coverage
100%
Covered branches: 40
Total branches: 40
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%22100%
BuildPaletteMap(...)100%11100%
BuildThemeMap(...)100%44100%
BuildThemeVariantMap(...)100%44100%
GetBrandState(...)100%1414100%
GetColors(...)100%1010100%
GetFont(...)100%66100%

File(s)

/home/runner/work/allyaria/allyaria/src/Allyaria.Theming/Helpers/ThemeMapper.cs

#LineLine coverage
 1namespace Allyaria.Theming.Helpers;
 2
 3/// <summary>
 4/// Provides mapping utilities between <see cref="Brand" /> configurations and Allyaria theming constructs, producing
 5/// <see cref="ThemeUpdater" /> instances used to construct theme components.
 6/// </summary>
 7/// <remarks>
 8///     <para>
 9///     The <see cref="ThemeMapper" /> acts as the bridge between brand-level definitions (fonts, palettes, variants) an
 10///     runtime theme generation.
 11///     </para>
 12///     <para>
 13///     It handles color palette resolution, font face selection, and state-based color derivation for light, dark, and
 14///     high-contrast variants.
 15///     </para>
 16/// </remarks>
 17internal sealed class ThemeMapper
 18{
 19    /// <summary>The primary <see cref="Brand" /> definition used for standard light and dark modes.</summary>
 20    private readonly Brand _brand;
 21
 22    /// <summary>The dedicated high-contrast <see cref="Brand" /> variant used when accessibility modes are enabled.</su
 23    private readonly Brand _highContrast;
 24
 25    /// <summary>Initializes a new instance of the <see cref="ThemeMapper" /> class.</summary>
 26    /// <param name="brand">An optional <see cref="Brand" /> instance. If omitted, a default <see cref="Brand" /> is cre
 7227    public ThemeMapper(Brand? brand = null)
 28    {
 7229        _brand = brand ?? new Brand();
 7230        _highContrast = Brand.CreateHighContrastBrand();
 7231    }
 32
 33    /// <summary>
 34    /// Builds a mapping between <see cref="BrandPalette" /> instances and <see cref="ComponentState" /> values.
 35    /// </summary>
 36    /// <param name="state">The <see cref="BrandState" /> defining the palette states.</param>
 37    /// <returns>
 38    /// An array of tuples pairing <see cref="BrandPalette" /> with its associated <see cref="ComponentState" />.
 39    /// </returns>
 40    private static (BrandPalette Palette, ComponentState ComponentState)[] BuildPaletteMap(BrandState state)
 41        =>
 78442        [
 78443            (state.Default, ComponentState.Default),
 78444            (state.Disabled, ComponentState.Disabled),
 78445            (state.Dragged, ComponentState.Dragged),
 78446            (state.Focused, ComponentState.Focused),
 78447            (state.Hovered, ComponentState.Hovered),
 78448            (state.Pressed, ComponentState.Pressed),
 78449            (state.Visited, ComponentState.Visited)
 78450        ];
 51
 52    /// <summary>Builds a mapping of light and dark theme variants from the given <see cref="Brand" />.</summary>
 53    /// <param name="brand">The <see cref="Brand" /> from which to derive color themes.</param>
 54    /// <param name="isHighContrast">Indicates whether high-contrast variants should be mapped.</param>
 55    /// <returns>
 56    /// An array of tuples pairing <see cref="BrandTheme" /> with its corresponding <see cref="ThemeType" />.
 57    /// </returns>
 58    private static (BrandTheme Theme, ThemeType ThemeType)[] BuildThemeMap(Brand brand, bool isHighContrast)
 59        =>
 25160        [
 25161            (brand.Variant.Dark, isHighContrast
 25162                ? ThemeType.HighContrastDark
 25163                : ThemeType.Dark),
 25164            (brand.Variant.Light, isHighContrast
 25165                ? ThemeType.HighContrastLight
 25166                : ThemeType.Light)
 25167        ];
 68
 69    /// <summary>
 70    /// Builds a mapping for light and dark theme <em>variants</em> derived from the base <see cref="Brand" />.
 71    /// </summary>
 72    /// <param name="brand">The <see cref="Brand" /> used for variant mapping.</param>
 73    /// <param name="isHighContrast">Specifies whether high-contrast mappings should be included.</param>
 74    /// <returns>An array of tuples mapping <see cref="BrandTheme" /> variants to <see cref="ThemeType" /> values.</retu
 75    private static (BrandTheme Theme, ThemeType ThemeType)[] BuildThemeVariantMap(Brand brand, bool isHighContrast)
 76        =>
 14177        [
 14178            (brand.Variant.DarkVariant, isHighContrast
 14179                ? ThemeType.HighContrastDark
 14180                : ThemeType.Dark),
 14181            (brand.Variant.LightVariant, isHighContrast
 14182                ? ThemeType.HighContrastLight
 14183                : ThemeType.Light)
 14184        ];
 85
 86    /// <summary>
 87    /// Retrieves a <see cref="BrandState" /> from a <see cref="BrandTheme" /> based on the specified
 88    /// <see cref="PaletteType" />.
 89    /// </summary>
 90    /// <param name="theme">The <see cref="BrandTheme" /> to search.</param>
 91    /// <param name="paletteType">The <see cref="PaletteType" /> indicating which palette to return.</param>
 92    /// <returns>A <see cref="BrandState" /> corresponding to the given palette type.</returns>
 93    private static BrandState GetBrandState(BrandTheme theme, PaletteType paletteType)
 78494        => paletteType switch
 78495        {
 22696            PaletteType.Elevation1 => theme.Elevation1,
 297            PaletteType.Elevation2 => theme.Elevation2,
 298            PaletteType.Elevation3 => theme.Elevation3,
 299            PaletteType.Elevation4 => theme.Elevation4,
 2100            PaletteType.Elevation5 => theme.Elevation5,
 14101            PaletteType.Error => theme.Error,
 2102            PaletteType.Info => theme.Info,
 226103            PaletteType.Primary => theme.Primary,
 30104            PaletteType.Secondary => theme.Secondary,
 2105            PaletteType.Success => theme.Success,
 270106            PaletteType.Surface => theme.Surface,
 2107            PaletteType.Tertiary => theme.Tertiary,
 2108            PaletteType.Warning => theme.Warning,
 2109            _ => theme.Surface
 784110        };
 111
 112    /// <summary>
 113    /// Generates a list of <see cref="ThemeUpdater" /> instances representing color mappings for a component type.
 114    /// </summary>
 115    /// <param name="isHighContrast">Indicates whether high-contrast colors should be used.</param>
 116    /// <param name="isVariant">Specifies whether to use variant color mappings.</param>
 117    /// <param name="paletteType">The <see cref="PaletteType" /> indicating which color family to map.</param>
 118    /// <param name="componentType">The <see cref="ComponentType" /> representing the styled component.</param>
 119    /// <param name="styleType">The <see cref="StyleType" /> to which the color applies.</param>
 120    /// <param name="getColor">
 121    /// A delegate selecting which <see cref="HexColor" /> to extract from a <see cref="BrandPalette" />
 122    /// .
 123    /// </param>
 124    /// <returns>A list of <see cref="ThemeUpdater" /> instances for applying the derived colors.</returns>
 125    public IReadOnlyList<ThemeUpdater> GetColors(bool isHighContrast,
 126        bool isVariant,
 127        PaletteType paletteType,
 128        ComponentType componentType,
 129        StyleType styleType,
 130        Func<BrandPalette, HexColor?> getColor)
 131    {
 392132        var list = new List<ThemeUpdater>();
 133
 392134        var brand = isHighContrast
 392135            ? _highContrast
 392136            : _brand;
 137
 392138        var themeMap = isVariant
 392139            ? BuildThemeVariantMap(brand: brand, isHighContrast: isHighContrast)
 392140            : BuildThemeMap(brand: brand, isHighContrast: isHighContrast);
 141
 2352142        foreach ((var themeItem, var themeType) in themeMap)
 143        {
 784144            var brandState = GetBrandState(theme: themeItem, paletteType: paletteType);
 784145            var paletteMap = BuildPaletteMap(state: brandState);
 146
 12544147            foreach ((var palette, var state) in paletteMap)
 148            {
 5488149                var color = getColor(arg: palette);
 150
 5488151                if (color is not null)
 152                {
 5474153                    list.Add(
 5474154                        item: new ThemeUpdater(
 5474155                            Navigator: ThemeNavigator.Initialize
 5474156                                .SetComponentTypes(componentType)
 5474157                                .SetThemeTypes(themeType)
 5474158                                .SetComponentStates(state)
 5474159                                .SetStyleTypes(styleType),
 5474160                            Value: new StyleColor(color: color.Value)
 5474161                        )
 5474162                    );
 163                }
 164            }
 165        }
 166
 392167        return list;
 168    }
 169
 170    /// <summary>
 171    /// Creates a <see cref="ThemeUpdater" /> that maps the appropriate font family from the current <see cref="Brand" /
 172    /// its high-contrast counterpart.
 173    /// </summary>
 174    /// <param name="isHighContrast">Specifies whether to use high-contrast font mapping.</param>
 175    /// <param name="componentType">The <see cref="ComponentType" /> for which the font applies.</param>
 176    /// <param name="fontType">The <see cref="FontFaceType" /> defining which font family to use.</param>
 177    /// <returns>A <see cref="ThemeUpdater" /> containing a <see cref="StyleString" /> with the selected font family.</r
 178    public ThemeUpdater GetFont(bool isHighContrast, ComponentType componentType, FontFaceType fontType)
 179    {
 24180        var brand = isHighContrast
 24181            ? _highContrast
 24182            : _brand;
 183
 24184        var fontFace = fontType switch
 24185        {
 1186            FontFaceType.Monospace => brand.Font.Monospace,
 21187            FontFaceType.SansSerif => brand.Font.SansSerif,
 1188            FontFaceType.Serif => brand.Font.Serif,
 1189            _ => brand.Font.SansSerif
 24190        };
 191
 24192        return new ThemeUpdater(
 24193            Navigator: ThemeNavigator.Initialize
 24194                .SetComponentTypes(componentType)
 24195                .SetContrastThemeTypes(isHighContrast: isHighContrast)
 24196                .SetAllComponentStates()
 24197                .SetStyleTypes(StyleType.FontFamily),
 24198            Value: new StyleString(value: fontFace)
 24199        );
 200    }
 201}