Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ColorPicker Updates #4502

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<Setter Property="ColorSpectrumShape" Value="Box"/>
<Setter Property="IsAlphaEnabled" Value="False"/>
<Setter Property="IsHexInputVisible" Value="True"/>
<Setter Property="ShowAccentColors" Value="False"/>
</Style>
</controls:ColorPickerButton.ColorPickerStyle>
</controls:ColorPickerButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
Color="Navy"
ColorSpectrumShape="Box"
IsAlphaEnabled="False"
IsHexInputVisible="True" />
IsHexInputVisible="True"
ShowAccentColors="False" />
<!-- Example 2 -->
<Border Background="{ThemeResource SystemChromeMediumColor}"
CornerRadius="4"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Globalization;
using Microsoft.Toolkit.Uwp.Helpers;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;

namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// Creates an accent color for a base color value.
/// </summary>
public class AccentColorConverter : IValueConverter
{
/// <summary>
/// The amount to change the Value channel for each accent color step.
/// </summary>
public const double ValueDelta = 0.1;

/// <summary>
/// This does not account for perceptual differences and also does not match with
/// system accent color calculation.
/// </summary>
/// <remarks>
/// Use the HSV representation as it's more perceptual.
/// In most cases only the value is changed by a fixed percentage so the algorithm is reproducible.
/// </remarks>
/// <param name="hsvColor">The base color to calculate the accent from.</param>
/// <param name="accentStep">The number of accent color steps to move.</param>
/// <returns>The new accent color.</returns>
public static HsvColor GetAccent(HsvColor hsvColor, int accentStep)
{
if (accentStep != 0)
{
double colorValue = hsvColor.V;
colorValue += accentStep * AccentColorConverter.ValueDelta;
colorValue = Math.Round(colorValue, 2);

return new HsvColor()
{
A = Math.Clamp(hsvColor.A, 0.0, 1.0),
H = Math.Clamp(hsvColor.H, 0.0, 360.0),
S = Math.Clamp(hsvColor.S, 0.0, 1.0),
V = Math.Clamp(colorValue, 0.0, 1.0),
};
}
else
{
return hsvColor;
}
}

/// <inheritdoc/>
public object Convert(
object value,
Type targetType,
object parameter,
string language)
{
int accentStep;
Color? rgbColor = null;
HsvColor? hsvColor = null;

// Get the current color in HSV
if (value is Color valueColor)
{
rgbColor = valueColor;
}
else if (value is HsvColor valueHsvColor)
{
hsvColor = valueHsvColor;
}
else if (value is SolidColorBrush valueBrush)
{
rgbColor = valueBrush.Color;
}
else
{
// Invalid color value provided
return DependencyProperty.UnsetValue;
}

// Get the value component delta
try
{
accentStep = int.Parse(parameter?.ToString(), CultureInfo.InvariantCulture);
}
catch
{
// Invalid parameter provided, unable to convert to integer
return DependencyProperty.UnsetValue;
}

if (hsvColor == null &&
rgbColor != null)
{
hsvColor = rgbColor.Value.ToHsv();
}

if (hsvColor != null)
{
var hsv = AccentColorConverter.GetAccent(hsvColor.Value, accentStep);

return Uwp.Helpers.ColorHelper.FromHsv(hsv.H, hsv.S, hsv.V, hsv.A);
}
else
{
return DependencyProperty.UnsetValue;
}
}

/// <inheritdoc/>
public object ConvertBack(
object value,
Type targetType,
object parameter,
string language)
{
return DependencyProperty.UnsetValue;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,33 @@ public bool IsColorPaletteVisible
}
}
}

/// <summary>
/// Identifies the <see cref="ShowAccentColors"/> dependency property.
/// </summary>
public static readonly DependencyProperty ShowAccentColorsProperty =
DependencyProperty.Register(
nameof(ShowAccentColors),
typeof(bool),
typeof(ColorPicker),
new PropertyMetadata(
true,
(s, e) => (s as ColorPicker)?.OnDependencyPropertyChanged(s, e)));

/// <summary>
/// Gets or sets a value indicating whether accent colors are shown along
/// with the preview color.
/// </summary>
public bool ShowAccentColors
{
get => (bool)this.GetValue(ShowAccentColorsProperty);
set
{
if (object.Equals(value, this.GetValue(ShowAccentColorsProperty)) == false)
{
this.SetValue(ShowAccentColorsProperty, value);
}
}
}
}
}