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