940cdd5ad87f76df2d6b5b78b03c337c0a71e277
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / XamlBinding / StyleSheets / StyleSheet.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.IO;
5 using System.Reflection;
6 using System.Runtime.CompilerServices;
7 using System.Xml;
8 using Tizen.NUI.Xaml;
9 using Tizen.NUI.Binding;
10
11 namespace Tizen.NUI.StyleSheets
12 {
13     internal sealed class StyleSheet : IStyle
14     {
15         StyleSheet()
16         {
17         }
18
19         internal IDictionary<Selector, Style> Styles { get; set; } = new Dictionary<Selector, Style>();
20
21         public static StyleSheet FromAssemblyResource(Assembly assembly, string resourceId, IXmlLineInfo lineInfo = null)
22         {
23             using (var stream = assembly.GetManifestResourceStream(resourceId)) {
24                 if (stream == null)
25                     throw new XamlParseException($"No resource found for '{resourceId}'.", lineInfo);
26                 using (var reader = new StreamReader(stream)) {
27                     return FromReader(reader);
28                 }
29             }
30         }
31
32         //used by code generated by XamlC. Has to stay public
33         [EditorBrowsable(EditorBrowsableState.Never)]
34         public static StyleSheet FromString(string stylesheet)
35         {
36             if (stylesheet == null)
37                 throw new ArgumentNullException(nameof(stylesheet));
38             using (var reader = new StringReader(stylesheet))
39                 return FromReader(reader);
40         }
41
42         public static StyleSheet FromReader(TextReader reader)
43         {
44             if (reader == null)
45                 throw new ArgumentNullException(nameof(reader));
46
47             return Parse(new CssReader(reader));
48         }
49
50         [MethodImpl(MethodImplOptions.AggressiveInlining)]
51         static StyleSheet Parse(CssReader reader)
52         {
53             var sheet = new StyleSheet();
54
55             Style style = null;
56             var selector = Selector.All;
57
58             int p;
59             bool inStyle = false;
60             reader.SkipWhiteSpaces();
61             while ((p = reader.Peek()) > 0) {
62                 switch ((char)p) {
63                 case '@':
64                     throw new NotSupportedException("AT-rules not supported");
65                 case '{':
66                     reader.Read();
67                     style = Style.Parse(reader, '}');
68                     inStyle = true;
69                     break;
70                 case '}':
71                     reader.Read();
72                     if (!inStyle)
73                         throw new Exception();
74                     inStyle = false;
75                     sheet.Styles.Add(selector, style);
76                     style = null;
77                     selector = Selector.All;
78                     break;
79                 default:
80                     selector = Selector.Parse(reader, '{');
81                     break;
82                 }
83             }
84             return sheet;
85         }
86
87         Type IStyle.TargetType
88             => typeof(/*VisualElement*/BaseHandle);
89
90         void IStyle.Apply(BindableObject bindable)
91         {
92             var styleable = bindable as Element;
93             if (styleable == null)
94                 return;
95             Apply(styleable);
96         }
97
98         void Apply(Element styleable)
99         {
100             ApplyCore(styleable);
101             foreach (var child in styleable.LogicalChildrenInternal)
102                 ((IStyle)this).Apply(child);
103         }
104
105         void ApplyCore(Element styleable)
106         {
107             var visualStylable = styleable as /*VisualElement*/BaseHandle;
108             if (visualStylable == null)
109                 return;
110             foreach (var kvp in Styles) {
111                 var selector = kvp.Key;
112                 var style = kvp.Value;
113                 // if (!selector.Matches(styleable))
114                 //      continue;
115                 style.Apply(visualStylable);
116             }
117         }
118
119         void IStyle.UnApply(BindableObject bindable)
120         {
121             throw new NotImplementedException();
122         }
123     }
124 }