[NUI] Fix Svace issues
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / XamlBinding / MergedStyle.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Reflection;
5 using Tizen.NUI.StyleSheets;
6 using Tizen.NUI.BaseComponents;
7
8 namespace Tizen.NUI.Binding
9 {
10     internal sealed class MergedStyle : IStyle
11     {
12         ////If the base type is one of these, stop registering dynamic resources further
13         ////The last one (typeof(Element)) is a safety guard as we might be creating VisualElement directly in internal code
14         static readonly IList<Type> s_stopAtTypes = new List<Type> { typeof(View), typeof(Element) };
15
16         IList<BindableProperty> _classStyleProperties;
17
18         readonly List<BindableProperty> _implicitStyles = new List<BindableProperty>();
19
20         IList<Style> _classStyles;
21
22         IStyle _implicitStyle;
23
24         IStyle _style;
25
26         IList<string> _styleClass;
27
28         public MergedStyle(Type targetType, BindableObject target)
29         {
30             Target = target;
31             TargetType = targetType;
32             RegisterImplicitStyles();
33             Apply(Target);
34         }
35
36         public IStyle Style
37         {
38             get { return _style; }
39             set { SetStyle(ImplicitStyle, ClassStyles, value); }
40         }
41
42         public IList<string> StyleClass
43         {
44             get { return _styleClass; }
45             set
46             {
47                 if (_styleClass == value)
48                     return;
49
50                 if (_styleClass != null && _classStyles != null)
51                     foreach (var classStyleProperty in _classStyleProperties)
52                         Target.RemoveDynamicResource(classStyleProperty);
53
54                 _styleClass = value;
55
56                 if (_styleClass != null) {
57                     _classStyleProperties = new List<BindableProperty> ();
58                     foreach (var styleClass in _styleClass) {
59                         var classStyleProperty = BindableProperty.Create ("ClassStyle", typeof(IList<Style>), typeof(View), default(IList<Style>),
60                             propertyChanged: (bindable, oldvalue, newvalue) => ((View)bindable)._mergedStyle.OnClassStyleChanged());
61                         _classStyleProperties.Add (classStyleProperty);
62                         Target.OnSetDynamicResource (classStyleProperty, Tizen.NUI.Binding.Style.StyleClassPrefix + styleClass);
63                     }
64                 }
65             }
66         }
67
68         public BindableObject Target { get; }
69
70         IList<Style> ClassStyles
71         {
72             get { return _classStyles; }
73             set { SetStyle(ImplicitStyle, value, Style); }
74         }
75
76         IStyle ImplicitStyle
77         {
78             get { return _implicitStyle; }
79             set { SetStyle(value, ClassStyles, Style); }
80         }
81
82         public void Apply(BindableObject bindable)
83         {
84             ImplicitStyle?.Apply(bindable);
85             if (ClassStyles != null)
86                 foreach (var classStyle in ClassStyles)
87                     ((IStyle)classStyle)?.Apply(bindable);
88             Style?.Apply(bindable);
89         }
90
91         public Type TargetType { get; }
92
93         public void UnApply(BindableObject bindable)
94         {
95             Style?.UnApply(bindable);
96             if (ClassStyles != null)
97                 foreach (var classStyle in ClassStyles)
98                     ((IStyle)classStyle)?.UnApply(bindable);
99             ImplicitStyle?.UnApply(bindable);
100         }
101
102         void OnClassStyleChanged()
103         {
104             ClassStyles = _classStyleProperties.Select (p => (Target.GetValue (p) as IList<Style>)?.FirstOrDefault (s => s.CanBeAppliedTo (TargetType))).ToList ();
105         }
106
107         void OnImplicitStyleChanged()
108         {
109             var first = true;
110             foreach (BindableProperty implicitStyleProperty in _implicitStyles)
111             {
112                 var implicitStyle = (Style)Target.GetValue(implicitStyleProperty);
113                 if (implicitStyle != null)
114                 {
115                     if (first || implicitStyle.ApplyToDerivedTypes)
116                     {
117                         ImplicitStyle = implicitStyle;
118                         return;
119                     }
120                 }
121                 first = false;
122             }
123         }
124
125         void RegisterImplicitStyles()
126         {
127             Type type = TargetType;
128             if (type == null)
129             {
130                 return;
131             }
132             while (true) {
133                 BindableProperty implicitStyleProperty = BindableProperty.Create(nameof(ImplicitStyle), typeof(Style), typeof(View), default(Style),
134                         propertyChanged: (bindable, oldvalue, newvalue) => OnImplicitStyleChanged());
135                 _implicitStyles.Add(implicitStyleProperty);
136                 Target.SetDynamicResource(implicitStyleProperty, type?.FullName);
137                 type = type.GetTypeInfo().BaseType;
138                 if (s_stopAtTypes.Contains(type))
139                     return;
140             }
141         }
142
143         void SetStyle(IStyle implicitStyle, IList<Style> classStyles, IStyle style)
144         {
145             bool shouldReApplyStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles || Style != style;
146             bool shouldReApplyClassStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles;
147             bool shouldReApplyImplicitStyle = implicitStyle != ImplicitStyle && (Style as Style == null || ((Style)Style).CanCascade);
148
149             if (shouldReApplyStyle)
150                 Style?.UnApply(Target);
151             if (shouldReApplyClassStyle && ClassStyles != null)
152                 foreach (var classStyle in ClassStyles)
153                     ((IStyle)classStyle)?.UnApply(Target);
154             if (shouldReApplyImplicitStyle)
155                 ImplicitStyle?.UnApply(Target);
156
157             _implicitStyle = implicitStyle;
158             _classStyles = classStyles;
159             _style = style;
160
161             if (shouldReApplyImplicitStyle)
162                 ImplicitStyle?.Apply(Target);
163             if (shouldReApplyClassStyle && ClassStyles != null)
164                 foreach (var classStyle in ClassStyles)
165                     ((IStyle)classStyle)?.Apply(Target);
166             if (shouldReApplyStyle)
167                 Style?.Apply(Target);
168         }
169     }
170 }