Browse Source

template binding and xaml extensions operational

donandren 8 years ago
parent
commit
d55a2b2227

+ 8 - 3
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoaderPortableXaml.cs

@@ -195,13 +195,18 @@ namespace Avalonia.Markup.Xaml
             }
         }
 
-        internal static object LoadFromReader(XamlReader reader, object instance = null)
+        internal static object LoadFromReader(XamlReader reader, object instance)
         {
             var writer = AvaloniaXamlObjectWriter.Create(_context, instance);
 
-            XamlServices.Transform(reader, writer);
+             XamlServices.Transform(reader, writer);
 
-            return writer.Result;
+            return writer.Result;           
+        }
+
+        internal static object LoadFromReader(XamlReader reader)
+        {
+            return XamlServices.Load(reader);
         }
 
         /// <summary>

+ 54 - 1
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs

@@ -1,12 +1,64 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
-using OmniXaml;
 using Avalonia.Data;
 using Avalonia.Markup.Xaml.Data;
+using System;
 
 namespace Avalonia.Markup.Xaml.MarkupExtensions
 {
+
+#if !OMNIXAML
+
+    using Portable.Xaml.Markup;
+
+    [MarkupExtensionReturnType(typeof(Binding))]
+    public class BindingExtension : MarkupExtension
+    {
+        public BindingExtension()
+        {
+        }
+
+        public BindingExtension(string path)
+        {
+            Path = path;
+        }
+
+        public override object ProvideValue(IServiceProvider serviceProvider)
+        {
+            return new Binding
+            {
+                Converter = Converter,
+                ConverterParameter = ConverterParameter,
+                ElementName = ElementName,
+                FallbackValue = FallbackValue,
+                Mode = Mode,
+                Path = Path,
+                Priority = Priority,
+            };
+        }
+
+        public IValueConverter Converter { get; set; }
+
+        public object ConverterParameter { get; set; }
+
+        public string ElementName { get; set; }
+
+        public object FallbackValue { get; set; } = AvaloniaProperty.UnsetValue;
+
+        public BindingMode Mode { get; set; }
+
+        [ConstructorArgument("path")]
+        public string Path { get; set; }
+
+        public BindingPriority Priority { get; set; } = BindingPriority.LocalValue;
+
+        public object Source { get; set; }
+    }
+#else
+
+    using OmniXaml;
+
     public class BindingExtension : MarkupExtension
     {
         public BindingExtension()
@@ -41,4 +93,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
         public BindingPriority Priority { get; set; } = BindingPriority.LocalValue;
         public object Source { get; set; }
     }
+#endif
 }

+ 34 - 1
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/RelativeSourceExtension.cs

@@ -1,11 +1,43 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
-using OmniXaml;
+
 using Avalonia.Markup.Xaml.Data;
 
+
 namespace Avalonia.Markup.Xaml.MarkupExtensions
 {
+#if !OMNIXAML
+
+    using System;
+    using Portable.Xaml.Markup;
+
+    public class RelativeSourceExtension : MarkupExtension
+    {
+        public RelativeSourceExtension()
+        {
+        }
+
+        public RelativeSourceExtension(RelativeSourceMode mode)
+        {
+            Mode = mode;
+        }
+
+        public override object ProvideValue(IServiceProvider serviceProvider)
+        {
+            return new RelativeSource
+            {
+                Mode = Mode,
+            };
+        }
+
+        [ConstructorArgument("mode")]
+        public RelativeSourceMode Mode { get; set; }
+    }
+#else
+
+    using OmniXaml;
+
     public class RelativeSourceExtension : MarkupExtension
     {
         public RelativeSourceExtension()
@@ -27,4 +59,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
 
         public RelativeSourceMode Mode { get; set; }
     }
+#endif
 }

+ 2 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/Standard/StaticExtension.cs

@@ -9,6 +9,7 @@ using Glass.Core;
 
 namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard
 {
+#if OMNIXAML
     public class StaticExtension : MarkupExtension
     {
         public StaticExtension()
@@ -83,4 +84,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard
             throw new ArgumentException($"Static member '{type}.{name}' not found.");
         }
     }
+#endif
 }

+ 2 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/Standard/TypeExtension.cs

@@ -9,6 +9,7 @@ using Glass.Core;
 
 namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard
 {
+#if OMNIXAML
     [ContentProperty("TargetType")]
     public class TypeExtension : MarkupExtension
     {
@@ -46,4 +47,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.Standard
             return ResolveFromString(TypeName, markupExtensionContext.ValueContext.TypeRepository);
         }
     }
+#endif
 }

+ 14 - 2
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StaticExtension.cs

@@ -4,11 +4,22 @@
 using System;
 using System.Linq;
 using System.Reflection;
-using OmniXaml;
-using Glass.Core;
+
 
 namespace Avalonia.Markup.Xaml.MarkupExtensions
 {
+#if !OMNIXAML
+
+    //TODO: check do we need something more than std Portable.xaml static??
+    public class StaticExtension : Portable.Xaml.Markup.StaticExtension
+    {
+
+    }
+
+#else
+    using OmniXaml;
+    using Glass.Core;
+
     public class StaticExtension : MarkupExtension
     {
         public StaticExtension()
@@ -83,4 +94,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
             throw new ArgumentException($"Static member '{type}.{name}' not found.");
         }
     }
+#endif
 }

+ 28 - 1
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/StyleResourceExtension.cs

@@ -3,13 +3,39 @@
 
 using System;
 using System.Reactive.Linq;
-using OmniXaml;
+
 using Avalonia.LogicalTree;
 using Avalonia.Markup.Xaml.Data;
 using Avalonia.Styling;
 
+
 namespace Avalonia.Markup.Xaml.MarkupExtensions
 {
+#if !OMNIXAML
+
+    using Portable.Xaml.Markup;
+
+    [MarkupExtensionReturnType(typeof(StyleResourceBinding))]
+    public class StyleResourceExtension : MarkupExtension
+    {
+        public StyleResourceExtension(string name)
+        {
+            Name = name;
+        }
+
+        public override object ProvideValue(IServiceProvider serviceProvider)
+        {
+            return new StyleResourceBinding(this.Name);
+        }
+
+        [ConstructorArgument("name")]
+        public string Name { get; set; }
+    }
+
+#else
+
+    using OmniXaml;
+
     public class StyleResourceExtension : MarkupExtension
     {
         public StyleResourceExtension(string name)
@@ -24,4 +50,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
 
         public string Name { get; set; }
     }
+#endif
 }

+ 49 - 1
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TemplateBindingExtension.cs

@@ -1,12 +1,59 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
-using OmniXaml;
 using Avalonia.Data;
 using Avalonia.Markup.Xaml.Data;
 
 namespace Avalonia.Markup.Xaml.MarkupExtensions
 {
+#if !OMNIXAML
+
+    using System;
+    using Portable.Xaml.Markup;
+
+    [MarkupExtensionReturnType(typeof(Binding))]
+    public class TemplateBindingExtension : MarkupExtension
+    {
+        public TemplateBindingExtension()
+        {
+        }
+
+        public TemplateBindingExtension(string path)
+        {
+            Path = path;
+        }
+
+        public override object ProvideValue(IServiceProvider serviceProvider)
+        {
+            return new Binding
+            {
+                Converter = Converter,
+                ElementName = ElementName,
+                Mode = Mode,
+                RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
+                Path = Path,
+                Priority = Priority,
+            };
+        }
+
+        public IValueConverter Converter { get; set; }
+
+        public string ElementName { get; set; }
+
+        public object FallbackValue { get; set; }
+
+        public BindingMode Mode { get; set; }
+
+        [ConstructorArgument("path")]
+        public string Path { get; set; }
+
+        public BindingPriority Priority { get; set; } = BindingPriority.TemplatedParent;
+    }
+
+#else
+    
+    using OmniXaml;
+
     public class TemplateBindingExtension : MarkupExtension
     {
         public TemplateBindingExtension()
@@ -38,4 +85,5 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
         public string Path { get; set; }
         public BindingPriority Priority { get; set; } = BindingPriority.TemplatedParent;
     }
+#endif
 }

+ 18 - 6
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/TypeExtension.cs

@@ -1,14 +1,24 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
-using System;
-using OmniXaml;
-using OmniXaml.Attributes;
-using OmniXaml.Typing;
-using Glass.Core;
-
 namespace Avalonia.Markup.Xaml.MarkupExtensions
 {
+#if !OMNIXAML
+
+    //TODO: check do we need something more than std Portable.xaml type??
+    public class TypeExtension : Portable.Xaml.Markup.TypeExtension
+    {
+
+    }
+
+#else
+
+    using System;
+    using OmniXaml;
+    using OmniXaml.Attributes;
+    using OmniXaml.Typing;
+    using Glass.Core;
+
     [ContentProperty("TargetType")]
     public class TypeExtension : MarkupExtension
     {
@@ -46,4 +56,6 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
             return ResolveFromString(TypeName, markupExtensionContext.ValueContext.TypeRepository);
         }
     }
+
+#endif
 }

+ 43 - 4
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs

@@ -5,6 +5,8 @@ using System.Reflection;
 using Avalonia.Markup.Xaml.Context;
 using Portable.Xaml;
 using Portable.Xaml.ComponentModel;
+using am = Avalonia.Metadata;
+using Avalonia.Data;
 
 namespace Avalonia.Markup.Xaml.PortableXaml
 {
@@ -51,10 +53,15 @@ namespace Avalonia.Markup.Xaml.PortableXaml
                 }
             }
 
-            Type type = _avaloniaTypeProvider.FindType(xmlNamespace, xmlLocalName, genArgs);
+            // MarkupExtension type could omit "Extension" part in XML name.
+            Type type = _avaloniaTypeProvider.FindType(xmlNamespace, xmlLocalName, genArgs)
+                                ?? _avaloniaTypeProvider.FindType(xmlNamespace,
+                                                                xmlLocalName + "Extension",
+                                                                genArgs);
 
             if (type == null)
             {
+
                 //let's try the simple types
                 //in Portable xaml xmlns:sys='clr-namespace:System;assembly=mscorlib'
                 //and sys:Double is not resolved
@@ -118,12 +125,44 @@ namespace Avalonia.Markup.Xaml.PortableXaml
 
         public override XamlType GetXamlType(Type type)
         {
-            if (type.FullName.StartsWith("Avalonia."))
+            //if (type.FullName.StartsWith("Avalonia."))
+            //{
+            //    return new AvaloniaXamlType(type, this);
+            //}
+            return base.GetXamlType(type);
+        }
+
+
+        protected override XamlMember GetAttachableProperty(string attachablePropertyName, MethodInfo getter, MethodInfo setter)
+        {
+            return base.GetAttachableProperty(attachablePropertyName, getter, setter);
+        }
+
+        protected override XamlMember GetProperty(PropertyInfo pi)
+        {
+            Type objType = pi.DeclaringType;
+            string name = pi.Name;
+
+            var avProp = AvaloniaPropertyRegistry.Instance.FindRegistered(objType, name);
+
+            var assignBindingAttr = pi.GetCustomAttribute<AssignBindingAttribute>();
+
+            if (avProp != null)
             {
-                return new AvaloniaXamlType(type, this);
+                return new AvaloniaPropertyXamlMember(avProp, pi, this)
+                {
+                    AssignBinding = assignBindingAttr != null
+                };
             }
 
-            return base.GetXamlType(type);
+            var dependAttr = pi.GetCustomAttribute<am.DependsOnAttribute>();
+
+            if (dependAttr != null)
+            {
+                return new DependOnXamlMember(dependAttr.Name, pi, this);
+            }
+
+            return base.GetProperty(pi);
         }
     }
 }

+ 73 - 10
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs

@@ -1,31 +1,94 @@
 using System;
 using System.Collections.Generic;
 using System.Reflection;
+using Avalonia.Data;
 using Portable.Xaml;
 using Portable.Xaml.Schema;
-using am = Avalonia.Metadata;
+
 
 namespace Avalonia.Markup.Xaml.PortableXaml
 {
-    public class AvaloniaXamlType : XamlType
+    //public class AvaloniaXamlType : XamlType
+    //{
+    //    public AvaloniaXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
+    //        base(underlyingType, schemaContext)
+    //    {
+    //    }
+
+    //    protected override XamlMember LookupMember(string name, bool skipReadOnlyCheck)
+    //    {
+    //        return base.LookupMember(name, skipReadOnlyCheck);
+    //    }
+    //}
+
+    public class AvaloniaPropertyXamlMember : XamlMember
     {
-        public AvaloniaXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
-            base(underlyingType, schemaContext)
+        public bool AssignBinding { get; set; } = false;
+
+        public AvaloniaProperty Property { get; }
+
+        public AvaloniaPropertyXamlMember(AvaloniaProperty property,
+                        PropertyInfo propertyInfo,
+                        XamlSchemaContext schemaContext) :
+            base(propertyInfo, schemaContext)
         {
+            Property = property;
         }
 
-        protected override XamlMember LookupMember(string name, bool skipReadOnlyCheck)
+        protected override XamlMemberInvoker LookupInvoker()
         {
-            var pi = UnderlyingType.GetRuntimeProperty(name);
+            return new AvaloniaPropertyInvoker(this);
+        }
 
-            var dependAttr = pi.GetCustomAttribute<am.DependsOnAttribute>();
+        private class AvaloniaPropertyInvoker : XamlMemberInvoker
+        {
+            public AvaloniaPropertyInvoker(XamlMember member) : base(member)
+            {
+            }
 
-            if (dependAttr != null)
+            public override void SetValue(object instance, object value)
             {
-                return new DependOnXamlMember(dependAttr.Name, pi, SchemaContext);
+                if (Property != null)
+                {
+                    var obj = ((IAvaloniaObject)instance);
+                    if (value is IBinding && !Member.AssignBinding)
+                    {
+                        ApplyBinding(obj, (IBinding)value);
+                    }
+                    else
+                    {
+                        obj.SetValue(Property, value);
+                    }
+                }
+                else
+                {
+                    base.SetValue(instance, value);
+                }
+            }
+
+            public override object GetValue(object instance)
+            {
+                if (Property != null)
+                {
+                    return ((IAvaloniaObject)instance).GetValue(Property);
+                }
+                else
+                {
+                    return base.GetValue(instance);
+                }
             }
 
-            return base.LookupMember(name, skipReadOnlyCheck);
+            private void ApplyBinding(IAvaloniaObject obj, IBinding binding)
+            {
+                //TODO: in Context.PropertyAccessor there is
+                //some quirk stuff check it later
+                obj.Bind(Property, binding);
+            }
+
+            private AvaloniaProperty Property => Member.Property;
+
+            private new AvaloniaPropertyXamlMember Member =>
+                            (AvaloniaPropertyXamlMember)base.Member;
         }
     }