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,2008 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 internal static Color
StaticConvertFromString (ITypeDescriptorContext context
, string s
, CultureInfo culture
)
66 culture
= CultureInfo
.InvariantCulture
;
73 // Try to process both NamedColor and SystemColors from the KnownColor enumeration
74 if (Char
.IsLetter (s
[0])) {
77 kc
= (KnownColor
) Enum
.Parse (typeof (KnownColor
), s
, true);
80 // whatever happens MS throws an basic Exception
81 string msg
= Locale
.GetText ("Invalid color name '{0}'.", s
);
82 throw new Exception (msg
, new FormatException (msg
, e
));
84 return KnownColors
.FromKnownColor (kc
);
87 String numSeparator
= culture
.TextInfo
.ListSeparator
;
88 Color result
= Color
.Empty
;
90 if (s
.IndexOf (numSeparator
) == -1) {
91 bool sharp
= (s
[0] == '#');
92 int start
= sharp
? 1 : 0;
94 // deal with #hex, 0xhex and #0xhex
95 if ((s
.Length
> start
+ 1) && (s
[start
] == '0')) {
96 hex
= ((s
[start
+ 1] == 'x') || (s
[start
+ 1] == 'X'));
102 s
= s
.Substring (start
);
105 argb
= Int32
.Parse (s
, NumberStyles
.HexNumber
);
107 catch (Exception e
) {
108 // whatever happens MS throws an basic Exception
109 string msg
= Locale
.GetText ("Invalid Int32 value '{0}'.", s
);
110 throw new Exception (msg
, e
);
113 // note that the default alpha value for a 6 hex digit (i.e. when none are present) is
114 // 0xFF while shorter string defaults to 0xFF - unless both # an 0x are specified
115 if ((s
.Length
< 6) || ((s
.Length
== 6) && sharp
&& hex
))
117 else if ((argb
>> 24) == 0)
118 argb
|= unchecked((int)0xFF000000);
119 result
= Color
.FromArgb (argb
);
123 if (result
.IsEmpty
) {
124 Int32Converter converter
= new Int32Converter ();
125 String
[] components
= s
.Split (numSeparator
.ToCharArray ());
127 // MS seems to convert the indivual component to int before
128 // checking the number of components
129 int[] numComponents
= new int[components
.Length
];
130 for (int i
= 0; i
< numComponents
.Length
; i
++) {
131 numComponents
[i
] = (int) converter
.ConvertFrom (context
,
132 culture
, components
[i
]);
135 switch (components
.Length
) {
137 result
= Color
.FromArgb (numComponents
[0]);
140 result
= Color
.FromArgb (numComponents
[0], numComponents
[1],
144 result
= Color
.FromArgb (numComponents
[0], numComponents
[1],
145 numComponents
[2], numComponents
[3]);
148 throw new ArgumentException (s
+ " is not a valid color value.");
152 if (!result
.IsEmpty
) {
153 // Look for a named or system color with those values
154 Color known
= KnownColors
.FindColorMatch (result
);
163 public override object ConvertFrom (ITypeDescriptorContext context
,
167 string s
= value as string;
169 return base.ConvertFrom (context
, culture
, value);
171 return StaticConvertFromString (context
, s
, culture
);
174 public override object ConvertTo (ITypeDescriptorContext context
,
177 Type destinationType
)
179 if (value is Color
) {
180 Color color
= (Color
) value;
181 if (destinationType
== typeof (string)) {
182 if (color
== Color
.Empty
)
185 if (color
.IsKnownColor
|| color
.IsNamedColor
)
188 String numSeparator
= culture
.TextInfo
.ListSeparator
;
190 StringBuilder sb
= new StringBuilder ();
191 if (color
.A
!= 255) {
193 sb
.Append (numSeparator
);
197 sb
.Append (numSeparator
);
201 sb
.Append (numSeparator
);
205 return sb
.ToString ();
206 } else if (destinationType
== typeof (InstanceDescriptor
)) {
208 return new InstanceDescriptor (typeof (Color
).GetField ("Empty"), null);
209 } else if (color
.IsSystemColor
) {
210 return new InstanceDescriptor (typeof (SystemColors
).GetProperty (color
.Name
), null);
211 } else if (color
.IsKnownColor
){
212 return new InstanceDescriptor (typeof (Color
).GetProperty (color
.Name
), null);
214 MethodInfo met
= typeof(Color
).GetMethod ("FromArgb", new Type
[] { typeof(int), typeof(int), typeof(int), typeof(int) }
);
215 return new InstanceDescriptor (met
, new object[] {color.A, color.R, color.G, color.B }
);
220 return base.ConvertTo (context
, culture
, value, destinationType
);
223 public override StandardValuesCollection
GetStandardValues (ITypeDescriptorContext context
)
225 lock (creatingCached
) {
229 Color
[] colors
= new Color
[KnownColors
.Values
.Length
- 1];
230 Array
.Copy (KnownColors
.Values
, 1, colors
, 0, colors
.Length
);
232 Array colors
= Array
.CreateInstance (typeof (Color
), KnownColors
.ArgbValues
.Length
- 1);
233 for (int i
=1; i
< KnownColors
.ArgbValues
.Length
; i
++) {
234 colors
.SetValue (KnownColors
.FromKnownColor ((KnownColor
)i
), i
- 1);
238 Array
.Sort (colors
, 0, colors
.Length
, new CompareColors ());
239 cached
= new StandardValuesCollection (colors
);
245 public override bool GetStandardValuesSupported (ITypeDescriptorContext context
)
250 sealed class CompareColors
: IComparer
{
252 public int Compare (object x
, object y
)
254 return String
.Compare (((Color
) x
).Name
, ((Color
) y
).Name
);