[ColorPicker]Custom color formats (#22141)

* [ColorPicker] Development: custom color formats, first steps

* ColorPicker development of custom format handling.

* Custom color format developmnet.
Added common helper class for format string
Fixed settings loading
Added numbering if default name exists   (My format (1))

* Custom color format implementation.
Extended the colorPicker settings with the format string
Updated the color to string conversion

* Custom color format in color picker, development.
Adding edit, delete buttons. Implement functionality
Re-arranging settings panel (newly created formats at the top)
Implementing details (valid parameters, more format elements, more types)

* Minor commit

* Development color picker custom formats. "Last" steps.
Replacing hard coded english strings with resources, polishing.

* Adding help to the format edit dialog.

* Undoing changes unwillingly commited in Host module

* Fixing bug unable to delete a custom format after renaming it - use the colorformat object as reference (and not the name)
Modifying the default custom formula
Removing unnecessary using directives

* Udating the default user defined color format

* Removing unnecessary using directive

* ColorPicker Implementing custom color formats: adding custom formats to the default format selection (dropdown box).

* Fix binding of name and example

* Custom color formats, implemented steps:
vorwarts compatibility loading settings.
Fixed UI as requested (removed one settings panel, added button to the first panel)

* Minor change in the UI: description modified

* ColorPicker Custom Color Formats develepoment.
Added conversion from old predefined formats to customizable formats.
Extended default settings (in case settings file is deleted/corrupted).
Minor fixes.

* Fixing color format parameters.
Implementing 3 different Saturation calculations, 2 Hue calculations and 2 Lightness calculations (depending color format)

* Color Picker: New/Edit Color format. Fixing bug when cancelling addition/edit

* ColorPicker. Updating help section, available parameters

* Fix spellchecker

* Remove the MinWidth so that scrollviewers can be drawn

* ColorPicker bugfix: Not allowing to delete the last color format.
This commit is contained in:
Laszlo Nemeth
2022-12-02 17:44:53 +01:00
committed by GitHub
parent 77dfaab17e
commit ec0fb6a4c7
35 changed files with 2324 additions and 1092 deletions

View File

@@ -65,21 +65,21 @@
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Content Include="Shaders\GridShader.fx" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -77,14 +77,16 @@ namespace ColorPicker.Controls
private static void SelectedColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var self = (ColorFormatControl)d;
var colorText = self.ColorFormatModel.Convert((Color)e.NewValue);
var colorText = self.ColorFormatModel.GetColorText((Color)e.NewValue);
self.ColorTextRepresentationTextBlock.Text = colorText;
self.ColorTextRepresentationTextBlock.ToolTip = colorText;
self.SelectedColorCopyHelperText = string.Format(CultureInfo.InvariantCulture, "{0} {1}", self.ColorFormatModel.FormatName, colorText);
}
private static void ColorFormatModelPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ColorFormatControl)d).FormatNameTextBlock.Text = ((ColorFormatModel)e.NewValue).FormatName;
((ColorFormatControl)d).FormatNameTextBlock.ToolTip = ((ColorFormatModel)e.NewValue).FormatName;
}
private static void ColorCopiedBorderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

View File

@@ -12,6 +12,7 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using ColorPicker.Helpers;
using ManagedCommon;
using ModernWpf.Controls;
using ModernWpf.Controls.Primitives;
@@ -81,7 +82,7 @@ namespace ColorPicker.Controls
control._ignoreRGBChanges = false;
control._ignoreHexChanges = false;
var hsv = ColorHelper.ConvertToHSVColor(System.Drawing.Color.FromArgb(newColor.R, newColor.G, newColor.B));
var hsv = ColorFormatHelper.ConvertToHSVColor(System.Drawing.Color.FromArgb(newColor.R, newColor.G, newColor.B));
SetColorVariationsForCurrentColor(d, hsv);
}
@@ -309,7 +310,7 @@ namespace ColorPicker.Controls
{
if (!_ignoreGradientsChanges)
{
var hsv = ColorHelper.ConvertToHSVColor(color);
var hsv = ColorFormatHelper.ConvertToHSVColor(color);
var huePosition = (hsv.hue / 360) * HueGradientSlider.Maximum;
var saturationPosition = hsv.saturation * SaturationGradientSlider.Maximum;

View File

@@ -12,38 +12,6 @@ namespace ColorPicker.Helpers
/// </summary>
internal static class ColorHelper
{
/// <summary>
/// Convert a given <see cref="Color"/> to a CMYK color (cyan, magenta, yellow, black key)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The cyan[0..1], magenta[0..1], yellow[0..1] and black key[0..1] of the converted color</returns>
internal static (double cyan, double magenta, double yellow, double blackKey) ConvertToCMYKColor(Color color)
{
// special case for black (avoid division by zero)
if (color.R == 0 && color.G == 0 && color.B == 0)
{
return (0d, 0d, 0d, 1d);
}
var red = color.R / 255d;
var green = color.G / 255d;
var blue = color.B / 255d;
var blackKey = 1d - Math.Max(Math.Max(red, green), blue);
// special case for black (avoid division by zero)
if (1d - blackKey == 0d)
{
return (0d, 0d, 0d, 1d);
}
var cyan = (1d - red - blackKey) / (1d - blackKey);
var magenta = (1d - green - blackKey) / (1d - blackKey);
var yellow = (1d - blue - blackKey) / (1d - blackKey);
return (cyan, magenta, yellow, blackKey);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a float color styling(0.1f, 0.1f, 0.1f)
/// </summary>
@@ -51,220 +19,5 @@ namespace ColorPicker.Helpers
/// <returns>The int / 255d for each value to get value between 0 and 1</returns>
internal static (double red, double green, double blue) ConvertToDouble(Color color)
=> (color.R / 255d, color.G / 255d, color.B / 255d);
/// <summary>
/// Convert a given <see cref="Color"/> to a HSB color (hue, saturation, brightness)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], saturation [0..1] and brightness [0..1] of the converted color</returns>
internal static (double hue, double saturation, double brightness) ConvertToHSBColor(Color color)
{
// HSB and HSV represents the same color space
return ConvertToHSVColor(color);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a HSI color (hue, saturation, intensity)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], saturation [0..1] and intensity [0..1] of the converted color</returns>
internal static (double hue, double saturation, double intensity) ConvertToHSIColor(Color color)
{
// special case for black
if (color.R == 0 && color.G == 0 && color.B == 0)
{
return (0d, 0d, 0d);
}
var red = color.R / 255d;
var green = color.G / 255d;
var blue = color.B / 255d;
var intensity = (red + green + blue) / 3d;
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
return (color.GetHue(), 1d - (min / intensity), intensity);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a HSL color (hue, saturation, lightness)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], saturation [0..1] and lightness [0..1] values of the converted color</returns>
internal static (double hue, double saturation, double lightness) ConvertToHSLColor(Color color)
{
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
var lightness = (max + min) / 2d;
if (lightness == 0d || min == max)
{
return (color.GetHue(), 0d, lightness);
}
else if (lightness > 0d && lightness <= 0.5d)
{
return (color.GetHue(), (max - min) / (max + min), lightness);
}
return (color.GetHue(), (max - min) / (2d - (max + min)), lightness);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a HSV color (hue, saturation, value)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], saturation [0..1] and value [0..1] of the converted color</returns>
internal static (double hue, double saturation, double value) ConvertToHSVColor(Color color)
{
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
return (color.GetHue(), max == 0d ? 0d : (max - min) / max, max);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a HWB color (hue, whiteness, blackness)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], whiteness [0..1] and blackness [0..1] of the converted color</returns>
internal static (double hue, double whiteness, double blackness) ConvertToHWBColor(Color color)
{
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
return (color.GetHue(), min, 1 - max);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a natural color (hue, whiteness, blackness)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue, whiteness [0..1] and blackness [0..1] of the converted color</returns>
internal static (string hue, double whiteness, double blackness) ConvertToNaturalColor(Color color)
{
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
return (GetNaturalColorFromHue(color.GetHue()), min, 1 - max);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a CIE LAB color (LAB)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The lightness [0..100] and two chromaticities [-128..127]</returns>
internal static (double lightness, double chromaticityA, double chromaticityB) ConvertToCIELABColor(Color color)
{
var xyz = ConvertToCIEXYZColor(color);
var lab = GetCIELABColorFromCIEXYZ(xyz.x, xyz.y, xyz.z);
return lab;
}
/// <summary>
/// Convert a given <see cref="Color"/> to a CIE XYZ color (XYZ)
/// The constants of the formula matches this Wikipedia page, but at a higher precision:
/// https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation_(sRGB_to_CIE_XYZ)
/// This page provides a method to calculate the constants:
/// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The X [0..1], Y [0..1] and Z [0..1]</returns>
internal static (double x, double y, double z) ConvertToCIEXYZColor(Color color)
{
double r = color.R / 255d;
double g = color.G / 255d;
double b = color.B / 255d;
// inverse companding, gamma correction must be undone
double rLinear = (r > 0.04045) ? Math.Pow((r + 0.055) / 1.055, 2.4) : (r / 12.92);
double gLinear = (g > 0.04045) ? Math.Pow((g + 0.055) / 1.055, 2.4) : (g / 12.92);
double bLinear = (b > 0.04045) ? Math.Pow((b + 0.055) / 1.055, 2.4) : (b / 12.92);
return (
(rLinear * 0.41239079926595948) + (gLinear * 0.35758433938387796) + (bLinear * 0.18048078840183429),
(rLinear * 0.21263900587151036) + (gLinear * 0.71516867876775593) + (bLinear * 0.07219231536073372),
(rLinear * 0.01933081871559185) + (gLinear * 0.11919477979462599) + (bLinear * 0.95053215224966058)
);
}
/// <summary>
/// Convert a CIE XYZ color <see cref="double"/> to a CIE LAB color (LAB) adapted to sRGB D65 white point
/// The constants of the formula used come from this wikipedia page:
/// https://en.wikipedia.org/wiki/CIELAB_color_space#Converting_between_CIELAB_and_CIEXYZ_coordinates
/// </summary>
/// <param name="x">The <see cref="x"/> represents a mix of the three CIE RGB curves</param>
/// <param name="y">The <see cref="y"/> represents the luminance</param>
/// <param name="z">The <see cref="z"/> is quasi-equal to blue (of CIE RGB)</param>
/// <returns>The lightness [0..100] and two chromaticities [-128..127]</returns>
private static (double lightness, double chromaticityA, double chromaticityB)
GetCIELABColorFromCIEXYZ(double x, double y, double z)
{
// sRGB reference white (x=0.3127, y=0.3290, Y=1.0), actually CIE Standard Illuminant D65 truncated to 4 decimal places,
// then converted to XYZ using the formula:
// X = x * (Y / y)
// Y = Y
// Z = (1 - x - y) * (Y / y)
double x_n = 0.9504559270516717;
double y_n = 1.0;
double z_n = 1.0890577507598784;
// Scale XYZ values relative to reference white
x /= x_n;
y /= y_n;
z /= z_n;
// XYZ to CIELab transformation
double delta = 6d / 29;
double m = (1d / 3) * Math.Pow(delta, -2);
double t = Math.Pow(delta, 3);
double fx = (x > t) ? Math.Pow(x, 1.0 / 3.0) : (x * m) + (16.0 / 116.0);
double fy = (y > t) ? Math.Pow(y, 1.0 / 3.0) : (y * m) + (16.0 / 116.0);
double fz = (z > t) ? Math.Pow(z, 1.0 / 3.0) : (z * m) + (16.0 / 116.0);
double l = (116 * fy) - 16;
double a = 500 * (fx - fy);
double b = 200 * (fy - fz);
return (l, a, b);
}
/// <summary>
/// Return the natural color for the given hue value
/// </summary>
/// <param name="hue">The hue value to convert</param>
/// <returns>A natural color</returns>
private static string GetNaturalColorFromHue(double hue)
{
if (hue < 60d)
{
return $"R{Math.Round(hue / 0.6d, 0)}";
}
if (hue < 120d)
{
return $"Y{Math.Round((hue - 60d) / 0.6d, 0)}";
}
if (hue < 180d)
{
return $"G{Math.Round((hue - 120d) / 0.6d, 0)}";
}
if (hue < 240d)
{
return $"C{Math.Round((hue - 180d) / 0.6d, 0)}";
}
if (hue < 300d)
{
return $"B{Math.Round((hue - 240d) / 0.6d, 0)}";
}
return $"M{Math.Round((hue - 300d) / 0.6d, 0)}";
}
}
}

View File

@@ -1,264 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Drawing;
using ColorPicker.Properties;
namespace ColorPicker.Helpers
{
public static class ColorNameHelper
{
public const float DBLEPSILON = 2.2204460492503131e-16f;
// For the purposes of naming colors, there are four steps that we go through.
//
// 1. For numerical ease, we convert the HSL values from the range [0, 1]
// to the range [0, 255].
//
// 2. If luminosity is sufficiently high or low (> 240 or < 20), or if
// saturation is sufficiently low (<= 20), then we declare that we're in the
// achromatic range. In this case, we return either white, black, or three
// different shades of gray (depending on luminosity).
//
// 3. If we do have a chromatic color, the first thing we need to determine
// about it is what the hue limits are for its saturation value - at different
// levels of saturation, we have different hue values that we'll consider the
// boundaries for different classes of named colors. The hue limits for various
// saturation values are as below.
//
// The numbers correspond to the following color buckets, with 0 meaning that
// that bucket does not apply to the given saturation value:
//
// 1 - coral, 2 - red, 3 - orange, 4 - brown, 5 - tan, 6 - gold, 7 - yellow, 8 - olive green (with brown),
// 9 - olive green (with green) 10 - lime green, 11 - green - 12 - bright green 13 - teal, 14 - aqua,
// 15 - turquoise, 16 - pale blue, 17 - blue, 18 - blue-gray, 19 - indigo, 20 - purple, 21 - pink, 22 - brown, 23 - red
private static int[] hueLimitsForSatLevel1 = // Sat: 20-75
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
8, 0, 0, 44, 0, 0, 0, 63, 0, 0, 122, 0, 134, 0, 0, 0, 0, 166, 176, 241, 0, 256, 0,
};
private static int[] hueLimitsForSatLevel2 = // Sat: 75-115
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
0, 10, 0, 32, 46, 0, 0, 0, 61, 0, 106, 0, 136, 144, 0, 0, 0, 158, 166, 241, 0, 0, 256,
};
private static int[] hueLimitsForSatLevel3 = // Sat: 115-150
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
0, 8, 0, 0, 39, 46, 0, 0, 0, 71, 120, 0, 131, 144, 0, 0, 163, 0, 177, 211, 249, 0, 256,
};
private static int[] hueLimitsForSatLevel4 = // Sat: 150-240
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
0, 11, 26, 0, 0, 38, 45, 0, 0, 56, 100, 121, 129, 0, 140, 0, 180, 0, 0, 224, 241, 0, 256,
};
private static int[] hueLimitsForSatLevel5 = // Sat: 240-255
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
0, 13, 27, 0, 0, 36, 45, 0, 0, 59, 118, 0, 127, 136, 142, 0, 185, 0, 0, 216, 239, 0, 256,
};
// 4. Once we have the color bucket, next we have three sub-buckets that we need to worry about,
// corresponding to three different levels of luminosity. For example, if we're in the "blue" bucket,
// that might correspond to light blue, blue, or dark blue, depending on luminosity.
// For each bucket, the luminosity cutoffs for the purposes of discerning between light, mid, and dark colors
// are different, so we define luminosity limits for low and high luminosity for each bucket, as follows:
private static int[] lumLimitsForHueIndexLow =
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
130, 100, 115, 100, 100, 100, 110, 75, 100, 90, 100, 100, 100, 100, 80, 100, 100, 100, 100, 100, 100, 100, 100,
};
private static int[] lumLimitsForHueIndexHigh =
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
170, 170, 170, 155, 170, 170, 170, 170, 170, 115, 170, 170, 170, 170, 170, 170, 170, 170, 150, 150, 170, 140, 165,
};
// 5. Finally, once we have a luminosity sub-bucket in the saturation color bucket, we have everything we need
// to retrieve a name. For each of the 23 buckets, we have names associated with light, mid, and dark variations
// of that color, which are defined as follows:
private static string[] colorNamesLight =
{
Resources.TEXT_COLOR_CORAL,
Resources.TEXT_COLOR_ROSE,
Resources.TEXT_COLOR_LIGHTORANGE,
Resources.TEXT_COLOR_TAN,
Resources.TEXT_COLOR_TAN,
Resources.TEXT_COLOR_LIGHTYELLOW,
Resources.TEXT_COLOR_LIGHTYELLOW,
Resources.TEXT_COLOR_TAN,
Resources.TEXT_COLOR_LIGHTGREEN,
Resources.TEXT_COLOR_LIME,
Resources.TEXT_COLOR_LIGHTGREEN,
Resources.TEXT_COLOR_LIGHTGREEN,
Resources.TEXT_COLOR_AQUA,
Resources.TEXT_COLOR_SKYBLUE,
Resources.TEXT_COLOR_LIGHTTURQUOISE,
Resources.TEXT_COLOR_PALEBLUE,
Resources.TEXT_COLOR_LIGHTBLUE,
Resources.TEXT_COLOR_ICEBLUE,
Resources.TEXT_COLOR_PERIWINKLE,
Resources.TEXT_COLOR_LAVENDER,
Resources.TEXT_COLOR_PINK,
Resources.TEXT_COLOR_TAN,
Resources.TEXT_COLOR_ROSE,
};
private static string[] colorNamesMid =
{
Resources.TEXT_COLOR_CORAL,
Resources.TEXT_COLOR_RED,
Resources.TEXT_COLOR_ORANGE,
Resources.TEXT_COLOR_BROWN,
Resources.TEXT_COLOR_TAN,
Resources.TEXT_COLOR_GOLD,
Resources.TEXT_COLOR_YELLOW,
Resources.TEXT_COLOR_OLIVEGREEN,
Resources.TEXT_COLOR_OLIVEGREEN,
Resources.TEXT_COLOR_GREEN,
Resources.TEXT_COLOR_GREEN,
Resources.TEXT_COLOR_BRIGHTGREEN,
Resources.TEXT_COLOR_TEAL,
Resources.TEXT_COLOR_AQUA,
Resources.TEXT_COLOR_TURQUOISE,
Resources.TEXT_COLOR_PALEBLUE,
Resources.TEXT_COLOR_BLUE,
Resources.TEXT_COLOR_BLUEGRAY,
Resources.TEXT_COLOR_INDIGO,
Resources.TEXT_COLOR_PURPLE,
Resources.TEXT_COLOR_PINK,
Resources.TEXT_COLOR_BROWN,
Resources.TEXT_COLOR_RED,
};
private static string[] colorNamesDark =
{
Resources.TEXT_COLOR_BROWN,
Resources.TEXT_COLOR_DARKRED,
Resources.TEXT_COLOR_BROWN,
Resources.TEXT_COLOR_BROWN,
Resources.TEXT_COLOR_BROWN,
Resources.TEXT_COLOR_DARKYELLOW,
Resources.TEXT_COLOR_DARKYELLOW,
Resources.TEXT_COLOR_BROWN,
Resources.TEXT_COLOR_DARKGREEN,
Resources.TEXT_COLOR_DARKGREEN,
Resources.TEXT_COLOR_DARKGREEN,
Resources.TEXT_COLOR_DARKGREEN,
Resources.TEXT_COLOR_DARKTEAL,
Resources.TEXT_COLOR_DARKTEAL,
Resources.TEXT_COLOR_DARKTEAL,
Resources.TEXT_COLOR_DARKBLUE,
Resources.TEXT_COLOR_DARKBLUE,
Resources.TEXT_COLOR_BLUEGRAY,
Resources.TEXT_COLOR_INDIGO,
Resources.TEXT_COLOR_DARKPURPLE,
Resources.TEXT_COLOR_PLUM,
Resources.TEXT_COLOR_BROWN,
Resources.TEXT_COLOR_DARKRED,
};
public static string GetColorName(Color color)
{
var (hue, sat, lum) = ColorHelper.ConvertToHSLColor(color);
hue = (hue == 0 ? 0 : hue / 360) * 255; // this implementation is using normalization to 0-255 instead of 0-360°
sat = sat * 255;
lum = lum * 255;
// First, if we're in the achromatic state, return the appropriate achromatic color name.
if (lum > 240)
{
return Resources.TEXT_COLOR_WHITE;
}
else if (lum < 20)
{
return Resources.TEXT_COLOR_BLACK;
}
if (sat <= 20)
{
if (lum > 170)
{
return Resources.TEXT_COLOR_LIGHTGRAY;
}
else if (lum > 100)
{
return Resources.TEXT_COLOR_GRAY;
}
else
{
return Resources.TEXT_COLOR_DARKGRAY;
}
}
// If we have a chromatic color, we need to first get the hue limits for the saturation value.
int[] pHueLimits;
if (sat > 20 && sat <= 75)
{
pHueLimits = hueLimitsForSatLevel1;
}
else if (sat > 75 && sat <= 115)
{
pHueLimits = hueLimitsForSatLevel2;
}
else if (sat > 115 && sat <= 150)
{
pHueLimits = hueLimitsForSatLevel3;
}
else if (sat > 150 && sat <= 240)
{
pHueLimits = hueLimitsForSatLevel4;
}
else
{
pHueLimits = hueLimitsForSatLevel5;
}
// Now that we have that, we can get the color index, which represents which
// of the 23 buckets we're located in.
int colorIndex = -1;
for (int i = 0; i < colorNamesMid.Length; ++i)
{
if (hue < pHueLimits[i])
{
colorIndex = i;
break;
}
}
// Assuming we got a color index (and we always should get one), then next we need to
// figure out which luminosity sub-bucket we're located in.
// Once we have that, we'll return the color name from the appropriate array.
if (colorIndex != -1)
{
if (lum > lumLimitsForHueIndexHigh[colorIndex])
{
return colorNamesLight[colorIndex];
}
else if (lum < lumLimitsForHueIndexLow[colorIndex])
{
return colorNamesDark[colorIndex];
}
else
{
return colorNamesMid[colorIndex];
}
}
return string.Empty;
}
public static bool AreClose(double a, double b)
{
return (float)Math.Abs(a - b) <= DBLEPSILON * (float)Math.Abs(a);
}
}
}

View File

@@ -5,6 +5,7 @@
using System;
using System.Drawing;
using System.Globalization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
namespace ColorPicker.Helpers
@@ -12,7 +13,7 @@ namespace ColorPicker.Helpers
/// <summary>
/// Helper class to easier work with color representation
/// </summary>
internal static class ColorRepresentationHelper
public static class ColorRepresentationHelper
{
/// <summary>
/// Return a <see cref="string"/> representation of a given <see cref="Color"/>
@@ -20,10 +21,10 @@ namespace ColorPicker.Helpers
/// <param name="color">The <see cref="Color"/> for the presentation</param>
/// <param name="colorRepresentationType">The type of the representation</param>
/// <returns>A <see cref="string"/> representation of a color</returns>
internal static string GetStringRepresentationFromMediaColor(System.Windows.Media.Color color, ColorRepresentationType colorRepresentationType)
internal static string GetStringRepresentationFromMediaColor(System.Windows.Media.Color color, string colorRepresentationType)
{
var drawingcolor = Color.FromArgb(color.A, color.R, color.G, color.B);
return GetStringRepresentation(drawingcolor, colorRepresentationType);
return GetStringRepresentation(drawingcolor, colorRepresentationType, string.Empty);
}
/// <summary>
@@ -32,26 +33,26 @@ namespace ColorPicker.Helpers
/// <param name="color">The <see cref="Color"/> for the presentation</param>
/// <param name="colorRepresentationType">The type of the representation</param>
/// <returns>A <see cref="string"/> representation of a color</returns>
internal static string GetStringRepresentation(Color color, ColorRepresentationType colorRepresentationType)
internal static string GetStringRepresentation(Color color, string colorRepresentationType, string colorFormat)
=> colorRepresentationType switch
{
ColorRepresentationType.CMYK => ColorToCMYK(color),
ColorRepresentationType.HEX => ColorToHex(color),
ColorRepresentationType.HSB => ColorToHSB(color),
ColorRepresentationType.HSI => ColorToHSI(color),
ColorRepresentationType.HSL => ColorToHSL(color),
ColorRepresentationType.HSV => ColorToHSV(color),
ColorRepresentationType.HWB => ColorToHWB(color),
ColorRepresentationType.NCol => ColorToNCol(color),
ColorRepresentationType.RGB => ColorToRGB(color),
ColorRepresentationType.CIELAB => ColorToCIELAB(color),
ColorRepresentationType.CIEXYZ => ColorToCIEXYZ(color),
ColorRepresentationType.VEC4 => ColorToFloat(color),
ColorRepresentationType.DecimalValue => ColorToDecimal(color),
ColorRepresentationType.HexInteger => ColorToHexInteger(color),
"CMYK" => ColorToCMYK(color),
"HEX" => ColorToHex(color),
"HSB" => ColorToHSB(color),
"HSI" => ColorToHSI(color),
"HSL" => ColorToHSL(color),
"HSV" => ColorToHSV(color),
"HWB" => ColorToHWB(color),
"NCol" => ColorToNCol(color),
"RGB" => ColorToRGB(color),
"CIELAB" => ColorToCIELAB(color),
"CIEXYZ" => ColorToCIEXYZ(color),
"VEC4" => ColorToFloat(color),
"Decimal" => ColorToDecimal(color),
"HEX Int" => ColorToHexInteger(color),
// Fall-back value, when "_userSettings.CopiedColorRepresentation.Value" is incorrect
_ => ColorToHex(color),
_ => string.IsNullOrEmpty(colorFormat) ? ColorToHex(color) : ColorFormatHelper.GetStringRepresentation(color, colorFormat),
};
/// <summary>
@@ -61,7 +62,7 @@ namespace ColorPicker.Helpers
/// <returns>A <see cref="string"/> representation of a CMYK color</returns>
private static string ColorToCMYK(Color color)
{
var (cyan, magenta, yellow, blackKey) = ColorHelper.ConvertToCMYKColor(color);
var (cyan, magenta, yellow, blackKey) = ColorFormatHelper.ConvertToCMYKColor(color);
cyan = Math.Round(cyan * 100);
magenta = Math.Round(magenta * 100);
@@ -95,7 +96,7 @@ namespace ColorPicker.Helpers
/// <returns>A <see cref="string"/> representation of a HSB color</returns>
private static string ColorToHSB(Color color)
{
var (hue, saturation, brightness) = ColorHelper.ConvertToHSBColor(color);
var (hue, saturation, brightness) = ColorFormatHelper.ConvertToHSBColor(color);
hue = Math.Round(hue);
saturation = Math.Round(saturation * 100);
@@ -139,7 +140,7 @@ namespace ColorPicker.Helpers
/// <returns>A <see cref="string"/> representation of a HSI color</returns>
private static string ColorToHSI(Color color)
{
var (hue, saturation, intensity) = ColorHelper.ConvertToHSIColor(color);
var (hue, saturation, intensity) = ColorFormatHelper.ConvertToHSIColor(color);
hue = Math.Round(hue);
saturation = Math.Round(saturation * 100);
@@ -157,7 +158,7 @@ namespace ColorPicker.Helpers
/// <returns>A <see cref="string"/> representation of a HSL color</returns>
private static string ColorToHSL(Color color)
{
var (hue, saturation, lightness) = ColorHelper.ConvertToHSLColor(color);
var (hue, saturation, lightness) = ColorFormatHelper.ConvertToHSLColor(color);
hue = Math.Round(hue);
saturation = Math.Round(saturation * 100);
@@ -176,7 +177,7 @@ namespace ColorPicker.Helpers
/// <returns>A <see cref="string"/> representation of a HSV color</returns>
private static string ColorToHSV(Color color)
{
var (hue, saturation, value) = ColorHelper.ConvertToHSVColor(color);
var (hue, saturation, value) = ColorFormatHelper.ConvertToHSVColor(color);
hue = Math.Round(hue);
saturation = Math.Round(saturation * 100);
@@ -195,7 +196,7 @@ namespace ColorPicker.Helpers
/// <returns>A <see cref="string"/> representation of a HWB color</returns>
private static string ColorToHWB(Color color)
{
var (hue, whiteness, blackness) = ColorHelper.ConvertToHWBColor(color);
var (hue, whiteness, blackness) = ColorFormatHelper.ConvertToHWBColor(color);
hue = Math.Round(hue);
whiteness = Math.Round(whiteness * 100);
@@ -213,7 +214,7 @@ namespace ColorPicker.Helpers
/// <returns>A <see cref="string"/> representation of a natural color</returns>
private static string ColorToNCol(Color color)
{
var (hue, whiteness, blackness) = ColorHelper.ConvertToNaturalColor(color);
var (hue, whiteness, blackness) = ColorFormatHelper.ConvertToNaturalColor(color);
whiteness = Math.Round(whiteness * 100);
blackness = Math.Round(blackness * 100);
@@ -240,7 +241,7 @@ namespace ColorPicker.Helpers
/// <returns>A <see cref="string"/> representation of a CIE LAB color</returns>
private static string ColorToCIELAB(Color color)
{
var (lightness, chromaticityA, chromaticityB) = ColorHelper.ConvertToCIELABColor(color);
var (lightness, chromaticityA, chromaticityB) = ColorFormatHelper.ConvertToCIELABColor(color);
lightness = Math.Round(lightness, 2);
chromaticityA = Math.Round(chromaticityA, 2);
chromaticityB = Math.Round(chromaticityB, 2);
@@ -257,7 +258,7 @@ namespace ColorPicker.Helpers
/// <returns>A <see cref="string"/> representation of a CIE XYZ color</returns>
private static string ColorToCIEXYZ(Color color)
{
var (x, y, z) = ColorHelper.ConvertToCIEXYZColor(color);
var (x, y, z) = ColorFormatHelper.ConvertToCIEXYZColor(color);
x = Math.Round(x * 100, 4);
y = Math.Round(y * 100, 4);

View File

@@ -38,7 +38,7 @@ namespace ColorPicker.Helpers
var tmp = new Dictionary<string, string>();
foreach (var colorFormatModel in colorFormatModels)
{
var colorInSpecificFormat = colorFormatModel.Convert(color);
var colorInSpecificFormat = colorFormatModel.GetColorText(color);
if (colorFormatModel.FormatName == "HEX")
{
colorInSpecificFormat = "#" + colorInSpecificFormat;
@@ -65,7 +65,7 @@ namespace ColorPicker.Helpers
i = 1;
foreach (Color color in (IList)colorsToExport)
{
var colorInSpecificFormat = colorFormatModel.Convert(color);
var colorInSpecificFormat = colorFormatModel.GetColorText(color);
if (colorFormatModel.FormatName == "HEX")
{
colorInSpecificFormat = "#" + colorInSpecificFormat;

View File

@@ -4,6 +4,7 @@
using System;
using System.Windows.Media;
using ManagedCommon;
namespace ColorPicker.Models
{
@@ -12,5 +13,17 @@ namespace ColorPicker.Models
public string FormatName { get; set; }
public Func<Color, string> Convert { get; set; }
public string FormatString { get; set; }
public string GetColorText(Color color)
{
if (Convert != null)
{
return Convert(color);
}
return ColorFormatHelper.GetStringRepresentation(System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B), FormatString);
}
}
}

View File

@@ -330,384 +330,6 @@ namespace ColorPicker.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Aqua.
/// </summary>
public static string TEXT_COLOR_AQUA {
get {
return ResourceManager.GetString("TEXT_COLOR_AQUA", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Black.
/// </summary>
public static string TEXT_COLOR_BLACK {
get {
return ResourceManager.GetString("TEXT_COLOR_BLACK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Blue.
/// </summary>
public static string TEXT_COLOR_BLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_BLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Blue gray.
/// </summary>
public static string TEXT_COLOR_BLUEGRAY {
get {
return ResourceManager.GetString("TEXT_COLOR_BLUEGRAY", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Bright green.
/// </summary>
public static string TEXT_COLOR_BRIGHTGREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_BRIGHTGREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Brown.
/// </summary>
public static string TEXT_COLOR_BROWN {
get {
return ResourceManager.GetString("TEXT_COLOR_BROWN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Coral.
/// </summary>
public static string TEXT_COLOR_CORAL {
get {
return ResourceManager.GetString("TEXT_COLOR_CORAL", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark blue.
/// </summary>
public static string TEXT_COLOR_DARKBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark gray.
/// </summary>
public static string TEXT_COLOR_DARKGRAY {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKGRAY", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark green.
/// </summary>
public static string TEXT_COLOR_DARKGREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKGREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark purple.
/// </summary>
public static string TEXT_COLOR_DARKPURPLE {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKPURPLE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark red.
/// </summary>
public static string TEXT_COLOR_DARKRED {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKRED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark teal.
/// </summary>
public static string TEXT_COLOR_DARKTEAL {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKTEAL", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark yellow.
/// </summary>
public static string TEXT_COLOR_DARKYELLOW {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKYELLOW", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Gold.
/// </summary>
public static string TEXT_COLOR_GOLD {
get {
return ResourceManager.GetString("TEXT_COLOR_GOLD", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Gray.
/// </summary>
public static string TEXT_COLOR_GRAY {
get {
return ResourceManager.GetString("TEXT_COLOR_GRAY", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Green.
/// </summary>
public static string TEXT_COLOR_GREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_GREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ice blue.
/// </summary>
public static string TEXT_COLOR_ICEBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_ICEBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Indigo.
/// </summary>
public static string TEXT_COLOR_INDIGO {
get {
return ResourceManager.GetString("TEXT_COLOR_INDIGO", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lavender.
/// </summary>
public static string TEXT_COLOR_LAVENDER {
get {
return ResourceManager.GetString("TEXT_COLOR_LAVENDER", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light blue.
/// </summary>
public static string TEXT_COLOR_LIGHTBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light gray.
/// </summary>
public static string TEXT_COLOR_LIGHTGRAY {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTGRAY", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light green.
/// </summary>
public static string TEXT_COLOR_LIGHTGREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTGREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light orange.
/// </summary>
public static string TEXT_COLOR_LIGHTORANGE {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTORANGE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light turquoise.
/// </summary>
public static string TEXT_COLOR_LIGHTTURQUOISE {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTTURQUOISE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light yellow.
/// </summary>
public static string TEXT_COLOR_LIGHTYELLOW {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTYELLOW", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lime.
/// </summary>
public static string TEXT_COLOR_LIME {
get {
return ResourceManager.GetString("TEXT_COLOR_LIME", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Olive green.
/// </summary>
public static string TEXT_COLOR_OLIVEGREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_OLIVEGREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Orange.
/// </summary>
public static string TEXT_COLOR_ORANGE {
get {
return ResourceManager.GetString("TEXT_COLOR_ORANGE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pale blue.
/// </summary>
public static string TEXT_COLOR_PALEBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_PALEBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Periwinkle.
/// </summary>
public static string TEXT_COLOR_PERIWINKLE {
get {
return ResourceManager.GetString("TEXT_COLOR_PERIWINKLE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pink.
/// </summary>
public static string TEXT_COLOR_PINK {
get {
return ResourceManager.GetString("TEXT_COLOR_PINK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Plum.
/// </summary>
public static string TEXT_COLOR_PLUM {
get {
return ResourceManager.GetString("TEXT_COLOR_PLUM", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Purple.
/// </summary>
public static string TEXT_COLOR_PURPLE {
get {
return ResourceManager.GetString("TEXT_COLOR_PURPLE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Red.
/// </summary>
public static string TEXT_COLOR_RED {
get {
return ResourceManager.GetString("TEXT_COLOR_RED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Rose.
/// </summary>
public static string TEXT_COLOR_ROSE {
get {
return ResourceManager.GetString("TEXT_COLOR_ROSE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sky blue.
/// </summary>
public static string TEXT_COLOR_SKYBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_SKYBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Tan.
/// </summary>
public static string TEXT_COLOR_TAN {
get {
return ResourceManager.GetString("TEXT_COLOR_TAN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Teal.
/// </summary>
public static string TEXT_COLOR_TEAL {
get {
return ResourceManager.GetString("TEXT_COLOR_TEAL", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Turquoise.
/// </summary>
public static string TEXT_COLOR_TURQUOISE {
get {
return ResourceManager.GetString("TEXT_COLOR_TURQUOISE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to White.
/// </summary>
public static string TEXT_COLOR_WHITE {
get {
return ResourceManager.GetString("TEXT_COLOR_WHITE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Yellow.
/// </summary>
public static string TEXT_COLOR_YELLOW {
get {
return ResourceManager.GetString("TEXT_COLOR_YELLOW", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value slider.
/// </summary>

View File

@@ -205,174 +205,6 @@
<value>Value slider</value>
<comment>Tool tip that appears when hovering over a slider that represents the color value (from HSV)</comment>
</data>
<data name="TEXT_COLOR_WHITE" xml:space="preserve">
<value>White</value>
<comment>White color</comment>
</data>
<data name="TEXT_COLOR_BLACK" xml:space="preserve">
<value>Black</value>
<comment>Black color</comment>
</data>
<data name="TEXT_COLOR_LIGHTGRAY" xml:space="preserve">
<value>Light gray</value>
<comment>Light gray color</comment>
</data>
<data name="TEXT_COLOR_GRAY" xml:space="preserve">
<value>Gray</value>
<comment>Gray color</comment>
</data>
<data name="TEXT_COLOR_DARKGRAY" xml:space="preserve">
<value>Dark gray</value>
<comment>Dark gray color</comment>
</data>
<data name="TEXT_COLOR_CORAL" xml:space="preserve">
<value>Coral</value>
<comment>Coral color</comment>
</data>
<data name="TEXT_COLOR_ROSE" xml:space="preserve">
<value>Rose</value>
<comment>Rose color</comment>
</data>
<data name="TEXT_COLOR_LIGHTORANGE" xml:space="preserve">
<value>Light orange</value>
<comment>Light orange color</comment>
</data>
<data name="TEXT_COLOR_TAN" xml:space="preserve">
<value>Tan</value>
<comment>Tan color</comment>
</data>
<data name="TEXT_COLOR_LIGHTYELLOW" xml:space="preserve">
<value>Light yellow</value>
<comment>Light yellow color</comment>
</data>
<data name="TEXT_COLOR_LIGHTGREEN" xml:space="preserve">
<value>Light green</value>
<comment>Light green color</comment>
</data>
<data name="TEXT_COLOR_LIME" xml:space="preserve">
<value>Lime</value>
<comment>Lime color</comment>
</data>
<data name="TEXT_COLOR_AQUA" xml:space="preserve">
<value>Aqua</value>
<comment>Aqua color</comment>
</data>
<data name="TEXT_COLOR_SKYBLUE" xml:space="preserve">
<value>Sky blue</value>
<comment>Sky blue color</comment>
</data>
<data name="TEXT_COLOR_LIGHTTURQUOISE" xml:space="preserve">
<value>Light turquoise</value>
<comment>Light turquoise color</comment>
</data>
<data name="TEXT_COLOR_PALEBLUE" xml:space="preserve">
<value>Pale blue</value>
<comment>Pale blue color</comment>
</data>
<data name="TEXT_COLOR_LIGHTBLUE" xml:space="preserve">
<value>Light blue</value>
<comment>Light blue color</comment>
</data>
<data name="TEXT_COLOR_ICEBLUE" xml:space="preserve">
<value>Ice blue</value>
<comment>Ice blue color</comment>
</data>
<data name="TEXT_COLOR_PERIWINKLE" xml:space="preserve">
<value>Periwinkle</value>
<comment>Periwinkle color</comment>
</data>
<data name="TEXT_COLOR_LAVENDER" xml:space="preserve">
<value>Lavender</value>
<comment>Lavender color</comment>
</data>
<data name="TEXT_COLOR_PINK" xml:space="preserve">
<value>Pink</value>
<comment>Pink color</comment>
</data>
<data name="TEXT_COLOR_RED" xml:space="preserve">
<value>Red</value>
<comment>Red color</comment>
</data>
<data name="TEXT_COLOR_ORANGE" xml:space="preserve">
<value>Orange</value>
<comment>Orange color</comment>
</data>
<data name="TEXT_COLOR_BROWN" xml:space="preserve">
<value>Brown</value>
<comment>Brown color</comment>
</data>
<data name="TEXT_COLOR_GOLD" xml:space="preserve">
<value>Gold</value>
<comment>Gold color</comment>
</data>
<data name="TEXT_COLOR_YELLOW" xml:space="preserve">
<value>Yellow</value>
<comment>Yellow color</comment>
</data>
<data name="TEXT_COLOR_OLIVEGREEN" xml:space="preserve">
<value>Olive green</value>
<comment>Olive green color</comment>
</data>
<data name="TEXT_COLOR_GREEN" xml:space="preserve">
<value>Green</value>
<comment>Green color</comment>
</data>
<data name="TEXT_COLOR_BRIGHTGREEN" xml:space="preserve">
<value>Bright green</value>
<comment>Rose color</comment>
</data>
<data name="TEXT_COLOR_TEAL" xml:space="preserve">
<value>Teal</value>
<comment>Teal color</comment>
</data>
<data name="TEXT_COLOR_TURQUOISE" xml:space="preserve">
<value>Turquoise</value>
<comment>Turquoise color</comment>
</data>
<data name="TEXT_COLOR_BLUE" xml:space="preserve">
<value>Blue</value>
<comment>Blue color</comment>
</data>
<data name="TEXT_COLOR_BLUEGRAY" xml:space="preserve">
<value>Blue gray</value>
<comment>Blue gray color</comment>
</data>
<data name="TEXT_COLOR_INDIGO" xml:space="preserve">
<value>Indigo</value>
<comment>Indigo color</comment>
</data>
<data name="TEXT_COLOR_PURPLE" xml:space="preserve">
<value>Purple</value>
<comment>Purple color</comment>
</data>
<data name="TEXT_COLOR_DARKRED" xml:space="preserve">
<value>Dark red</value>
<comment>Dark red color</comment>
</data>
<data name="TEXT_COLOR_DARKYELLOW" xml:space="preserve">
<value>Dark yellow</value>
<comment>Dark yellow color</comment>
</data>
<data name="TEXT_COLOR_DARKGREEN" xml:space="preserve">
<value>Dark green</value>
<comment>Dark green color</comment>
</data>
<data name="TEXT_COLOR_DARKTEAL" xml:space="preserve">
<value>Dark teal</value>
<comment>Dark teal color</comment>
</data>
<data name="TEXT_COLOR_DARKBLUE" xml:space="preserve">
<value>Dark blue</value>
<comment>Dark blue color</comment>
</data>
<data name="TEXT_COLOR_DARKPURPLE" xml:space="preserve">
<value>Dark purple</value>
<comment>Dark purple color</comment>
</data>
<data name="TEXT_COLOR_PLUM" xml:space="preserve">
<value>Plum</value>
<comment>Plum color</comment>
</data>
<data name="Select_color" xml:space="preserve">
<value>Select color</value>
</data>

View File

@@ -14,7 +14,9 @@ namespace ColorPicker.Settings
SettingItem<bool> ChangeCursor { get; }
SettingItem<ColorRepresentationType> CopiedColorRepresentation { get; set; }
SettingItem<string> CopiedColorRepresentation { get; set; }
SettingItem<string> CopiedColorRepresentationFormat { get; set; }
SettingItem<ColorPickerActivationAction> ActivationAction { get; }
@@ -22,7 +24,7 @@ namespace ColorPicker.Settings
SettingItem<int> ColorHistoryLimit { get; }
ObservableCollection<string> VisibleColorFormats { get; }
ObservableCollection<System.Collections.Generic.KeyValuePair<string, string>> VisibleColorFormats { get; }
SettingItem<bool> ShowColorName { get; }

View File

@@ -39,7 +39,7 @@ namespace ColorPicker.Settings
_settingsUtils = new SettingsUtils();
ChangeCursor = new SettingItem<bool>(true);
ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut);
CopiedColorRepresentation = new SettingItem<ColorRepresentationType>(ColorRepresentationType.HEX);
CopiedColorRepresentation = new SettingItem<string>(ColorRepresentationType.HEX.ToString());
ActivationAction = new SettingItem<ColorPickerActivationAction>(ColorPickerActivationAction.OpenEditor);
ColorHistoryLimit = new SettingItem<int>(20);
ColorHistory.CollectionChanged += ColorHistory_CollectionChanged;
@@ -55,7 +55,7 @@ namespace ColorPicker.Settings
{
if (!_loadingColorsHistory)
{
var settings = _settingsUtils.GetSettingsOrDefault<ColorPickerSettings>(ColorPickerModuleName);
var settings = _settingsUtils.GetSettingsOrDefault<ColorPickerSettings, ColorPickerSettingsVersion1>(ColorPickerModuleName, settingsUpgrader: ColorPickerSettings.UpgradeSettings);
ColorHistory.CollectionChanged -= ColorHistory_CollectionChanged;
settings.Properties.ColorHistory = ColorHistory.ToList();
ColorHistory.CollectionChanged += ColorHistory_CollectionChanged;
@@ -67,7 +67,9 @@ namespace ColorPicker.Settings
public SettingItem<bool> ChangeCursor { get; private set; }
public SettingItem<ColorRepresentationType> CopiedColorRepresentation { get; set; }
public SettingItem<string> CopiedColorRepresentation { get; set; }
public SettingItem<string> CopiedColorRepresentationFormat { get; set; }
public SettingItem<ColorPickerActivationAction> ActivationAction { get; private set; }
@@ -75,7 +77,7 @@ namespace ColorPicker.Settings
public SettingItem<int> ColorHistoryLimit { get; }
public ObservableCollection<string> VisibleColorFormats { get; private set; } = new ObservableCollection<string>();
public ObservableCollection<System.Collections.Generic.KeyValuePair<string, string>> VisibleColorFormats { get; private set; } = new ObservableCollection<System.Collections.Generic.KeyValuePair<string, string>>();
public SettingItem<bool> ShowColorName { get; }
@@ -101,12 +103,18 @@ namespace ColorPicker.Settings
defaultColorPickerSettings.Save(_settingsUtils);
}
var settings = _settingsUtils.GetSettingsOrDefault<ColorPickerSettings>(ColorPickerModuleName);
var settings = _settingsUtils.GetSettingsOrDefault<ColorPickerSettings, ColorPickerSettingsVersion1>(ColorPickerModuleName, settingsUpgrader: ColorPickerSettings.UpgradeSettings);
if (settings != null)
{
ChangeCursor.Value = settings.Properties.ChangeCursor;
ActivationShortcut.Value = settings.Properties.ActivationShortcut.ToString();
if (settings.Properties.CopiedColorRepresentation == null)
{
settings.Properties.CopiedColorRepresentation = "HEX";
}
CopiedColorRepresentation.Value = settings.Properties.CopiedColorRepresentation;
CopiedColorRepresentationFormat = new SettingItem<string>(string.Empty);
ActivationAction.Value = settings.Properties.ActivationAction;
ColorHistoryLimit.Value = settings.Properties.ColorHistoryLimit;
ShowColorName.Value = settings.Properties.ShowColorName;
@@ -128,9 +136,14 @@ namespace ColorPicker.Settings
VisibleColorFormats.Clear();
foreach (var item in settings.Properties.VisibleColorFormats)
{
if (item.Value)
if (item.Value.Key)
{
VisibleColorFormats.Add(item.Key);
VisibleColorFormats.Add(new System.Collections.Generic.KeyValuePair<string, string>(item.Key, item.Value.Value));
}
if (item.Key == CopiedColorRepresentation.Value)
{
CopiedColorRepresentationFormat.Value = item.Value.Value;
}
}
}
@@ -165,7 +178,7 @@ namespace ColorPicker.Settings
public void SendSettingsTelemetry()
{
Logger.LogInfo("Sending settings telemetry");
var settings = _settingsUtils.GetSettingsOrDefault<ColorPickerSettings>(ColorPickerModuleName);
var settings = _settingsUtils.GetSettingsOrDefault<ColorPickerSettings, ColorPickerSettingsVersion1>(ColorPickerModuleName, settingsUpgrader: ColorPickerSettings.UpgradeSettings);
var properties = settings?.Properties;
if (properties == null)
{

View File

@@ -12,7 +12,7 @@ namespace ColorPicker.Telemetry
[EventData]
public class ColorPickerSettings : EventBase, IEvent
{
public ColorPickerSettings(IDictionary<string, bool> editorFormats)
public ColorPickerSettings(IDictionary<string, KeyValuePair<bool, string>> editorFormats)
{
EditorFormats = editorFormats;
EventName = "ColorPicker_Settings";
@@ -26,7 +26,7 @@ namespace ColorPicker.Telemetry
public bool ShowColorName { get; set; }
public IDictionary<string, bool> EditorFormats { get; }
public IDictionary<string, KeyValuePair<bool, string>> EditorFormats { get; }
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
}

View File

@@ -247,7 +247,7 @@ namespace ColorPicker.ViewModels
{
FormatName = ColorRepresentationType.HEX.ToString(),
#pragma warning disable CA1304 // Specify CultureInfo
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HEX).ToLower(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HEX.ToString()).ToLower(),
#pragma warning restore CA1304 // Specify CultureInfo
});
@@ -255,82 +255,82 @@ namespace ColorPicker.ViewModels
new ColorFormatModel()
{
FormatName = ColorRepresentationType.RGB.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.RGB),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.RGB.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.HSL.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSL),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSL.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.HSV.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSV),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSV.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.CMYK.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CMYK),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CMYK.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.HSB.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSB),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSB.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.HSI.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSI),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSI.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.HWB.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HWB),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HWB.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.NCol.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.NCol),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.NCol.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.CIELAB.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CIELAB),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CIELAB.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.CIEXYZ.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CIEXYZ),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CIEXYZ.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.VEC4.ToString(),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.VEC4),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.VEC4.ToString()),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = "Decimal",
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.DecimalValue),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, "Decimal"),
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = "HEX Int",
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HexInteger),
Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, "HEX Int"),
});
_userSettings.VisibleColorFormats.CollectionChanged += VisibleColorFormats_CollectionChanged;
@@ -349,11 +349,7 @@ namespace ColorPicker.ViewModels
foreach (var colorFormat in _userSettings.VisibleColorFormats)
{
var colorRepresentation = _allColorRepresentations.FirstOrDefault(it => it.FormatName.ToUpperInvariant() == colorFormat.ToUpperInvariant());
if (colorRepresentation != null)
{
ColorRepresentations.Add(colorRepresentation);
}
ColorRepresentations.Add(new ColorFormatModel() { FormatName = colorFormat.Key.ToUpperInvariant(), Convert = null, FormatString = colorFormat.Value });
}
}
}

View File

@@ -15,6 +15,7 @@ using ColorPicker.Settings;
using ColorPicker.ViewModelContracts;
using Common.UI;
using interop;
using ManagedCommon;
namespace ColorPicker.ViewModels
{
@@ -174,7 +175,7 @@ namespace ColorPicker.ViewModels
private void SetColorDetails(System.Drawing.Color color)
{
ColorBrush = new SolidColorBrush(Color.FromArgb(color.A, color.R, color.G, color.B));
ColorText = ColorRepresentationHelper.GetStringRepresentation(color, _userSettings.CopiedColorRepresentation.Value);
ColorText = ColorRepresentationHelper.GetStringRepresentation(color, _userSettings.CopiedColorRepresentation.Value, _userSettings.CopiedColorRepresentationFormat.Value);
ColorName = ColorNameHelper.GetColorName(color);
}

View File

@@ -6,6 +6,7 @@ using System;
using System.Drawing;
using System.Globalization;
using ColorPicker.Helpers;
using ManagedCommon;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.ColorPicker.UnitTests
@@ -53,7 +54,7 @@ namespace Microsoft.ColorPicker.UnitTests
blue = Convert.ToInt32(Math.Round(255d / 100d * blue)); // [0%..100%] to [0..255]
var color = Color.FromArgb(255, red, green, blue);
var result = ColorHelper.ConvertToHSLColor(color);
var result = ColorFormatHelper.ConvertToHSLColor(color);
// hue[0°..360°]
Assert.AreEqual(result.hue, hue, 0.2d);
@@ -102,7 +103,7 @@ namespace Microsoft.ColorPicker.UnitTests
blue = Convert.ToInt32(Math.Round(255d / 100d * blue)); // [0%..100%] to [0..255]
var color = Color.FromArgb(255, red, green, blue);
var result = ColorHelper.ConvertToHSVColor(color);
var result = ColorFormatHelper.ConvertToHSVColor(color);
// hue [0°..360°]
Assert.AreEqual(result.hue, hue, 0.2d);
@@ -151,7 +152,7 @@ namespace Microsoft.ColorPicker.UnitTests
blue = Convert.ToInt32(Math.Round(255d / 100d * blue)); // [0%..100%] to [0..255]
var color = Color.FromArgb(255, red, green, blue);
var result = ColorHelper.ConvertToHSBColor(color);
var result = ColorFormatHelper.ConvertToHSBColor(color);
// hue [0°..360°]
Assert.AreEqual(result.hue, hue, 0.2d);
@@ -195,7 +196,7 @@ namespace Microsoft.ColorPicker.UnitTests
public void ColorRGBtoCMYKTest(int cyan, int magenta, int yellow, int blackKey, int red, int green, int blue)
{
var color = Color.FromArgb(255, red, green, blue);
var result = ColorHelper.ConvertToCMYKColor(color);
var result = ColorFormatHelper.ConvertToCMYKColor(color);
// cyan[0..1]
Assert.AreEqual(result.cyan * 100d, cyan, 0.5d);
@@ -245,7 +246,7 @@ namespace Microsoft.ColorPicker.UnitTests
var blue = int.Parse(hexValue.AsSpan(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
var color = Color.FromArgb(255, red, green, blue);
var result = ColorHelper.ConvertToHSIColor(color);
var result = ColorFormatHelper.ConvertToHSIColor(color);
// hue[0°..360°]
Assert.AreEqual(result.hue, hue, 0.5d);
@@ -293,7 +294,7 @@ namespace Microsoft.ColorPicker.UnitTests
var blue = int.Parse(hexValue.AsSpan(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
var color = Color.FromArgb(255, red, green, blue);
var result = ColorHelper.ConvertToHWBColor(color);
var result = ColorFormatHelper.ConvertToHWBColor(color);
// hue[0°..360°]
Assert.AreEqual(result.hue, hue, 0.5d);
@@ -341,7 +342,7 @@ namespace Microsoft.ColorPicker.UnitTests
var blue = int.Parse(hexValue.AsSpan(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
var color = Color.FromArgb(255, red, green, blue);
var result = ColorHelper.ConvertToNaturalColor(color);
var result = ColorFormatHelper.ConvertToNaturalColor(color);
// hue
Assert.AreEqual(result.hue, hue);
@@ -397,7 +398,7 @@ namespace Microsoft.ColorPicker.UnitTests
var blue = int.Parse(hexValue.AsSpan(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
var color = Color.FromArgb(255, red, green, blue);
var result = ColorHelper.ConvertToCIELABColor(color);
var result = ColorFormatHelper.ConvertToCIELABColor(color);
// lightness[0..100]
Assert.AreEqual(Math.Round(result.lightness, 2), lightness);
@@ -461,7 +462,7 @@ namespace Microsoft.ColorPicker.UnitTests
var blue = int.Parse(hexValue.AsSpan(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
var color = Color.FromArgb(255, red, green, blue);
var result = ColorHelper.ConvertToCIEXYZColor(color);
var result = ColorFormatHelper.ConvertToCIEXYZColor(color);
// x[0..0.95047]
Assert.AreEqual(Math.Round(result.x * 100, 4), x);
@@ -488,7 +489,7 @@ namespace Microsoft.ColorPicker.UnitTests
try
{
_ = ColorHelper.ConvertToCMYKColor(color);
_ = ColorFormatHelper.ConvertToCMYKColor(color);
}
// intentionally trying to catch

View File

@@ -4,7 +4,6 @@
using System.Drawing;
using ColorPicker.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.ColorPicker.UnitTests
@@ -13,24 +12,24 @@ namespace Microsoft.ColorPicker.UnitTests
public class ColorRepresentationHelperTest
{
[TestMethod]
[DataRow(ColorRepresentationType.CMYK, "cmyk(0%, 0%, 0%, 100%)")]
[DataRow(ColorRepresentationType.HEX, "000000")]
[DataRow(ColorRepresentationType.NCol, "R0, 0%, 100%")]
[DataRow(ColorRepresentationType.HSB, "hsb(0, 0%, 0%)")]
[DataRow(ColorRepresentationType.HSI, "hsi(0, 0%, 0%)")]
[DataRow(ColorRepresentationType.HSL, "hsl(0, 0%, 0%)")]
[DataRow(ColorRepresentationType.HSV, "hsv(0, 0%, 0%)")]
[DataRow(ColorRepresentationType.HWB, "hwb(0, 0%, 100%)")]
[DataRow(ColorRepresentationType.RGB, "rgb(0, 0, 0)")]
[DataRow(ColorRepresentationType.CIELAB, "CIELab(0, 0, 0)")]
[DataRow(ColorRepresentationType.CIEXYZ, "XYZ(0, 0, 0)")]
[DataRow(ColorRepresentationType.VEC4, "(0f, 0f, 0f, 1f)")]
[DataRow(ColorRepresentationType.DecimalValue, "0")]
[DataRow(ColorRepresentationType.HexInteger, "0xFF000000")]
[DataRow("CMYK", "cmyk(0%, 0%, 0%, 100%)")]
[DataRow("HEX", "000000")]
[DataRow("NCol", "R0, 0%, 100%")]
[DataRow("HSB", "hsb(0, 0%, 0%)")]
[DataRow("HSI", "hsi(0, 0%, 0%)")]
[DataRow("HSL", "hsl(0, 0%, 0%)")]
[DataRow("HSV", "hsv(0, 0%, 0%)")]
[DataRow("HWB", "hwb(0, 0%, 100%)")]
[DataRow("RGB", "rgb(0, 0, 0)")]
[DataRow("CIELAB", "CIELab(0, 0, 0)")]
[DataRow("CIEXYZ", "XYZ(0, 0, 0)")]
[DataRow("VEC4", "(0f, 0f, 0f, 1f)")]
[DataRow("Decimal", "0")]
[DataRow("HEX Int", "0xFF000000")]
public void GetStringRepresentationTest(ColorRepresentationType type, string expected)
public void GetStringRepresentationTest(string type, string expected)
{
var result = ColorRepresentationHelper.GetStringRepresentation(Color.Black, type);
var result = ColorRepresentationHelper.GetStringRepresentation(Color.Black, type, string.Empty);
Assert.AreEqual(result, expected);
}
}