[NUI] Public RemoveBinding and ClearBinding apis
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / XamlBinding / BindableObject.cs
index 9bac951..b5390fa 100755 (executable)
@@ -45,8 +45,6 @@ namespace Tizen.NUI.Binding
         bool applying;
         object inheritedContext;
 
-        private object bindingContext;
-
         /// <summary>
         /// Gets or sets object that contains the properties that will be targeted by the bound properties that belong to this BindableObject.
         /// </summary>
@@ -64,10 +62,7 @@ namespace Tizen.NUI.Binding
         [EditorBrowsable(EditorBrowsableState.Never)]
         public int LinePosition { get; set; } = -1;
 
-        void IDynamicResourceHandler.SetDynamicResource(BindableProperty property, string key)
-        {
-            SetDynamicResource(property, key, false);
-        }
+        void IDynamicResourceHandler.SetDynamicResource(BindableProperty property, string key) => SetDynamicResource(property, key, false);
 
         /// <summary>
         /// Raised when a property has changed.
@@ -94,14 +89,10 @@ namespace Tizen.NUI.Binding
                 {
                     nameToBindableProperty2.TryGetValue(keyValuePair.Key, out var bindableProperty);
 
-                    if (null != bindableProperty && (SettedPropeties.Contains(bindableProperty) || other.SettedPropeties.Contains(bindableProperty)))
+                    if (null != bindableProperty && other.IsSet(bindableProperty))
                     {
                         object value = other.GetValue(bindableProperty);
-
-                        if (null != value)
-                        {
-                            SetValue(keyValuePair.Value, value);
-                        }
+                        InternalSetValue(keyValuePair.Value, value);
                     }
                 }
             }
@@ -142,10 +133,7 @@ namespace Tizen.NUI.Binding
         [EditorBrowsable(EditorBrowsableState.Never)]
         public event EventHandler BindingContextChanged;
 
-        internal void ClearValue(BindableProperty property, bool fromStyle)
-        {
-            ClearValue(property, fromStyle: fromStyle, checkAccess: true);
-        }
+        internal void ClearValue(BindableProperty property, bool fromStyle) => ClearValue(property, fromStyle: fromStyle, checkAccess: true);
 
         /// <summary>
         /// Clears any value set by Tizen.NUI.Xaml.BindableObject.SetValue.
@@ -195,7 +183,7 @@ namespace Tizen.NUI.Binding
             if (property == null)
                 throw new ArgumentNullException(nameof(property));
 
-            if (!IsBinded && property.ValueGetter != null)
+            if (!IsBound && property.ValueGetter != null)
             {
                 return property.ValueGetter(this);
             }
@@ -219,7 +207,8 @@ namespace Tizen.NUI.Binding
         /// Removes a previously set binding.
         /// </summary>
         /// <param name="property">The BindableProperty from which to remove bindings.</param>
-        internal void RemoveBinding(BindableProperty property)
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void RemoveBinding(BindableProperty property)
         {
             if (property == null)
                 throw new ArgumentNullException(nameof(property));
@@ -238,23 +227,58 @@ namespace Tizen.NUI.Binding
         /// <param name="binding">The binding to set.</param>
         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public void SetBinding(BindableProperty targetProperty, BindingBase binding)
+        public void SetBinding(BindableProperty targetProperty, BindingBase binding) => SetBinding(targetProperty, binding, false);
+
+        /// Internal used, will never changed to not hidden.
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public virtual bool IsCreateByXaml
         {
-            SetBinding(targetProperty, binding, false);
+            get;
+            set;
         }
 
-        private bool isCreateByXaml = false;
-        /// Only used by the IL of xaml, will never changed to not hidden.
+        /// This will be public opened in next ACR.
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public virtual bool IsCreateByXaml
+        public void EnforceNotifyBindedInstance(BindableProperty property)
         {
-            get
+            if (null != property)
             {
-                return isCreateByXaml;
-            }
-            set
-            {
-                isCreateByXaml = value;
+                BindablePropertyContext context = GetOrCreateContext(property);
+                BindingBase binding = context.Binding;
+
+                var currentlyApplying = applying;
+
+                if (binding != null && !currentlyApplying)
+                {
+                    applying = true;
+                    binding.Apply(true);
+                    applying = false;
+                }
+
+                OnPropertyChanged(property.PropertyName);
+
+                PropertyToGroup.TryGetValue(property, out HashSet<BindableProperty> propertyGroup);
+
+                if (null != propertyGroup)
+                {
+                    foreach (var relativeProperty in propertyGroup)
+                    {
+                        if (relativeProperty != property)
+                        {
+                            var relativeContext = GetOrCreateContext(relativeProperty);
+                            var relativeBinding = relativeContext.Binding;
+
+                            if (null != relativeBinding)
+                            {
+                                applying = true;
+                                relativeBinding.Apply(true);
+                                applying = false;
+                            }
+
+                            OnPropertyChanged(relativeProperty.PropertyName);
+                        }
+                    }
+                }
             }
         }
 
@@ -268,7 +292,13 @@ namespace Tizen.NUI.Binding
         [EditorBrowsable(EditorBrowsableState.Never)]
         public void SetValue(BindableProperty property, object value)
         {
-            if (true == IsBinded)
+            InternalSetValue(property, value);
+            ChangedPropertiesSetExcludingStyle.Add(property);
+        }
+
+        internal void InternalSetValue(BindableProperty property, object value)
+        {
+            if (true == IsBound)
             {
                 SetValue(property, value, false, true);
             }
@@ -280,59 +310,33 @@ namespace Tizen.NUI.Binding
                 }
 
                 object oldvalue = null;
-                if (null == property.DefaultValueCreator)
+                BindablePropertyContext context = GetOrCreateContext(property);
+                if (null != context)
                 {
-                    BindablePropertyContext context = GetOrCreateContext(property);
-                    if (null != context)
-                    {
-                        oldvalue = context.Value;
-                        context.Value = value;
-                    }
-                }
-                else
-                {
-                    oldvalue = property.DefaultValueCreator.Invoke(this);
+                    context.Attributes |= BindableContextAttributes.IsManuallySet;
+                    oldvalue = context.Value;
+                    context.Value = value;
                 }
 
+                property.PropertyChanging?.Invoke(this, oldvalue, value);
                 property.PropertyChanged?.Invoke(this, oldvalue, value);
 
                 OnPropertyChanged(property.PropertyName);
                 OnPropertyChangedWithData(property);
             }
-
-            SettedPropeties.Add(property);
         }
 
-        private HashSet<BindableProperty> settedPropeties;
-        private HashSet<BindableProperty> SettedPropeties
+        private HashSet<BindableProperty> changedPropertiesSetExcludingStyle;
+        internal protected HashSet<BindableProperty> ChangedPropertiesSetExcludingStyle
         {
             get
             {
-                if (null == settedPropeties)
+                if (null == changedPropertiesSetExcludingStyle)
                 {
-                    settedPropeties = new HashSet<BindableProperty>();
+                    changedPropertiesSetExcludingStyle = new HashSet<BindableProperty>();
                 }
 
-                return settedPropeties;
-            }
-        }
-
-        internal void SetValueAndForceSendChangeSignal(BindableProperty property, object value)
-        {
-            if (property == null)
-                throw new ArgumentNullException(nameof(property));
-
-            if (true == isCreateByXaml)
-            {
-                if (property.IsReadOnly)
-                    throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName));
-
-                SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
-                    SetValuePrivateFlags.ManuallySet | SetValuePrivateFlags.CheckAccess, true);
-            }
-            else
-            {
-                property.PropertyChanged?.Invoke(this, null, value);
+                return changedPropertiesSetExcludingStyle;
             }
         }
 
@@ -412,10 +416,7 @@ namespace Tizen.NUI.Binding
         /// </summary>
         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
-        protected void ApplyBindings()
-        {
-            ApplyBindings(skipBindingContext: false, fromBindingContextChanged: false);
-        }
+        protected void ApplyBindings() => ApplyBindings(skipBindingContext: false, fromBindingContextChanged: false);
 
         /// <summary>
         /// Override this method to execute an action when the BindingContext changes.
@@ -606,7 +607,7 @@ namespace Tizen.NUI.Binding
             if (fromStyle && !CanBeSetFromStyle(targetProperty))
                 return;
 
-            IsBinded = true;
+            IsBound = true;
 
             var context = GetOrCreateContext(targetProperty);
             if (fromStyle)
@@ -639,10 +640,7 @@ namespace Tizen.NUI.Binding
             return false;
         }
 
-        internal void SetDynamicResource(BindableProperty property, string key)
-        {
-            SetDynamicResource(property, key, false);
-        }
+        internal void SetDynamicResource(BindableProperty property, string key) => SetDynamicResource(property, key, false);
 
         internal void SetDynamicResource(BindableProperty property, string key, bool fromStyle)
         {
@@ -664,14 +662,11 @@ namespace Tizen.NUI.Binding
             OnSetDynamicResource(property, key);
         }
 
-        internal void SetValue(BindableProperty property, object value, bool fromStyle)
-        {
-            SetValue(property, value, fromStyle, true);
-        }
+        internal void SetValue(BindableProperty property, object value, bool fromStyle) => SetValue(property, value, fromStyle, true);
 
         internal void SetValueCore(BindablePropertyKey propertyKey, object value, SetValueFlags attributes = SetValueFlags.None)
         {
-            SetValueCore(propertyKey.BindableProperty, value, attributes, SetValuePrivateFlags.None, false);
+            SetValueCore(propertyKey.BindableProperty, value, attributes, SetValuePrivateFlags.None);
         }
 
         /// <summary>
@@ -681,12 +676,9 @@ namespace Tizen.NUI.Binding
         /// <param name="value">The value to set</param>
         /// <param name="attributes">The set value flag</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes = SetValueFlags.None)
-        {
-            SetValueCore(property, value, attributes, SetValuePrivateFlags.Default, false);
-        }
+        internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes = SetValueFlags.None) => SetValueCore(property, value, attributes, SetValuePrivateFlags.Default);
 
-        internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, bool forceSendChangeSignal)
+        internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
         {
             bool checkAccess = (privateAttributes & SetValuePrivateFlags.CheckAccess) != 0;
             bool manuallySet = (privateAttributes & SetValuePrivateFlags.ManuallySet) != 0;
@@ -744,7 +736,7 @@ namespace Tizen.NUI.Binding
             else
             {
                 context.Attributes |= BindableContextAttributes.IsBeingSet;
-                SetValueActual(property, context, value, currentlyApplying, forceSendChangeSignal, attributes, silent);
+                SetValueActual(property, context, value, currentlyApplying, attributes, silent);
 
                 Queue<SetValueArgs> delayQueue = context.DelayedSetters;
                 if (delayQueue != null)
@@ -752,7 +744,7 @@ namespace Tizen.NUI.Binding
                     while (delayQueue.Count > 0)
                     {
                         SetValueArgs s = delayQueue.Dequeue();
-                        SetValueActual(s.Property, s.Context, s.Value, s.CurrentlyApplying, forceSendChangeSignal, s.Attributes);
+                        SetValueActual(s.Property, s.Context, s.Value, s.CurrentlyApplying, s.Attributes);
                     }
 
                     context.DelayedSetters = null;
@@ -780,8 +772,30 @@ namespace Tizen.NUI.Binding
             }
         }
 
+        /// <summary>
+        /// Check if object is bound or not.
+        /// This API used for legacy codes.
+        /// Should be removed after all app usage replaced into IsBound.
+        /// </summary>
+        [Obsolete("This has been deprecated in API11. Use IsBound property instead.")]
         internal bool IsBinded
         {
+            get
+            {
+                return IsBound;
+            }
+            set
+            {
+                IsBound = value;
+            }
+        }
+
+        /// <summary>
+        /// Check if object is bound or not.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool IsBound
+        {
             get;
             set;
         } = false;
@@ -794,7 +808,7 @@ namespace Tizen.NUI.Binding
 
             if (newvalue is BindableObject targetBindableObject)
             {
-                targetBindableObject.IsBinded = true;
+                targetBindableObject.IsBound = true;
             }
         }
 
@@ -910,11 +924,10 @@ namespace Tizen.NUI.Binding
                 return;
 
             SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource,
-                (fromStyle ? SetValuePrivateFlags.FromStyle : SetValuePrivateFlags.ManuallySet) | (checkAccess ? SetValuePrivateFlags.CheckAccess : 0),
-                false);
+                (fromStyle ? SetValuePrivateFlags.FromStyle : SetValuePrivateFlags.ManuallySet) | (checkAccess ? SetValuePrivateFlags.CheckAccess : 0));
         }
 
-        void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, bool forceSendChangeSignal, SetValueFlags attributes, bool silent = false)
+        void SetValueActual(BindableProperty property, BindablePropertyContext context, object value, bool currentlyApplying, SetValueFlags attributes, bool silent = false)
         {
             object original = context.Value;
             bool raiseOnEqual = (attributes & SetValueFlags.RaiseOnEqual) != 0;
@@ -953,71 +966,36 @@ namespace Tizen.NUI.Binding
 
             PropertyToGroup.TryGetValue(property, out HashSet<BindableProperty> propertyGroup);
 
-            if (!silent)
+            if (!silent && (!same || raiseOnEqual))
             {
-                if ((!same || raiseOnEqual))
-                {
-                    property.PropertyChanged?.Invoke(this, original, value);
-
-                    if (binding != null && !currentlyApplying)
-                    {
-                        applying = true;
-                        binding.Apply(true);
-                        applying = false;
-                    }
-
-                    OnPropertyChanged(property.PropertyName);
-
-                    if (null != propertyGroup)
-                    {
-                        foreach (var relativeProperty in propertyGroup)
-                        {
-                            if (relativeProperty != property)
-                            {
-                                var relativeContext = GetOrCreateContext(relativeProperty);
-                                var relativeBinding = relativeContext.Binding;
+                property.PropertyChanged?.Invoke(this, original, value);
 
-                                if (null != relativeBinding)
-                                {
-                                    applying = true;
-                                    relativeBinding.Apply(true);
-                                    applying = false;
-                                }
-
-                                OnPropertyChanged(relativeProperty.PropertyName);
-                            }
-                        }
-                    }
-                }
-                else if (true == same && true == forceSendChangeSignal)
+                if (binding != null && !currentlyApplying)
                 {
-                    if (binding != null && !currentlyApplying)
-                    {
-                        applying = true;
-                        binding.Apply(true);
-                        applying = false;
-                    }
+                    applying = true;
+                    binding.Apply(true);
+                    applying = false;
+                }
 
-                    OnPropertyChanged(property.PropertyName);
+                OnPropertyChanged(property.PropertyName);
 
-                    if (null != propertyGroup)
+                if (null != propertyGroup)
+                {
+                    foreach (var relativeProperty in propertyGroup)
                     {
-                        foreach (var relativeProperty in propertyGroup)
+                        if (relativeProperty != property)
                         {
-                            if (relativeProperty != property)
-                            {
-                                var relativeContext = GetOrCreateContext(relativeProperty);
-                                var relativeBinding = relativeContext.Binding;
-
-                                if (null != relativeBinding)
-                                {
-                                    applying = true;
-                                    relativeBinding.Apply(true);
-                                    applying = false;
-                                }
+                            var relativeContext = GetOrCreateContext(relativeProperty);
+                            var relativeBinding = relativeContext.Binding;
 
-                                OnPropertyChanged(relativeProperty.PropertyName);
+                            if (null != relativeBinding)
+                            {
+                                applying = true;
+                                relativeBinding.Apply(true);
+                                applying = false;
                             }
+
+                            OnPropertyChanged(relativeProperty.PropertyName);
                         }
                     }
                 }
@@ -1118,7 +1096,11 @@ namespace Tizen.NUI.Binding
             }
         }
 
-        internal void ClearBinding()
+        /// <summary>
+        /// Unapplies all previously set bindings.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void ClearBinding()
         {
             foreach (var property in properties)
             {