2 using System.Collections.Generic;
3 using System.Reflection;
4 using Tizen.NUI.StyleSheets;
5 using System.ComponentModel;
6 using Tizen.NUI.BaseComponents;
8 namespace Tizen.NUI.Binding
10 [EditorBrowsable(EditorBrowsableState.Never)]
11 [ContentProperty("Setters")]
12 public sealed class XamlStyle : IStyle
14 internal const string StyleClassPrefix = "Tizen.NUI.Binding.StyleClass.";
16 const int CleanupTrigger = 128;
17 int cleanupThreshold = CleanupTrigger;
19 readonly BindableProperty basedOnResourceProperty = BindableProperty.CreateAttached("BasedOnResource", typeof(XamlStyle), typeof(XamlStyle), default(XamlStyle),
20 propertyChanged: OnBasedOnResourceChanged);
22 readonly List<WeakReference<BindableObject>> targets = new List<WeakReference<BindableObject>>(4);
24 XamlStyle basedOnStyle;
26 string baseResourceKey;
28 IList<Behavior> behaviors;
30 IList<TriggerBase> triggers;
32 [EditorBrowsable(EditorBrowsableState.Never)]
33 public XamlStyle([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 [EditorBrowsable(EditorBrowsableState.Never)]
43 public bool ApplyToDerivedTypes { get; set; }
45 [EditorBrowsable(EditorBrowsableState.Never)]
46 public XamlStyle BasedOn
48 get { return basedOnStyle; }
51 if (basedOnStyle == value)
53 if (!ValidateBasedOn(value))
54 throw new ArgumentException("BasedOn.TargetType is not compatible with TargetType");
55 XamlStyle oldValue = basedOnStyle;
57 BasedOnChanged(oldValue, value);
59 BaseResourceKey = null;
63 [EditorBrowsable(EditorBrowsableState.Never)]
64 public string BaseResourceKey
66 get { return baseResourceKey; }
69 if (baseResourceKey == value)
71 baseResourceKey = value;
72 //update all DynamicResources
73 foreach (WeakReference<BindableObject> bindableWr in targets)
75 BindableObject target;
76 if (!bindableWr.TryGetTarget(out target))
78 target.RemoveDynamicResource(basedOnResourceProperty);
80 target.SetDynamicResource(basedOnResourceProperty, value);
87 internal IList<Behavior> Behaviors
89 get { return behaviors ?? (behaviors = new AttachedCollection<Behavior>()); }
92 [EditorBrowsable(EditorBrowsableState.Never)]
93 public bool CanCascade { get; set; }
95 [EditorBrowsable(EditorBrowsableState.Never)]
96 public string Class { get; set; }
98 [EditorBrowsable(EditorBrowsableState.Never)]
99 public IList<Setter> Setters { get; }
101 [EditorBrowsable(EditorBrowsableState.Never)]
102 public IList<TriggerBase> Triggers
104 get { return triggers ?? (triggers = new AttachedCollection<TriggerBase>()); }
107 void IStyle.Apply(BindableObject bindable)
109 targets.Add(new WeakReference<BindableObject>(bindable));
110 if (BaseResourceKey != null)
111 bindable.SetDynamicResource(basedOnResourceProperty, BaseResourceKey);
112 ApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));
113 CleanUpWeakReferences();
116 [EditorBrowsable(EditorBrowsableState.Never)]
117 public Type TargetType { get; }
119 void IStyle.UnApply(BindableObject bindable)
121 UnApplyCore(bindable, BasedOn ?? GetBasedOnResource(bindable));
122 bindable.RemoveDynamicResource(basedOnResourceProperty);
123 targets.RemoveAll(wr =>
125 BindableObject target;
126 return wr.TryGetTarget(out target) && target == bindable;
130 internal bool CanBeAppliedTo(Type targetType)
132 if (TargetType == targetType)
134 if (!ApplyToDerivedTypes)
138 targetType = targetType.GetTypeInfo().BaseType;
139 if (TargetType == targetType)
141 } while (targetType != typeof(Element));
145 void ApplyCore(BindableObject bindable, XamlStyle basedOn)
148 ((IStyle)basedOn).Apply(bindable);
150 foreach (Setter setter in Setters)
151 setter.Apply(bindable, true);
152 ((AttachedCollection<Behavior>)Behaviors).AttachTo(bindable);
153 ((AttachedCollection<TriggerBase>)Triggers).AttachTo(bindable);
156 void BasedOnChanged(XamlStyle oldValue, XamlStyle newValue)
158 foreach (WeakReference<BindableObject> bindableRef in targets)
160 BindableObject bindable;
161 if (!bindableRef.TryGetTarget(out bindable))
164 UnApplyCore(bindable, oldValue);
165 ApplyCore(bindable, newValue);
169 XamlStyle GetBasedOnResource(BindableObject bindable)
171 return (XamlStyle)bindable.GetValue(basedOnResourceProperty);
174 static void OnBasedOnResourceChanged(BindableObject bindable, object oldValue, object newValue)
176 XamlStyle style = (bindable as View).XamlStyle;
179 style.UnApplyCore(bindable, (XamlStyle)oldValue);
180 style.ApplyCore(bindable, (XamlStyle)newValue);
183 void UnApplyCore(BindableObject bindable, XamlStyle basedOn)
185 ((AttachedCollection<TriggerBase>)Triggers).DetachFrom(bindable);
186 ((AttachedCollection<Behavior>)Behaviors).DetachFrom(bindable);
187 foreach (Setter setter in Setters)
188 setter.UnApply(bindable, true);
191 ((IStyle)basedOn).UnApply(bindable);
194 bool ValidateBasedOn(XamlStyle value)
198 return value.TargetType.IsAssignableFrom(TargetType);
201 void CleanUpWeakReferences()
203 if (targets.Count < cleanupThreshold)
208 targets.RemoveAll(t => !t.TryGetTarget(out _));
209 cleanupThreshold = targets.Count + CleanupTrigger;