CommunityToolkit / CommunityToolkit/Labs-Windows

[Proposal] New ColorHelper API

Open
#756 0 comments 0 reactions 0 assignees View on GitHub
experiment :test_tube:
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.