Fixes MakeTransparent method
[mono.git] / mcs / class / System.Drawing / System.Drawing / ColorConverter.cs
1 //
2 // System.Drawing.ColorConverter
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //      Ravindra (rkumar@novell.com)
7 //
8 // Copyright (C) 2002 Ximian, Inc.  http://www.ximian.com
9 // Copyright (C) 2004 Novell, Inc.  http://www.novell.com
10 //
11
12 //
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System;
36 using System.Collections;
37 using System.ComponentModel;
38 using System.Globalization;
39 using System.Text;
40
41 namespace System.Drawing
42 {
43         public class ColorConverter : TypeConverter
44         {
45                 static StandardValuesCollection cached;
46                 static object creatingCached = new object ();
47
48                 public ColorConverter () { }
49
50                 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
51                 {
52                         if (sourceType == typeof (string))
53                                 return true;
54
55                         return base.CanConvertFrom (context, sourceType);
56                 }
57
58                 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
59                 {
60                         if (destinationType == typeof (String))
61                                 return true;
62
63                         return base.CanConvertTo (context, destinationType);
64                 }
65
66                 public override object ConvertFrom (ITypeDescriptorContext context,
67                                                     CultureInfo culture,
68                                                     object value)
69                 {
70                         string s = value as string;
71                         if (s == null)
72                                 return base.ConvertFrom (context, culture, value);
73
74                         object named = Color.NamedColors [s];
75                         if (named != null)
76                                 return (Color) named;
77
78                         named = Color.SystemColors [s];
79                         if (named != null)
80                                 return (Color) named;
81
82                         String numSeparator = culture.NumberFormat.NumberGroupSeparator;
83
84                         int A, R, G, B;
85                         if (s.IndexOf (numSeparator) > 0) { // "A, R, G, B" format
86                                 String [] components = s.Split (numSeparator.ToCharArray ());
87                                 if (components.Length == 3) {
88                                         A = 255;
89                                         R = GetNumber (components [0].Trim ());
90                                         G = GetNumber (components [1].Trim ());
91                                         B = GetNumber (components [2].Trim ());
92                                 }
93                                 else if (components.Length == 4) {
94                                         A = GetNumber (components [0].Trim ());
95                                         R = GetNumber (components [1].Trim ());
96                                         G = GetNumber (components [2].Trim ());
97                                         B = GetNumber (components [3].Trim ());
98                                 }
99                                 else
100                                         throw new ArgumentException (s + " is not a valid color value.");
101                         } 
102                         else { // #RRGGBB format
103                                 int i = GetNumber (s.Trim ());
104                                 A = (int) (i >> 24) & 0xFF;
105                                 if (A == 0)
106                                         A = 255;
107                                 R = (i >> 16) & 0xFF;
108                                 G = (i >> 8) & 0xFF;
109                                 B = i & 0xFF;
110                         }
111
112                         Color result = Color.FromArgb (A, R, G, B);
113                         // Look for a named or system color with those values
114                         foreach (Color c in Color.NamedColors.Values) {
115                                 if (c == result)
116                                         return c;
117                         }
118
119                         foreach (Color c in Color.SystemColors.Values) {
120                                 if (c == result)
121                                         return c;
122                         }
123
124                         return result;
125                 }
126
127                 public override object ConvertTo (ITypeDescriptorContext context,
128                                                   CultureInfo culture,
129                                                   object value,
130                                                   Type destinationType)
131                 {
132                         if ((destinationType == typeof (string)) && (value is Color)) {
133                                 Color color = (Color) value;
134                                 StringBuilder sb = new StringBuilder ();
135                                 sb.Append (color.A); sb.Append (", ");
136                                 sb.Append (color.R); sb.Append (", ");
137                                 sb.Append (color.G); sb.Append (", ");
138                                 sb.Append (color.B);
139                                 return sb.ToString ();
140                         }
141
142                         return base.ConvertTo (context, culture, value, destinationType);
143                 }
144
145                 public override StandardValuesCollection GetStandardValues (ITypeDescriptorContext context)
146                 {
147                         if (cached != null)
148                                 return cached;
149
150                         lock (creatingCached)
151                         {
152                                 if (cached != null)
153                                         return cached;
154                         
155                                 ICollection named = (ICollection) Color.NamedColors.Values;
156                                 ICollection system = (ICollection) Color.SystemColors.Values;
157                                 Array colors = Array.CreateInstance (typeof (Color), named.Count + system.Count);
158                                 named.CopyTo (colors, 0);
159                                 system.CopyTo (colors, named.Count);
160                                 Array.Sort (colors, 0, colors.Length, new CompareColors ());
161                                 cached = new StandardValuesCollection (colors);
162                         }
163
164                         return cached;
165                 }
166
167                 public override bool GetStandardValuesSupported (ITypeDescriptorContext context)
168                 {
169                         return true;
170                 }
171
172                 private int GetNumber (String str)
173                 {
174                         int number;
175
176                         if (str.StartsWith ("#0x") || str.StartsWith ("#0X")) 
177                                 // #0xRRGGBB format. Parse hex string.
178                                 number = Int32.Parse (str.Substring (3), NumberStyles.HexNumber);
179
180                         else if (str [0] == '#') 
181                                 // #RRGGBB format. Parse hex string.
182                                 number = Int32.Parse (str.Substring (1), NumberStyles.HexNumber);
183
184                         else if (str.StartsWith ("0x") || str.StartsWith ("0X"))
185                                 // 0xRRGGBB format. Parse hex string.
186                                 number = Int32.Parse (str.Substring (2), NumberStyles.HexNumber);
187
188                         else    // if (str [0] == '-' || str [0] == '+' || Char.IsDigit (str [0]))
189                                 // [+/-]RRGGBB format. Parse decimal string.
190                                 number = Int32.Parse (str, NumberStyles.Integer);
191
192                         return number;
193                 }
194
195                 class CompareColors : IComparer
196                 {
197                         public int Compare (object x, object y)
198                         {
199                                 return String.Compare (((Color) x).Name, ((Color) y).Name);
200                         }
201                 }
202         }
203 }