Release 10.0.0.16997
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / Xaml / FillResourceDictionariesVisitor.cs
1 /*
2  * Copyright(c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 using System;
19 using System.Collections;
20 using System.Collections.Generic;
21 using System.Reflection;
22 using Tizen.NUI.Binding;
23
24 namespace Tizen.NUI.Xaml
25 {
26     internal class FillResourceDictionariesVisitor : IXamlNodeVisitor
27     {
28         public FillResourceDictionariesVisitor(HydrationContext context)
29         {
30             Context = context;
31         }
32
33         HydrationContext Context { get; }
34         Dictionary<INode, object> Values => Context.Values;
35
36         public TreeVisitingMode VisitingMode => TreeVisitingMode.TopDown;
37         public bool StopOnDataTemplate => true;
38         public bool StopOnResourceDictionary => false;
39         public bool VisitNodeOnDataTemplate => false;
40
41         public bool IsResourceDictionary(ElementNode node) => typeof(ResourceDictionary).IsAssignableFrom(Context.Types[node]);
42
43         public void Visit(ValueNode node, INode parentNode)
44         {
45             if (!typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode)]))
46                 return;
47
48             node.Accept(new ApplyPropertiesVisitor(Context, stopOnResourceDictionary: false), parentNode);
49         }
50
51         public void Visit(MarkupNode node, INode parentNode)
52         {
53         }
54
55         public void Visit(ElementNode node, INode parentNode)
56         {
57             var value = Values[node];
58             XmlName propertyName;
59             //Set RD to VE
60             if (typeof(ResourceDictionary).IsAssignableFrom(Context.Types[node]) && ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName))
61             {
62                 if ((propertyName.LocalName == "Resources" ||
63                      propertyName.LocalName.EndsWith(".Resources", StringComparison.Ordinal)) && value is ResourceDictionary)
64                 {
65                     var source = Values[parentNode];
66                     ApplyPropertiesVisitor.SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node);
67                     return;
68                 }
69             }
70
71             //Only proceed further if the node is a keyless RD
72             if (parentNode is IElementNode
73                 && typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode)])
74                 && !((IElementNode)parentNode).Properties.ContainsKey(XmlName.xKey))
75                 node.Accept(new ApplyPropertiesVisitor(Context, stopOnResourceDictionary: false), parentNode);
76             else if (parentNode is ListNode
77                      && typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode.Parent)])
78                      && !((IElementNode)parentNode.Parent).Properties.ContainsKey(XmlName.xKey))
79                 node.Accept(new ApplyPropertiesVisitor(Context, stopOnResourceDictionary: false), parentNode);
80         }
81
82         public void Visit(RootNode node, INode parentNode)
83         {
84         }
85
86         public void Visit(ListNode node, INode parentNode)
87         {
88         }
89
90         public bool SkipChildren(INode node, INode parentNode)
91         {
92             var enode = node as ElementNode;
93             if (enode is null)
94                 return false;
95             if (parentNode is IElementNode
96                 && typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode)])
97                 && !((IElementNode)parentNode).Properties.ContainsKey(XmlName.xKey))
98                 return true;
99             if (parentNode is ListNode
100                 && typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode.Parent)])
101                 && !((IElementNode)parentNode.Parent).Properties.ContainsKey(XmlName.xKey))
102                 return true;
103             return false;
104         }
105     }
106 }