From a030fcd934bb4d511031ba58e2676d1d0b287193 Mon Sep 17 00:00:00 2001 From: brianlagunas_cp Date: Tue, 15 Mar 2011 22:40:22 +0000 Subject: [PATCH] initial checkin of new ColorCanvas control. This is an advanced color control that is not within a popup, but acts as a stand alone control that allows you to select colors by using a color canvas, or by setting RGB and Alpha values. --- .../ColorCanvas/Implementation/ColorCanvas.cs | 413 ++++++++++++++++++ .../Implementation/ColorSpectrumSlider.cs | 86 ++++ .../ColorCanvas/Themes/Generic.xaml | 234 ++++++++++ .../ColorPicker/Implementation/ColorPicker.cs | 70 +++ .../Implementation/ColorUtilities.cs | 24 - .../ColorPicker/Themes/Generic.xaml | 7 +- .../SolidColorBrushToColorConverter.cs | 33 ++ .../Core/Primitives/HsvColor.cs | 18 + .../Core/Utilities/ColorUtilities.cs | 172 ++++++++ .../PropertyGrid/Themes/Generic.xaml | 2 +- .../WPFToolkit.Extended/Themes/Generic.xaml | 4 +- .../WPFToolkit.Extended.csproj | 10 +- 12 files changed, 1042 insertions(+), 31 deletions(-) create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorCanvas.cs create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorSpectrumSlider.cs create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Themes/Generic.xaml delete mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorUtilities.cs create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Converters/SolidColorBrushToColorConverter.cs create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/HsvColor.cs create mode 100644 ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ColorUtilities.cs diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorCanvas.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorCanvas.cs new file mode 100644 index 00000000..2b922d02 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorCanvas.cs @@ -0,0 +1,413 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using Microsoft.Windows.Controls.Primitives; +using Microsoft.Windows.Controls.Core.Utilities; + +namespace Microsoft.Windows.Controls +{ + public class ColorCanvas : Control + { + #region Private Members + + private TranslateTransform _colorShadeSelectorTransform = new TranslateTransform(); + private Canvas _colorShadingCanvas; + private Canvas _colorShadeSelector; + private ColorSpectrumSlider _spectrumSlider; + private Point? _currentColorPosition; + + #endregion //Private Members + + #region Properties + + #region SelectedColor + + public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorCanvas), new UIPropertyMetadata(Colors.White, OnSelectedColorChanged)); + public Color SelectedColor + { + get { return (Color)GetValue(SelectedColorProperty); } + set { SetValue(SelectedColorProperty, value); } + } + + private static void OnSelectedColorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + ColorCanvas colorCanvas = o as ColorCanvas; + if (colorCanvas != null) + colorCanvas.OnSelectedColorChanged((Color)e.OldValue, (Color)e.NewValue); + } + + protected virtual void OnSelectedColorChanged(Color oldValue, Color newValue) + { + UpdateRGBValues(newValue); + } + + #endregion //SelectedColor + + #region RGB + + #region A + + public static readonly DependencyProperty AProperty = DependencyProperty.Register("A", typeof(byte), typeof(ColorCanvas), new UIPropertyMetadata((byte)255, new PropertyChangedCallback(OnAChanged), new CoerceValueCallback(OnCoerceA))); + + private static object OnCoerceA(DependencyObject o, object value) + { + ColorCanvas colorCanvas = o as ColorCanvas; + if (colorCanvas != null) + return colorCanvas.OnCoerceA((byte)value); + else + return value; + } + + private static void OnAChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + ColorCanvas colorCanvas = o as ColorCanvas; + if (colorCanvas != null) + colorCanvas.OnAChanged((byte)e.OldValue, (byte)e.NewValue); + } + + protected virtual byte OnCoerceA(byte value) + { + // TODO: Keep the proposed value within the desired range. + return value; + } + + protected virtual void OnAChanged(byte oldValue, byte newValue) + { + UpdateRGBColor(); + } + + public byte A + { + // IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property! + get + { + return (byte)GetValue(AProperty); + } + set + { + SetValue(AProperty, value); + } + } + + #endregion //A + + #region R + + public static readonly DependencyProperty RProperty = DependencyProperty.Register("R", typeof(byte), typeof(ColorCanvas), new UIPropertyMetadata((byte)255, new PropertyChangedCallback(OnRChanged), new CoerceValueCallback(OnCoerceR))); + + private static object OnCoerceR(DependencyObject o, object value) + { + ColorCanvas colorCanvas = o as ColorCanvas; + if (colorCanvas != null) + return colorCanvas.OnCoerceR((byte)value); + else + return value; + } + + private static void OnRChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + ColorCanvas colorCanvas = o as ColorCanvas; + if (colorCanvas != null) + colorCanvas.OnRChanged((byte)e.OldValue, (byte)e.NewValue); + } + + protected virtual byte OnCoerceR(byte value) + { + // TODO: Keep the proposed value within the desired range. + return value; + } + + protected virtual void OnRChanged(byte oldValue, byte newValue) + { + UpdateRGBColor(); + } + + public byte R + { + // IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property! + get + { + return (byte)GetValue(RProperty); + } + set + { + SetValue(RProperty, value); + } + } + + + #endregion //R + + #region G + + public static readonly DependencyProperty GProperty = DependencyProperty.Register("G", typeof(byte), typeof(ColorCanvas), new UIPropertyMetadata((byte)255, new PropertyChangedCallback(OnGChanged), new CoerceValueCallback(OnCoerceG))); + + private static object OnCoerceG(DependencyObject o, object value) + { + ColorCanvas colorCanvas = o as ColorCanvas; + if (colorCanvas != null) + return colorCanvas.OnCoerceG((byte)value); + else + return value; + } + + private static void OnGChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + ColorCanvas colorCanvas = o as ColorCanvas; + if (colorCanvas != null) + colorCanvas.OnGChanged((byte)e.OldValue, (byte)e.NewValue); + } + + protected virtual byte OnCoerceG(byte value) + { + // TODO: Keep the proposed value within the desired range. + return value; + } + + protected virtual void OnGChanged(byte oldValue, byte newValue) + { + UpdateRGBColor(); + } + + public byte G + { + // IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property! + get + { + return (byte)GetValue(GProperty); + } + set + { + SetValue(GProperty, value); + } + } + + + #endregion //G + + #region B + + public static readonly DependencyProperty BProperty = DependencyProperty.Register("B", typeof(byte), typeof(ColorCanvas), new UIPropertyMetadata((byte)255, new PropertyChangedCallback(OnBChanged), new CoerceValueCallback(OnCoerceB))); + + private static object OnCoerceB(DependencyObject o, object value) + { + ColorCanvas colorCanvas = o as ColorCanvas; + if (colorCanvas != null) + return colorCanvas.OnCoerceB((byte)value); + else + return value; + } + + private static void OnBChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + ColorCanvas colorCanvas = o as ColorCanvas; + if (colorCanvas != null) + colorCanvas.OnBChanged((byte)e.OldValue, (byte)e.NewValue); + } + + protected virtual byte OnCoerceB(byte value) + { + // TODO: Keep the proposed value within the desired range. + return value; + } + + protected virtual void OnBChanged(byte oldValue, byte newValue) + { + UpdateRGBColor(); + } + + public byte B + { + // IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property! + get + { + return (byte)GetValue(BProperty); + } + set + { + SetValue(BProperty, value); + } + } + + + #endregion //B + + #endregion //RGB + + #region HexadecimalString + + public static readonly DependencyProperty HexadecimalStringProperty = DependencyProperty.Register("HexadecimalString", typeof(string), typeof(ColorCanvas), 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 Constructors + + static ColorCanvas() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorCanvas), new FrameworkPropertyMetadata(typeof(ColorCanvas))); + } + + #endregion //Constructors + + #region Base Class Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _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; + + SetSelectedColorAndPositionSelector(SelectedColor); + } + + #endregion //Base Class Overrides + + #region Event Handlers + + void ColorShadingCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + Point p = e.GetPosition(_colorShadingCanvas); + UpdateColorShadeSelectorPositionAndCalculateColor(p, true); + } + + void ColorShadingCanvas_MouseMove(object sender, MouseEventArgs e) + { + if (e.LeftButton == MouseButtonState.Pressed) + { + Point p = e.GetPosition(_colorShadingCanvas); + UpdateColorShadeSelectorPositionAndCalculateColor(p, true); + 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); + } + } + + #endregion //Event Handlers + + #region Methods + + private void UpdateRGBColor() + { + SelectedColor = Color.FromArgb(A, R, G, B); + UpdateColorShadeSelectorPosition(SelectedColor); + } + + private void UpdateSelectedColor(Color color) + { + SelectedColor = Color.FromArgb(color.A, color.R, color.G, color.B); + } + + private void UpdateRGBValues(Color color) + { + A = color.A; + R = color.R; + G = color.G; + B = color.B; + } + + private void SetSelectedColorAndPositionSelector(Color color) + { + UpdateSelectedColor(color); + UpdateRGBValues(color); + UpdateColorShadeSelectorPosition(color); + } + + private void UpdateColorShadeSelectorPositionAndCalculateColor(Point p, bool calculateColor) + { + 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; + + if (calculateColor) + CalculateColor(p); + } + + private void UpdateColorShadeSelectorPosition(Color color) + { + if (_spectrumSlider == null || _colorShadingCanvas == null) + return; + + _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) - 5; + _colorShadeSelectorTransform.Y = (p.Y * _colorShadingCanvas.Height) - 5; + } + + private void CalculateColor(Point p) + { + HsvColor hsv = new HsvColor(360 - _spectrumSlider.Value, 1, 1) { S = p.X, V = 1 - p.Y }; + var currentColor = ColorUtilities.ConvertHsvToRgb(hsv.H, hsv.S, hsv.V); + currentColor.A = A; + SelectedColor = currentColor; + HexadecimalString = SelectedColor.ToString(); + } + + #endregion //Methods + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorSpectrumSlider.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorSpectrumSlider.cs new file mode 100644 index 00000000..54bb6e9e --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorSpectrumSlider.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Shapes; +using Microsoft.Windows.Controls.Core.Utilities; + +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/ColorCanvas/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Themes/Generic.xaml new file mode 100644 index 00000000..b7f71e71 --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Themes/Generic.xaml @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorPicker.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorPicker.cs index e4bef7f9..ce9b8f48 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorPicker.cs +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorPicker.cs @@ -5,6 +5,7 @@ using System.Windows.Media; using System.Windows.Controls.Primitives; using System.Collections.ObjectModel; using System.Windows.Input; +using Microsoft.Windows.Controls.Core.Utilities; namespace Microsoft.Windows.Controls { @@ -44,6 +45,29 @@ namespace Microsoft.Windows.Controls #endregion //ButtonStyle + #region DisplayAvailableColors + + public static readonly DependencyProperty DisplayAvailableColorsProperty = DependencyProperty.Register("DisplayAvailableColors", typeof(bool), typeof(ColorPicker), new UIPropertyMetadata(true, OnDisplayAvailableColorsChanged)); + public bool DisplayAvailableColors + { + get { return (bool)GetValue(DisplayAvailableColorsProperty); } + set { SetValue(DisplayAvailableColorsProperty, value); } + } + + private static void OnDisplayAvailableColorsChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + ColorPicker colorPicker = o as ColorPicker; + if (colorPicker != null) + colorPicker.OnDisplayAvailableColorsChanged((bool)e.OldValue, (bool)e.NewValue); + } + + protected virtual void OnDisplayAvailableColorsChanged(bool oldValue, bool newValue) + { + // TODO: Add your property changed side-effects. Descendants can override as well. + } + + #endregion //DisplayAvailableColors + #region DisplayColorAndName public static readonly DependencyProperty DisplayColorAndNameProperty = DependencyProperty.Register("DisplayColorAndName", typeof(bool), typeof(ColorPicker), new UIPropertyMetadata(false)); @@ -55,6 +79,52 @@ namespace Microsoft.Windows.Controls #endregion //DisplayColorAndName + #region DisplayRecentColors + + public static readonly DependencyProperty DisplayRecentColorsProperty = DependencyProperty.Register("DisplayRecentColors", typeof(bool), typeof(ColorPicker), new UIPropertyMetadata(true, OnDisplayRecentColorsChanged)); + public bool DisplayRecentColors + { + get { return (bool)GetValue(DisplayRecentColorsProperty); } + set { SetValue(DisplayRecentColorsProperty, value); } + } + + private static void OnDisplayRecentColorsChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + ColorPicker colorPicker = o as ColorPicker; + if (colorPicker != null) + colorPicker.OnDisplayRecentColorsChanged((bool)e.OldValue, (bool)e.NewValue); + } + + protected virtual void OnDisplayRecentColorsChanged(bool oldValue, bool newValue) + { + // TODO: Add your property changed side-effects. Descendants can override as well. + } + + #endregion //DisplayRecentColors + + #region DisplayStandardColors + + public static readonly DependencyProperty DisplayStandardColorsProperty = DependencyProperty.Register("DisplayStandardColors", typeof(bool), typeof(ColorPicker), new UIPropertyMetadata(true, OnDisplayStandardColorsChanged)); + public bool DisplayStandardColors + { + get { return (bool)GetValue(DisplayStandardColorsProperty); } + set { SetValue(DisplayStandardColorsProperty, value); } + } + + private static void OnDisplayStandardColorsChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + ColorPicker colorPicker = o as ColorPicker; + if (colorPicker != null) + colorPicker.OnDisplayStandardColorsChanged((bool)e.OldValue, (bool)e.NewValue); + } + + protected virtual void OnDisplayStandardColorsChanged(bool oldValue, bool newValue) + { + // TODO: Add your property changed side-effects. Descendants can override as well. + } + + #endregion //DisplayStandardColors + #region IsOpen public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register("IsOpen", typeof(bool), typeof(ColorPicker), new UIPropertyMetadata(false)); diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorUtilities.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorUtilities.cs deleted file mode 100644 index 6076ad18..00000000 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorUtilities.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Linq; -using System.Windows.Media; -using System.Reflection; -using System.Collections.Generic; - -namespace Microsoft.Windows.Controls -{ - static class ColorUtilities - { - public static readonly Dictionary KnownColors = GetKnownColors(); - - public static string GetColorName(this Color color) - { - return KnownColors.Where(kvp => kvp.Value.Equals(color)).Select(kvp => kvp.Key).FirstOrDefault(); - } - - private static Dictionary GetKnownColors() - { - var colorProperties = typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.Public); - return colorProperties.ToDictionary(p => p.Name, p => (Color)p.GetValue(null, null)); - } - } -} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Themes/Generic.xaml index a2877738..7c2af261 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Themes/Generic.xaml @@ -14,6 +14,7 @@ + @@ -196,7 +197,7 @@ - + @@ -217,7 +218,7 @@ - + @@ -238,7 +239,7 @@ - + diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Converters/SolidColorBrushToColorConverter.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Converters/SolidColorBrushToColorConverter.cs new file mode 100644 index 00000000..901f235b --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Converters/SolidColorBrushToColorConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Windows.Data; +using System.Windows.Media; + +namespace Microsoft.Windows.Controls.Core.Converters +{ + public class SolidColorBrushToColorConverter : IValueConverter + { + #region IValueConverter Members + + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + SolidColorBrush brush = value as SolidColorBrush; + if (brush != null) + return brush.Color; + + return default(Color); + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (value != null) + { + Color color = (Color)value; + return new SolidColorBrush(color); + } + + return default(SolidColorBrush); + } + + #endregion + } +} diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/HsvColor.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/HsvColor.cs new file mode 100644 index 00000000..4756686c --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/HsvColor.cs @@ -0,0 +1,18 @@ +using System; + +namespace Microsoft.Windows.Controls.Primitives +{ + 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/Core/Utilities/ColorUtilities.cs b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ColorUtilities.cs new file mode 100644 index 00000000..9d5364ce --- /dev/null +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ColorUtilities.cs @@ -0,0 +1,172 @@ +using System; +using System.Linq; +using System.Windows.Media; +using System.Reflection; +using System.Collections.Generic; +using Microsoft.Windows.Controls.Primitives; + +namespace Microsoft.Windows.Controls.Core.Utilities +{ + static class ColorUtilities + { + public static readonly Dictionary KnownColors = GetKnownColors(); + + public static string GetColorName(this Color color) + { + return KnownColors.Where(kvp => kvp.Value.Equals(color)).Select(kvp => kvp.Key).FirstOrDefault(); + } + + private static Dictionary GetKnownColors() + { + var colorProperties = typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.Public); + return colorProperties.ToDictionary(p => p.Name, p => (Color)p.GetValue(null, null)); + } + + /// + /// 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/PropertyGrid/Themes/Generic.xaml b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml index cafcdcb6..f851614b 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml @@ -317,7 +317,7 @@ + Style="{StaticResource OptionsToggleButtonStyle}" ToolTip="Categorized"> - + + @@ -15,5 +16,4 @@ - diff --git a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj index f15199aa..89d94ef3 100644 --- a/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj +++ b/ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj @@ -75,6 +75,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -132,11 +136,15 @@ + + - + + +