2 // System.Drawing.ColorConverter
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 // Ravindra (rkumar@novell.com)
8 // Copyright (C) 2002 Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2004,2006 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.ComponentModel;
33 using System.Globalization;
35 using System.ComponentModel.Design.Serialization;
36 using System.Reflection;
38 namespace System.Drawing
40 public class ColorConverter : TypeConverter
42 static StandardValuesCollection cached;
43 static object creatingCached = new object ();
45 public ColorConverter () { }
47 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
49 if (sourceType == typeof (string))
52 return base.CanConvertFrom (context, sourceType);
55 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
57 if (destinationType == typeof (InstanceDescriptor))
60 return base.CanConvertTo (context, destinationType);
63 public override object ConvertFrom (ITypeDescriptorContext context,
67 string s = value as string;
69 return base.ConvertFrom (context, culture, value);
77 object named = Color.NamedColors [s];
81 named = Color.SystemColors [s];
85 String numSeparator = culture.TextInfo.ListSeparator;
87 Int32Converter converter = new Int32Converter ();
91 if (s.IndexOf (numSeparator) == -1) {
92 if ((s.Length == 8 && (s.StartsWith ("0x") || s.StartsWith ("0X")))
93 || (s.Length == 7 && s.StartsWith ("#"))) {
94 result = Color.FromArgb (-16777216 | (int) converter.
95 ConvertFromString (context, culture, s));
97 else if ((s.Length == 5 && (s.StartsWith ("0x") || s.StartsWith ("0X")))
98 || (s.Length == 4 && s.StartsWith ("#"))) {
99 int i = (int) converter.ConvertFromString (context, culture, s);
100 i = ((i & 0xf00) << 12) | ((i & 0xf00) << 8) |
101 ((i & 0xf0) << 8) | ((i & 0xf0) << 4) |
102 ((i & 0xf) << 4) | (i & 0xf);
103 result = Color.FromArgb ( -16777216 | i );
104 } else if (s.StartsWith ("#") && (s.Length > 9) && !s.StartsWith ("#0x")) {
105 throw new Exception (Locale.GetText ("{0} isn't a valid color (integer too large).", s));
109 if (result == null) {
110 String [] components = s.Split (numSeparator.ToCharArray ());
112 // MS seems to convert the indivual component to int before
113 // checking the number of components
114 int[] numComponents = new int[components.Length];
115 for (int i = 0; i < numComponents.Length; i++) {
116 numComponents[i] = (int) converter.ConvertFrom (context,
117 culture, components[i]);
120 switch (components.Length) {
122 result = Color.FromArgb (numComponents[0]);
125 result = Color.FromArgb (numComponents[0], numComponents[1],
129 result = Color.FromArgb (numComponents[0], numComponents[1],
130 numComponents[2], numComponents[3]);
133 throw new ArgumentException (s + " is not a valid color value.");
137 if (result != null) {
138 Color resultColor = (Color) result;
140 // Look for a named or system color with those values
141 foreach (Color c in Color.NamedColors.Values) {
142 if (c == resultColor)
146 foreach (Color c in Color.SystemColors.Values) {
147 if (c == resultColor)
155 public override object ConvertTo (ITypeDescriptorContext context,
158 Type destinationType)
160 if ((destinationType == typeof (string)) && (value is Color)) {
161 Color color = (Color) value;
163 if (color == Color.Empty) {
167 if (color.IsKnownColor) {
171 if (color.IsNamedColor)
174 String numSeparator = culture.TextInfo.ListSeparator;
176 StringBuilder sb = new StringBuilder ();
177 if (color.A != 255) {
179 sb.Append (numSeparator);
183 sb.Append (numSeparator);
187 sb.Append (numSeparator);
191 return sb.ToString ();
194 if (destinationType == typeof (InstanceDescriptor) && value is Color) {
195 Color c = (Color)value;
197 return new InstanceDescriptor (typeof (SystemColors).GetProperty (c.Name), null);
199 MethodInfo met = typeof(Color).GetMethod ("FromArgb", new Type[] { typeof(int), typeof(int), typeof(int), typeof(int) } );
200 return new InstanceDescriptor (met, new object[] {c.A, c.R, c.G, c.B });
204 return base.ConvertTo (context, culture, value, destinationType);
207 public override StandardValuesCollection GetStandardValues (ITypeDescriptorContext context)
209 lock (creatingCached) {
213 ICollection named = (ICollection) Color.NamedColors.Values;
214 ICollection system = (ICollection) Color.SystemColors.Values;
215 Array colors = Array.CreateInstance (typeof (Color), named.Count + system.Count);
216 named.CopyTo (colors, 0);
217 system.CopyTo (colors, named.Count);
218 Array.Sort (colors, 0, colors.Length, new CompareColors ());
219 cached = new StandardValuesCollection (colors);
225 public override bool GetStandardValuesSupported (ITypeDescriptorContext context)
230 class CompareColors : IComparer
232 public int Compare (object x, object y)
234 return String.Compare (((Color) x).Name, ((Color) y).Name);