2 // MoonlightTypeConverter.cs
5 // Moonlight List (moonlight-list@lists.ximian.com)
7 // Copyright 2008 Novell, Inc.
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
31 using System
.ComponentModel
;
32 using System
.Globalization
;
34 using System
.Windows
.Input
;
35 using System
.Windows
.Media
;
36 using System
.Reflection
;
40 internal sealed class MoonlightTypeConverter
: TypeConverter
{
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))
63 // allow specifying SolidColorBrushes using color literals
64 if (sourceType
== typeof(Color
) && destinationType
.IsAssignableFrom(typeof(SolidColorBrush
)))
67 if (IsAssignableToIConvertible (sourceType
) && IsAssignableToIConvertible (destinationType
))
70 return base.CanConvertFrom (context
, sourceType
);
73 public override object ConvertFrom (ITypeDescriptorContext context
, System
.Globalization
.CultureInfo culture
, object value)
75 if (destinationType
== typeof (object))
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
);
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
118 if (k
== Kind
.CURSOR
)
121 // XXX this leaks unmanaged_value?
122 IntPtr unmanaged_value
;
124 if (NativeMethods
.value_from_str (k
,
127 out unmanaged_value
)) {
128 value = Value
.ToObject (destinationType
, unmanaged_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);
181 public static object ConvertObject (PropertyInfo prop
, object val
, Type objectType
)
183 // Should i return default(T) if property.PropertyType is a valuetype?
187 if (prop
.PropertyType
.IsAssignableFrom (val
.GetType ()))
190 if (prop
.PropertyType
== typeof (string))
191 return val
.ToString ();
193 TypeConverter tc
= Helper
.GetConverterFor (prop
, prop
.PropertyType
);
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?
209 if (dp
.PropertyType
.IsAssignableFrom (val
.GetType ()))
212 if (dp
.PropertyType
== typeof (string))
213 return val
.ToString ();
215 TypeConverter tc
= null;
218 tc
= Helper
.GetConverterFor (GetGetterMethodForAttachedDP (dp
, val
), dp
.PropertyType
);
220 else if (objectType
!= null) {
221 PropertyInfo pi
= objectType
.GetProperty (dp
.Name
);
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
);
230 tc
= new MoonlightTypeConverter (pi
.Name
, pi
.PropertyType
);
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
);