Skip to content

Commit 0d6fceb

Browse files
authoredDec 17, 2023
Merge pull request #96 from atc-net/feature/ThemeManagerHelper
Feature/theme manager helper
2 parents 950b543 + 404c891 commit 0d6fceb

File tree

8 files changed

+198
-20
lines changed

8 files changed

+198
-20
lines changed
 
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// ReSharper disable CheckNamespace
2+
namespace Atc.Wpf.Theming;
3+
4+
public enum AtcAppsBrushKeyType
5+
{
6+
Highlight,
7+
AccentBase,
8+
Accent,
9+
Accent2,
10+
Accent3,
11+
Accent4,
12+
ThemeBackground,
13+
ThemeBackground1,
14+
ThemeBackground2,
15+
ThemeBackground3,
16+
ThemeBackground4,
17+
ThemeBackground5,
18+
ThemeBackground6,
19+
ThemeBackground7,
20+
ThemeForeground7,
21+
ThemeForeground6,
22+
ThemeForeground5,
23+
ThemeForeground4,
24+
ThemeForeground3,
25+
ThemeForeground2,
26+
ThemeForeground1,
27+
ThemeForeground,
28+
IdealForeground,
29+
Gray1,
30+
Gray2,
31+
Gray3,
32+
Gray4,
33+
Gray5,
34+
Gray6,
35+
Gray7,
36+
Gray8,
37+
Gray9,
38+
Gray10,
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// ReSharper disable CheckNamespace
2+
namespace Atc.Wpf.Theming;
3+
4+
public enum AtcAppsColorKeyType
5+
{
6+
Highlight,
7+
AccentBase,
8+
Accent,
9+
Accent2,
10+
Accent3,
11+
Accent4,
12+
ThemeBackground,
13+
ThemeBackground1,
14+
ThemeBackground2,
15+
ThemeBackground3,
16+
ThemeBackground4,
17+
ThemeBackground5,
18+
ThemeBackground6,
19+
ThemeBackground7,
20+
ThemeForeground7,
21+
ThemeForeground6,
22+
ThemeForeground5,
23+
ThemeForeground4,
24+
ThemeForeground3,
25+
ThemeForeground2,
26+
ThemeForeground1,
27+
ThemeForeground,
28+
IdealForeground,
29+
Gray1,
30+
Gray2,
31+
Gray3,
32+
Gray4,
33+
Gray5,
34+
Gray6,
35+
Gray7,
36+
Gray8,
37+
Gray9,
38+
Gray10,
39+
}

‎src/Atc.Wpf.Theming/GlobalUsings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
global using System.Collections;
2+
global using System.Collections.Concurrent;
23
global using System.Collections.ObjectModel;
34
global using System.Collections.Specialized;
45
global using System.ComponentModel;
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
namespace Atc.Wpf.Theming.Helpers;
2+
3+
public static class ThemeManagerHelper
4+
{
5+
private static readonly ConcurrentDictionary<string, Color> CacheColors = new(StringComparer.Ordinal);
6+
private static readonly ConcurrentDictionary<string, SolidColorBrush> CacheBrushes = new(StringComparer.Ordinal);
7+
8+
public static Color GetColorByResourceKey(
9+
AtcAppsColorKeyType colorKey)
10+
=> GetColorByResourceKey(colorKey.ToString());
11+
12+
public static Color GetColorByResourceKey(
13+
string resourceKey)
14+
{
15+
ArgumentException.ThrowIfNullOrEmpty(resourceKey);
16+
17+
if (!resourceKey.StartsWith("AtcApps.Colors.", StringComparison.OrdinalIgnoreCase))
18+
{
19+
resourceKey = $"AtcApps.Colors.{resourceKey}";
20+
}
21+
22+
var currentTheme = ThemeManager.Current.DetectTheme(Application.Current)!;
23+
var cacheKey = $"{currentTheme.BaseColorScheme}_{resourceKey}";
24+
25+
if (CacheColors.TryGetValue(cacheKey, out var cacheColor))
26+
{
27+
return cacheColor;
28+
}
29+
30+
var color = (Color)currentTheme.Resources[resourceKey]!;
31+
CacheColors.TryAdd(cacheKey, color);
32+
return color;
33+
}
34+
35+
public static SolidColorBrush GetBrushByResourceKey(
36+
AtcAppsBrushKeyType brushKey)
37+
=> GetBrushByResourceKey(brushKey.ToString());
38+
39+
public static SolidColorBrush GetBrushByResourceKey(
40+
string resourceKey)
41+
{
42+
ArgumentException.ThrowIfNullOrEmpty(resourceKey);
43+
44+
if (!resourceKey.StartsWith("AtcApps.Brushes.", StringComparison.OrdinalIgnoreCase))
45+
{
46+
resourceKey = $"AtcApps.Brushes.{resourceKey}";
47+
}
48+
49+
var currentTheme = ThemeManager.Current.DetectTheme(Application.Current)!;
50+
var cacheKey = $"{currentTheme.BaseColorScheme}_{resourceKey}";
51+
52+
if (CacheBrushes.TryGetValue(cacheKey, out var cacheBrush))
53+
{
54+
return cacheBrush;
55+
}
56+
57+
var brush = (SolidColorBrush)currentTheme.Resources[resourceKey]!;
58+
if (brush.CanFreeze)
59+
{
60+
brush.Freeze();
61+
}
62+
63+
CacheBrushes.TryAdd(cacheKey, brush);
64+
return brush;
65+
}
66+
67+
public static Color GetPrimaryAccentColor()
68+
{
69+
var currentTheme = ThemeManager.Current.DetectTheme(Application.Current)!;
70+
return currentTheme.PrimaryAccentColor;
71+
}
72+
73+
public static SolidColorBrush GetPrimaryAccentBrush()
74+
{
75+
var color = GetPrimaryAccentColor();
76+
var brush = new SolidColorBrush(color);
77+
brush.Freeze();
78+
return brush;
79+
}
80+
}

‎src/Atc.Wpf/Helpers/ColorHelper.cs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,21 @@ public static void InitializeWithSupportedLanguages()
3030
ArgumentException.ThrowIfNullOrEmpty(value);
3131
ArgumentNullException.ThrowIfNull(culture);
3232

33-
EnsureColorNamesForCulture(culture);
34-
35-
var colorKey = GetColorKeyFromCulture(culture);
36-
37-
if (value.StartsWith('#') &&
38-
ColorConverter.ConvertFromString(value) is Color color)
33+
if (value.StartsWith('#'))
3934
{
40-
return ColorNames[colorKey]
41-
.FirstOrDefault(x => string.Equals(x.Key.ToString(GlobalizationConstants.EnglishCultureInfo), color.ToString(GlobalizationConstants.EnglishCultureInfo), StringComparison.OrdinalIgnoreCase))
42-
.Key;
35+
try
36+
{
37+
if (ColorConverter.ConvertFromString(value) is Color color)
38+
{
39+
return color;
40+
}
41+
42+
return null;
43+
}
44+
catch
45+
{
46+
return null;
47+
}
4348
}
4449

4550
if (!value.Contains(' ', StringComparison.Ordinal))
@@ -52,7 +57,9 @@ public static void InitializeWithSupportedLanguages()
5257
}
5358
}
5459

55-
return ColorNames[colorKey]
60+
EnsureColorNamesForCulture(culture);
61+
62+
return ColorNames[GetColorKeyFromCulture(culture)]
5663
.FirstOrDefault(x => string.Equals(x.Value, value, StringComparison.OrdinalIgnoreCase))
5764
.Key;
5865
}

‎src/Atc.Wpf/Helpers/SolidColorBrushHelper.cs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ namespace Atc.Wpf.Helpers;
44
/// <summary>
55
/// A Helper class for the SolidColorBrush.
66
/// </summary>
7+
[SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "OK.")]
78
public static class SolidColorBrushHelper
89
{
910
private static readonly ConcurrentDictionary<string, SolidColorBrush> BaseBrushes = new(StringComparer.Ordinal);
@@ -29,16 +30,21 @@ public static void InitializeWithSupportedLanguages()
2930
ArgumentException.ThrowIfNullOrEmpty(value);
3031
ArgumentNullException.ThrowIfNull(culture);
3132

32-
EnsureBrushNamesForCulture(culture);
33-
34-
var brushKey = GetBrushKeyFromCulture(culture);
35-
36-
if (value.StartsWith('#') &&
37-
ColorConverter.ConvertFromString(value) is Color color)
33+
if (value.StartsWith('#'))
3834
{
39-
return BrushNames[brushKey]
40-
.FirstOrDefault(x => string.Equals(x.Key.Color.ToString(GlobalizationConstants.EnglishCultureInfo), color.ToString(GlobalizationConstants.EnglishCultureInfo), StringComparison.OrdinalIgnoreCase))
41-
.Key;
35+
try
36+
{
37+
if (ColorConverter.ConvertFromString(value) is Color color)
38+
{
39+
return new SolidColorBrush(color);
40+
}
41+
42+
return null;
43+
}
44+
catch
45+
{
46+
return null;
47+
}
4248
}
4349

4450
if (!value.Contains(' ', StringComparison.Ordinal))
@@ -51,7 +57,9 @@ public static void InitializeWithSupportedLanguages()
5157
}
5258
}
5359

54-
return BrushNames[brushKey]
60+
EnsureBrushNamesForCulture(culture);
61+
62+
return BrushNames[GetBrushKeyFromCulture(culture)]
5563
.FirstOrDefault(x => string.Equals(x.Value, value, StringComparison.OrdinalIgnoreCase))
5664
.Key;
5765
}

‎test/Atc.Wpf.Tests/Helpers/ColorHelperTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public void GetBrushFromString(string input, byte r, byte g, byte b, int lcid)
3434
}
3535

3636
[Theory]
37+
[InlineData("#FF333333", 0x33, 0x33, 0x33)]
38+
[InlineData("#FF666666", 0x66, 0x66, 0x66)]
3739
[InlineData("#FF00CED1", 0, 206, 209)]
3840
[InlineData("#00CED1", 0, 206, 209)]
3941
[InlineData("#FF2F4F4F", 47, 79, 79)]

‎test/Atc.Wpf.Tests/Helpers/SolidColorBrushHelperTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public void GetBrushFromString(string input, byte r, byte g, byte b, int lcid)
3434
}
3535

3636
[Theory]
37+
[InlineData("#FF333333", 0x33, 0x33, 0x33)]
38+
[InlineData("#FF666666", 0x66, 0x66, 0x66)]
3739
[InlineData("#FF00CED1", 0, 206, 209)]
3840
[InlineData("#00CED1", 0, 206, 209)]
3941
[InlineData("#FF2F4F4F", 47, 79, 79)]

0 commit comments

Comments
 (0)
Please sign in to comment.