Files
LanMountainDesktop/LanMontainDesktop/Services/ThemeColorSystemService.cs
lincube b224f07e69 0.1.5
2026-02-28 03:00:25 +08:00

148 lines
7.9 KiB
C#

using Avalonia.Controls;
using Avalonia.Media;
using LanMontainDesktop.Theme;
namespace LanMontainDesktop.Services;
public static class ThemeColorSystemService
{
private const double WcagNormalTextContrast = 4.5;
private const double WcagLargeTextContrast = 3.0;
public static void ApplyThemeResources(
IResourceDictionary resources,
ThemeColorContext context)
{
var palette = BuildPalette(context);
resources["AdaptivePrimaryBrush"] = new SolidColorBrush(palette.Primary);
resources["AdaptiveSecondaryBrush"] = new SolidColorBrush(palette.Secondary);
resources["AdaptiveAccentBrush"] = new SolidColorBrush(palette.Accent);
resources["AdaptiveOnAccentBrush"] = new SolidColorBrush(palette.OnAccent);
resources["AdaptiveSurfaceBaseBrush"] = new SolidColorBrush(palette.SurfaceBase);
resources["AdaptiveSurfaceRaisedBrush"] = new SolidColorBrush(palette.SurfaceRaised);
resources["AdaptiveSurfaceOverlayBrush"] = new SolidColorBrush(palette.SurfaceOverlay);
resources["AdaptiveTextPrimaryBrush"] = new SolidColorBrush(palette.TextPrimary);
resources["AdaptiveTextSecondaryBrush"] = new SolidColorBrush(palette.TextSecondary);
resources["AdaptiveTextMutedBrush"] = new SolidColorBrush(palette.TextMuted);
resources["AdaptiveTextAccentBrush"] = new SolidColorBrush(palette.TextAccent);
resources["AdaptiveNavTextBrush"] = new SolidColorBrush(palette.NavText);
resources["AdaptiveNavSelectedTextBrush"] = new SolidColorBrush(palette.NavSelectedText);
resources["AdaptiveNavSelectionIndicatorBrush"] = new SolidColorBrush(palette.NavSelectionIndicator);
resources["AdaptiveNavItemBackgroundBrush"] = new SolidColorBrush(palette.NavItemBackground);
resources["AdaptiveNavItemHoverBackgroundBrush"] = new SolidColorBrush(palette.NavItemHoverBackground);
resources["AdaptiveNavItemSelectedBackgroundBrush"] = new SolidColorBrush(palette.NavItemSelectedBackground);
resources["AdaptiveToggleOnBrush"] = new SolidColorBrush(palette.ToggleOn);
resources["AdaptiveToggleOffBrush"] = new SolidColorBrush(palette.ToggleOff);
resources["AdaptiveToggleBorderBrush"] = new SolidColorBrush(palette.ToggleBorder);
resources["SystemAccentColor"] = palette.Accent;
resources["SystemAccentColorLight1"] = palette.AccentLight1;
resources["SystemAccentColorLight2"] = palette.AccentLight2;
resources["SystemAccentColorLight3"] = palette.AccentLight3;
resources["SystemAccentColorDark1"] = palette.AccentDark1;
resources["SystemAccentColorDark2"] = palette.AccentDark2;
resources["SystemAccentColorDark3"] = palette.AccentDark3;
resources["SystemAccentColorLight1Brush"] = new SolidColorBrush(palette.AccentLight1);
resources["SystemAccentColorLight2Brush"] = new SolidColorBrush(palette.AccentLight2);
resources["SystemAccentColorLight3Brush"] = new SolidColorBrush(palette.AccentLight3);
resources["SystemAccentColorDark1Brush"] = new SolidColorBrush(palette.AccentDark1);
resources["SystemAccentColorDark2Brush"] = new SolidColorBrush(palette.AccentDark2);
resources["SystemAccentColorDark3Brush"] = new SolidColorBrush(palette.AccentDark3);
resources["SystemAccentColorBrush"] = new SolidColorBrush(palette.Accent);
}
public static void ApplyThemeResources(
IResourceDictionary resources,
Color accentColor,
bool isLightBackground,
bool isLightNavBackground)
{
ApplyThemeResources(resources, new ThemeColorContext(
accentColor,
isLightBackground,
isLightNavBackground,
!isLightBackground));
}
private static AppThemePalette BuildPalette(ThemeColorContext context)
{
var accent = context.AccentColor;
var accentLight1 = ColorMath.Blend(accent, Color.Parse("#FFFFFFFF"), 0.22);
var accentLight2 = ColorMath.Blend(accent, Color.Parse("#FFFFFFFF"), 0.38);
var accentLight3 = ColorMath.Blend(accent, Color.Parse("#FFFFFFFF"), 0.54);
var accentDark1 = ColorMath.Blend(accent, Color.Parse("#FF0B1220"), 0.16);
var accentDark2 = ColorMath.Blend(accent, Color.Parse("#FF0B1220"), 0.28);
var accentDark3 = ColorMath.Blend(accent, Color.Parse("#FF020617"), 0.40);
var primary = context.IsNightMode ? accentLight1 : accentDark1;
var secondary = context.IsNightMode ? accentLight2 : accentDark2;
var surfaceBase = context.IsNightMode ? Color.Parse("#FF0B1220") : Color.Parse("#FFF3F7FB");
var surfaceRaised = context.IsNightMode ? Color.Parse("#FF1E293B") : Color.Parse("#FFFFFFFF");
var surfaceOverlay = context.IsNightMode ? Color.Parse("#CC0B1220") : Color.Parse("#CCE2E8F0");
var textPrimaryPreferred = context.IsLightBackground ? Color.Parse("#FF0B1220") : Color.Parse("#FFF8FAFC");
var textPrimary = ColorMath.EnsureContrast(textPrimaryPreferred, surfaceRaised, WcagNormalTextContrast);
var textSecondary = ColorMath.EnsureContrast(
ColorMath.Blend(textPrimary, surfaceRaised, context.IsNightMode ? 0.24 : 0.44),
surfaceRaised,
WcagLargeTextContrast);
var textMuted = ColorMath.EnsureContrast(
ColorMath.Blend(textPrimary, surfaceRaised, context.IsNightMode ? 0.40 : 0.58),
surfaceRaised,
WcagLargeTextContrast);
var textAccent = context.IsLightBackground
? ColorMath.EnsureContrast(ColorMath.Blend(accent, Color.Parse("#FF0B1220"), 0.20), surfaceRaised, WcagNormalTextContrast)
: ColorMath.EnsureContrast(ColorMath.Blend(accent, Color.Parse("#FFFFFFFF"), 0.16), surfaceRaised, WcagNormalTextContrast);
var navSurface = context.IsLightNavBackground ? surfaceRaised : Color.Parse("#FF111827");
var navText = ColorMath.EnsureContrast(
context.IsLightNavBackground ? Color.Parse("#FF0B1220") : Color.Parse("#FFF8FAFC"),
navSurface,
WcagNormalTextContrast);
var selectedSurfaceForContrast = ColorMath.Blend(accent, navSurface, 0.18);
var navSelectedText = ColorMath.EnsureContrast(Color.Parse("#FFFFFFFF"), selectedSurfaceForContrast, WcagNormalTextContrast);
var navItemBackground = context.IsLightNavBackground ? Color.Parse("#33FFFFFF") : Color.Parse("#2A0F172A");
var navItemHoverBackground = context.IsLightNavBackground
? ColorMath.WithAlpha(ColorMath.Blend(accentLight2, Color.Parse("#FFFFFFFF"), 0.48), 0x66)
: ColorMath.WithAlpha(ColorMath.Blend(accentDark1, Color.Parse("#33111827"), 0.32), 0x78);
var navItemSelectedBackground = ColorMath.WithAlpha(accent, context.IsNightMode ? (byte)0xCE : (byte)0xD9);
var navSelectionIndicator = ColorMath.EnsureContrast(accentLight1, navSurface, WcagLargeTextContrast);
var toggleOn = context.IsNightMode ? accent : accentDark1;
var toggleOff = context.IsNightMode ? Color.Parse("#66475569") : Color.Parse("#66CBD5E1");
var toggleBorder = context.IsNightMode ? Color.Parse("#80E2E8F0") : Color.Parse("#8094A3B8");
var onAccent = ColorMath.EnsureContrast(Color.Parse("#FFFFFFFF"), accent, WcagNormalTextContrast);
return new AppThemePalette(
primary,
secondary,
accent,
onAccent,
accentLight1,
accentLight2,
accentLight3,
accentDark1,
accentDark2,
accentDark3,
surfaceBase,
surfaceRaised,
surfaceOverlay,
textPrimary,
textSecondary,
textMuted,
textAccent,
navText,
navSelectedText,
navSelectionIndicator,
navItemBackground,
navItemHoverBackground,
navItemSelectedBackground,
toggleOn,
toggleOff,
toggleBorder);
}
}