From 73e0d61cbf6cd195d413b2c9f5acddef2c0c1141 Mon Sep 17 00:00:00 2001
From: Dominik Titl <78549750+morning4coffe-dev@users.noreply.github.com>
Date: Sun, 25 Aug 2024 15:28:54 +0200
Subject: [PATCH] feat: Implement `ColorHelper`
---
.../Microsoft_UI/ColorHelperTests.xaml | 13 +++
.../Microsoft_UI/ColorHelperTests.xaml.cs | 51 +++++++++
.../Toolkit/ElevatedView_Tester.xaml.cs | 22 +---
.../UITests.Shared/UITests.Shared.projitems | 8 ++
src/Uno.UI/UI/ColorHelper.cs | 104 +++++++++++++++---
5 files changed, 163 insertions(+), 35 deletions(-)
create mode 100644 src/SamplesApp/UITests.Shared/Microsoft_UI/ColorHelperTests.xaml
create mode 100644 src/SamplesApp/UITests.Shared/Microsoft_UI/ColorHelperTests.xaml.cs
diff --git a/src/SamplesApp/UITests.Shared/Microsoft_UI/ColorHelperTests.xaml b/src/SamplesApp/UITests.Shared/Microsoft_UI/ColorHelperTests.xaml
new file mode 100644
index 000000000000..1d3ec5627eac
--- /dev/null
+++ b/src/SamplesApp/UITests.Shared/Microsoft_UI/ColorHelperTests.xaml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
diff --git a/src/SamplesApp/UITests.Shared/Microsoft_UI/ColorHelperTests.xaml.cs b/src/SamplesApp/UITests.Shared/Microsoft_UI/ColorHelperTests.xaml.cs
new file mode 100644
index 000000000000..383bf12a48bd
--- /dev/null
+++ b/src/SamplesApp/UITests.Shared/Microsoft_UI/ColorHelperTests.xaml.cs
@@ -0,0 +1,51 @@
+using System.Drawing;
+using Microsoft.UI;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Data;
+using Private.Infrastructure;
+using Uno.UI.Samples.Controls;
+using Uno.UI.Samples.UITests.Helpers;
+using Windows.Devices.Sensors;
+
+namespace UITests.Shared.Microsoft_UI;
+
+[SampleControlInfo("Microsoft.UI", "ColorHelper", description: "Demonstrates use of Microsoft.UI.ColorHelper", viewModelType: typeof(ColorHelperTestsViewModel), ignoreInSnapshotTests: true)]
+public sealed partial class ColorHelperTests : UserControl
+{
+ public ColorHelperTests()
+ {
+ this.InitializeComponent();
+ }
+}
+
+[Bindable]
+internal class ColorHelperTestsViewModel(UnitTestDispatcherCompat dispatcher) : ViewModelBase(dispatcher)
+{
+ private string _colorName;
+ private string _colorValue = "6f2526";
+
+ public string ColorValue
+ {
+ get => _colorValue;
+ set
+ {
+ _colorValue = value;
+ RaisePropertyChanged();
+ }
+ }
+
+ public Command ConvertCommand => new((p) =>
+ {
+ ColorName = ColorHelper.ToDisplayName(ColorHelper.ConvertColorFromHexString(ColorValue));
+ });
+
+ public string ColorName
+ {
+ get => _colorName;
+ private set
+ {
+ _colorName = value;
+ RaisePropertyChanged();
+ }
+ }
+}
diff --git a/src/SamplesApp/UITests.Shared/Toolkit/ElevatedView_Tester.xaml.cs b/src/SamplesApp/UITests.Shared/Toolkit/ElevatedView_Tester.xaml.cs
index c2494883701c..402751c76208 100644
--- a/src/SamplesApp/UITests.Shared/Toolkit/ElevatedView_Tester.xaml.cs
+++ b/src/SamplesApp/UITests.Shared/Toolkit/ElevatedView_Tester.xaml.cs
@@ -54,30 +54,10 @@ public string ColorString
private void OnValuesChanged()
{
- Color color = ConvertColorFromHexString(ColorString);
+ Color color = Microsoft.UI.ColorHelper.ConvertColorFromHexString(ColorString);
ElevatedElement.ShadowColor = color;
ElevatedElement.Elevation = Elevation;
ElevatedElement.CornerRadius = new CornerRadius(Radius);
}
-
- private Color ConvertColorFromHexString(string colorString)
- {
- try
- {
- //Target hex string
- colorString = colorString.Replace("#", string.Empty);
- // from #RRGGBB string
- var a = (byte)System.Convert.ToUInt32(colorString.Substring(0, 2), 16);
- var r = (byte)System.Convert.ToUInt32(colorString.Substring(2, 2), 16);
- var g = (byte)System.Convert.ToUInt32(colorString.Substring(4, 2), 16);
- var b = (byte)System.Convert.ToUInt32(colorString.Substring(6, 2), 16);
- //get the color
- return Color.FromArgb(a, r, g, b);
- }
- catch
- {
- return Colors.Black;
- }
- }
}
}
diff --git a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems
index 690160643260..429ba7518eff 100644
--- a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems
+++ b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems
@@ -10,6 +10,10 @@
UITests
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -5448,6 +5452,9 @@
+
+ ColorHelperTests.xaml
+
@@ -9736,6 +9743,7 @@
+
diff --git a/src/Uno.UI/UI/ColorHelper.cs b/src/Uno.UI/UI/ColorHelper.cs
index 0e685254f7ae..1da7023f89f6 100644
--- a/src/Uno.UI/UI/ColorHelper.cs
+++ b/src/Uno.UI/UI/ColorHelper.cs
@@ -1,26 +1,102 @@
using System;
using System.ComponentModel;
-using Microsoft.UI;
+using System.Linq;
+using DirectUI;
+using WindowsColor = Windows/*Intentional space for WinUI upgrade tool*/.UI.Color;
-using Color = global::Windows/*Intentional space for WinUI upgrade tool*/.UI.Color;
+namespace Microsoft.UI;
-namespace Microsoft.UI
+public static partial class ColorHelper
{
- public static partial class ColorHelper
+ ///
+ /// Retrieves the display name of the specified color.
+ ///
+ /// The color to get the name for.
+ /// The localized display name of the color.
+ public static string ToDisplayName(WindowsColor color)
{
-#if __ANDROID__ || __IOS__ || IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
- [global::Uno.NotImplemented("__ANDROID__", "__IOS__", "IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
- public static string ToDisplayName(Color color)
+ //uno specific
+
+ var closestKnownColor = Enum.GetValues()
+ .OrderBy(c => ColorDistance(new WindowsColor((uint)c), color))
+ .First();
+
+ var resourceId = closestKnownColor.ToString();
+ var resource = DXamlCore.Current.GetLocalizedResourceString(resourceId);
+
+ if (string.IsNullOrEmpty(resource))
{
- throw new global::System.NotImplementedException("The member string ColorHelper.ToDisplayName(Color color) is not implemented in Uno.");
+ return closestKnownColor.ToString();
}
-#endif
- [EditorBrowsable(EditorBrowsableState.Never)]
- public static Color FromARGB(byte a, byte r, byte g, byte b)
- => Color.FromArgb(a, r, g, b);
+ return resource;
+ }
+
+ //uno specific
+ static double ColorDistance(WindowsColor color1, WindowsColor color2)
+ {
+ var r1 = (int)(color1.R);
+ var g1 = (int)(color1.G);
+ var b1 = (int)(color1.B);
+ var r2 = (int)(color2.R);
+ var g2 = (int)(color2.G);
+ var b2 = (int)(color2.B);
+
+ return Math.Sqrt(Math.Pow(r1 - r2, 2) + Math.Pow(g1 - g2, 2) + Math.Pow(b1 - b2, 2));
+ }
+
+ ///
+ /// Converts a color string in hex format to a Windows.UI.Color.
+ ///
+ internal static WindowsColor ConvertColorFromHexString(string colorString)
+ {
+ try
+ {
+ colorString = colorString.Replace("#", string.Empty);
+
+ byte a = 255;
+ byte r, g, b;
- public static Color FromArgb(byte a, byte r, byte g, byte b)
- => Color.FromArgb(a, r, g, b);
+ if (colorString.Length == 6)
+ {
+ // #RRGGBB format
+ r = (byte)Convert.ToUInt32(colorString.Substring(0, 2), 16);
+ g = (byte)Convert.ToUInt32(colorString.Substring(2, 2), 16);
+ b = (byte)Convert.ToUInt32(colorString.Substring(4, 2), 16);
+ }
+ else if (colorString.Length == 8)
+ {
+ // #AARRGGBB format
+ a = (byte)Convert.ToUInt32(colorString.Substring(0, 2), 16);
+ r = (byte)Convert.ToUInt32(colorString.Substring(2, 2), 16);
+ g = (byte)Convert.ToUInt32(colorString.Substring(4, 2), 16);
+ b = (byte)Convert.ToUInt32(colorString.Substring(6, 2), 16);
+ }
+ else
+ {
+ return Colors.Black;
+ }
+
+ return WindowsColor.FromArgb(a, r, g, b);
+ }
+ catch
+ {
+ return Colors.Black;
+ }
}
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static WindowsColor FromARGB(byte a, byte r, byte g, byte b)
+ => WindowsColor.FromArgb(a, r, g, b);
+
+ ///
+ /// Generates a Color structure, based on discrete Byte values for ARGB components. C# and Microsoft Visual Basic code should use Color.FromArgb instead.
+ ///
+ /// The A (transparency) component of the desired color. Range is 0-255.
+ /// The R component of the desired color. Range is 0-255.
+ /// The G component of the desired color. Range is 0-255.
+ /// The B component of the desired color. Range is 0-255.
+ /// The generated Color value.
+ public static WindowsColor FromArgb(byte a, byte r, byte g, byte b)
+ => WindowsColor.FromArgb(a, r, g, b);
}