Browse Source

styles working

pull/916/head
donandren 10 years ago
committed by Andrey Kunchev
parent
commit
e71d9fc93f
  1. 3
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  2. 2
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaRuntimeTypeSource.cs
  3. 2
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaTypeFeatureProvider.cs
  4. 94
      src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs
  5. 24
      src/Markup/Avalonia.Markup.Xaml/Converters/BrushTypeConverter.cs
  6. 26
      src/Markup/Avalonia.Markup.Xaml/Converters/SelectorTypeConverter.cs
  7. 71
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaDefaultTypeConverters.cs
  8. 19
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaTypeAttributeProvider.cs
  9. 13
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs
  10. 94
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs
  11. 37
      src/Markup/Avalonia.Markup.Xaml/PortableXaml/TypeDescriptorExtensions.cs

3
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -44,6 +44,7 @@
<Compile Include="AvaloniaXamlLoader.cs" />
<Compile Include="PortableXaml\AvaloniaMemberAttributeProvider.cs" />
<Compile Include="PortableXaml\AvaloniaNameScope.cs" />
<Compile Include="PortableXaml\AvaloniaDefaultTypeConverters.cs" />
<Compile Include="PortableXaml\AvaloniaXamlObjectWriter.cs" />
<Compile Include="PortableXaml\AvaloniaRuntimeTypeProvider.cs" />
<Compile Include="PortableXaml\AvaloniaXamlSchemaContext.cs" />
@ -274,6 +275,8 @@
<Compile Include="Parsers\SelectorGrammar.cs" />
<Compile Include="Parsers\SelectorParser.cs" />
<Compile Include="PortableXaml\AvaloniaTypeAttributeProvider.cs" />
<Compile Include="PortableXaml\AvaloniaXamlType.cs" />
<Compile Include="PortableXaml\TypeDescriptorExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="AvaloniaXamlLoaderOmniXaml.cs" />
<Compile Include="Styling\StyleInclude.cs" />

2
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaRuntimeTypeSource.cs

@ -1,5 +1,6 @@
namespace Avalonia.Markup.Xaml.Context
{
#if OMNIXAML
using System;
using System.Collections.Generic;
using System.Linq;
@ -88,4 +89,5 @@ namespace Avalonia.Markup.Xaml.Context
return inner.GetAttachableMember(name, getter, setter);
}
}
#endif
}

2
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaTypeFeatureProvider.cs

@ -23,6 +23,7 @@ using OmniMetadata = OmniXaml.Typing.Metadata;
namespace Avalonia.Markup.Xaml.Context
{
#if OMNIXAML
public class AvaloniaTypeFeatureProvider : ITypeFeatureProvider
{
private Dictionary<Type, OmniMetadata> _metadata =
@ -177,4 +178,5 @@ namespace Avalonia.Markup.Xaml.Context
RegisterTypeConverter(typeof(FontWeight), new FontWeightConverter());
}
}
#endif
}

94
src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs

@ -4,12 +4,99 @@
using System;
using System.Globalization;
using System.Linq;
using OmniXaml;
using OmniXaml.TypeConversion;
using Avalonia.Styling;
namespace Avalonia.Markup.Xaml.Converters
{
using Avalonia.Styling;
using Portable.Xaml;
#if !OMNIXAML
using Portable.Xaml.ComponentModel;
using Portable.Xaml.Markup;
public class AvaloniaPropertyTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var s = (string)value;
string typeName;
string propertyName;
Type type = null;
ParseProperty(s, out typeName, out propertyName);
if (typeName == null)
{
var amb = context.GetService<IAmbientProvider>();
var sc = context.GetService<IXamlSchemaContextProvider>().SchemaContext;
var xamlStyleType = sc.GetXamlType(typeof(Style));
var ambValue = amb.GetFirstAmbientValue(xamlStyleType) as AmbientPropertyValue;
var style = ambValue?.Value as Style;
type = style.Selector?.TargetType;
if (type == null)
{
throw new Exception(
"Could not determine the target type. Please fully qualify the property name.");
}
}
else
{
//type = context.TypeRepository.GetByQualifiedName(typeName)?.UnderlyingType;
if (type == null)
{
throw new Exception($"Could not find type '{typeName}'.");
}
}
// First look for non-attached property on the type and then look for an attached property.
var property = AvaloniaPropertyRegistry.Instance.FindRegistered(type, s) ??
AvaloniaPropertyRegistry.Instance.GetAttached(type)
.FirstOrDefault(x => x.Name == propertyName);
if (property == null)
{
throw new Exception(
$"Could not find AvaloniaProperty '{type.Name}.{propertyName}'.");
}
return property;
}
private void ParseProperty(string s, out string typeName, out string propertyName)
{
var split = s.Split('.');
if (split.Length == 1)
{
typeName = null;
propertyName = split[0];
}
else if (split.Length == 2)
{
typeName = split[0];
propertyName = split[1];
}
else
{
throw new Exception($"Invalid property name: '{s}'.");
}
}
}
#else
using OmniXaml;
using OmniXaml.TypeConversion;
public class AvaloniaPropertyTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
@ -93,4 +180,5 @@ namespace Avalonia.Markup.Xaml.Converters
}
}
}
#endif
}

24
src/Markup/Avalonia.Markup.Xaml/Converters/BrushTypeConverter.cs

@ -3,11 +3,32 @@
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
using Avalonia.Media;
namespace Avalonia.Markup.Xaml.Converters
{
#if !OMNIXAML
using Portable.Xaml.ComponentModel;
public class BrushTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return Brush.Parse((string)value);
}
}
#else
using OmniXaml.TypeConversion;
public class BrushTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
@ -30,4 +51,5 @@ namespace Avalonia.Markup.Xaml.Converters
throw new NotImplementedException();
}
}
#endif
}

26
src/Markup/Avalonia.Markup.Xaml/Converters/SelectorTypeConverter.cs

@ -3,11 +3,33 @@
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
using Avalonia.Markup.Xaml.Parsers;
namespace Avalonia.Markup.Xaml.Converters
{
#if !OMNIXAML
using Portable.Xaml.ComponentModel;
public class SelectorTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var parser = new SelectorParser((t, ns) => context.ResolveType(ns, t));
return parser.Parse((string)value);
}
}
#else
using OmniXaml.TypeConversion;
public class SelectorTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
@ -31,4 +53,6 @@ namespace Avalonia.Markup.Xaml.Converters
throw new NotImplementedException();
}
}
#endif
}

71
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaDefaultTypeConverters.cs

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Avalonia.Markup.Xaml.Converters;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Styling;
namespace Avalonia.Markup.Xaml.PortableXaml
{
public class AvaloniaDefaultTypeConverters
{
private static Dictionary<Type, Type> _defaultConverters = new Dictionary<Type, Type>()
{
{ typeof(IBitmap), typeof(BitmapTypeConverter)},
{ typeof(IBrush), typeof(BrushTypeConverter) },
//{ typeof(Color), typeof(ColorTypeConverter) },
//{ typeof(Classes), typeof(ClassesTypeConverter) },
//{ typeof(ColumnDefinitions), typeof(ColumnDefinitionsTypeConverter) },
//{ typeof(DateTime), typeof(DateTimeTypeConverter) },
//{ typeof(Geometry), typeof(GeometryTypeConverter) },
//{ typeof(GridLength), typeof(GridLengthTypeConverter) },
//{ typeof(KeyGesture), typeof(KeyGestureConverter) },
//{ typeof(AvaloniaList<double>), typeof(AvaloniaListTypeConverter<double>) },
//{ typeof(IMemberSelector), typeof(MemberSelectorTypeConverter) },
//{ typeof(Point), typeof(PointTypeConverter) },
//{ typeof(IList<Point>), typeof(PointsListTypeConverter) },
{ typeof(AvaloniaProperty), typeof(AvaloniaPropertyTypeConverter) },
//{ typeof(RelativePoint), typeof(RelativePointTypeConverter) },
//{ typeof(RelativeRect), typeof(RelativeRectTypeConverter) },
//{ typeof(RowDefinitions), typeof(RowDefinitionsTypeConverter) },
//{ typeof(Size), typeof(SizeTypeConverter) },
{ typeof(Selector), typeof(SelectorTypeConverter)},
//{ typeof(SolidColorBrush), typeof(BrushTypeConverter) },
//{ typeof(Thickness), typeof(ThicknessTypeConverter) },
//{ typeof(TimeSpan), typeof(TimeSpanTypeConverter) },
//{ typeof(Uri), typeof(Converters.UriTypeConverter) },
//{ typeof(Cursor), typeof(CursorTypeConverter) },
//{ typeof(WindowIcon), typeof(IconTypeConverter) },
//{ typeof(FontWeight), typeof(FontWeightConverter) },
};
public static Type GetTypeConverter(Type type)
{
Type converterType;
Type curType = type;
while (curType != null)
{
if (_defaultConverters.TryGetValue(curType, out converterType))
{
if (curType != type)
{
_defaultConverters[curType] = converterType;
}
return converterType;
}
else
{
_defaultConverters[curType] = null;
}
curType = curType.GetTypeInfo().BaseType;
}
return null;
}
}
}

19
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaTypeAttributeProvider.cs

@ -43,6 +43,25 @@ namespace Avalonia.Markup.Xaml.PortableXaml
};
}
}
else if (attributeType == typeof(TypeConverterAttribute))
{
var attribs = _type.GetTypeInfo().GetCustomAttributes(attributeType, inherit);
if (attribs?.Any() != true)
{
var convType = AvaloniaDefaultTypeConverters.GetTypeConverter(_type);
if (convType != null)
{
return new object[]
{
new TypeConverterAttribute(convType)
};
}
}
return (attribs as object[]) ?? attribs.ToArray();
}
var attr = _type.GetTypeInfo().GetCustomAttributes(attributeType, inherit);
return (attr as object[]) ?? attr.ToArray();

13
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlSchemaContext.cs

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Avalonia.Markup.Xaml.Context;
@ -30,7 +29,7 @@ namespace Avalonia.Markup.Xaml.PortableXaml
type = base.GetXamlType(xamlNamespace, name, typeArguments);
}
}
catch(Exception e)
catch (Exception e)
{
//TODO: log or wrap exception
throw e;
@ -66,5 +65,15 @@ namespace Avalonia.Markup.Xaml.PortableXaml
protected override ICustomAttributeProvider GetCustomAttributeProvider(MemberInfo member)
=> new AvaloniaMemberAttributeProvider(member);
public override XamlType GetXamlType(Type type)
{
if (type.FullName.StartsWith("Avalonia."))
{
return new AvaloniaXamlType(type, this);
}
return base.GetXamlType(type);
}
}
}

94
src/Markup/Avalonia.Markup.Xaml/PortableXaml/AvaloniaXamlType.cs

@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Portable.Xaml;
using Portable.Xaml.Schema;
using am = Avalonia.Metadata;
namespace Avalonia.Markup.Xaml.PortableXaml
{
public class AvaloniaXamlType : XamlType
{
public AvaloniaXamlType(Type underlyingType, XamlSchemaContext schemaContext) :
base(underlyingType, schemaContext)
{
}
protected override XamlMember LookupMember(string name, bool skipReadOnlyCheck)
{
var pi = UnderlyingType.GetRuntimeProperty(name);
var dependAttr = pi.GetCustomAttribute<am.DependsOnAttribute>();
if (dependAttr != null)
{
return new DependOnXamlMember(dependAttr.Name, pi, SchemaContext);
}
return base.LookupMember(name, skipReadOnlyCheck);
}
}
public class DependOnXamlMember : XamlMember
{
private string _dependOn;
public DependOnXamlMember(string dependOn,
PropertyInfo propertyInfo,
XamlSchemaContext schemaContext) :
base(propertyInfo, schemaContext)
{
_dependOn = dependOn;
}
private XamlMember _dependOnMember;
public XamlMember DependOnMember
{
get
{
return _dependOnMember ??
(_dependOnMember = DeclaringType.GetMember(_dependOn));
}
}
protected override IList<XamlMember> LookupDependsOn()
{
return new List<XamlMember>() { DeclaringType.GetMember(_dependOn) };
}
protected override XamlMemberInvoker LookupInvoker()
{
return new DependOnInvoker(this);
}
private class DependOnInvoker : XamlMemberInvoker
{
public DependOnInvoker(XamlMember member) : base(member)
{
}
public override void SetValue(object instance, object value)
{
if (value is string &&
(Member.UnderlyingMember as PropertyInfo).PropertyType != typeof(string))
{
var dpm = (Member as DependOnXamlMember).DependOnMember.UnderlyingMember;
var pi = (dpm as PropertyInfo);
var avp = pi.GetValue(instance) as AvaloniaProperty;
Type targetType = avp != null ? avp.PropertyType : pi.PropertyType;
var xamTargetType = Member.DeclaringType.SchemaContext.GetXamlType(targetType);
var ttConv = xamTargetType?.TypeConverter?.ConverterInstance;
if (ttConv != null)
{
value = ttConv.ConvertFromString(value as string);
}
}
base.SetValue(instance, value);
}
}
}
}

37
src/Markup/Avalonia.Markup.Xaml/PortableXaml/TypeDescriptorExtensions.cs

@ -0,0 +1,37 @@
using System;
using Portable.Xaml.Markup;
namespace Portable.Xaml.ComponentModel
{
internal static class TypeDescriptorExtensions
{
/// <summary>
/// Gets the service from ITypeDescriptorContext
/// usually in TypeConverter in xaml reader context
/// examples:
/// context.GetService<IXamlTypeResolver>()
/// context.GetService<IXamlNamespaceResolver>()
/// context.GetService<IXamlNameProvider>()
/// context.GetService<INamespacePrefixLookup>()
/// context.GetService<IXamlSchemaContextProvider>()
/// context.GetService<IRootObjectProvider>()
/// context.GetService<IProvideValueTarget>()
/// </summary>
/// <typeparam name="T">Service Type</typeparam>
/// <param name="ctx">The TypeDescriptor context.</param>
/// <returns></returns>
public static T GetService<T>(this ITypeDescriptorContext ctx) where T : class
{
return ctx.GetService(typeof(T)) as T;
}
public static Type ResolveType(this ITypeDescriptorContext ctx, string namespacePrefix, string type)
{
var tr = ctx.GetService<IXamlTypeResolver>();
string name = string.IsNullOrEmpty(namespacePrefix) ? type : $"{namespacePrefix}:{type}";
return tr?.Resolve(name);
}
}
}
Loading…
Cancel
Save