1 using System.Collections.Generic;
2 using System.Diagnostics;
5 using Tizen.NUI.Binding;
6 using Tizen.NUI.Binding.Internals;
8 namespace Tizen.NUI.Xaml
10 internal interface INode
12 List<string> IgnorablePrefixes { get; set; }
14 IXmlNamespaceResolver NamespaceResolver { get; }
16 INode Parent { get; set; }
18 void Accept(IXamlNodeVisitor visitor, INode parentNode);
22 internal interface IValueNode : INode
26 internal interface IElementNode : INode, IListNode
28 Dictionary<XmlName, INode> Properties { get; }
29 List<XmlName> SkipProperties { get; }
30 INameScope Namescope { get; }
31 XmlType XmlType { get; }
32 string NamespaceURI { get; }
35 internal interface IListNode : INode
37 List<INode> CollectionItems { get; }
40 [DebuggerDisplay("{NamespaceUri}:{Name}")]
41 internal class XmlType
43 public XmlType(string namespaceUri, string name, IList<XmlType> typeArguments)
45 NamespaceUri = namespaceUri;
47 TypeArguments = typeArguments;
50 public string NamespaceUri { get; }
51 public string Name { get; }
52 public IList<XmlType> TypeArguments { get; }
55 internal abstract class BaseNode : IXmlLineInfo, INode
57 protected BaseNode(IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
59 NamespaceResolver = namespaceResolver;
60 LineNumber = linenumber;
61 LinePosition = lineposition;
64 public IXmlNamespaceResolver NamespaceResolver { get; }
65 public INode Parent { get; set; }
66 public List<string> IgnorablePrefixes { get; set; }
67 public int LineNumber { get; set; }
68 public int LinePosition { get; set; }
70 public bool HasLineInfo() => LineNumber >= 0 && LinePosition >= 0;
72 public abstract void Accept(IXamlNodeVisitor visitor, INode parentNode);
73 public abstract INode Clone();
76 [DebuggerDisplay("{Value}")]
77 internal class ValueNode : BaseNode, IValueNode
79 public ValueNode(object value, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
80 : base(namespaceResolver, linenumber, lineposition)
85 public object Value { get; set; }
87 public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
89 visitor.Visit(this, parentNode);
92 public override INode Clone() => new ValueNode(Value, NamespaceResolver, LineNumber, LinePosition) {
93 IgnorablePrefixes = IgnorablePrefixes
97 [DebuggerDisplay("{MarkupString}")]
98 internal class MarkupNode : BaseNode, IValueNode
100 public MarkupNode(string markupString, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
101 : base(namespaceResolver, linenumber, lineposition)
103 MarkupString = markupString;
106 public string MarkupString { get; }
108 public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
110 visitor.Visit(this, parentNode);
113 public override INode Clone() => new MarkupNode(MarkupString, NamespaceResolver, LineNumber, LinePosition) {
114 IgnorablePrefixes = IgnorablePrefixes
118 [DebuggerDisplay("{XmlType.Name}")]
119 internal class ElementNode : BaseNode, IValueNode, IElementNode
121 public ElementNode(XmlType type, string namespaceURI, IXmlNamespaceResolver namespaceResolver, int linenumber = -1,
122 int lineposition = -1)
123 : base(namespaceResolver, linenumber, lineposition)
125 Properties = new Dictionary<XmlName, INode>();
126 SkipProperties = new List<XmlName>();
127 CollectionItems = new List<INode>();
129 NamespaceURI = namespaceURI;
132 public Dictionary<XmlName, INode> Properties { get; }
133 public List<XmlName> SkipProperties { get; }
134 public List<INode> CollectionItems { get; }
135 public XmlType XmlType { get; }
136 public string NamespaceURI { get; }
137 public INameScope Namescope { get; set; }
139 public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
141 if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.TopDown)
142 visitor.Visit(this, parentNode);
144 if (!SkipChildren(visitor, this, parentNode)) {
145 foreach (var node in Properties.Values.ToList())
146 node.Accept(visitor, this);
147 foreach (var node in CollectionItems)
148 node.Accept(visitor, this);
151 if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.BottomUp)
152 visitor.Visit(this, parentNode);
156 bool IsDataTemplate(INode parentNode)
158 var parentElement = parentNode as IElementNode;
160 if (parentElement != null &&
161 parentElement.Properties.TryGetValue(XmlName._CreateContent, out createContent) &&
162 createContent == this)
167 bool IsResourceDictionary() => XmlType.Name == "ResourceDictionary";
169 protected bool SkipChildren(IXamlNodeVisitor visitor, INode node, INode parentNode) =>
170 (visitor.StopOnDataTemplate && IsDataTemplate(parentNode))
171 || (visitor.StopOnResourceDictionary && IsResourceDictionary())
172 || visitor.SkipChildren(node, parentNode);
174 protected bool SkipVisitNode(IXamlNodeVisitor visitor, INode parentNode) =>
175 !visitor.VisitNodeOnDataTemplate && IsDataTemplate(parentNode);
177 public override INode Clone()
179 var clone = new ElementNode(XmlType, NamespaceURI, NamespaceResolver, LineNumber, LinePosition) {
180 IgnorablePrefixes = IgnorablePrefixes
182 foreach (var kvp in Properties)
183 clone.Properties.Add(kvp.Key, kvp.Value.Clone());
184 foreach (var p in SkipProperties)
185 clone.SkipProperties.Add(p);
186 foreach (var p in CollectionItems)
187 clone.CollectionItems.Add(p.Clone());
192 internal abstract class RootNode : ElementNode
194 protected RootNode(XmlType xmlType, IXmlNamespaceResolver nsResolver) : base(xmlType, xmlType.NamespaceUri, nsResolver)
198 public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
200 if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.TopDown)
201 visitor.Visit(this, parentNode);
203 if (!SkipChildren(visitor, this, parentNode)) {
204 foreach (var node in Properties.Values.ToList())
205 node.Accept(visitor, this);
206 foreach (var node in CollectionItems)
207 node.Accept(visitor, this);
210 if (!SkipVisitNode(visitor, parentNode) && visitor.VisitingMode == TreeVisitingMode.BottomUp)
211 visitor.Visit(this, parentNode);
215 internal class ListNode : BaseNode, IListNode, IValueNode
217 public ListNode(IList<INode> nodes, IXmlNamespaceResolver namespaceResolver, int linenumber = -1, int lineposition = -1)
218 : base(namespaceResolver, linenumber, lineposition)
220 CollectionItems = nodes.ToList();
223 public XmlName XmlName { get; set; }
224 public List<INode> CollectionItems { get; set; }
226 public override void Accept(IXamlNodeVisitor visitor, INode parentNode)
228 if (visitor.VisitingMode == TreeVisitingMode.TopDown)
229 visitor.Visit(this, parentNode);
230 foreach (var node in CollectionItems)
231 node.Accept(visitor, this);
232 if (visitor.VisitingMode == TreeVisitingMode.BottomUp)
233 visitor.Visit(this, parentNode);
236 public override INode Clone()
238 var items = new List<INode>();
239 foreach (var p in CollectionItems)
240 items.Add(p.Clone());
241 return new ListNode(items, NamespaceResolver, LineNumber, LinePosition) {
242 IgnorablePrefixes = IgnorablePrefixes
247 internal static class INodeExtensions
249 public static bool SkipPrefix(this INode node, string prefix)
252 if (node.IgnorablePrefixes != null && node.IgnorablePrefixes.Contains(prefix))
255 } while (node != null);