internal object InvokeInternal(string name, params object [] args) { CheckName(name); CheckHandle(); int length = args == null ? 0 : args.Length; object result = null; Mono.Value res; Mono.Value [] vargs = new Mono.Value [length]; for (int i = 0; i < length; i++) { ScriptObjectHelper.ToValue(ref vargs [i], args [i]); } if (!NativeMethods.html_object_invoke(PluginHost.Handle, Handle, name, vargs, (uint)length, out res)) { throw new InvalidOperationException(); } using (res) if (res.k != Mono.Kind.INVALID) { result = ScriptObjectHelper.FromValue(res); } return(result); }
internal object InvokeSelfInternal(params object [] args) { CheckHandle(); int length = args == null ? 0 : args.Length; object result = null; Mono.Value res; Mono.Value [] vargs = new Mono.Value [length]; for (int i = 0; i < length; i++) { ScriptObjectHelper.ToValue(ref vargs [i], args [i]); } try { if (!NativeMethods.html_object_invoke_self(PluginHost.Handle, Handle, vargs, (uint)length, out res)) { throw new InvalidOperationException(); } if (res.k != Mono.Kind.INVALID) { result = ScriptObjectHelper.FromValue(res); } } finally { res.Dispose(); foreach (var v in vargs) { v.Dispose(); } } return(result); }
internal static void SetPropertyInternal(IntPtr h, string name, object value) { CheckName(name); Mono.Value dp = new Mono.Value(); ScriptObjectHelper.ToValue(ref dp, value); using (dp) { NativeMethods.html_object_set_property(PluginHost.Handle, h, name, ref dp); } }
private unsafe bool AddChild (XamlCallbackData *data, Value* parent_parent_ptr, bool parent_is_property, string parent_xmlns, Value *parent_ptr, IntPtr parent_data, Value* child_ptr, IntPtr child_data) { object parent = Value.ToObject (null, parent_ptr); object child = Value.ToObject (null, child_ptr); if (parent_is_property) { object parent_parent = Value.ToObject (null, parent_parent_ptr); return AddChildToProperty (data, parent_parent, parent_xmlns, parent, child, child_data); } return AddChildToItem (data, parent_parent_ptr, parent, parent_data, child_ptr, child, child_data); }
private unsafe MethodInfo GetMethodForAttachedProperty (Value *top_level, string xmlns, string type_name, string full_type_name, string prop_name, string method_prefix, Type [] arg_types) { string assembly_name = AssemblyNameFromXmlns (xmlns); string ns = ClrNamespaceFromXmlns (xmlns); if (assembly_name == null && !TryGetDefaultAssemblyName (top_level, out assembly_name)) { Console.Error.WriteLine ("Unable to find an assembly to load type from."); return null; } Assembly clientlib; if (LoadAssembly (assembly_name, out clientlib) != AssemblyLoadResult.Success) { Console.Error.WriteLine ("couldn't load assembly: {0} namespace: {1}", assembly_name, ns); return null; } Type attach_type = clientlib.GetType (full_type_name, false); if (attach_type == null) { attach_type = Application.GetComponentTypeFromName (type_name); if (attach_type == null) { Console.Error.WriteLine ("attach type is null type name: {0} full type name: {1}", type_name, full_type_name); return null; } } MethodInfo [] methods = attach_type.GetMethods (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); string method_name = String.Concat (method_prefix, prop_name); foreach (MethodInfo method in methods) { if (method.Name != method_name) continue; ParameterInfo [] the_params = method.GetParameters (); if (the_params.Length != arg_types.Length) continue; bool match = true; for (int i = 0; i < arg_types.Length; i++) { if (!arg_types [i].IsAssignableFrom (the_params [i].ParameterType)) { Console.WriteLine ("NOT A MATCH: {0} -- {1} : {2}", method, arg_types [i], the_params [i]); match = false; break; } } if (match) return method; } return null; }
private unsafe bool SetProperty (XamlCallbackData *data, string xmlns, Value* target_ptr, IntPtr target_data, Value* target_parent_ptr, string prop_xmlns, string name, Value* value_ptr, IntPtr value_data) { string error; object target = Value.ToObject (null, target_ptr); if (target == null) { Console.Error.WriteLine ("target is null: {0} {1} {2}", (IntPtr)target_ptr, name, xmlns); return false; } if (name == null) { if (TrySetEnumContentProperty (data, xmlns, target, target_ptr, target_data, value_ptr, value_data)) return true; if (TrySetCollectionContentProperty (xmlns, target, target_ptr, target_data, value_ptr, value_data)) return true; if (TrySetObjectTextProperty (data, xmlns, target, target_ptr, target_data, value_ptr, value_data)) return true; Console.Error.WriteLine ("no property name supplied"); return false; } string full_name = name; int dot = name.IndexOf ('.'); string type_name = null; if (dot >= 0) { type_name = name.Substring (0, dot); if (prop_xmlns != null) { string ns = ClrNamespaceFromXmlns (prop_xmlns); if (ns != null) type_name = String.Concat (ns, ".", type_name); } name = name.Substring (++dot, name.Length - dot); } if (TrySetExpression (data, xmlns, target, target_data, target_parent_ptr, type_name, prop_xmlns, name, full_name, value_ptr, value_data)) return true; if (!IsAttachedProperty (data, target, xmlns, prop_xmlns, full_name)) { if (TrySetPropertyReflection (data, xmlns, target, target_data, target_parent_ptr, type_name, name, value_ptr, value_data, out error)) return true; if (TrySetEventReflection (data, xmlns, target, type_name, name, value_ptr, out error)) return true; } else { if (TrySetAttachedProperty (data, xmlns, target, target_data, prop_xmlns, full_name, value_ptr)) return true; } return false; }
private IntPtr ValueToIntPtr (Value v) { IntPtr ptr = Marshal.AllocHGlobal (Marshal.SizeOf (v)); Marshal.StructureToPtr (v, ptr, false); return ptr; }
// // Proxy so that we return bool in case of any failures, instead of // generating an exception and unwinding the stack. // private unsafe bool cb_set_property (XamlCallbackData *data, string xmlns, Value* target, IntPtr target_data, Value* target_parent, string prop_xmlns, string name, Value* value_ptr, IntPtr value_data, ref MoonError error) { try { return SetProperty (data, xmlns, target, target_data, target_parent, prop_xmlns, name, value_ptr, value_data); } catch (Exception ex) { try { Console.Error.WriteLine ("ManagedXamlLoader::SetProperty ({0}, {1}, {2}, {3}, {4}) threw an exception: {5}", (IntPtr) data->top_level, xmlns, (IntPtr)target, name, (IntPtr)value_ptr, ex.Message); Console.Error.WriteLine (ex); error = new MoonError (ex); return false; } catch { return false; } } }
public void Hydrate (Value value, string xaml, bool createNamescope, bool validateTemplates) { Hydrate (value, xaml, createNamescope, validateTemplates, false); }
protected abstract void HydrateInternal (Value value, string xaml, bool createNamescope, bool validateTemplates, bool import_default_xmlns);
private unsafe bool TrySetExpression (XamlCallbackData *data, string xmlns, object target, IntPtr target_data, Value* target_parent_ptr, string type_name, string prop_xmlns, string name, string full_name, Value* value_ptr, IntPtr value_data) { DependencyObject dob = target as DependencyObject; object obj_value = Value.ToObject (null, value_ptr); string str_value = obj_value as string; if (str_value == null) return false; if (!str_value.StartsWith ("{")) return false; MarkupExpressionParser p = new SL3MarkupExpressionParser (target, name, data->parser, target_data); string expression = str_value; object o = p.ParseExpression (ref expression); if (o == null) return false; if (o is Binding) { Binding binding = o as Binding; DependencyProperty prop = null; if (dob != null) { string full_type_name = type_name; if (IsAttachedProperty (full_name)) GetNameForAttachedProperty (xmlns, prop_xmlns, full_name, out type_name, out full_type_name); prop = LookupDependencyPropertyForBinding (data, dob, full_type_name, name); if (prop == null && IsAttachedProperty (full_name)) prop = LookupDependencyPropertyForBinding (data, dob, full_name.Split ('.')[0], name); } // If it's null we should look for a regular CLR property if (prop != null) { BindingOperations.SetBinding (dob, prop, binding); return true; } } if (o is TemplateBindingExpression) { // Applying a {TemplateBinding} to a DO which is not a FrameworkElement should silently discard // the binding. if (!(dob is FrameworkElement)) return true; TemplateBindingExpression tb = o as TemplateBindingExpression; IntPtr context = NativeMethods.sl3_xaml_loader_get_context (data->loader); IntPtr source_ptr = NativeMethods.xaml_context_get_template_binding_source (context); // Silently discard TemplateBindings which are not in ControlTemplates FrameworkTemplate source_template = (FrameworkTemplate) NativeDependencyObjectHelper.Lookup (NativeMethods.xaml_context_get_source_template (context)); if (!(source_template is ControlTemplate)) return true; DependencyObject templateSourceObject = NativeDependencyObjectHelper.FromIntPtr (source_ptr) as DependencyObject; if (templateSourceObject == null) return false; DependencyProperty sourceProperty = DependencyProperty.Lookup (templateSourceObject.GetKind(), tb.SourcePropertyName); if (sourceProperty == null) return false; DependencyProperty prop = null; if (dob != null) prop = LookupDependencyPropertyForBinding (data, dob, type_name, name); if (prop == null) return false; tb.TargetProperty = prop; tb.SourceProperty = sourceProperty; ((FrameworkElement) dob).SetTemplateBinding (prop, tb); return true; } if (IsAttachedProperty (full_name)) return TrySetAttachedProperty (data, xmlns, target, target_data, prop_xmlns, full_name, o); PropertyInfo pi = target.GetType ().GetProperty (name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy); o = ConvertType (pi, pi.PropertyType, o); SetValue (data, target_data, pi, target, o); return true; }
private unsafe bool TrySetAttachedProperty (XamlCallbackData *data, string xmlns, object target, IntPtr target_data, string prop_xmlns, string name, Value* value_ptr) { string full_name = name; string type_name = null; string full_type_name = null; name = GetNameForAttachedProperty (xmlns, prop_xmlns, name, out type_name, out full_type_name); if (name == null) return false; string error = null; object o_value = GetObjectValue (target, target_data, name, data->parser, value_ptr, out error); return TrySetAttachedProperty (data, xmlns, target, target_data, prop_xmlns, full_name, o_value); }
private unsafe bool LookupPropertyObject (Value* top_level, Value* parent_value, string xmlns, string name, int dot, bool create, out Value value) { string prop_name = name.Substring (dot + 1); object parent = Value.ToObject (null, parent_value); if (parent == null) { value = Value.Empty; return false; } PropertyInfo pi = null; bool is_attached = true; string type_name = name.Substring (0, dot); Type t = parent.GetType (); while (t != typeof (object)) { if (t.Name == type_name) { is_attached = false; break; } t = t.BaseType; } if (is_attached) { Type attach_type = null; string full_type_name = type_name; if (xmlns != null) { string ns = ClrNamespaceFromXmlns (xmlns); full_type_name = String.Concat (ns, ".", type_name); } MethodInfo get_method = GetGetMethodForAttachedProperty (top_level, xmlns, type_name, full_type_name, prop_name); if (get_method != null) attach_type = get_method.ReturnType; if (attach_type == null) { value = Value.Empty; return false; } ManagedType mt = Deployment.Current.Types.Find (attach_type); value = Value.Empty; value.IsNull = true; value.k = mt.native_handle; return true; } else { pi = parent.GetType ().GetProperty (name.Substring (dot + 1), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy); if (pi == null) { value = Value.Empty; return false; } ManagedType mt = Deployment.Current.Types.Find (pi.PropertyType); value = Value.Empty; value.k = mt.native_handle; value.IsNull = true; return true; } }
private unsafe bool LookupComponentFromName (Value* top_level, string name, bool create, out Value value) { if (!create) { Type type = Application.GetComponentTypeFromName (name); if (type == null) { value = Value.Empty; return false; } value = Value.Empty; value.k = Deployment.Current.Types.Find (type).native_handle; return true; } object obj = Application.CreateComponentFromName (name); if (obj == null) { value = Value.Empty; return false; } value = Value.FromObject (obj, false); return true; }
private unsafe bool LookupObject (Value *top_level, Value *parent, string xmlns, string name, bool create, bool is_property, out Value value) { if (name == null) throw new ArgumentNullException ("type_name"); if (is_property) { int dot = name.IndexOf ('.'); return LookupPropertyObject (top_level, parent, xmlns, name, dot, create, out value); } if (top_level == null && xmlns == null) { return LookupComponentFromName (top_level, name, create, out value); } string assembly_name = AssemblyNameFromXmlns (xmlns); string clr_namespace = ClrNamespaceFromXmlns (xmlns); string full_name = string.IsNullOrEmpty (clr_namespace) ? name : clr_namespace + "." + name; Type type = LookupType (top_level, assembly_name, full_name); if (type == null) { Console.Error.WriteLine ("ManagedXamlLoader::LookupObject: GetType ({0}) failed using assembly: {1} ({2}, {3}).", name, assembly_name, xmlns, full_name); value = Value.Empty; return false; } if (create) { if (!type.IsPublic) { value = Value.Empty; throw new XamlParseException ("Attempting to create a private type"); } object res = null; try { res = Activator.CreateInstance (type); } catch (TargetInvocationException ex) { Console.WriteLine (ex); Console.Error.WriteLine ("ManagedXamlLoader::LookupObject: CreateInstance ({0}) failed: {1}", name, ex.InnerException); value = Value.Empty; return false; } if (res == null) { Console.Error.WriteLine ("ManagedXamlLoader::LookupObject ({0}, {1}, {2}): unable to create object instance: '{3}', the object was of type '{4}'", assembly_name, xmlns, name, full_name, type.FullName); value = Value.Empty; return false; } // This is freed in native. value = Value.FromObject (res, false); } else { value = Value.Empty; value.k = Deployment.Current.Types.Find (type).native_handle; } return true; }
private unsafe bool TryGetDefaultAssemblyName (Value* top_level, out string assembly_name) { if (assembly != null) { assembly_name = assembly.GetName ().Name; return true; } object obj = Value.ToObject (null, top_level); if (obj == null) { assembly_name = null; return false; } assembly_name = obj.GetType ().Assembly.GetName ().Name; return true; }
private unsafe bool cb_add_child (XamlCallbackData *data, Value* parent_parent, bool parent_is_property, string parent_xmlns, Value *parent, IntPtr parent_data, Value* child, IntPtr child_data, ref MoonError error) { try { return AddChild (data, parent_parent, parent_is_property, parent_xmlns, parent, parent_data, child, child_data); } catch (Exception ex) { Console.Error.WriteLine (ex); error = new MoonError (ex); return false; } }
// // Hydrates the object dob from the given xaml // public void Hydrate (Value value, string xaml) { Hydrate (value, xaml, true, false, false); }
private unsafe bool TrySetPropertyReflection (XamlCallbackData *data, string xmlns, object target, IntPtr target_data, Value* target_parent_ptr, string type_name, string name, Value* value_ptr, IntPtr value_data, out string error) { PropertyInfo pi = target.GetType ().GetProperty (name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy); if (pi == null) { error = "Property does not exist."; return false; } if (!SetPropertyFromValue (data, target, target_data, target_parent_ptr, pi, value_ptr, value_data, out error)) return false; error = null; return true; }
public void Hydrate (Value value, string xaml, bool createNamescope) { Hydrate (value, xaml, createNamescope, false, false); }
private static unsafe object GetObjectValue (object target, IntPtr target_data, string prop_name, IntPtr parser, Value* value_ptr, out string error) { error = null; IntPtr unmanaged_value = IntPtr.Zero; object o_value = Value.ToObject (null, value_ptr); if (error == null && unmanaged_value != IntPtr.Zero) o_value = Value.ToObject (null, unmanaged_value); if (o_value is String && SL3MarkupExpressionParser.IsStaticResource ((string) o_value)) { MarkupExpressionParser mp = new SL3MarkupExpressionParser ((DependencyObject) target, prop_name, parser, target_data); string str_value = o_value as String; o_value = mp.ParseExpression (ref str_value); } return o_value; }
public void Hydrate (Value value, string xaml, bool createNamescope, bool validateTemplates, bool import_default_xmlns) { HydrateInternal (value, xaml, createNamescope, validateTemplates, import_default_xmlns); }
private static unsafe IntPtr ParseTemplate (Value *context_ptr, string resource_base, IntPtr surface, IntPtr binding_source, string xaml, ref MoonError error) { XamlContext context = Value.ToObject (typeof (XamlContext), context_ptr) as XamlContext; var parser = new XamlParser (context); var source = NativeDependencyObjectHelper.FromIntPtr (binding_source); if (source == null) { error = new MoonError (parser.ParseException ("Attempting to parse a template with an invalid binding source.")); return IntPtr.Zero; } FrameworkElement fwe = source as FrameworkElement; if (fwe == null) { error = new MoonError (parser.ParseException ("Only FrameworkElements can be used as TemplateBinding sources.")); return IntPtr.Zero; } context.IsExpandingTemplate = true; context.TemplateBindingSource = fwe; INativeEventObjectWrapper dob = null; try { dob = parser.ParseString (xaml) as INativeEventObjectWrapper; } catch (Exception e) { error = new MoonError (e); return IntPtr.Zero; } if (dob == null) { error = new MoonError (parser.ParseException ("Unable to parse template item.")); return IntPtr.Zero; } return dob.NativeHandle; }
private static DependencyProperty RegisterAny(string name, Type propertyType, Type ownerType, PropertyMetadata metadata, bool attached, bool readOnly, bool setsParent, bool custom) { ManagedType property_type; ManagedType owner_type; UnmanagedPropertyChangeHandler handler = null; CustomDependencyProperty result; bool is_nullable = false; object default_value = DependencyProperty.UnsetValue; PropertyChangedCallback property_changed_callback = null; if (name == null) throw new ArgumentNullException ("name"); if (name.Length == 0) throw new ArgumentException("The 'name' argument cannot be an empty string"); if (propertyType == null) throw new ArgumentNullException ("propertyType"); if (ownerType == null) throw new ArgumentNullException ("ownerType"); if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition () == typeof (Nullable<>)) { is_nullable = true; // Console.WriteLine ("DependencyProperty.RegisterAny (): found nullable {0}, got nullable {1}", propertyType.FullName, propertyType.GetGenericArguments () [0].FullName); propertyType = propertyType.GetGenericArguments () [0]; } Types types = Deployment.Current.Types; property_type = types.Find (propertyType); owner_type = types.Find (ownerType); if (metadata != null) { default_value = metadata.DefaultValue ?? UnsetValue; property_changed_callback = metadata.property_changed_callback; } if ((default_value == DependencyProperty.UnsetValue) && propertyType.IsValueType && !is_nullable) default_value = Activator.CreateInstance (propertyType); if (default_value != null && default_value != UnsetValue && !propertyType.IsAssignableFrom (default_value.GetType ())) throw new ArgumentException (string.Format ("DefaultValue is of type {0} which is not compatible with type {1}", default_value.GetType (), propertyType)); if (property_changed_callback != null) handler = UnmanagedPropertyChangedCallbackSafe; Value v; if (default_value == DependencyProperty.UnsetValue) { v = new Value { k = types.TypeToKind (propertyType), IsNull = true }; default_value = null; } else { v = Value.FromObject (default_value, true); } IntPtr handle; using (v) { var val = v; if (custom) handle = NativeMethods.dependency_property_register_custom_property (name, property_type.native_handle, owner_type.native_handle, ref val, attached, readOnly, handler); else handle = NativeMethods.dependency_property_register_core_property (name, property_type.native_handle, owner_type.native_handle, ref val, attached, readOnly, handler); } if (handle == IntPtr.Zero) return null; if (is_nullable) NativeMethods.dependency_property_set_is_nullable (handle, true); result = new CustomDependencyProperty (handle, name, property_type, owner_type, default_value); result.attached = attached; result.PropertyChangedHandler = handler; result.property_changed_callback = property_changed_callback; return result; }
// // How do we support "null" values, should the caller take care of that? // // The caller is responsible for calling value_free_value on the returned Value public static Value FromObject (object v, bool box_value_types) { Value value = new Value (); unsafe { // get rid of this case right away. if (box_value_types && v.GetType().IsValueType) { //Console.WriteLine ("Boxing a value of type {0}:", v.GetType()); GCHandle handle = GCHandle.Alloc (v); value.k = Deployment.Current.Types.TypeToKind (v.GetType ()); value.IsGCHandle = true; value.u.p = GCHandle.ToIntPtr (handle); return value; } if (v is IEasingFunction && !(v is EasingFunctionBase)) v = new EasingFunctionWrapper (v as IEasingFunction); if (v is INativeEventObjectWrapper) { INativeEventObjectWrapper dov = (INativeEventObjectWrapper) v; if (dov.NativeHandle == IntPtr.Zero) throw new Exception (String.Format ( "Object {0} has not set its native property", dov.GetType())); NativeMethods.event_object_ref (dov.NativeHandle); value.k = dov.GetKind (); value.u.p = dov.NativeHandle; } else if (v is DependencyProperty) { value.k = Kind.DEPENDENCYPROPERTY; value.u.p = ((DependencyProperty)v).Native; } else if (v is int || (v.GetType ().IsEnum && Enum.GetUnderlyingType (v.GetType()) == typeof(int))) { value.k = Deployment.Current.Types.TypeToKind (v.GetType ()); value.u.i32 = (int) v; } else if (v is bool) { value.k = Kind.BOOL; value.u.i32 = ((bool) v) ? 1 : 0; } else if (v is double) { value.k = Kind.DOUBLE; value.u.d = (double) v; } else if (v is float) { value.k = Kind.FLOAT; value.u.f = (float) v; } else if (v is long) { value.k = Kind.INT64; value.u.i64 = (long) v; } else if (v is TimeSpan) { TimeSpan ts = (TimeSpan) v; value.k = Kind.TIMESPAN; value.u.i64 = ts.Ticks; } else if (v is ulong) { value.k = Kind.UINT64; value.u.ui64 = (ulong) v; } else if (v is uint) { value.k = Kind.UINT32; value.u.ui32 = (uint) v; } else if (v is char) { value.k = Kind.CHAR; value.u.ui32 = (uint) (char) v; } else if (v is string) { value.k = Kind.STRING; value.u.p = StringToIntPtr ((string) v); } else if (v is Rect) { Rect rect = (Rect) v; value.k = Kind.RECT; value.u.p = Marshal.AllocHGlobal (sizeof (Rect)); Marshal.StructureToPtr (rect, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is Size) { Size size = (Size) v; value.k = Kind.SIZE; value.u.p = Marshal.AllocHGlobal (sizeof (Size)); Marshal.StructureToPtr (size, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is CornerRadius) { CornerRadius corner = (CornerRadius) v; value.k = Kind.CORNERRADIUS; value.u.p = Marshal.AllocHGlobal (sizeof (CornerRadius)); Marshal.StructureToPtr (corner, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is AudioFormat) { AudioFormat f = (AudioFormat) v; value.k = Kind.AUDIOFORMAT; value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedAudioFormat)); UnmanagedAudioFormat *format = (UnmanagedAudioFormat*) value.u.p; format->bitsPerSample = f.BitsPerSample; format->channels = f.Channels; format->samplesPerSecond = f.SamplesPerSecond; format->waveFormat = f.WaveFormat; } else if (v is VideoFormat) { VideoFormat f = (VideoFormat) v; value.k = Kind.VIDEOFORMAT; value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedVideoFormat)); UnmanagedVideoFormat *format = (UnmanagedVideoFormat*) value.u.p; format->framesPerSecond = f.FramesPerSecond; format->height = f.PixelHeight; format->width = f.PixelWidth; format->stride = f.Stride; format->pixelFormat = f.PixelFormat; } else if (v is Point) { Point pnt = (Point) v; value.k = Kind.POINT; value.u.p = Marshal.AllocHGlobal (sizeof (Point)); Marshal.StructureToPtr (pnt, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is Thickness) { Thickness thickness = (Thickness)v; value.k = Kind.THICKNESS; value.u.p = Marshal.AllocHGlobal (sizeof (Thickness)); Marshal.StructureToPtr (thickness, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is Color) { Color c = (Color) v; value.k = Kind.COLOR; value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedColor)); UnmanagedColor* color = (UnmanagedColor*) value.u.p; color->r = c.R / 255.0f; color->g = c.G / 255.0f; color->b = c.B / 255.0f; color->a = c.A / 255.0f; } else if (v is Matrix) { // hack around the fact that managed Matrix is a struct while unmanaged Matrix is a DO // i.e. the unmanaged and managed structure layouts ARE NOT equal return FromObject (new UnmanagedMatrix ((Matrix) v), box_value_types); } else if (v is StylusPoint) { return FromObject (new UnmanagedStylusPoint ((StylusPoint) v), box_value_types); } else if (v is Matrix3D) { // hack around the fact that managed Matrix3D is a struct while unmanaged Matrix3D is a DO // i.e. the unmanaged and managed structure layouts ARE NOT equal return FromObject (new UnmanagedMatrix3D ((Matrix3D) v), box_value_types); } else if (v is Duration) { Duration d = (Duration) v; value.k = Kind.DURATION; value.u.p = Marshal.AllocHGlobal (sizeof (Duration)); Marshal.StructureToPtr (d, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is KeyTime) { KeyTime k = (KeyTime) v; value.k = Kind.KEYTIME; value.u.p = Marshal.AllocHGlobal (sizeof (KeyTime)); Marshal.StructureToPtr (k, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is RepeatBehavior) { RepeatBehavior d = (RepeatBehavior) v; value.k = Kind.REPEATBEHAVIOR; value.u.p = Marshal.AllocHGlobal (sizeof (RepeatBehavior)); Marshal.StructureToPtr (d, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is FontFamily) { FontFamily family = (FontFamily) v; value.k = Kind.FONTFAMILY; value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontFamily)); Marshal.StructureToPtr (family, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is FontSource) { FontSource source = (FontSource) v; value.k = Kind.FONTSOURCE; if (source.wrapper != null || source.typeface != null) { value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontSource)); UnmanagedFontSource *ufs = (UnmanagedFontSource *) value.u.p; ufs->type = source.type; switch (source.type) { case FontSourceType.ManagedStream: ManagedStreamCallbacks callbacks = source.wrapper.GetCallbacks (); ufs->source.stream = Marshal.AllocHGlobal (sizeof (UnmanagedStreamCallbacks)); Marshal.StructureToPtr (callbacks, ufs->source.stream, false); break; case FontSourceType.GlyphTypeface: ufs->source.typeface = source.typeface.Native; break; } } else { value.IsNull = true; } } else if (v is PropertyPath) { PropertyPath propertypath = (PropertyPath) v; value.k = Kind.PROPERTYPATH; value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedPropertyPath)); UnmanagedPropertyPath *upp = (UnmanagedPropertyPath *) value.u.p; upp->property = propertypath.NativeDP; if (upp->property == IntPtr.Zero) upp->pathString = StringToIntPtr (propertypath.Path); else upp->pathString = IntPtr.Zero; upp->expandedPathString = IntPtr.Zero; } else if (v is Uri) { Uri uri = (Uri) v; value.k = Kind.URI; value.u.p = UnmanagedUri.FromUri (uri); } else if (v is XmlLanguage) { XmlLanguage lang = (XmlLanguage) v; value.k = Kind.STRING; value.u.p = StringToIntPtr (lang.IetfLanguageTag); } else if (v is Cursor) { Cursor c = (Cursor) v; value.k = Kind.CURSORTYPE; value.u.i32 = (int)c.cursor; } else if (v is GridLength) { GridLength gl = (GridLength) v; value.k = Kind.GRIDLENGTH; value.u.p = Marshal.AllocHGlobal (sizeof (GridLength)); Marshal.StructureToPtr (gl, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is FontStretch) { FontStretch stretch = (FontStretch) v; value.k = Kind.FONTSTRETCH; value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontStretch)); Marshal.StructureToPtr (stretch, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is FontStyle) { FontStyle style = (FontStyle) v; value.k = Kind.FONTSTYLE; value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontStyle)); Marshal.StructureToPtr (style, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is FontWeight) { FontWeight weight = (FontWeight) v; value.k = Kind.FONTWEIGHT; value.u.p = Marshal.AllocHGlobal (sizeof (UnmanagedFontWeight)); Marshal.StructureToPtr (weight, value.u.p, false); // Unmanaged and managed structure layout is equal. } else if (v is TextDecorationCollection) { value.k = Kind.TEXTDECORATIONS; value.u.i32 = (int) (v as TextDecorationCollection).Kind; } else if (v is Type) { Type t = v as Type; ManagedTypeInfo mti = new ManagedTypeInfo (); mti.full_name = StringToIntPtr (t.FullName); mti.Kind = Deployment.Current.Types.TypeToKind (t); value.k = Kind.MANAGEDTYPEINFO; value.u.p = Marshal.AllocHGlobal (sizeof (ManagedTypeInfo)); Marshal.StructureToPtr (mti, value.u.p, false); } else { //Console.WriteLine ("Do not know how to encode {0} yet, boxing it", v.GetType ()); // TODO: We probably need to marshal types that can animate as the // corresponding type (Point, Double, Color, etc). // TODO: We need to store the GCHandle somewhere so that we can free it, // or register a callback on the surface for the unmanaged code to call. GCHandle handle = GCHandle.Alloc (v); value.IsGCHandle = true; value.k = Deployment.Current.Types.TypeToKind (v.GetType ()); value.u.p = GCHandle.ToIntPtr (handle); } } return value; }
private unsafe bool TrySetEventReflection (XamlCallbackData *data, string xmlns, object publisher, string type_name, string name, Value* value_ptr, out string error) { object subscriber = null; EventInfo ie = publisher.GetType ().GetEvent (name); string handler_name = Value.ToObject (null, value_ptr) as string; try { subscriber = Value.ToObject (null, data->top_level); } catch { } //Console.WriteLine ("TrySetEventReflection ({0}, {1}, {2}, {3}, {4}, {5}) handler_name: {6}", data->top_level, xmlns, publisher, type_name, name, value_ptr, handler_name); if (ie == null) { error = "Event does not exist."; return false; } if (handler_name == null) { error = "No method name supplied for event handler."; return false; } MethodInfo invoker_info = ie.EventHandlerType.GetMethod ("Invoke"); ParameterInfo [] event_params = invoker_info.GetParameters (); Delegate d = null; Type stype = subscriber.GetType (); MethodInfo [] methods = stype.GetMethods (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance); MethodInfo candidate = null; bool name_match = false; for (int i = 0; i < methods.Length; i++) { MethodInfo m = methods [i]; ParameterInfo [] parameters; if (m.Name != handler_name) continue; if (name_match) { error = "Multiple candidates with the same name found for event handler."; // Console.WriteLine (error); return false; } name_match = true; if (m.ReturnType != typeof (void)) continue; parameters = m.GetParameters (); if (parameters.Length != event_params.Length) continue; bool match = true; for (int p = 0; p < parameters.Length; p++) { if (!event_params [p].ParameterType.IsSubclassOf (parameters [p].ParameterType) && parameters [p].ParameterType != event_params [p].ParameterType) { Console.WriteLine ("mismatch: {0} and {1}", parameters [p].ParameterType, event_params [p].ParameterType); match = false; break; } } if (!match) continue; if (candidate != null) { error = "Multiple candidates for event handler found."; // Console.WriteLine (error); return false; } candidate = m; } if (candidate == null) { error = "Event handler not found."; // Console.WriteLine (error); return false; } d = Delegate.CreateDelegate (ie.EventHandlerType, subscriber, candidate, false); if (d == null) { Console.Error.WriteLine ("ManagedXamlLoader::HookupEvent ({0}, {1}, {2}): unable to create delegate (src={3} target={4}).", (IntPtr) data->top_level, name, (IntPtr)value_ptr, ie.EventHandlerType, publisher); error = "Can not create even delegate."; return false; } // Console.Error.WriteLine ("ManagedXamlLoader::HookupEvent ({0}, {1}, {2}): Successfully created delegate (src={3} target={4}).", (IntPtr) data->top_level, name, value_ptr, ie.EventHandlerType, publisher); error = null; ie.AddEventHandler (publisher, d); return true; }
/// /// /// Callbacks invoked by the xaml.cpp C++ parser /// /// #region Callbacks from xaml.cpp // // Proxy so that we return IntPtr.Zero in case of any failures, instead of // genereting an exception and unwinding the stack. // private unsafe bool cb_lookup_object (XamlCallbackData *data, Value* parent, string xmlns, string name, bool create, bool is_property, out Value value, ref MoonError error) { value = Value.Empty; try { return LookupObject (data->top_level, parent, xmlns, name, create, is_property, out value); } catch (Exception ex) { NativeMethods.value_free_value (ref value); value = Value.Empty; Console.Error.WriteLine ("ManagedXamlLoader::LookupObject ({0}, {1}, {2}, {3}) failed: {3} ({4}).", (IntPtr) data->top_level, xmlns, create, name, ex.Message, ex.GetType ().FullName); Console.WriteLine (ex); error = new MoonError (ex); return false; } }
private unsafe bool TrySetEnumContentProperty (XamlCallbackData *data, string xmlns, object target, Value* target_ptr, IntPtr target_data, Value* value_ptr, IntPtr value_data) { object obj_value = Value.ToObject (null, value_ptr); string str_value = obj_value as string; if (str_value == null) return false; string assembly_name = AssemblyNameFromXmlns (xmlns); string clr_namespace = ClrNamespaceFromXmlns (xmlns); string type_name = NativeMethods.xaml_get_element_name (data->parser, target_data); string full_name = String.IsNullOrEmpty (clr_namespace) ? type_name : clr_namespace + "." + type_name; Type type = LookupType (data->top_level, assembly_name, full_name); if (type == null || !type.IsEnum) return false; object e = Enum.Parse (type, str_value, true); NativeMethods.value_free_value2 ((IntPtr)target_ptr); unsafe { Value *val = (Value *) target_ptr; GCHandle handle = GCHandle.Alloc (e); val->IsGCHandle = true; val->k = Deployment.Current.Types.TypeToKind (e.GetType ()); val->u.p = GCHandle.ToIntPtr (handle); } return true; }
private unsafe bool TrySetCollectionContentProperty (string xmlns, object target, Value* target_ptr, IntPtr target_data, Value* value_ptr, IntPtr value_data) { IList list = target as IList; if (list == null) return false; object value = Value.ToObject (null, value_ptr); list.Add (value); return true; }
public static unsafe object ToObject (Type type, Value* value) { if (value == null || value->IsNull) { return null; } if (value->IsGCHandle) { IntPtr managed_object = value->u.p; GCHandle handle = GCHandle.FromIntPtr (managed_object); return handle.Target; } switch (value->k) { case Kind.INVALID: return null; case Kind.DEPENDENCYPROPERTY: return DependencyProperty.Lookup (value->u.p); case Kind.BOOL: return value->u.i32 != 0; case Kind.DOUBLE: return value->u.d; case Kind.FLOAT: return value->u.f; case Kind.UINT64: return value->u.ui64; case Kind.INT64: return value->u.i64; case Kind.TIMESPAN: return new TimeSpan (value->u.i64); case Kind.CURSORTYPE: return Cursors.FromEnum ((CursorType) value->u.i32); case Kind.TEXTDECORATIONS: return (value->u.i32 == (int) TextDecorationKind.Underline) ? TextDecorations.Underline : null; case Kind.INT32: return value->u.i32; case Kind.CHAR: return (char) value->u.ui32; case Kind.SURFACE: return NativeDependencyObjectHelper.FromIntPtr (value->u.p); case Kind.STRING: { string str = Marshal.PtrToStringAuto (value->u.p); if (type == null) return str; // marshall back to the .NET type that we simply serialised as 'string' for unmanaged usage if (type == typeof (System.Windows.Markup.XmlLanguage)) return XmlLanguage.GetLanguage (str); else return str; } case Kind.URI: { UnmanagedUri *uri = (UnmanagedUri*)value->u.p; return uri->originalString == IntPtr.Zero ? new Uri("", UriKind.Relative) : new Uri (Marshal.PtrToStringAuto (uri->originalString), uri->isAbsolute ? UriKind.Absolute : UriKind.Relative); } case Kind.XMLLANGUAGE: { string str = Marshal.PtrToStringAuto (value->u.p); return XmlLanguage.GetLanguage (str); } case Kind.FONTFAMILY: { UnmanagedFontFamily *family = (UnmanagedFontFamily*)value->u.p; return new FontFamily (family == null ? null : Marshal.PtrToStringAuto (family->source)); } case Kind.FONTSTRETCH: { UnmanagedFontStretch *stretch = (UnmanagedFontStretch*)value->u.p; return new FontStretch (stretch == null ? FontStretchKind.Normal : stretch->stretch); } case Kind.FONTSTYLE: { UnmanagedFontStyle *style = (UnmanagedFontStyle*)value->u.p; return new FontStyle (style == null ? FontStyleKind.Normal : style->style); } case Kind.FONTWEIGHT: { UnmanagedFontWeight *weight = (UnmanagedFontWeight*)value->u.p; return new FontWeight (weight == null ? FontWeightKind.Normal : weight->weight); } case Kind.FONTSOURCE: { UnmanagedFontSource *fs = (UnmanagedFontSource *) value->u.p; ManagedStreamCallbacks callbacks; GlyphTypeface typeface; StreamWrapper wrapper; switch (fs->type) { case FontSourceType.ManagedStream: callbacks = (ManagedStreamCallbacks) Marshal.PtrToStructure (fs->source.stream, typeof (ManagedStreamCallbacks)); wrapper = (StreamWrapper) GCHandle.FromIntPtr (callbacks.handle).Target; return new FontSource (wrapper.stream); case FontSourceType.GlyphTypeface: typeface = new GlyphTypeface (fs->source.typeface); return new FontSource (typeface); default: throw new Exception (String.Format ("Do not know how to create a FontSource of type {0}", fs->type.ToString ())); } } case Kind.GLYPHTYPEFACE: { return new GlyphTypeface (value->u.p); } case Kind.PROPERTYPATH: { UnmanagedPropertyPath *propertypath = (UnmanagedPropertyPath *) value->u.p; if (propertypath == null) return new PropertyPath (null); if (propertypath->property != IntPtr.Zero) return null; return new PropertyPath (Marshal.PtrToStringAuto (propertypath->pathString)); } case Kind.POINT: { Point *point = (Point*)value->u.p; return (point == null) ? new Point (0,0) : *point; } case Kind.RECT: { Rect *rect = (Rect*)value->u.p; return (rect == null) ? new Rect (0,0,0,0) : *rect; } case Kind.SIZE: { Size *size = (Size*)value->u.p; return (size == null) ? new Size (0,0) : *size; } case Kind.CORNERRADIUS: { CornerRadius *corner = (CornerRadius*)value->u.p; return (corner == null) ? new CornerRadius (0) : *corner; } case Kind.AUDIOFORMAT: { UnmanagedAudioFormat *format = (UnmanagedAudioFormat*)value->u.p; return (format == null) ? new AudioFormat () : format->ToAudioFormat (); } case Kind.VIDEOFORMAT: { UnmanagedVideoFormat *format = (UnmanagedVideoFormat*)value->u.p; return (format == null) ? new VideoFormat () : format->ToVideoFormat (); } case Kind.THICKNESS: { Thickness *thickness = (Thickness*)value->u.p; return (thickness == null) ? new Thickness (0) : *thickness; } case Kind.COLOR: { UnmanagedColor *color = (UnmanagedColor*)value->u.p; if (color == null) return new Color (); return color->ToColor (); } case Kind.MATRIX: case Kind.UNMANAGEDMATRIX: { return new Matrix (value->u.p); } case Kind.MATRIX3D: case Kind.UNMANAGEDMATRIX3D: { return new Matrix3D (value->u.p); } case Kind.STYLUSPOINT: case Kind.UNMANAGEDSTYLUSPOINT: { var kind = value->k; var ptr = value->u.p; var x = (double) Value.ToObject (typeof (double), NativeMethods.dependency_object_get_value (ptr, kind, UnmanagedStylusPoint.XProperty.Native)); var y = (double) Value.ToObject (typeof (double), NativeMethods.dependency_object_get_value (ptr, kind, UnmanagedStylusPoint.YProperty.Native)); var pressure = (double) Value.ToObject (typeof (double), NativeMethods.dependency_object_get_value (ptr, kind, UnmanagedStylusPoint.PressureFactorProperty.Native)); return new StylusPoint { X = x, Y = y, PressureFactor = (float) pressure }; } case Kind.DURATION: { Duration* duration = (Duration*)value->u.p; return (duration == null) ? Duration.Automatic : *duration; } case Kind.KEYTIME: { KeyTime* keytime = (KeyTime*)value->u.p; return (keytime == null) ? KeyTime.FromTimeSpan (TimeSpan.Zero) : *keytime; } case Kind.GRIDLENGTH: { GridLength* gridlength = (GridLength*)value->u.p; return (gridlength == null) ? new GridLength () : *gridlength; } case Kind.REPEATBEHAVIOR: { RepeatBehavior *repeat = (RepeatBehavior*)value->u.p; return (repeat == null) ? new RepeatBehavior () : *repeat; } case Kind.MEDIAATTRIBUTE_COLLECTION: { MediaAttributeCollection attrs = (MediaAttributeCollection) NativeDependencyObjectHelper.Lookup (value->k, value->u.p); return attrs.AsDictionary (); } case Kind.MANAGEDTYPEINFO: { ManagedTypeInfo *type_info = (ManagedTypeInfo *) value->u.p; if (type_info == null) return null; return Deployment.Current.Types.KindToType (type_info->Kind); } default: Type tt = Deployment.Current.Types.KindToType (value->k); if (tt != null && tt.IsEnum) return Enum.ToObject (tt, value->u.i32); break; } if (NativeMethods.type_is_dependency_object (value->k)){ if (value->u.p == IntPtr.Zero) return null; return NativeDependencyObjectHelper.Lookup (value->k, value->u.p); } throw new Exception (String.Format ("Do not know how to convert {0} {1}. Managed type: {2}", value->k, (int) value->k, Deployment.Current.Types.KindToType (value->k))); }
private unsafe bool TrySetObjectTextProperty (XamlCallbackData *data, string xmlns, object target, Value* target_ptr, IntPtr target_data, Value* value_ptr, IntPtr value_data) { object obj_value = Value.ToObject (null, value_ptr); string str_value = obj_value as string; if (str_value == null) return false; string assembly_name = AssemblyNameFromXmlns (xmlns); string clr_namespace = ClrNamespaceFromXmlns (xmlns); string type_name = NativeMethods.xaml_get_element_name (data->parser, target_data); string full_name = String.IsNullOrEmpty (clr_namespace) ? type_name : clr_namespace + "." + type_name; Type type = LookupType (data->top_level, assembly_name, full_name); if (type == null || type.IsSubclassOf (typeof (DependencyObject))) return false; // For now just trim the string right here, in the future this should probably be done in the xaml parser object e = ConvertType (null, type, str_value.Trim ()); NativeMethods.value_free_value2 ((IntPtr)target_ptr); unsafe { Value *val = (Value *) target_ptr; GCHandle handle = GCHandle.Alloc (e); val->IsGCHandle = true; val->k = Deployment.Current.Types.TypeToKind (e.GetType ()); val->u.p = GCHandle.ToIntPtr (handle); } return true; }
public static void SetValue (INativeDependencyObjectWrapper wrapper, DependencyProperty dp, object value) { Type object_type; if (dp == null) throw new ArgumentNullException ("property"); CheckNativeAndThread (wrapper); if (dp.DeclaringType != null && !dp.IsAttached) { if (!dp.DeclaringType.IsAssignableFrom (wrapper.GetType ())) throw new System.ArgumentException (string.Format ("The DependencyProperty '{2}', registered on type {0} can't be used to set a value on an object of type {1}", dp.DeclaringType.AssemblyQualifiedName, wrapper.GetType ().AssemblyQualifiedName, dp.Name)); } if (value == null) { using (var val = new Value { k = NativeMethods.dependency_property_get_property_type(dp.Native), IsNull = true }) { var v = val; NativeMethods.dependency_object_set_value (wrapper.NativeHandle, dp.Native, ref v); } return; } if (value == DependencyProperty.UnsetValue) { // Setting to UnsetValue appears to be equivalent to ClearValue ClearValue (wrapper, dp); return; } // XXX we need this to work with all // INativeDependencyObjectWrapper, I expect.. // but right now the only one other than DO is // Application, which doesn't have any // settable properties, so we're safe for now. if (wrapper is DependencyObject) dp.Validate ((DependencyObject)wrapper, dp, value); object_type = value.GetType (); bool type_valid = false; if (dp.PropertyType.IsGenericTypeDefinition) { Type t = object_type; while (t != null) { if (dp.PropertyType.IsAssignableFrom (t)) { type_valid = true; break; } if (t.IsGenericType && !t.IsGenericTypeDefinition) t = t.GetGenericTypeDefinition (); else t = t.BaseType; } } else { type_valid = dp.PropertyType.IsAssignableFrom (object_type); } if (!type_valid) { throw new ArgumentException (string.Format ("The DependencyProperty '{3}.{2}', whose property type is {0} can't be set to value whose type is {1}", dp.PropertyType.FullName, object_type.FullName, dp.Name, dp.DeclaringType.FullName)); } using (var val = Value.FromObject (value, dp is CustomDependencyProperty)) { var v = val; NativeMethods.dependency_object_set_value (wrapper.NativeHandle, dp.Native, ref v); } }
private unsafe MethodInfo GetGetMethodForAttachedProperty (Value *top_level, string xmlns, string type_name, string full_type_name, string prop_name) { return GetMethodForAttachedProperty (top_level, xmlns, type_name, full_type_name, prop_name, "Get", new Type [] { typeof (DependencyObject) } ); }