2009-12-04 Jeffrey Stedfast <fejj@novell.com>
[moon.git] / class / System.Windows / Mono / MoonlightTypeConverter.cs
blob672fda2847a82930280de5a001306c095840b16f
1 //
2 // MoonlightTypeConverter.cs
3 //
4 // Contact:
5 // Moonlight List (moonlight-list@lists.ximian.com)
6 //
7 // Copyright 2008 Novell, Inc.
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using Mono;
30 using System;
31 using System.ComponentModel;
32 using System.Globalization;
33 using System.Windows;
34 using System.Windows.Input;
35 using System.Windows.Media;
36 using System.Reflection;
38 namespace Mono {
40 internal sealed class MoonlightTypeConverter : TypeConverter {
41 Kind destinationKind;
42 Type destinationType;
43 string propertyName;
45 public MoonlightTypeConverter (string propertyName, Type destinationType)
47 this.propertyName = propertyName;
48 this.destinationType = destinationType;
50 if (destinationType.IsEnum)
51 destinationType = typeof (Int32);
53 destinationKind = Deployment.Current.Types.TypeToKind (destinationType);
54 if (destinationKind == Kind.INVALID)
55 throw new InvalidOperationException (string.Format ("Cannot convert to type {0} (property {1})", destinationType, propertyName));
58 public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
60 if (sourceType == typeof(string))
61 return true;
63 // allow specifying SolidColorBrushes using color literals
64 if (sourceType == typeof(Color) && destinationType.IsAssignableFrom(typeof(SolidColorBrush)))
65 return true;
67 if (IsAssignableToIConvertible (sourceType) && IsAssignableToIConvertible (destinationType))
68 return true;
70 return base.CanConvertFrom (context, sourceType);
73 public override object ConvertFrom (ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
75 if (destinationType == typeof (object))
76 return value;
78 string str_val = value as String;
79 if (str_val != null) {
80 if (destinationType.IsEnum)
81 return Enum.Parse (destinationType, str_val, true);
83 if (destinationType == typeof (GridLength)) {
84 if (str_val == "Auto")
85 return new GridLength (1, GridUnitType.Auto);
86 else if (str_val == "*")
87 return new GridLength (1, GridUnitType.Star);
88 else
89 return new GridLength (double.Parse (str_val), GridUnitType.Pixel);
92 if (destinationType == typeof (TimeSpan))
93 return TimeSpan.Parse (str_val);
95 if (destinationType == typeof (FontWeight))
96 return new FontWeight ((FontWeightKind) Enum.Parse (typeof (FontWeightKind), str_val, true));
98 if (destinationType == typeof (FontStyle))
99 return new FontStyle ((FontStyleKind) Enum.Parse (typeof (FontStyleKind), str_val, true));
101 if (destinationType == typeof (FontStretch))
102 return new FontStretch ((FontStretchKind) Enum.Parse (typeof (FontStretchKind), str_val, true));
105 if (value is Color && destinationType.IsAssignableFrom(typeof(SolidColorBrush))) {
106 return new SolidColorBrush ((Color)value);
108 if (IsAssignableToIConvertible (value.GetType ()) && IsAssignableToIConvertible (destinationType))
109 return ValueFromConvertible (destinationType, (IConvertible) value);
111 if (str_val != null) {
112 Kind k = destinationKind;
114 /* ugh. our desire to use enums in
115 unmanaged code when the managed
116 code has structs is painful all
117 over. */
118 if (k == Kind.CURSOR)
119 k = Kind.INT32;
121 // XXX this leaks unmanaged_value?
122 IntPtr unmanaged_value;
124 if (NativeMethods.value_from_str (k,
125 propertyName,
126 str_val,
127 out unmanaged_value)) {
128 value = Value.ToObject (destinationType, unmanaged_value);
129 return value;
133 if (!base.CanConvertFrom (context, value.GetType ())) {
134 Console.Error.WriteLine ("MoonlightTypeConverter: Cannot convert from type {0} to type {1}", value.GetType(), destinationType);
137 return base.ConvertFrom (context, culture, value);
140 public static bool IsAssignableToIConvertible (Type type)
142 return typeof (IConvertible).IsAssignableFrom (type);
145 public static object ValueFromConvertible (Type type, IConvertible value)
147 if (type == typeof (string))
148 return Convert.ToString (value);
149 if (type == typeof (bool))
150 return Convert.ToBoolean (value);
151 if (type == typeof (byte))
152 return Convert.ToByte (value);
153 if (type == typeof (char))
154 return Convert.ToChar (value);
155 if (type == typeof (DateTime))
156 return Convert.ToDateTime (value);
157 if (type == typeof (Decimal))
158 return Convert.ToDecimal (value);
159 if (type == typeof (double))
160 return Convert.ToDouble (value);
161 if (type == typeof (Int16))
162 return Convert.ToInt16 (value);
163 if (type == typeof (Int32))
164 return Convert.ToInt32 (value);
165 if (type == typeof (Int64))
166 return Convert.ToInt64 (value);
167 if (type == typeof (SByte))
168 return Convert.ToSByte (value);
169 if (type == typeof (Single))
170 return Convert.ToSingle (value);
171 if (type == typeof (UInt16))
172 return Convert.ToUInt16 (value);
173 if (type == typeof (UInt32))
174 return Convert.ToUInt32 (value);
175 if (type == typeof (UInt64))
176 return Convert.ToUInt64 (value);
178 return value;
181 public static object ConvertObject (PropertyInfo prop, object val, Type objectType)
183 // Should i return default(T) if property.PropertyType is a valuetype?
184 if (val == null)
185 return val;
187 if (prop.PropertyType.IsAssignableFrom (val.GetType ()))
188 return val;
190 if (prop.PropertyType == typeof (string))
191 return val.ToString ();
193 TypeConverter tc = Helper.GetConverterFor (prop, prop.PropertyType);
194 if (tc == null)
195 tc = new MoonlightTypeConverter (prop.Name, prop.PropertyType);
197 if (!tc.CanConvertFrom (val.GetType()))
198 throw new Exception (string.Format ("type converter {0} can't convert from type {1}", tc.GetType(), val.GetType()));
200 return tc.ConvertFrom (null, Helper.DefaultCulture, val);
203 public static object ConvertObject (DependencyProperty dp, object val, Type objectType)
205 // Should i return default(T) if property.PropertyType is a valuetype?
206 if (val == null)
207 return val;
209 if (dp.PropertyType.IsAssignableFrom (val.GetType ()))
210 return val;
212 if (dp.PropertyType == typeof (string))
213 return val.ToString ();
215 TypeConverter tc = null;
217 if (dp.IsAttached) {
218 tc = Helper.GetConverterFor (GetGetterMethodForAttachedDP (dp, val), dp.PropertyType);
220 else if (objectType != null) {
221 PropertyInfo pi = objectType.GetProperty (dp.Name);
222 if (pi == null) {
223 Console.WriteLine ("+ failed to look up CLR property wrapper");
224 Console.WriteLine ("+ TargetType = {0}, property = {1}.{2}", objectType, dp.DeclaringType, dp.Name);
225 throw new Exception ("foo3");
228 tc = Helper.GetConverterFor (pi, pi.PropertyType);
229 if (tc == null)
230 tc = new MoonlightTypeConverter (pi.Name, pi.PropertyType);
233 if (tc == null)
234 tc = new MoonlightTypeConverter (dp.Name, dp.PropertyType);
236 if (!tc.CanConvertFrom (val.GetType()))
237 throw new Exception (string.Format ("type converter {0} can't convert from type {1}", tc.GetType(), val.GetType()));
239 return tc.ConvertFrom (val);
243 private static MethodInfo GetGetterMethodForAttachedDP (DependencyProperty dp, object obj)
245 MethodInfo res = dp.DeclaringType.GetMethod (String.Concat ("Get", dp.Name), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
246 return res;