using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Common.Resources; namespace HeuristicLab.Analysis.FitnessLandscape.BoxChart { [Item("Color", "A color")] [StorableClass] public class ColorValue : NamedItem { #region Constants & Initializers public static readonly Dictionary KnownColors = new Dictionary(); static ColorValue() { foreach (var name in Enum.GetNames(typeof(KnownColor))) { var kc = Color.FromName(name); if (!kc.IsSystemColor) KnownColors[kc.ToArgb()] = name; } } #endregion #region Fields private int r, g, b; [Storable] private double h; [Storable] private double s; [Storable] private double v; private Color? color; private Image icon; #endregion #region Properties public override bool CanChangeName { get { return false; } } public override bool CanChangeDescription { get { return false; } } public static new Image StaticItemImage { get { return VSImageLibrary.DisplayInColorVertical; } } public override Image ItemImage { get { if (icon != null) return icon; icon = new Bitmap(16, 16); using (var g = Graphics.FromImage(icon)) { using (var b = new SolidBrush(Color)) { g.FillRectangle(b, 0, 0, 16, 16); } } return icon; } } public int R { get { return r; } set { if (value == r) return; r = value; OnRGBChanged(); } } public int G { get { return g; } set { if (value == g) return; g = value; OnRGBChanged(); } } public int B { get { return b; } set { if (value == b) return; b = value; OnRGBChanged(); } } public double H { get { return h; } set { if (value == h) return; h = value; OnHSVChanged(); } } public double S { get { return s; } set { if (value == s) return; s = value; OnHSVChanged(); } } public double V { get { return v; } set { if (value == v) return; v = value; OnHSVChanged(); } } public Color Color { get { if (color.HasValue) return color.Value; color = Color.FromArgb(R, G, B); return color.Value; } set { if (value == Color) return; color = value; r = value.R; g = value.G; b = value.B; OnRGBChanged(); } } public bool IsNamedColor { get { return KnownColors.ContainsKey(Color.ToArgb()); } } #endregion #region Events protected virtual void OnRGBChanged() { RGBToHSV(r, g, b, out h, out s, out v); OnColorChanged(); } protected virtual void OnHSVChanged() { HSVtoRGB(h, s, v, out r, out g, out b); OnColorChanged(); } public event EventHandler ColorChanged; protected virtual void OnColorChanged() { color = null; icon = null; name = GetColorName(Color); EventHandler handler = ColorChanged; if (handler != null) handler(this, EventArgs.Empty); OnToStringChanged(); OnItemImageChanged(); OnNameChanged(); } #endregion #region Construction & Cloning [StorableConstructor] protected ColorValue(bool deserializing) : base(deserializing) { } protected ColorValue(ColorValue original, Cloner cloner) : base (original, cloner) { h = original.h; s = original.s; v = original.v; HSVtoRGB(h, s, v, out r, out g, out b); name = GetColorName(Color); } public ColorValue() : this(Color.White) {} public ColorValue(Color color) { this.color = color; r = color.R; g = color.G; b = color.B; RGBToHSV(r, g, b, out h, out s, out v); name = GetColorName(Color); } public ColorValue(double hue, double saturation, double value) { h = hue; s = saturation; v = value; HSVtoRGB(h, s, v, out r, out g, out b); name = GetColorName(Color); } public ColorValue(int red, int green, int blue) { r = red; g = green; b = blue; RGBToHSV(r, g, b, out h, out s, out v); name = GetColorName(Color); } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { HSVtoRGB(h, s, v, out r, out g, out b); name = GetColorName(Color); } public override IDeepCloneable Clone(Cloner cloner) { return new ColorValue(this, cloner); } #endregion public static string GetColorName(Color color) { int argb = color.ToArgb(); string colorName; if (KnownColors.TryGetValue(argb, out colorName)) return colorName; return string.Format("#{0:x2}{1:x2}{2:x2}", color.R, color.G, color.B); } public override string ToString() { return GetColorName(Color); } public static void RGBToHSV(int r, int g , int b, out double hue, out double saturation, out double value) { int max = Math.Max(r, Math.Max(g, b)); int min = Math.Min(r, Math.Min(g, b)); hue = Color.FromArgb(r, g, b).GetHue(); saturation = (max == 0) ? 0 : 1d - (1d * min / max); value = max / 255d; } public static void HSVtoRGB(double hue, double saturation, double value, out int r, out int g, out int b) { int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6; double f = hue / 60 - Math.Floor(hue / 60); value = value * 255; int v = Convert.ToInt32(value); int p = Convert.ToInt32(value * (1 - saturation)); int q = Convert.ToInt32(value * (1 - f * saturation)); int t = Convert.ToInt32(value * (1 - (1 - f) * saturation)); switch (hi) { 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; } } } }