Skip to content

Commit 4064179

Browse files
committed
Move ColorPickerSlider foreground/background calculation into the control itself
* Simplifies template by moving logic for foreground calulation into the slider itself * Switches the sliders to work entirely within HSV which means its background stops turning red when you get to a minimum value * Exposes properties to fix the Saturation/Value and Alpha channels at maximum when calculating backgrounds * Moves slider into Primitives namespace
1 parent 278bbf7 commit 4064179

File tree

8 files changed

+704
-249
lines changed

8 files changed

+704
-249
lines changed

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerButtonPage.xaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
5+
xmlns:primitives="using:Microsoft.Toolkit.Uwp.UI.Controls.Primitives"
56
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
67
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
78
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
89
mc:Ignorable="d">
910

1011
<Grid Visibility="Collapsed">
1112
<controls:ColorPickerButton />
12-
<controls:ColorPickerSlider />
13+
<primitives:ColorPickerSlider />
1314
</Grid>
1415
</Page>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerPage.xaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
55
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
66
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
7+
xmlns:primitives="using:Microsoft.Toolkit.Uwp.UI.Controls.Primitives"
78
mc:Ignorable="d"
89
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
910

1011
<Grid
1112
Visibility="Collapsed">
1213
<controls:ColorPicker />
13-
<controls:ColorPickerSlider />
14+
<primitives:ColorPickerSlider />
1415
</Grid>
1516

1617
</Page>

Microsoft.Toolkit.Uwp.UI.Controls/ColorPicker/ColorPicker.cs

Lines changed: 77 additions & 160 deletions
Large diffs are not rendered by default.

Microsoft.Toolkit.Uwp.UI.Controls/ColorPicker/ColorPicker.xaml

Lines changed: 54 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
4+
xmlns:primitives="using:Microsoft.Toolkit.Uwp.UI.Controls.Primitives"
45
xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
56
xmlns:ex="using:Microsoft.Toolkit.Uwp.UI.Extensions"
67
xmlns:localconverters="using:Microsoft.Toolkit.Uwp.UI.Controls.ColorPickerConverters">
@@ -107,16 +108,16 @@
107108
<RowDefinition Height="Auto" />
108109
<RowDefinition Height="*" />
109110
</Grid.RowDefinitions>
110-
<controls:ColorPickerSlider x:Name="ColorSpectrumThirdDimensionSlider"
111-
Grid.Row="1"
112-
Grid.RowSpan="2"
113-
Grid.Column="0"
114-
Width="20"
115-
Margin="0,0,12,0"
116-
HorizontalAlignment="Center"
117-
VerticalAlignment="Stretch"
118-
BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Color, Converter={StaticResource ContrastBrushConverter}, ConverterParameter={ThemeResource TextControlForeground}}"
119-
Orientation="Vertical" />
111+
<primitives:ColorPickerSlider x:Name="ColorSpectrumThirdDimensionSlider"
112+
Grid.Row="1"
113+
Grid.RowSpan="2"
114+
Grid.Column="0"
115+
Width="20"
116+
Margin="0,0,12,0"
117+
HorizontalAlignment="Center"
118+
VerticalAlignment="Stretch"
119+
DefaultForeground="{ThemeResource TextControlForeground}"
120+
Orientation="Vertical" />
120121
<!-- Keep in mind the spectrum is always HSV -->
121122
<!-- This must also not be named 'ColorSpectrum' to differentiate from the base class -->
122123
<ColorSpectrum x:Name="ColorSpectrumControl"
@@ -136,17 +137,17 @@
136137
MinSaturation="{TemplateBinding MinSaturation}"
137138
MinValue="{TemplateBinding MinValue}"
138139
Shape="{TemplateBinding ColorSpectrumShape}" />
139-
<controls:ColorPickerSlider x:Name="ColorSpectrumAlphaSlider"
140-
Grid.Row="1"
141-
Grid.RowSpan="2"
142-
Grid.Column="2"
143-
Width="20"
144-
Margin="12,0,0,0"
145-
HorizontalAlignment="Center"
146-
VerticalAlignment="Stretch"
147-
AutomationProperties.Name="Alpha Channel"
148-
BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Color, Converter={StaticResource ContrastBrushConverter}, ConverterParameter={ThemeResource TextControlForeground}}"
149-
Orientation="Vertical" />
140+
<primitives:ColorPickerSlider x:Name="ColorSpectrumAlphaSlider"
141+
Grid.Row="1"
142+
Grid.RowSpan="2"
143+
Grid.Column="2"
144+
Width="20"
145+
Margin="12,0,0,0"
146+
HorizontalAlignment="Center"
147+
VerticalAlignment="Stretch"
148+
AutomationProperties.Name="Alpha Channel"
149+
DefaultForeground="{ThemeResource TextControlForeground}"
150+
Orientation="Vertical" />
150151
</Grid>
151152
</controls:Case>
152153
<controls:Case Value="PaletteListBoxItem">
@@ -274,14 +275,14 @@
274275
VerticalAlignment="Center"
275276
AutomationProperties.Name="Red Channel"
276277
Style="{StaticResource InputTextBoxStyle}" />
277-
<controls:ColorPickerSlider x:Name="Channel1Slider"
278-
Grid.Row="2"
279-
Grid.Column="2"
280-
Margin="12,0,0,0"
281-
HorizontalAlignment="Stretch"
282-
VerticalAlignment="Center"
283-
AutomationProperties.Name="Red Channel"
284-
BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Color, Converter={StaticResource ContrastBrushConverter}, ConverterParameter={ThemeResource TextControlForeground}}" />
278+
<primitives:ColorPickerSlider x:Name="Channel1Slider"
279+
Grid.Row="2"
280+
Grid.Column="2"
281+
Margin="12,0,0,0"
282+
HorizontalAlignment="Stretch"
283+
VerticalAlignment="Center"
284+
AutomationProperties.Name="Red Channel"
285+
DefaultForeground="{ThemeResource TextControlForeground}" />
285286
<!-- Channel 2 RGB:Green HSV:Saturation -->
286287
<Border Grid.Row="3"
287288
Grid.Column="0"
@@ -304,14 +305,14 @@
304305
VerticalAlignment="Center"
305306
AutomationProperties.Name="Green Channel"
306307
Style="{StaticResource InputTextBoxStyle}" />
307-
<controls:ColorPickerSlider x:Name="Channel2Slider"
308-
Grid.Row="3"
309-
Grid.Column="2"
310-
Margin="12,0,0,0"
311-
HorizontalAlignment="Stretch"
312-
VerticalAlignment="Center"
313-
AutomationProperties.Name="Green Channel"
314-
BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Color, Converter={StaticResource ContrastBrushConverter}, ConverterParameter={ThemeResource TextControlForeground}}" />
308+
<primitives:ColorPickerSlider x:Name="Channel2Slider"
309+
Grid.Row="3"
310+
Grid.Column="2"
311+
Margin="12,0,0,0"
312+
HorizontalAlignment="Stretch"
313+
VerticalAlignment="Center"
314+
AutomationProperties.Name="Green Channel"
315+
DefaultForeground="{ThemeResource TextControlForeground}" />
315316
<!-- Channel 3 RGB:Blue HSV:Value -->
316317
<Border Grid.Row="4"
317318
Grid.Column="0"
@@ -334,14 +335,14 @@
334335
VerticalAlignment="Center"
335336
AutomationProperties.Name="Blue Channel"
336337
Style="{StaticResource InputTextBoxStyle}" />
337-
<controls:ColorPickerSlider x:Name="Channel3Slider"
338-
Grid.Row="4"
339-
Grid.Column="2"
340-
Margin="12,0,0,0"
341-
HorizontalAlignment="Stretch"
342-
VerticalAlignment="Center"
343-
AutomationProperties.Name="Blue Channel"
344-
BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Color, Converter={StaticResource ContrastBrushConverter}, ConverterParameter={ThemeResource TextControlForeground}}" />
338+
<primitives:ColorPickerSlider x:Name="Channel3Slider"
339+
Grid.Row="4"
340+
Grid.Column="2"
341+
Margin="12,0,0,0"
342+
HorizontalAlignment="Stretch"
343+
VerticalAlignment="Center"
344+
AutomationProperties.Name="Blue Channel"
345+
DefaultForeground="{ThemeResource TextControlForeground}" />
345346
<!-- Alpha channel -->
346347
<Border x:Name="AlphaChannelBorder"
347348
Grid.Row="5"
@@ -365,14 +366,14 @@
365366
VerticalAlignment="Center"
366367
AutomationProperties.Name="Alpha Channel"
367368
Style="{StaticResource InputTextBoxStyle}" />
368-
<controls:ColorPickerSlider x:Name="AlphaChannelSlider"
369-
Grid.Row="5"
370-
Grid.Column="2"
371-
Margin="12,0,0,0"
372-
HorizontalAlignment="Stretch"
373-
VerticalAlignment="Center"
374-
AutomationProperties.Name="Alpha Channel"
375-
BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Color, Converter={StaticResource ContrastBrushConverter}, ConverterParameter={ThemeResource TextControlForeground}}" />
369+
<primitives:ColorPickerSlider x:Name="AlphaChannelSlider"
370+
Grid.Row="5"
371+
Grid.Column="2"
372+
Margin="12,0,0,0"
373+
HorizontalAlignment="Stretch"
374+
VerticalAlignment="Center"
375+
AutomationProperties.Name="Alpha Channel"
376+
DefaultForeground="{ThemeResource TextControlForeground}" />
376377
</Grid>
377378
</controls:Case>
378379
</controls:SwitchPresenter>

Microsoft.Toolkit.Uwp.UI.Controls/ColorPicker/ColorPickerRenderingHelpers.cs

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,24 @@ internal class ColorPickerRenderingHelpers
2828
/// <param name="orientation">The orientation of the resulting bitmap (gradient direction).</param>
2929
/// <param name="colorRepresentation">The color representation being used: RGBA or HSVA.</param>
3030
/// <param name="channel">The specific color channel to vary.</param>
31-
/// <param name="baseRgbColor">The base RGB color used for channels not being changed.</param>
31+
/// <param name="baseHsvColor">The base HSV color used for channels not being changed.</param>
3232
/// <param name="checkerColor">The color of the checker background square.</param>
33+
/// <param name="isAlphaMaxForced">Fix the alpha channel value to maximum during calculation.
34+
/// This will remove any alpha/transparency from the other channel backgrounds.</param>
35+
/// <param name="isSaturationValueMaxForced">Fix the saturation and value channels to maximum
36+
/// during calculation in HSVA color representation.
37+
/// This will ensure colors are always discernible regardless of saturation/value.</param>
3338
/// <returns>A new bitmap representing a gradient of color channel values.</returns>
3439
public static async Task<byte[]> CreateChannelBitmapAsync(
3540
int width,
3641
int height,
3742
Orientation orientation,
3843
ColorRepresentation colorRepresentation,
3944
ColorChannel channel,
40-
Color baseRgbColor,
41-
Color? checkerColor)
45+
HsvColor baseHsvColor,
46+
Color? checkerColor,
47+
bool isAlphaMaxForced,
48+
bool isSaturationValueMaxForced)
4249
{
4350
if (width == 0 || height == 0)
4451
{
@@ -51,7 +58,7 @@ public static async Task<byte[]> CreateChannelBitmapAsync(
5158
double channelStep;
5259
byte[] bgraPixelData;
5360
byte[] bgraCheckeredPixelData = null;
54-
HsvColor baseHsvColor;
61+
Color baseRgbColor = Colors.White;
5562
Color rgbColor;
5663
int bgraPixelDataHeight;
5764
int bgraPixelDataWidth;
@@ -62,14 +69,64 @@ public static async Task<byte[]> CreateChannelBitmapAsync(
6269
bgraPixelDataHeight = height * 4;
6370
bgraPixelDataWidth = width * 4;
6471

65-
// Convert RGB to HSV once
66-
if (colorRepresentation == ColorRepresentation.Hsva)
72+
// Maximize alpha channel value
73+
if (isAlphaMaxForced &&
74+
channel != ColorChannel.Alpha)
6775
{
68-
baseHsvColor = baseRgbColor.ToHsv();
76+
baseHsvColor = new HsvColor()
77+
{
78+
H = baseHsvColor.H,
79+
S = baseHsvColor.S,
80+
V = baseHsvColor.V,
81+
A = 1.0
82+
};
6983
}
70-
else
84+
85+
// Convert HSV to RGB once
86+
if (colorRepresentation == ColorRepresentation.Rgba)
87+
{
88+
baseRgbColor = Uwp.Helpers.ColorHelper.FromHsv(
89+
baseHsvColor.H,
90+
baseHsvColor.S,
91+
baseHsvColor.V,
92+
baseHsvColor.A);
93+
}
94+
95+
// Maximize Saturation and Value channels when in HSVA mode
96+
if (isSaturationValueMaxForced &&
97+
colorRepresentation == ColorRepresentation.Hsva &&
98+
channel != ColorChannel.Alpha)
7199
{
72-
baseHsvColor = Colors.White.ToHsv();
100+
switch (channel)
101+
{
102+
case ColorChannel.Channel1:
103+
baseHsvColor = new HsvColor()
104+
{
105+
H = baseHsvColor.H,
106+
S = 1.0,
107+
V = 1.0,
108+
A = baseHsvColor.A
109+
};
110+
break;
111+
case ColorChannel.Channel2:
112+
baseHsvColor = new HsvColor()
113+
{
114+
H = baseHsvColor.H,
115+
S = baseHsvColor.S,
116+
V = 1.0,
117+
A = baseHsvColor.A
118+
};
119+
break;
120+
case ColorChannel.Channel3:
121+
baseHsvColor = new HsvColor()
122+
{
123+
H = baseHsvColor.H,
124+
S = 1.0,
125+
V = baseHsvColor.V,
126+
A = baseHsvColor.A
127+
};
128+
break;
129+
}
73130
}
74131

75132
// Create a checkered background

0 commit comments

Comments
 (0)