ColorPicker Sorted Colors

May 11, 2011 at 4:10 PM
Edited May 11, 2011 at 4:15 PM

Hey, 

Awesome library!

I found that the color picker is missing that colors are sorted so I've added it. No credit goes to me really since I just put together the pieces. Feel free to integrate it into the source code.

Sorted Colors

Basically at the end of the ColorPicker.cs file I've added:

 

private static ObservableCollection<ColorItem> CreateAvailableColors()
        {
            var _colorList = new List<ColorItem>();
            foreach (var item in ColorUtilities.KnownColors)
            {
                if (!String.Equals(item.Key, "Transparent"))
                {
                    var colorItem = new ColorItem(item.Value, item.Key);
                    if (!_colorList.Contains(colorItem))
                        _colorList.Add(colorItem);
                }
            }
            var _sortedColors = _colorList.OrderBy(item => item.Color, new ColorSorter());
            var _standardColors = new ObservableCollection<ColorItem>(_sortedColors);
            return _standardColors;
        }
        #endregion //Methods

        #region Private Classes
        /// <summary>
        /// The class _ColorSorter orders the colors based on the hue,
        /// saturation and brightness. This is the
        /// order that is also used by visual studio.
        /// Credit: http://www.codeproject.com/KB/selection/ColorPaletteControl.aspx
        /// </summary>
        /// <remarks>
        /// Some features from System.Drawing.Color are needed to properly sort the colors, they can be found in the ColorExtensions.
        /// </remarks>
        private class ColorSorter : IComparer<Color>
        {
            public int Compare(Color x, Color y)
            {
                // local variables
                float hx, hy, sx, sy, bx, by;

                // get Color values
                // get saturation values
                sx = x.GetSaturation();
                sy = y.GetSaturation();
                // get hue values
                hx = x.GetHue();
                hy = y.GetHue();
                // get brightness values
                bx = x.GetBrightness();
                by = y.GetBrightness();

                // determine order
                // 1 : hue       
                if (hx < hy) return -1;
                else if (hx > hy) return 1;
                else
                {
                    // 2 : saturation
                    if (sx < sy) return -1;
                    else if (sx > sy) return 1;
                    else
                    {
                        // 3 : brightness
                        if (bx < by) return -1;
                        else if (bx > by) return 1;
                        else return 0;
                    }
                }
            }
        }
        #endregion // Private Classes

 

Since this idea is based on the System.Drawing.Color, to get saturation, hue and brightness I had to add following extension methods:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;

namespace Microsoft.Windows.Controls
{
    /// <summary>
    /// Copied from System.Drawing.Color
    /// </summary>
    internal static class ColorExtensions
    {
        public static float GetSaturation(this Color color)
        {
            float num = ((float)color.R) / 255f;
            float num2 = ((float)color.G) / 255f;
            float num3 = ((float)color.B) / 255f;
            float num7 = 0f;
            float num4 = num;
            float num5 = num;
            if (num2 > num4)
            {
                num4 = num2;
            }
            if (num3 > num4)
            {
                num4 = num3;
            }
            if (num2 < num5)
            {
                num5 = num2;
            }
            if (num3 < num5)
            {
                num5 = num3;
            }
            if (num4 == num5)
            {
                return num7;
            }
            float num6 = (num4 + num5) / 2f;
            if (num6 <= 0.5)
            {
                return ((num4 - num5) / (num4 + num5));
            }
            return ((num4 - num5) / ((2f - num4) - num5));
        }

        public static float GetHue(this Color color)
        {
            if ((color.R == color.G) && (color.G == color.B))
            {
                return 0f;
            }
            float num = ((float)color.R) / 255f;
            float num2 = ((float)color.G) / 255f;
            float num3 = ((float)color.B) / 255f;
            float num7 = 0f;
            float num4 = num;
            float num5 = num;
            if (num2 > num4)
            {
                num4 = num2;
            }
            if (num3 > num4)
            {
                num4 = num3;
            }
            if (num2 < num5)
            {
                num5 = num2;
            }
            if (num3 < num5)
            {
                num5 = num3;
            }
            float num6 = num4 - num5;
            if (num == num4)
            {
                num7 = (num2 - num3) / num6;
            }
            else if (num2 == num4)
            {
                num7 = 2f + ((num3 - num) / num6);
            }
            else if (num3 == num4)
            {
                num7 = 4f + ((num - num2) / num6);
            }
            num7 *= 60f;
            if (num7 < 0f)
            {
                num7 += 360f;
            }
            return num7;
        }


        public static float GetBrightness(this Color color)
        {
            float num = ((float)color.R) / 255f;
            float num2 = ((float)color.G) / 255f;
            float num3 = ((float)color.B) / 255f;
            float num4 = num;
            float num5 = num;
            if (num2 > num4)
            {
                num4 = num2;
            }
            if (num3 > num4)
            {
                num4 = num3;
            }
            if (num2 < num5)
            {
                num5 = num2;
            }
            if (num3 < num5)
            {
                num5 = num3;
            }
            return ((num4 + num5) / 2f);
        }
    }
}

May 11, 2011 at 4:15 PM

This is an interetesting approach to sorting the colors.  Currently the colors are sorted alphabetically.  Maybe it will be nice to have a property to specify how to sort the colors.  Either Alphabetically or by Hue.

May 11, 2011 at 4:17 PM

Yes, for sure!

I've also just added a screenshot, so you can see how it looks like. The idea how to sort the colors comes from here: 

http://www.codeproject.com/KB/selection/ColorPaletteControl.aspx
Sep 24, 2012 at 5:49 PM

Hi!

I'm really interested in sorting colors, so this post seemed very useful for me, but I downloaded source code, and made these changes, but I'm getting many errors related to other components in this sense:

Error    26    The tag 'DropDownButton' does not exist in XML namespace 'http://schemas.xceed.com/wpf/xaml/toolkit'. Line 44 Position 11.    C:\pathIrrelevant\wpftoolkit-94609\Main\Source\ExtendedWPFToolkitSolution\Src\Samples\Modules\Samples.Modules.TimelinePanel\Views\HomeView.xaml    Samples.Modules.TimelinePanel

 

And also related to "orderby":

 

  'System.Collections.Generic.List<Xceed.Wpf.Toolkit.ColorItem>' does not contain a definition for 'OrderBy' and no extension method 'OrderBy' accepting a first argument of type 'System.Collections.Generic.List<Xceed.Wpf.Toolkit.ColorItem>' could be found (are you missing a using directive or an assembly reference?)   

 

What am I missing? And once I have these changes done, how can I intergrate it once again in my project? Thank you in advance,

Sep 25, 2012 at 7:37 PM

Issue 18700 has been created based on this discussion.