2 using System.Collections.Generic;
3 using System.Reflection;
4 using Tizen.NUI.StyleSheets;
5 using System.ComponentModel;
7 namespace Tizen.NUI.Binding
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
15 internal const string StyleClassPrefix = "Tizen.NUI.Binding.StyleClass.";
17 readonly BindableProperty _basedOnResourceProperty = BindableProperty.CreateAttached("BasedOnResource", typeof(Style), typeof(Style), default(Style),
18 propertyChanged: OnBasedOnResourceChanged);
20 readonly List<WeakReference<BindableObject>> _targets = new List<WeakReference<BindableObject>>(4);
24 string _baseResourceKey;
26 IList<Behavior> _behaviors;
28 IList<TriggerBase> _triggers;
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)
35 if (targetType == null)
36 throw new ArgumentNullException(nameof(targetType));
38 TargetType = targetType;
39 Setters = new List<Setter>();
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; }
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)]
52 get { return _basedOnStyle; }
55 if (_basedOnStyle == value)
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);
63 BaseResourceKey = null;
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
72 get { return _baseResourceKey; }
75 if (_baseResourceKey == value)
77 _baseResourceKey = value;
78 //update all DynamicResources
79 foreach (WeakReference<BindableObject> bindableWr in _targets)
81 BindableObject target;
82 if (!bindableWr.TryGetTarget(out target))
84 target.RemoveDynamicResource(_basedOnResourceProperty);
86 target.SetDynamicResource(_basedOnResourceProperty, value);
93 internal IList<Behavior> Behaviors
95 get { return _behaviors ?? (_behaviors = new AttachedCollection<Behavior>()); }
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; }
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; }
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; }
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
114 get { return _triggers ?? (_triggers = new AttachedCollection<TriggerBase>()); }
117 void IStyle.Apply(BindableObject bindable)
119 _targets.Add(new WeakReference<BindableObject>(bindable));
120 if (BaseResourceKey != null)
121 bindable.SetDynamicResource(_basedOnResourceProperty, BaseResourceKey);
122 ApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));
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; }
130 void IStyle.UnApply(BindableObject bindable)
132 UnApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));
133 bindable.RemoveDynamicResource(_basedOnResourceProperty);
134 _targets.RemoveAll(wr =>
136 BindableObject target;
137 return wr.TryGetTarget(out target) && target == bindable;
141 internal bool CanBeAppliedTo(Type targetType)
143 if (TargetType == targetType)
145 if (!ApplyToDerivedTypes)
149 targetType = targetType.GetTypeInfo().BaseType;
150 if (TargetType == targetType)
152 } while (targetType != typeof(Element));
156 void ApplyCore(BindableObject bindable, Style basedOn)
159 ((IStyle)basedOn).Apply(bindable);
161 foreach (Setter setter in Setters)
162 setter.Apply(bindable, true);
163 ((AttachedCollection<Behavior>)Behaviors).AttachTo(bindable);
164 ((AttachedCollection<TriggerBase>)Triggers).AttachTo(bindable);
167 void BasedOnChanged(Style oldValue, Style newValue)
169 foreach (WeakReference<BindableObject> bindableRef in _targets)
171 BindableObject bindable;
172 if (!bindableRef.TryGetTarget(out bindable))
175 UnApplyCore(bindable, oldValue);
176 ApplyCore(bindable, newValue);
180 Style GetBasedOnResource(BindableObject bindable)
182 return (Style)bindable.GetValue(_basedOnResourceProperty);
185 static void OnBasedOnResourceChanged(BindableObject bindable, object oldValue, object newValue)
187 // Style style = (bindable as /*VisualElement*/BaseHandle).Style;
188 // if (style == null)
190 // style.UnApplyCore(bindable, (Style)oldValue);
191 // style.ApplyCore(bindable, (Style)newValue);
194 void UnApplyCore(BindableObject bindable, Style basedOn)
196 ((AttachedCollection<TriggerBase>)Triggers).DetachFrom(bindable);
197 ((AttachedCollection<Behavior>)Behaviors).DetachFrom(bindable);
198 foreach (Setter setter in Setters)
199 setter.UnApply(bindable, true);
202 ((IStyle)basedOn).UnApply(bindable);
205 bool ValidateBasedOn(Style value)
209 return value.TargetType.IsAssignableFrom(TargetType);