diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerButtonXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerButtonXaml.bind index 8a84e01b04e..939f067a2b3 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerButtonXaml.bind +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerButtonXaml.bind @@ -10,19 +10,11 @@ - - - - - - - - - + + - - - + - - - + - - - + + + + + Ring-shaped spectrum + Alpha channel enabled + Only Color Palette Shown + + + + + + + - + \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerXaml.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerXaml.bind index 59d3454d6c0..1502d4ad1f0 100644 --- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerXaml.bind +++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/ColorPicker/ColorPickerXaml.bind @@ -60,7 +60,7 @@ Alpha channel enabled - - + + + + Ring-shaped spectrum + Alpha channel enabled + Only Color Palette Shown + + + \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.Properties.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.Properties.cs index 1c6e2cdd469..641e83131f5 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.Properties.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.Properties.cs @@ -20,7 +20,9 @@ public partial class ColorPicker nameof(CustomPaletteColors), typeof(ObservableCollection), typeof(ColorPicker), - new PropertyMetadata(null)); + new PropertyMetadata( + null, + (s, e) => (s as ColorPicker)?.OnDependencyPropertyChanged(s, e))); /// /// Gets the list of custom palette colors. @@ -38,7 +40,9 @@ public ObservableCollection CustomPaletteColors nameof(CustomPaletteColumnCount), typeof(int), typeof(ColorPicker), - new PropertyMetadata(4)); + new PropertyMetadata( + 4, + (s, e) => (s as ColorPicker)?.OnDependencyPropertyChanged(s, e))); /// /// Gets or sets the number of colors in each row (section) of the custom color palette. @@ -64,7 +68,9 @@ public int CustomPaletteColumnCount nameof(CustomPalette), typeof(IColorPalette), typeof(ColorPicker), - new PropertyMetadata(null)); + new PropertyMetadata( + null, + (s, e) => (s as ColorPicker)?.OnDependencyPropertyChanged(s, e))); /// /// Gets or sets the custom color palette. @@ -91,7 +97,9 @@ public IColorPalette CustomPalette nameof(IsColorPaletteVisible), typeof(bool), typeof(ColorPicker), - new PropertyMetadata(true)); + new PropertyMetadata( + true, + (s, e) => (s as ColorPicker)?.OnDependencyPropertyChanged(s, e))); /// /// Gets or sets a value indicating whether the color palette is visible. diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.cs index 12a20c8f4cc..7a22dbc8f70 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.cs @@ -40,6 +40,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls [TemplatePart(Name = nameof(ColorPicker.CheckeredBackground8Border), Type = typeof(Border))] [TemplatePart(Name = nameof(ColorPicker.CheckeredBackground9Border), Type = typeof(Border))] [TemplatePart(Name = nameof(ColorPicker.CheckeredBackground10Border), Type = typeof(Border))] + [TemplatePart(Name = nameof(ColorPicker.ColorPanelSelector), Type = typeof(ListBox))] [TemplatePart(Name = nameof(ColorPicker.ColorSpectrumControl), Type = typeof(ColorSpectrum))] [TemplatePart(Name = nameof(ColorPicker.ColorSpectrumAlphaSlider), Type = typeof(ColorPickerSlider))] [TemplatePart(Name = nameof(ColorPicker.ColorSpectrumThirdDimensionSlider), Type = typeof(ColorPickerSlider))] @@ -65,8 +66,6 @@ public partial class ColorPicker : Microsoft.UI.Xaml.Controls.ColorPicker private const int ColorUpdateInterval = 30; // Milliseconds private long tokenColor; - private long tokenCustomPalette; - private long tokenIsColorPaletteVisible; private bool callbacksConnected = false; private bool eventsConnected = false; @@ -78,6 +77,7 @@ public partial class ColorPicker : Microsoft.UI.Xaml.Controls.ColorPicker private Color? updatedRgbColor = null; private DispatcherQueueTimer dispatcherQueueTimer = null; + private ListBox ColorPanelSelector; private ColorSpectrum ColorSpectrumControl; private ColorPickerSlider ColorSpectrumAlphaSlider; private ColorPickerSlider ColorSpectrumThirdDimensionSlider; @@ -177,6 +177,8 @@ protected override void OnApplyTemplate() // We need to disconnect old events first this.ConnectEvents(false); + this.ColorPanelSelector = this.GetTemplateChild(nameof(ColorPanelSelector)); + this.ColorSpectrumControl = this.GetTemplateChild(nameof(ColorSpectrumControl)); this.ColorSpectrumAlphaSlider = this.GetTemplateChild(nameof(ColorSpectrumAlphaSlider)); this.ColorSpectrumThirdDimensionSlider = this.GetTemplateChild(nameof(ColorSpectrumThirdDimensionSlider)); @@ -216,6 +218,7 @@ protected override void OnApplyTemplate() base.OnApplyTemplate(); this.UpdateVisualState(false); + this.ValidateSelectedPanel(); this.isInitialized = true; this.SetActiveColorRepresentation(ColorRepresentation.Rgba); this.UpdateColorControlValues(); // TODO: This will also connect events after, can we optimize vs. doing it twice with the ConnectEvents above? @@ -247,23 +250,19 @@ private T GetTemplateChild(string childName, bool isRequired = false) /// True to connect callbacks, otherwise false. private void ConnectCallbacks(bool connected) { - if ((connected == true) && - (this.callbacksConnected == false)) + if (connected == true && + this.callbacksConnected == false) { // Add callbacks for dependency properties - this.tokenColor = this.RegisterPropertyChangedCallback(ColorProperty, OnColorChanged); - this.tokenCustomPalette = this.RegisterPropertyChangedCallback(CustomPaletteProperty, OnCustomPaletteChanged); - this.tokenIsColorPaletteVisible = this.RegisterPropertyChangedCallback(IsColorPaletteVisibleProperty, OnIsColorPaletteVisibleChanged); + this.tokenColor = this.RegisterPropertyChangedCallback(ColorProperty, OnColorChanged); this.callbacksConnected = true; } - else if ((connected == false) && - (this.callbacksConnected == true)) + else if (connected == false && + this.callbacksConnected == true) { // Remove callbacks for dependency properties - this.UnregisterPropertyChangedCallback(ColorProperty, this.tokenColor); - this.UnregisterPropertyChangedCallback(CustomPaletteProperty, this.tokenCustomPalette); - this.UnregisterPropertyChangedCallback(IsColorPaletteVisibleProperty, this.tokenIsColorPaletteVisible); + this.UnregisterPropertyChangedCallback(ColorProperty, this.tokenColor); this.callbacksConnected = false; } @@ -277,8 +276,8 @@ private void ConnectCallbacks(bool connected) /// True to connect event handlers, otherwise false. private void ConnectEvents(bool connected) { - if ((connected == true) && - (this.eventsConnected == false)) + if (connected == true && + this.eventsConnected == false) { // Add all events if (this.ColorSpectrumControl != null) { this.ColorSpectrumControl.ColorChanged += ColorSpectrum_ColorChanged; } @@ -331,8 +330,8 @@ private void ConnectEvents(bool connected) this.eventsConnected = true; } - else if ((connected == false) && - (this.eventsConnected == true)) + else if (connected == false && + this.eventsConnected == true) { // Remove all events if (this.ColorSpectrumControl != null) { this.ColorSpectrumControl.ColorChanged -= ColorSpectrum_ColorChanged; } @@ -1065,6 +1064,83 @@ private void SetDefaultPalette() return; } + /// + /// Validates and updates the current 'tab' or 'panel' selection. + /// If the currently selected tab is collapsed, the next visible tab will be selected. + /// + private void ValidateSelectedPanel() + { + object selectedItem = null; + + if (this.ColorPanelSelector != null) + { + if (this.ColorPanelSelector.SelectedItem == null && + this.ColorPanelSelector.Items.Count > 0) + { + // As a failsafe, forcefully select the first item + selectedItem = this.ColorPanelSelector.Items[0]; + } + else + { + selectedItem = this.ColorPanelSelector.SelectedItem; + } + + if (selectedItem is UIElement selectedElement && + selectedElement.Visibility == Visibility.Collapsed) + { + // Select the first visible item instead + foreach (object item in this.ColorPanelSelector.Items) + { + if (item is UIElement element && + element.Visibility == Visibility.Visible) + { + selectedItem = item; + break; + } + } + } + + this.ColorPanelSelector.SelectedItem = selectedItem; + } + + return; + } + + private void OnDependencyPropertyChanged(object sender, DependencyPropertyChangedEventArgs args) + { + DependencyObject senderControl = sender as DependencyObject; + + /* Note: ColorProperty is defined in the base class and cannot be used here + * See the OnColorChanged callback below + */ + + if (object.ReferenceEquals(args.Property, CustomPaletteProperty)) + { + IColorPalette palette = this.CustomPalette; + + if (palette != null) + { + this.CustomPaletteColumnCount = palette.ColorCount; + this.CustomPaletteColors.Clear(); + + for (int shadeIndex = 0; shadeIndex < palette.ShadeCount; shadeIndex++) + { + for (int colorIndex = 0; colorIndex < palette.ColorCount; colorIndex++) + { + this.CustomPaletteColors.Add(palette.GetColor(colorIndex, shadeIndex)); + } + } + } + } + else if (object.ReferenceEquals(args.Property, IsColorPaletteVisibleProperty)) + { + this.UpdateVisualState(false); + this.ValidateSelectedPanel(); + } + + return; + } + /*************************************************************************************** * * Color Update Timer @@ -1147,39 +1223,6 @@ private void OnColorChanged(DependencyObject d, DependencyProperty e) return; } - /// - /// Callback for when the dependency property value changes. - /// - private void OnCustomPaletteChanged(DependencyObject d, DependencyProperty e) - { - IColorPalette palette = this.CustomPalette; - - if (palette != null) - { - this.CustomPaletteColumnCount = palette.ColorCount; - this.CustomPaletteColors.Clear(); - - for (int shadeIndex = 0; shadeIndex < palette.ShadeCount; shadeIndex++) - { - for (int colorIndex = 0; colorIndex < palette.ColorCount; colorIndex++) - { - this.CustomPaletteColors.Add(palette.GetColor(colorIndex, shadeIndex)); - } - } - } - - return; - } - - /// - /// Callback for when the dependency property value changes. - /// - private void OnIsColorPaletteVisibleChanged(DependencyObject d, DependencyProperty e) - { - this.UpdateVisualState(false); - return; - } - /*************************************************************************************** * * Event Handling diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.xaml b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.xaml index 370be9af979..3641acb2e3c 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.xaml +++ b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPicker.xaml @@ -69,12 +69,13 @@ CornerRadius="4" /> - + - - - diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPickerSlider.Properties.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPickerSlider.Properties.cs index bf99d884dfd..2a0471a420a 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPickerSlider.Properties.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPickerSlider.Properties.cs @@ -104,7 +104,7 @@ public ColorRepresentation ColorRepresentation typeof(Brush), typeof(ColorPickerSlider), new PropertyMetadata( - new SolidColorBrush(Colors.Gray), + null, (s, e) => (s as ColorPickerSlider)?.OnDependencyPropertyChanged(s, e))); /// diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPickerSlider.xaml b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPickerSlider.xaml index 439e7040f2b..51027d2d0be 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPickerSlider.xaml +++ b/Microsoft.Toolkit.Uwp.UI.Controls.Input/ColorPicker/ColorPickerSlider.xaml @@ -9,6 +9,7 @@ TargetType="controls:ColorPickerSlider"> +