[NUI] Fix build warning CA1507
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / XamlBinding / Style.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4 using Tizen.NUI.StyleSheets;
5 using System.ComponentModel;
6
7 namespace Tizen.NUI.Binding
8 {
9     /// <since_tizen> 6 </since_tizen>
10     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
11     [EditorBrowsable(EditorBrowsableState.Never)]
12     [ContentProperty("Setters")]
13     public sealed class Style : IStyle
14     {
15         internal const string StyleClassPrefix = "Tizen.NUI.Binding.StyleClass.";
16
17         readonly BindableProperty _basedOnResourceProperty = BindableProperty.CreateAttached("BasedOnResource", typeof(Style), typeof(Style), default(Style),
18             propertyChanged: OnBasedOnResourceChanged);
19
20         readonly List<WeakReference<BindableObject>> _targets = new List<WeakReference<BindableObject>>(4);
21
22         Style _basedOnStyle;
23
24         string _baseResourceKey;
25
26         IList<Behavior> _behaviors;
27
28         IList<TriggerBase> _triggers;
29
30         /// <since_tizen> 6 </since_tizen>
31         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
32         [EditorBrowsable(EditorBrowsableState.Never)]
33         public Style([TypeConverter(typeof(TypeTypeConverter))] [Parameter("TargetType")] Type targetType)
34         {
35             if (targetType == null)
36                 throw new ArgumentNullException(nameof(targetType));
37
38             TargetType = targetType;
39             Setters = new List<Setter>();
40         }
41
42         /// <since_tizen> 6 </since_tizen>
43         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
44         [EditorBrowsable(EditorBrowsableState.Never)]
45         public bool ApplyToDerivedTypes { get; set; }
46
47         /// <since_tizen> 6 </since_tizen>
48         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
49         [EditorBrowsable(EditorBrowsableState.Never)]
50         public Style BasedOn
51         {
52             get { return _basedOnStyle; }
53             set
54             {
55                 if (_basedOnStyle == value)
56                     return;
57                 if (!ValidateBasedOn(value))
58                     throw new ArgumentException("BasedOn.TargetType is not compatible with TargetType");
59                 Style oldValue = _basedOnStyle;
60                 _basedOnStyle = value;
61                 BasedOnChanged(oldValue, value);
62                 if (value != null)
63                     BaseResourceKey = null;
64             }
65         }
66
67         /// <since_tizen> 6 </since_tizen>
68         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
69         [EditorBrowsable(EditorBrowsableState.Never)]
70         public string BaseResourceKey
71         {
72             get { return _baseResourceKey; }
73             set
74             {
75                 if (_baseResourceKey == value)
76                     return;
77                 _baseResourceKey = value;
78                 //update all DynamicResources
79                 foreach (WeakReference<BindableObject> bindableWr in _targets)
80                 {
81                     BindableObject target;
82                     if (!bindableWr.TryGetTarget(out target))
83                         continue;
84                     target.RemoveDynamicResource(_basedOnResourceProperty);
85                     if (value != null)
86                         target.SetDynamicResource(_basedOnResourceProperty, value);
87                 }
88                 if (value != null)
89                     BasedOn = null;
90             }
91         }
92
93         internal IList<Behavior> Behaviors
94         {
95             get { return _behaviors ?? (_behaviors = new AttachedCollection<Behavior>()); }
96         }
97
98         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
99         [EditorBrowsable(EditorBrowsableState.Never)]
100         public bool CanCascade { get; set; }
101
102         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
103         [EditorBrowsable(EditorBrowsableState.Never)]
104         public string Class { get; set; }
105
106         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
107         [EditorBrowsable(EditorBrowsableState.Never)]
108         public IList<Setter> Setters { get; }
109
110         /// This will be public opened in tizen_next after ACR done. Before ACR, need to be hidden as inhouse API.
111         [EditorBrowsable(EditorBrowsableState.Never)]
112         public IList<TriggerBase> Triggers
113         {
114             get { return _triggers ?? (_triggers = new AttachedCollection<TriggerBase>()); }
115         }
116
117         void IStyle.Apply(BindableObject bindable)
118         {
119             _targets.Add(new WeakReference<BindableObject>(bindable));
120             if (BaseResourceKey != null)
121                 bindable.SetDynamicResource(_basedOnResourceProperty, BaseResourceKey);
122             ApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));
123         }
124
125         /// <since_tizen> 6 </since_tizen>
126         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
127         [EditorBrowsable(EditorBrowsableState.Never)]
128         public Type TargetType { get; }
129
130         void IStyle.UnApply(BindableObject bindable)
131         {
132             UnApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));
133             bindable.RemoveDynamicResource(_basedOnResourceProperty);
134             _targets.RemoveAll(wr =>
135             {
136                 BindableObject target;
137                 return wr.TryGetTarget(out target) && target == bindable;
138             });
139         }
140
141         internal bool CanBeAppliedTo(Type targetType)
142         {
143             if (TargetType == targetType)
144                 return true;
145             if (!ApplyToDerivedTypes)
146                 return false;
147             do
148             {
149                 targetType = targetType.GetTypeInfo().BaseType;
150                 if (TargetType == targetType)
151                     return true;
152             } while (targetType != typeof(Element));
153             return false;
154         }
155
156         void ApplyCore(BindableObject bindable, Style basedOn)
157         {
158             if (basedOn != null)
159                 ((IStyle)basedOn).Apply(bindable);
160
161             foreach (Setter setter in Setters)
162                 setter.Apply(bindable, true);
163             ((AttachedCollection<Behavior>)Behaviors).AttachTo(bindable);
164             ((AttachedCollection<TriggerBase>)Triggers).AttachTo(bindable);
165         }
166
167         void BasedOnChanged(Style oldValue, Style newValue)
168         {
169             foreach (WeakReference<BindableObject> bindableRef in _targets)
170             {
171                 BindableObject bindable;
172                 if (!bindableRef.TryGetTarget(out bindable))
173                     continue;
174
175                 UnApplyCore(bindable, oldValue);
176                 ApplyCore(bindable, newValue);
177             }
178         }
179
180         Style GetBasedOnResource(BindableObject bindable)
181         {
182             return (Style)bindable.GetValue(_basedOnResourceProperty);
183         }
184
185         static void OnBasedOnResourceChanged(BindableObject bindable, object oldValue, object newValue)
186         {
187             // Style style = (bindable as /*VisualElement*/BaseHandle).Style;
188             // if (style == null)
189             //  return;
190             // style.UnApplyCore(bindable, (Style)oldValue);
191             // style.ApplyCore(bindable, (Style)newValue);
192         }
193
194         void UnApplyCore(BindableObject bindable, Style basedOn)
195         {
196             ((AttachedCollection<TriggerBase>)Triggers).DetachFrom(bindable);
197             ((AttachedCollection<Behavior>)Behaviors).DetachFrom(bindable);
198             foreach (Setter setter in Setters)
199                 setter.UnApply(bindable, true);
200
201             if (basedOn != null)
202                 ((IStyle)basedOn).UnApply(bindable);
203         }
204
205         bool ValidateBasedOn(Style value)
206         {
207             if (value == null)
208                 return true;
209             return value.TargetType.IsAssignableFrom(TargetType);
210         }
211     }
212 }