From e5b18d0b9c263b65b9121a25e19b6103e21d1d07 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 28 May 2022 01:25:59 -0400 Subject: [PATCH] Further work on ColorView --- .../Converters/ContrastBrushConverter.cs | 84 +++++++++ .../Themes/Fluent/ColorView.xaml | 165 +++++++++++++++++- 2 files changed, 246 insertions(+), 3 deletions(-) create mode 100644 src/Avalonia.Controls.ColorPicker/Converters/ContrastBrushConverter.cs diff --git a/src/Avalonia.Controls.ColorPicker/Converters/ContrastBrushConverter.cs b/src/Avalonia.Controls.ColorPicker/Converters/ContrastBrushConverter.cs new file mode 100644 index 0000000000..574f23dfae --- /dev/null +++ b/src/Avalonia.Controls.ColorPicker/Converters/ContrastBrushConverter.cs @@ -0,0 +1,84 @@ +using System; +using System.Globalization; +using Avalonia.Controls.Converters; +using Avalonia.Data.Converters; +using Avalonia.Media; + +namespace Avalonia.Controls.Primitives.Converters +{ + /// + /// Gets a , either black or white, depending on the luminance of the supplied color. + /// A default color supplied in the converter parameter may be returned if alpha is below the set threshold. + /// + public class ContrastBrushConverter : IValueConverter + { + private ToColorConverter toColorConverter = new ToColorConverter(); + + /// + /// Gets or sets the alpha channel threshold below which a default color is used instead of black/white. + /// + public byte AlphaThreshold { get; set; } = 128; + + /// + public object? Convert( + object? value, + Type targetType, + object? parameter, + CultureInfo culture) + { + Color comparisonColor; + Color? defaultColor = null; + + // Get the changing color to compare against + var convertedValue = toColorConverter.Convert(value, targetType, parameter, culture); + if (convertedValue is Color valueColor) + { + comparisonColor = valueColor; + } + else + { + // Invalid color value provided + return AvaloniaProperty.UnsetValue; + } + + // Get the default color when transparency is high + var convertedParameter = toColorConverter.Convert(parameter, targetType, parameter, culture); + if (convertedParameter is Color parameterColor) + { + defaultColor = parameterColor; + } + + if (comparisonColor.A < AlphaThreshold && + defaultColor.HasValue) + { + // If the transparency is less than the threshold, just use the default brush + // This can commonly be something like the TextControlForeground brush + return new SolidColorBrush(defaultColor.Value); + } + else + { + // Chose a white/black brush based on contrast to the base color + if (ColorHelper.GetRelativeLuminance(comparisonColor) <= 0.5) + { + // Dark color, return light for contrast + return new SolidColorBrush(Colors.White); + } + else + { + // Bright color, return dark for contrast + return new SolidColorBrush(Colors.Black); + } + } + } + + /// + public object? ConvertBack( + object? value, + Type targetType, + object? parameter, + CultureInfo culture) + { + return AvaloniaProperty.UnsetValue; + } + } +} diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml index 9f4324594d..5d3642a3b1 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml @@ -3,12 +3,15 @@ xmlns:converters="using:Avalonia.Controls.Converters" xmlns:primitives="using:Avalonia.Controls.Primitives" xmlns:pc="clr-namespace:Avalonia.Controls.Primitives.Converters;assembly=Avalonia.Controls.ColorPicker" + xmlns:globalization="clr-namespace:System.Globalization;assembly=mscorlib" x:CompileBindings="False"> + + + + + + + @@ -195,11 +230,11 @@ - + + + + + + + + + + + + + + + +