From c3d408de724bda609feb132c5a0ee70f77000e63 Mon Sep 17 00:00:00 2001 From: dongsug-song <35130733+dongsug-song@users.noreply.github.com> Date: Wed, 19 Jun 2019 16:45:38 +0900 Subject: [PATCH] [NUI] Add LoadFromXamlFile() (#892) --- src/Tizen.NUI/src/internal/Xaml/XamlLoader.cs | 147 +++++++++++++++------ src/Tizen.NUI/src/public/Xaml/ViewExtensions.cs | 11 ++ .../src/public/XamlBinding/NameScopeExtensions.cs | 2 +- 3 files changed, 119 insertions(+), 41 deletions(-) diff --git a/src/Tizen.NUI/src/internal/Xaml/XamlLoader.cs b/src/Tizen.NUI/src/internal/Xaml/XamlLoader.cs index e486e97..601ef7d 100755 --- a/src/Tizen.NUI/src/internal/Xaml/XamlLoader.cs +++ b/src/Tizen.NUI/src/internal/Xaml/XamlLoader.cs @@ -39,17 +39,19 @@ using Tizen.NUI.Binding.Internals; namespace Tizen.NUI.Xaml.Internals { - [Obsolete ("Replaced by ResourceLoader")] + [Obsolete("Replaced by ResourceLoader")] internal static class XamlLoader { static Func xamlFileProvider; - public static Func XamlFileProvider { + public static Func XamlFileProvider + { get { return xamlFileProvider; } - internal set { + internal set + { xamlFileProvider = value; Tizen.NUI.Xaml.DesignMode.IsDesignModeEnabled = true; - //¯\_(ツ)_/¯ the previewer forgot to set that bool + //¯\_(??_/¯ the previewer forgot to set that bool DoNotThrowOnExceptions = value != null; } } @@ -133,7 +135,8 @@ namespace Tizen.NUI.Xaml continue; if (reader.NodeType == XmlNodeType.XmlDeclaration) continue; - if (reader.NodeType != XmlNodeType.Element) { + if (reader.NodeType != XmlNodeType.Element) + { Debug.WriteLine("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value); continue; } @@ -143,12 +146,13 @@ namespace Tizen.NUI.Xaml (view as Element).IsCreateByXaml = true; } - var rootnode = new RuntimeRootNode (new XmlType (reader.NamespaceURI, reader.Name, null), view, (IXmlNamespaceResolver)reader); - XamlParser.ParseXaml (rootnode, reader); - Visit (rootnode, new HydrationContext { + var rootnode = new RuntimeRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), view, (IXmlNamespaceResolver)reader); + XamlParser.ParseXaml(rootnode, reader); + Visit(rootnode, new HydrationContext + { RootElement = view, #pragma warning disable 0618 - ExceptionHandler = ResourceLoader.ExceptionHandler ?? (Internals.XamlLoader.DoNotThrowOnExceptions ? e => { }: (Action)null) + ExceptionHandler = ResourceLoader.ExceptionHandler ?? (Internals.XamlLoader.DoNotThrowOnExceptions ? e => { } : (Action)null) #pragma warning restore 0618 }); break; @@ -156,50 +160,54 @@ namespace Tizen.NUI.Xaml } } - [Obsolete ("Use the XamlFileProvider to provide xaml files. We will remove this when Cycle 8 hits Stable.")] - public static object Create (string xaml, bool doNotThrow = false) + [Obsolete("Use the XamlFileProvider to provide xaml files. We will remove this when Cycle 8 hits Stable.")] + public static object Create(string xaml, bool doNotThrow = false) { object inflatedView = null; using (var textreader = new StringReader(xaml)) - using (var reader = XmlReader.Create (textreader)) { - while (reader.Read ()) { + using (var reader = XmlReader.Create(textreader)) + { + while (reader.Read()) + { //Skip until element if (reader.NodeType == XmlNodeType.Whitespace) continue; if (reader.NodeType == XmlNodeType.XmlDeclaration) continue; - if (reader.NodeType != XmlNodeType.Element) { + if (reader.NodeType != XmlNodeType.Element) + { Debug.WriteLine("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value); continue; } - var rootnode = new RuntimeRootNode (new XmlType (reader.NamespaceURI, reader.Name, null), null, (IXmlNamespaceResolver)reader); - XamlParser.ParseXaml (rootnode, reader); - var visitorContext = new HydrationContext { + var rootnode = new RuntimeRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), null, (IXmlNamespaceResolver)reader); + XamlParser.ParseXaml(rootnode, reader); + var visitorContext = new HydrationContext + { ExceptionHandler = doNotThrow ? e => { } : (Action)null, }; - var cvv = new CreateValuesVisitor (visitorContext); - cvv.Visit ((ElementNode)rootnode, null); - inflatedView = rootnode.Root = visitorContext.Values [rootnode]; + var cvv = new CreateValuesVisitor(visitorContext); + cvv.Visit((ElementNode)rootnode, null); + inflatedView = rootnode.Root = visitorContext.Values[rootnode]; visitorContext.RootElement = inflatedView as BindableObject; - Visit (rootnode, visitorContext); + Visit(rootnode, visitorContext); break; } } return inflatedView; } - static void Visit (RootNode rootnode, HydrationContext visitorContext) + static void Visit(RootNode rootnode, HydrationContext visitorContext) { - rootnode.Accept (new XamlNodeVisitor ((node, parent) => node.Parent = parent), null); //set parents for {StaticResource} - rootnode.Accept (new ExpandMarkupsVisitor (visitorContext), null); - rootnode.Accept (new PruneIgnoredNodesVisitor(), null); - rootnode.Accept (new NamescopingVisitor (visitorContext), null); //set namescopes for {x:Reference} - rootnode.Accept (new CreateValuesVisitor (visitorContext), null); - rootnode.Accept (new RegisterXNamesVisitor (visitorContext), null); - rootnode.Accept (new FillResourceDictionariesVisitor (visitorContext), null); - rootnode.Accept (new ApplyPropertiesVisitor (visitorContext, true), null); + rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); //set parents for {StaticResource} + rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null); + rootnode.Accept(new PruneIgnoredNodesVisitor(), null); + rootnode.Accept(new NamescopingVisitor(visitorContext), null); //set namescopes for {x:Reference} + rootnode.Accept(new CreateValuesVisitor(visitorContext), null); + rootnode.Accept(new RegisterXNamesVisitor(visitorContext), null); + rootnode.Accept(new FillResourceDictionariesVisitor(visitorContext), null); + rootnode.Accept(new ApplyPropertiesVisitor(visitorContext, true), null); } static string GetAnimationXaml(string animationXamlPath) @@ -268,7 +276,8 @@ namespace Tizen.NUI.Xaml var assembly = type.GetTypeInfo().Assembly; string resourceId; - if (XamlResources.TryGetValue(type, out resourceId)) { + if (XamlResources.TryGetValue(type, out resourceId)) + { var result = ReadResourceAsXaml(type, assembly, resourceId); if (result != null) return result; @@ -280,8 +289,10 @@ namespace Tizen.NUI.Xaml // first pass, pray to find it because the user named it correctly - foreach (var resource in resourceNames) { - if (ResourceMatchesFilename(assembly, resource, likelyResourceName)) { + foreach (var resource in resourceNames) + { + if (ResourceMatchesFilename(assembly, resource, likelyResourceName)) + { resourceName = resource; var xaml = ReadResourceAsXaml(type, assembly, resource); if (xaml != null) @@ -291,7 +302,8 @@ namespace Tizen.NUI.Xaml // okay maybe they at least named it .xaml - foreach (var resource in resourceNames) { + foreach (var resource in resourceNames) + { if (!resource.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase)) continue; @@ -301,7 +313,8 @@ namespace Tizen.NUI.Xaml return xaml; } - foreach (var resource in resourceNames) { + foreach (var resource in resourceNames) + { if (resource.EndsWith(".xaml", StringComparison.OrdinalIgnoreCase)) continue; @@ -317,14 +330,16 @@ namespace Tizen.NUI.Xaml //legacy... static bool ResourceMatchesFilename(Assembly assembly, string resource, string filename) { - try { + try + { var info = assembly.GetManifestResourceInfo(resource); if (!string.IsNullOrEmpty(info.FileName) && string.Compare(info.FileName, filename, StringComparison.OrdinalIgnoreCase) == 0) return true; } - catch (PlatformNotSupportedException) { + catch (PlatformNotSupportedException) + { // Because Win10 + .NET Native } @@ -339,8 +354,10 @@ namespace Tizen.NUI.Xaml static string ReadResourceAsXaml(Type type, Assembly assembly, string likelyTargetName, bool validate = false) { using (var stream = assembly.GetManifestResourceStream(likelyTargetName)) - using (var reader = new StreamReader(stream)) { - if (validate) { + using (var reader = new StreamReader(stream)) + { + if (validate) + { // terrible validation of XML. Unfortunately it will probably work most of the time since comments // also start with a <. We can't bring in any real deps. @@ -366,12 +383,62 @@ namespace Tizen.NUI.Xaml public class RuntimeRootNode : RootNode { - public RuntimeRootNode(XmlType xmlType, object root, IXmlNamespaceResolver resolver) : base (xmlType, resolver) + public RuntimeRootNode(XmlType xmlType, object root, IXmlNamespaceResolver resolver) : base(xmlType, resolver) { Root = root; } public object Root { get; internal set; } } + + internal static string GetXamlForName(string nameOfXamlFile) + { + string xaml; + string resourceName = nameOfXamlFile + ".xaml"; + string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource; + + NUILog.Debug($"resource=({resource})"); + + int windowWidth = Window.Instance.Size.Width; + int windowHeight = Window.Instance.Size.Height; + + string likelyResourcePath = resource + "layout/" + windowWidth.ToString() + "x" + windowHeight.ToString() + "/" + resourceName; + + NUILog.Debug($"likelyResourcePath=({likelyResourcePath})"); + + + if (!File.Exists(likelyResourcePath)) + { + likelyResourcePath = resource + "layout/" + resourceName; + } + + //Find the xaml file in the layout folder + if (File.Exists(likelyResourcePath)) + { + StreamReader reader = new StreamReader(likelyResourcePath); + xaml = reader.ReadToEnd(); + + NUILog.Debug($"File is exist!, try with xaml: {xaml}"); + + // Layer + var pattern = String.Format("x:Class *= *\"{0}\"", "Tizen.NUI.Layer"); + var regex = new Regex(pattern, RegexOptions.ECMAScript); + if (regex.IsMatch(xaml) || xaml.Contains(String.Format("x:Class=\"{0}\"", "Tizen.NUI.Layer"))) + { + return xaml; + } + // View + pattern = String.Format("x:Class *= *\"{0}\"", "Tizen.NUI.BaseComponents.View"); + regex = new Regex(pattern, RegexOptions.ECMAScript); + if (regex.IsMatch(xaml) || xaml.Contains(String.Format("x:Class=\"{0}\"", "Tizen.NUI.BaseComponents.View"))) + { + return xaml; + } + + throw new XamlParseException(string.Format("Can't find type {0}", "Tizen.NUI.XamlMainPage nor View nor Layer"), new XmlLineInfo()); + } + return null; + } + } } diff --git a/src/Tizen.NUI/src/public/Xaml/ViewExtensions.cs b/src/Tizen.NUI/src/public/Xaml/ViewExtensions.cs index 2197921..4749b65 100755 --- a/src/Tizen.NUI/src/public/Xaml/ViewExtensions.cs +++ b/src/Tizen.NUI/src/public/Xaml/ViewExtensions.cs @@ -74,5 +74,16 @@ namespace Tizen.NUI.Xaml { return XamlLoader.LoadObject(path); } + + [EditorBrowsable(EditorBrowsableState.Never)] + public static TXaml LoadFromXamlFile(this TXaml view, string nameOfXamlFile) + { + NUILog.Debug($"LoadFromXamlFile(nameOfXamlFile={nameOfXamlFile})"); + + string xamlScript = XamlLoader.GetXamlForName(nameOfXamlFile); + XamlLoader.Load(view, xamlScript); + return view; + } + } } \ No newline at end of file diff --git a/src/Tizen.NUI/src/public/XamlBinding/NameScopeExtensions.cs b/src/Tizen.NUI/src/public/XamlBinding/NameScopeExtensions.cs index b1c047f..fd9eb90 100755 --- a/src/Tizen.NUI/src/public/XamlBinding/NameScopeExtensions.cs +++ b/src/Tizen.NUI/src/public/XamlBinding/NameScopeExtensions.cs @@ -17,7 +17,7 @@ namespace Tizen.NUI.Binding internal static T FindByName(this INameScope namescope, string name) { - return (T)namescope.FindByName(name); + return (T)namescope?.FindByName(name); } private static Stack elementStack = new Stack(); -- 2.7.4