[NUI] Fix StyleCop warning CA1823 (#2222)
[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                 {
58                     _classStyleProperties = new List<BindableProperty>();
59                     foreach (var styleClass in _styleClass)
60                     {
61                         var classStyleProperty = BindableProperty.Create("ClassStyle", typeof(IList<Style>), typeof(View), default(IList<Style>),
62                             propertyChanged: (bindable, oldvalue, newvalue) => ((View)bindable)._mergedStyle.OnClassStyleChanged());
63                         _classStyleProperties.Add(classStyleProperty);
64                         Target.OnSetDynamicResource(classStyleProperty, Tizen.NUI.Binding.Style.StyleClassPrefix + styleClass);
65                     }
66                 }
67             }
68         }
69
70         public BindableObject Target { get; }
71
72         IList<Style> ClassStyles
73         {
74             get { return _classStyles; }
75             set { SetStyle(ImplicitStyle, value, Style); }
76         }
77
78         IStyle ImplicitStyle
79         {
80             get { return _implicitStyle; }
81             set { SetStyle(value, ClassStyles, Style); }
82         }
83
84         public void Apply(BindableObject bindable)
85         {
86             ImplicitStyle?.Apply(bindable);
87             if (ClassStyles != null)
88                 foreach (var classStyle in ClassStyles)
89                     ((IStyle)classStyle)?.Apply(bindable);
90             Style?.Apply(bindable);
91         }
92
93         public Type TargetType { get; }
94
95         public void UnApply(BindableObject bindable)
96         {
97             Style?.UnApply(bindable);
98             if (ClassStyles != null)
99                 foreach (var classStyle in ClassStyles)
100                     ((IStyle)classStyle)?.UnApply(bindable);
101             ImplicitStyle?.UnApply(bindable);
102         }
103
104         void OnClassStyleChanged()
105         {
106             ClassStyles = _classStyleProperties.Select(p => (Target.GetValue(p) as IList<Style>)?.FirstOrDefault(s => s.CanBeAppliedTo(TargetType))).ToList();
107         }
108
109         void OnImplicitStyleChanged()
110         {
111             var first = true;
112             foreach (BindableProperty implicitStyleProperty in _implicitStyles)
113             {
114                 var implicitStyle = (Style)Target.GetValue(implicitStyleProperty);
115                 if (implicitStyle != null)
116                 {
117                     if (first || implicitStyle.ApplyToDerivedTypes)
118                     {
119                         ImplicitStyle = implicitStyle;
120                         return;
121                     }
122                 }
123                 first = false;
124             }
125         }
126
127         void RegisterImplicitStyles()
128         {
129             Type type = TargetType;
130             if (type == null)
131             {
132                 return;
133             }
134             while (true)
135             {
136                 BindableProperty implicitStyleProperty = BindableProperty.Create(nameof(ImplicitStyle), typeof(Style), typeof(View), default(Style),
137                         propertyChanged: (bindable, oldvalue, newvalue) => OnImplicitStyleChanged());
138                 _implicitStyles.Add(implicitStyleProperty);
139                 Target.SetDynamicResource(implicitStyleProperty, type.FullName);
140                 type = type.GetTypeInfo().BaseType;
141                 if (s_stopAtTypes.Contains(type))
142                     return;
143             }
144         }
145
146         void SetStyle(IStyle implicitStyle, IList<Style> classStyles, IStyle style)
147         {
148             bool shouldReApplyStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles || Style != style;
149             bool shouldReApplyClassStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles;
150             bool shouldReApplyImplicitStyle = implicitStyle != ImplicitStyle && (Style as Style == null || ((Style)Style).CanCascade);
151
152             if (shouldReApplyStyle)
153                 Style?.UnApply(Target);
154             if (shouldReApplyClassStyle && ClassStyles != null)
155                 foreach (var classStyle in ClassStyles)
156                     ((IStyle)classStyle)?.UnApply(Target);
157             if (shouldReApplyImplicitStyle)
158                 ImplicitStyle?.UnApply(Target);
159
160             _implicitStyle = implicitStyle;
161             _classStyles = classStyles;
162             _style = style;
163
164             if (shouldReApplyImplicitStyle)
165                 ImplicitStyle?.Apply(Target);
166             if (shouldReApplyClassStyle && ClassStyles != null)
167                 foreach (var classStyle in ClassStyles)
168                     ((IStyle)classStyle)?.Apply(Target);
169             if (shouldReApplyStyle)
170                 Style?.Apply(Target);
171         }
172     }
173 }