2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Diagnostics;
5 using System.Globalization;
7 using System.Reflection;
9 using Tizen.NUI.Binding.Internals;
12 namespace Tizen.NUI.Binding
14 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
15 [EditorBrowsable(EditorBrowsableState.Never)]
16 [ProvideCompiled("Tizen.NUI.Xaml.Core.XamlC.BindablePropertyConverter")]
17 [TypeConversion(typeof(BindableProperty))]
18 public sealed class BindablePropertyConverter : TypeConverter, IExtendedTypeConverter
20 object IExtendedTypeConverter.ConvertFrom(CultureInfo culture, object value, IServiceProvider serviceProvider)
22 return ((IExtendedTypeConverter)this).ConvertFromInvariantString(value as string, serviceProvider);
25 object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceProvider serviceProvider)
27 if (string.IsNullOrWhiteSpace(value))
29 if (serviceProvider == null)
31 var parentValuesProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideParentValues;
32 var typeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
33 if (typeResolver == null)
35 IXmlLineInfo lineinfo = null;
36 var xmlLineInfoProvider = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider;
37 if (xmlLineInfoProvider != null)
38 lineinfo = xmlLineInfoProvider.XmlLineInfo;
39 string[] parts = value.Split('.');
41 if (parts.Length == 1)
43 if (parentValuesProvider == null)
45 string msg = string.Format("Can't resolve {0}", parts[0]);
46 throw new XamlParseException(msg, lineinfo);
48 object parent = parentValuesProvider.ParentObjects.Skip(1).FirstOrDefault();
49 if (parentValuesProvider.TargetObject is Setter)
51 var style = parent as Style;
52 var triggerBase = parent as TriggerBase;
53 var visualState = parent as VisualState;
55 type = style.TargetType;
56 else if (triggerBase != null)
57 type = triggerBase.TargetType;
58 else if (visualState != null)
59 type = FindTypeForVisualState(parentValuesProvider, lineinfo);
61 else if (parentValuesProvider.TargetObject is Trigger)
62 type = (parentValuesProvider.TargetObject as Trigger).TargetType;
63 else if (parentValuesProvider.TargetObject is XamlPropertyCondition && (parent as TriggerBase) != null)
64 type = (parent as TriggerBase).TargetType;
67 throw new XamlParseException($"Can't resolve {parts [0]}", lineinfo);
69 return ConvertFrom(type, parts[0], lineinfo);
71 if (parts.Length == 2)
73 if (!typeResolver.TryResolve(parts[0], out type))
75 string msg = string.Format("Can't resolve {0}", parts[0]);
76 throw new XamlParseException(msg, lineinfo);
78 return ConvertFrom(type, parts[1], lineinfo);
80 throw new XamlParseException($"Can't resolve {value}. Syntax is [[prefix:]Type.]PropertyName.", lineinfo);
83 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
84 [EditorBrowsable(EditorBrowsableState.Never)]
85 public override object ConvertFromInvariantString(string value)
87 if (string.IsNullOrWhiteSpace(value))
89 if (value.Contains(":"))
91 Console.WriteLine(null, "Can't resolve properties with xml namespace prefix.");
94 string[] parts = value.Split('.');
95 if (parts.Length != 2)
97 Console.WriteLine(null, $"Can't resolve {value}. Accepted syntax is Type.PropertyName.");
100 Type type = Type.GetType("Tizen.NUI." + parts[0]);
101 return ConvertFrom(type, parts[1], null);
104 BindableProperty ConvertFrom(Type type, string propertyName, IXmlLineInfo lineinfo)
106 string name = propertyName + "Property";
107 FieldInfo bpinfo = type.GetField(fi => fi.Name == name && fi.IsStatic && fi.IsPublic && fi.FieldType == typeof(BindableProperty));
109 throw new XamlParseException($"Can't resolve {name} on {type.Name}", lineinfo);
110 var bp = bpinfo.GetValue(null) as BindableProperty;
111 var isObsolete = bpinfo.GetCustomAttribute<ObsoleteAttribute>() != null;
112 if (bp != null && bp.PropertyName != propertyName && !isObsolete)
113 throw new XamlParseException($"The PropertyName of {type.Name}.{name} is not {propertyName}", lineinfo);
117 Type FindTypeForVisualState(IProvideParentValues parentValueProvider, IXmlLineInfo lineInfo)
119 var parents = parentValueProvider.ParentObjects.ToList();
121 // Skip 0; we would not be making this check if TargetObject were not a Setter
122 // Skip 1; we would not be making this check if the immediate parent were not a VisualState
124 // VisualStates must be in a VisualStateGroup
125 if(!(parents[2] is VisualStateGroup)) {
126 throw new XamlParseException($"Expected {nameof(VisualStateGroup)} but found {parents[2]}.", lineInfo);
129 var vsTarget = parents[3];
131 // Are these Visual States directly on a VisualElement?
132 if (vsTarget is /*VisualElement*/BaseHandle)
134 return vsTarget.GetType();
137 if (!(parents[3] is VisualStateGroupList))
139 throw new XamlParseException($"Expected {nameof(VisualStateGroupList)} but found {parents[3]}.", lineInfo);
142 if (!(parents[4] is Setter))
144 throw new XamlParseException($"Expected {nameof(Setter)} but found {parents[4]}.", lineInfo);
147 // These must be part of a Style; verify that
148 if (!(parents[5] is Style style))
150 throw new XamlParseException($"Expected {nameof(Style)} but found {parents[5]}.", lineInfo);
153 return style.TargetType;