CommunityToolkit / CommunityToolkit/Labs-Windows
[Proposal] New ColorHelper API
- Dominant language
- C#
- Stars
- 482
- Forks
- 89
- PR merge metrics
- No merged PRs in 30d
Description
### Approved from Discussion
https://discord.com/channels/372137812037730304/1430217634204356608
### Problem Statement
The current ColorHelper API is unintuitive for an object-oriented environment and poorly utilizes the HsvColor and HslColor.
### Overview
Proposed ColorHelper API
```cs
public static class ColorHelper
{
public static bool TryParseColor(string colorString, out Color color);
public static bool TryParseHexColor(string hexString, out Color color);
public static bool TryParseHslColor(string hslColor, out Color color);
public static bool TryParseHsvColor(string hsvColor, out Color color);
public static bool TryParseScreenColor(string screenColor, out Color color);
public static bool TryParseColorName(string colorName, out Color color);
public static Color ParseColor(string colorString);
public static Color ParseHexColor(string hexString);
public static Color ParseHslColor(string hslColor);
public static Color ParseHsvColor(string hsvColor);
public static Color ParseScreenColor(string screenColor);
public static Color ParseColorName(string colorName);
}
public static class ColorExtensions
{
public static int ToInt(this Color color);
public static HslColor ToHsl(this Color color);
public static HsvColor ToHsv(this Color color);
}
public struct HslColor
{
// The properties will apply clamps on set to restrict the values to a valid range
public double H { readonly get; set;}
public double S { readonly get; set;}
public double L { readonly get; set;}
public double A { readonly get; set;}
public static HslColor Create(double hue, double saturation, double lightness, double alpha = 1);
public Color ToColor();
public string ToString(); // hsv(hue, sat, lightness)
// Cast operators
public static implicit operator Color(HslColor color);
public static explicit operator HslColor(Color color);
public static explicit operator HslColor(HsvColor color);
}
public struct HsvColor
{
// The properties will apply clamps on set to restrict the values to a valid range
public double H { readonly get; set;}
public double S { readonly get; set;}
public double V { readonly get; set;}
public double A { readonly get; set;}
public static HsvColor Create(double hue, double saturation, double value, double alpha = 1);
public Color ToColor();
public string ToString(); // hsv(hue, sat, value)
// Cast operators
public static implicit operator Color(HsvColor color);
public static explicit operator HsvColor(Color color);
public static explicit operator HsvColor(HslColor color);
}
```
### Breaking Changes
Due to its nature as an API change, this proposal would introduce breaking changes. However, each of these changes can be easily remedied by a simple change in function call or by utilizing a casting operation.
#### Method changes
*(These will be marked obsolete, but will still be available until the next major version)*
- `ToHex(this Color color)` - Redundant with `ToString()`
- `ToColor(this string colorString)` - Replaced with `ColorHelper.ParseColor(string colorString)`
- `ColorHelper.FromHsl(double hue, ...)` - Replaced with `(Color)HslColor.Create(double hue, ...)` (NOTE: The cast could be done implicitly)
- `ColorHelper.FromHsv(double hue, ...)` - Replaced with `(Color)HsvColor.Create(double hue, ...)` (NOTE: The cast could be done implicitly)
Also, the `ToColor` function only supported hex, screen color, and color name parsing. In the current version I have drafted, `ParseColor` also only supports these and does not support hsl or hsv, even though in my opinion it probably should... This would result in a changed behavior, and therefore I have not yet added it.
#### Struct changes
All members of the `HslColor` and `HsvColor` structs were public fields with no constraints in value.
These have been replaced with properties that have been restricted to valid ranges for the property. If a developer had been relying on invalid ranges or behavior related to the members being fields, this will no longer work.
In the following example, `hsl.H` would previously be `500` but will now be clamped to `360`.
```cs
HslColor hsl = default;
hsl.H = 500;
```
These changes also mean that the struct must be given a value before being used.
For example, the following code would be valid before but would now say that `hsl` is not defined on the second line.
```cs
HslColor hsl;
hsl.H = 240;
```
Contributor guide
Assessment
This issue has not been assessed yet.