[NUI] Adjust directory (#903)
[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             while (true) {
129                 BindableProperty implicitStyleProperty = BindableProperty.Create("ImplicitStyle", typeof(Style), typeof(View), default(Style),
130                         propertyChanged: (bindable, oldvalue, newvalue) => OnImplicitStyleChanged());
131                 _implicitStyles.Add(implicitStyleProperty);
132                 Target.SetDynamicResource(implicitStyleProperty, type.FullName);
133                 type = type.GetTypeInfo().BaseType;
134                 if (s_stopAtTypes.Contains(type))
135                     return;
136             }
137         }
138
139         void SetStyle(IStyle implicitStyle, IList<Style> classStyles, IStyle style)
140         {
141             bool shouldReApplyStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles || Style != style;
142             bool shouldReApplyClassStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles;
143             bool shouldReApplyImplicitStyle = implicitStyle != ImplicitStyle && (Style as Style == null || ((Style)Style).CanCascade);
144
145             if (shouldReApplyStyle)
146                 Style?.UnApply(Target);
147             if (shouldReApplyClassStyle && ClassStyles != null)
148                 foreach (var classStyle in ClassStyles)
149                     ((IStyle)classStyle)?.UnApply(Target);
150             if (shouldReApplyImplicitStyle)
151                 ImplicitStyle?.UnApply(Target);
152
153             _implicitStyle = implicitStyle;
154             _classStyles = classStyles;
155             _style = style;
156
157             if (shouldReApplyImplicitStyle)
158                 ImplicitStyle?.Apply(Target);
159             if (shouldReApplyClassStyle && ClassStyles != null)
160                 foreach (var classStyle in ClassStyles)
161                     ((IStyle)classStyle)?.Apply(Target);
162             if (shouldReApplyStyle)
163                 Style?.Apply(Target);
164         }
165     }
166 }