From 6d10a6e4b0676e8c7418543f33b831c07fa1b951 Mon Sep 17 00:00:00 2001 From: brianlagunas_cp Date: Sun, 15 Aug 2010 05:21:48 +0000 Subject: [PATCH] Initial checkin of new ColorPicker control --- .../ColorPicker/ColorPicker.cs | 389 ++++++++++++++++++ .../ColorPicker/ColorPicker.xaml | 367 +++++++++++++++++ .../ColorPicker/ColorSpectrumSlider.cs | 85 ++++ .../ColorPicker/ColorUtilities.cs | 156 +++++++ .../ColorPicker/HsvColor.cs | 18 + .../WPFToolkit.Extended/Themes/Generic.xaml | 363 ++++++++++++++++ .../WPFToolkit.Extended.csproj | 8 + 7 files changed, 1386 insertions(+) create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.cs create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.xaml create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorSpectrumSlider.cs create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorUtilities.cs create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/HsvColor.cs diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.cs new file mode 100644 index 00000000..19e55bcb --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.cs @@ -0,0 +1,389 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Controls.Primitives; + +namespace Microsoft.Windows.Controls +{ + public class ColorPicker : Control + { + #region Private Members + + ToggleButton _colorPickerToggleButton; + Popup _colorPickerCanvasPopup; + Button _okButton; + private TranslateTransform _colorShadeSelectorTransform = new TranslateTransform(); + private Canvas _colorShadingCanvas; + private Canvas _colorShadeSelector; + private ColorSpectrumSlider _spectrumSlider; + private Point? _currentColorPosition; + private Color _currentColor = Colors.White; + + #endregion //Private Members + + #region Constructors + + static ColorPicker() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker))); + } + + public ColorPicker() + { + + } + + #endregion //Constructors + + #region Properties + + public static readonly DependencyProperty CurrentColorProperty = DependencyProperty.Register("CurrentColor", typeof(Color), typeof(ColorPicker), new PropertyMetadata(Colors.White)); + public Color CurrentColor + { + get { return (Color)GetValue(CurrentColorProperty); } + set { SetValue(CurrentColorProperty, value); } + } + + #region SelectedColor + + public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorPicker), new FrameworkPropertyMetadata(Colors.White, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(SelectedColorPropertyChanged))); + public Color SelectedColor + { + get { return (Color)GetValue(SelectedColorProperty); } + set { SetValue(SelectedColorProperty, value); } + } + + private static void SelectedColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker colorPicker = (ColorPicker)d; + colorPicker.SetSelectedColor((Color)e.NewValue); + } + + #endregion //SelectedColor + + #region ScRGB + + #region ScA + + public static readonly DependencyProperty ScAProperty = DependencyProperty.Register("ScA", typeof(float), typeof(ColorPicker), new PropertyMetadata((float)1, new PropertyChangedCallback(OnScAPropertyChangedChanged))); + public double ScA + { + get { return (double)GetValue(ScAProperty); } + set { SetValue(ScAProperty, value); } + } + + private static void OnScAPropertyChangedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker c = (ColorPicker)d; + c.SetScA((float)e.NewValue); + } + + protected virtual void SetScA(float newValue) + { + _currentColor.ScA = newValue; + A = _currentColor.A; + CurrentColor = _currentColor; + HexadecimalString = _currentColor.ToString(); + } + + #endregion //ScA + + #region ScR + + public static readonly DependencyProperty ScRProperty = DependencyProperty.Register("ScR", typeof(float), typeof(ColorPicker), new PropertyMetadata((float)1, new PropertyChangedCallback(ScRChanged))); + public double ScR + { + get { return (double)GetValue(ScRProperty); } + set { SetValue(RProperty, value); } + } + + private static void ScRChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + + } + + #endregion //ScR + + #region ScG + + public static readonly DependencyProperty ScGProperty = DependencyProperty.Register("ScG", typeof(float), typeof(ColorPicker), new PropertyMetadata((float)1, new PropertyChangedCallback(ScGChanged))); + public double ScG + { + get { return (double)GetValue(ScGProperty); } + set { SetValue(GProperty, value); } + } + + private static void ScGChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + + } + + #endregion //ScG + + #region ScB + + public static readonly DependencyProperty ScBProperty = DependencyProperty.Register("ScB", typeof(float), typeof(ColorPicker), new PropertyMetadata((float)1, new PropertyChangedCallback(OnScBPropertyChanged))); + public double ScB + { + get { return (double)GetValue(BProperty); } + set { SetValue(BProperty, value); } + } + + private static void OnScBPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + + } + + #endregion //ScB + + #endregion //ScRGB + + #region RGB + + #region A + + public static readonly DependencyProperty AProperty = DependencyProperty.Register("A", typeof(byte), typeof(ColorPicker), new PropertyMetadata((byte)255, new PropertyChangedCallback(OnAPropertyChanged))); + public byte A + { + get { return (byte)GetValue(AProperty); } + set { SetValue(AProperty, value); } + } + + private static void OnAPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ColorPicker c = (ColorPicker)d; + c.SetA((byte)e.NewValue); + } + + protected virtual void SetA(byte newValue) + { + _currentColor.A = newValue; + SetValue(CurrentColorProperty, _currentColor); + } + + #endregion //A + + #region R + + public static readonly DependencyProperty RProperty = DependencyProperty.Register("R", typeof(byte), typeof(ColorPicker), new PropertyMetadata((byte)255, new PropertyChangedCallback(OnRPropertyChanged))); + public byte R + { + get { return (byte)GetValue(RProperty); } + set { SetValue(RProperty, value); } + } + + private static void OnRPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + + } + + #endregion //R + + #region G + + public static readonly DependencyProperty GProperty = DependencyProperty.Register("G", typeof(byte), typeof(ColorPicker), new PropertyMetadata((byte)255, new PropertyChangedCallback(OnGPropertyChanged))); + public byte G + { + get { return (byte)GetValue(GProperty); } + set { SetValue(GProperty, value); } + } + + private static void OnGPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + + } + + #endregion //G + + #region B + + public static readonly DependencyProperty BProperty = DependencyProperty.Register("B", typeof(byte), typeof(ColorPicker), new PropertyMetadata((byte)255, new PropertyChangedCallback(OnBPropertyChanged))); + public byte B + { + get { return (byte)GetValue(BProperty); } + set { SetValue(BProperty, value); } + } + + private static void OnBPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + + } + + #endregion //B + + #endregion //RGB + + #region HexadecimalString + + public static readonly DependencyProperty HexadecimalStringProperty = DependencyProperty.Register("HexadecimalString", typeof(string), typeof(ColorPicker), new PropertyMetadata("#FFFFFFFF", new PropertyChangedCallback(OnHexadecimalStringPropertyChanged))); + public string HexadecimalString + { + get { return (string)GetValue(HexadecimalStringProperty); } + set { SetValue(HexadecimalStringProperty, value); } + } + + private static void OnHexadecimalStringPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + + } + + #endregion //HexadecimalString + + #endregion //Properties + + #region Base Class Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _colorPickerToggleButton = (ToggleButton)GetTemplateChild("PART_ColorPickerToggleButton"); + _colorPickerToggleButton.Click += ColorPickerToggleButton_Clicked; + + _colorPickerCanvasPopup = (Popup)GetTemplateChild("PART_ColorPickerCanvasPopup"); + + _colorShadingCanvas = (Canvas)GetTemplateChild("PART_ColorShadingCanvas"); + _colorShadingCanvas.MouseLeftButtonDown += ColorShadingCanvas_MouseLeftButtonDown; + _colorShadingCanvas.MouseMove += ColorShadingCanvas_MouseMove; + _colorShadingCanvas.SizeChanged += ColorShadingCanvas_SizeChanged; + + _colorShadeSelector = (Canvas)GetTemplateChild("PART_ColorShadeSelector"); + _colorShadeSelector.RenderTransform = _colorShadeSelectorTransform; + + _spectrumSlider = (ColorSpectrumSlider)GetTemplateChild("PART_SpectrumSlider"); + _spectrumSlider.ValueChanged += SpectrumSlider_ValueChanged; + + _okButton = (Button)GetTemplateChild("PART_OkButton"); + _okButton.Click += OkButton_Click; + } + + #endregion //Base Class Overrides + + #region Event Handlers + + void ColorShadingCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + Point p = e.GetPosition(_colorShadingCanvas); + UpdateColorShadeSelectorPositionAndCalculateColor(p); + } + + void ColorShadingCanvas_MouseMove(object sender, MouseEventArgs e) + { + if (e.LeftButton == MouseButtonState.Pressed) + { + Point p = e.GetPosition(_colorShadingCanvas); + UpdateColorShadeSelectorPositionAndCalculateColor(p); + Mouse.Synchronize(); + } + } + + void ColorShadingCanvas_SizeChanged(object sender, SizeChangedEventArgs e) + { + if (_currentColorPosition != null) + { + Point _newPoint = new Point + { + X = ((Point)_currentColorPosition).X * e.NewSize.Width, + Y = ((Point)_currentColorPosition).Y * e.NewSize.Height + }; + + UpdateColorShadeSelectorPositionAndCalculateColor(_newPoint, false); + } + } + + void SpectrumSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) + { + if (_currentColorPosition != null) + { + CalculateColor((Point)_currentColorPosition); + } + } + + void OkButton_Click(object sender, RoutedEventArgs e) + { + if (_colorPickerCanvasPopup.IsOpen || _colorPickerToggleButton.IsChecked == true) + { + CloseColorPicker(); + SelectedColor = CurrentColor; + } + } + + void ColorPickerToggleButton_Clicked(object sender, RoutedEventArgs e) + { + _colorPickerCanvasPopup.IsOpen = _colorPickerToggleButton.IsChecked ?? false; + } + + #endregion //Event Handlers + + #region Methods + + private void CloseColorPicker() + { + _colorPickerToggleButton.IsChecked = false; + _colorPickerCanvasPopup.IsOpen = false; + } + + private void SetSelectedColor(Color theColor) + { + _currentColor = theColor; + SetValue(AProperty, _currentColor.A); + SetValue(RProperty, _currentColor.R); + SetValue(GProperty, _currentColor.G); + SetValue(BProperty, _currentColor.B); + UpdateColorShadeSelectorPosition(theColor); + } + + private void UpdateColorShadeSelectorPositionAndCalculateColor(Point p, bool calculateColor = true) + { + if (p.Y < 0) + p.Y = 0; + + if (p.X < 0) + p.X = 0; + + if (p.X > _colorShadingCanvas.ActualWidth) + p.X = _colorShadingCanvas.ActualWidth; + + if (p.Y > _colorShadingCanvas.ActualHeight) + p.Y = _colorShadingCanvas.ActualHeight; + + _colorShadeSelectorTransform.X = p.X - (_colorShadeSelector.Width / 2); + _colorShadeSelectorTransform.Y = p.Y - (_colorShadeSelector.Height / 2); + + p.X = p.X / _colorShadingCanvas.ActualWidth; + p.Y = p.Y / _colorShadingCanvas.ActualHeight; + + _currentColorPosition = p; + + CalculateColor(p); + } + + private void UpdateColorShadeSelectorPosition(Color color) + { + _currentColorPosition = null; + + HsvColor hsv = ColorUtilities.ConvertRgbToHsv(color.R, color.G, color.B); + _spectrumSlider.Value = hsv.H; + + Point p = new Point(hsv.S, 1 - hsv.V); + + _currentColorPosition = p; + + _colorShadeSelectorTransform.X = p.X * _colorShadingCanvas.Width; + _colorShadeSelectorTransform.Y = p.Y * _colorShadingCanvas.Height; + } + + private void CalculateColor(Point p) + { + HsvColor hsv = new HsvColor(360 - _spectrumSlider.Value, 1, 1) { S = p.X, V = 1 - p.Y }; + _currentColor = ColorUtilities.ConvertHsvToRgb(hsv.H, hsv.S, hsv.V); ; + _currentColor.ScA = (float)GetValue(ScAProperty); + CurrentColor = _currentColor; + SetValue(HexadecimalStringProperty, _currentColor.ToString()); + } + + #endregion //Methods + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.xaml new file mode 100644 index 00000000..7b07bb77 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorPicker.xaml @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorSpectrumSlider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorSpectrumSlider.cs new file mode 100644 index 00000000..c4eac2d8 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorSpectrumSlider.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Shapes; + +namespace Microsoft.Windows.Controls +{ + internal class ColorSpectrumSlider : Slider + { + #region Private Members + + private Rectangle _spectrumDisplay; + private LinearGradientBrush _pickerBrush; + + #endregion //Private Members + + #region Constructors + + static ColorSpectrumSlider() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorSpectrumSlider), new FrameworkPropertyMetadata(typeof(ColorSpectrumSlider))); + } + + #endregion //Constructors + + #region Dependency Properties + + public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorSpectrumSlider), new PropertyMetadata(System.Windows.Media.Colors.Transparent)); + public Color SelectedColor + { + get { return (Color)GetValue(SelectedColorProperty); } + set { SetValue(SelectedColorProperty, value); } + } + + #endregion //Dependency Properties + + #region Base Class Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _spectrumDisplay = (Rectangle)GetTemplateChild("PART_SpectrumDisplay"); + CreateSpectrum(); + OnValueChanged(Double.NaN, Value); + } + + protected override void OnValueChanged(double oldValue, double newValue) + { + base.OnValueChanged(oldValue, newValue); + + Color color = ColorUtilities.ConvertHsvToRgb(360 - newValue, 1, 1); + SelectedColor = color; + } + + #endregion //Base Class Overrides + + #region Methods + + private void CreateSpectrum() + { + _pickerBrush = new LinearGradientBrush(); + _pickerBrush.StartPoint = new Point(0.5, 0); + _pickerBrush.EndPoint = new Point(0.5, 1); + _pickerBrush.ColorInterpolationMode = ColorInterpolationMode.SRgbLinearInterpolation; + + List colorsList = ColorUtilities.GenerateHsvSpectrum(); + + double stopIncrement = (double)1 / colorsList.Count; + + int i; + for (i = 0; i < colorsList.Count; i++) + { + _pickerBrush.GradientStops.Add(new GradientStop(colorsList[i], i * stopIncrement)); + } + + _pickerBrush.GradientStops[i - 1].Offset = 1.0; + _spectrumDisplay.Fill = _pickerBrush; + } + + #endregion //Methods + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorUtilities.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorUtilities.cs new file mode 100644 index 00000000..e621c22b --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/ColorUtilities.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Windows.Media; + +namespace Microsoft.Windows.Controls +{ + internal static class ColorUtilities + { + /// + /// Converts an RGB color to an HSV color. + /// + /// + /// + /// + /// + public static HsvColor ConvertRgbToHsv(int r, int b, int g) + { + double delta, min; + double h = 0, s, v; + + min = Math.Min(Math.Min(r, g), b); + v = Math.Max(Math.Max(r, g), b); + delta = v - min; + + if (v == 0.0) + { + s = 0; + } + else + s = delta / v; + + if (s == 0) + h = 0.0; + + else + { + if (r == v) + h = (g - b) / delta; + else if (g == v) + h = 2 + (b - r) / delta; + else if (b == v) + h = 4 + (r - g) / delta; + + h *= 60; + if (h < 0.0) + h = h + 360; + + } + + return new HsvColor { H = h, S = s, V = v / 255 }; + } + + /// + /// Converts an HSV color to an RGB color. + /// + /// + /// + /// + /// + public static Color ConvertHsvToRgb(double h, double s, double v) + { + double r = 0, g = 0, b = 0; + + if (s == 0) + { + r = v; + g = v; + b = v; + } + else + { + int i; + double f, p, q, t; + + if (h == 360) + h = 0; + else + h = h / 60; + + i = (int)Math.Truncate(h); + f = h - i; + + p = v * (1.0 - s); + q = v * (1.0 - (s * f)); + t = v * (1.0 - (s * (1.0 - f))); + + switch (i) + { + case 0: + { + r = v; + g = t; + b = p; + break; + } + case 1: + { + r = q; + g = v; + b = p; + break; + } + case 2: + { + r = p; + g = v; + b = t; + break; + } + case 3: + { + r = p; + g = q; + b = v; + break; + } + case 4: + { + r = t; + g = p; + b = v; + break; + } + default: + { + r = v; + g = p; + b = q; + break; + } + } + + } + + return Color.FromArgb(255, (byte)(r * 255), (byte)(g * 255), (byte)(b * 255)); + } + + /// + /// Generates a list of colors with hues ranging from 0 360 and a saturation and value of 1. + /// + /// + public static List GenerateHsvSpectrum() + { + List colorsList = new List(8); + + for (int i = 0; i < 29; i++) + { + colorsList.Add(ColorUtilities.ConvertHsvToRgb(i * 12, 1, 1)); + } + + colorsList.Add(ColorUtilities.ConvertHsvToRgb(0, 1, 1)); + + return colorsList; + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/HsvColor.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/HsvColor.cs new file mode 100644 index 00000000..eed5c3bd --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/HsvColor.cs @@ -0,0 +1,18 @@ +using System; + +namespace Microsoft.Windows.Controls +{ + internal struct HsvColor + { + public double H; + public double S; + public double V; + + public HsvColor(double h, double s, double v) + { + H = h; + S = s; + V = v; + } + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml index 8ba81fbd..2250ce15 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml @@ -612,4 +612,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj index fac27c96..7c5cf251 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj @@ -61,6 +61,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -74,6 +78,10 @@ + + + + Code