X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2FTizen.NUI%2Fsrc%2Fpublic%2FXamlBinding%2FBindableObject.cs;h=c6566970f1509ca44b692d788b93d455242f2f83;hb=0384e2cc1c295729b3b69690c6353a93867731dc;hp=60a89d8ab02f298160351fbd726c89f739d7db07;hpb=04ef6b2b791203424528656ce6bc701113b2d51e;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git diff --git a/src/Tizen.NUI/src/public/XamlBinding/BindableObject.cs b/src/Tizen.NUI/src/public/XamlBinding/BindableObject.cs index 60a89d8..c656697 100755 --- a/src/Tizen.NUI/src/public/XamlBinding/BindableObject.cs +++ b/src/Tizen.NUI/src/public/XamlBinding/BindableObject.cs @@ -1,5 +1,5 @@ -/* - * Copyright(c) 2021 Samsung Electronics Co., Ltd. +/* + * Copyright(c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Reflection; +using System.Linq; using System.Runtime.CompilerServices; using Tizen.NUI.Binding.Internals; @@ -36,44 +37,14 @@ namespace Tizen.NUI.Binding /// [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty BindingContextProperty = - BindableProperty.Create(nameof(BindingContext), typeof(object), typeof(BindableObject), null, propertyChanged: (BindableProperty.BindingPropertyChangedDelegate)((bindable, oldValue, newValue) => - { - var bindableObject = (BindableObject)bindable; - if (newValue != null) - { - bindableObject.bindingContext = newValue; - bindableObject.FlushBinding(); + BindableProperty.Create(nameof(BindingContext), typeof(object), typeof(BindableObject), default(object), BindingMode.OneWay, null, BindingContextPropertyChanged, + null, null, BindingContextPropertyBindingChanging); - if (newValue is BindableObject targetBindableObject) - { - targetBindableObject.IsBinded = true; - } - } - }), - defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) => - { - if (null != bindable.bindingContext) - { - return bindable.bindingContext; - } - - if (bindable is Container container) - { - return container.Parent?.BindingContext; - } - else - { - return null; - } - })); - - readonly List properties = new List(4); + readonly Dictionary properties = new Dictionary(4); bool applying; object inheritedContext; - private object bindingContext; - /// /// Gets or sets object that contains the properties that will be targeted by the bound properties that belong to this BindableObject. /// @@ -85,6 +56,12 @@ namespace Tizen.NUI.Binding set { SetValue(BindingContextProperty, value); } } + [EditorBrowsable(EditorBrowsableState.Never)] + public int LineNumber { get; set; } = -1; + + [EditorBrowsable(EditorBrowsableState.Never)] + public int LinePosition { get; set; } = -1; + void IDynamicResourceHandler.SetDynamicResource(BindableProperty property, string key) { SetDynamicResource(property, key, false); @@ -115,20 +92,44 @@ namespace Tizen.NUI.Binding { nameToBindableProperty2.TryGetValue(keyValuePair.Key, out var bindableProperty); - if (null != bindableProperty) + if (null != bindableProperty && other.IsSet(bindableProperty)) { object value = other.GetValue(bindableProperty); - - if (null != value) - { - SetValue(keyValuePair.Value, value); - } + InternalSetValue(keyValuePair.Value, value); } } } } /// + /// Copy all binding from other object. + /// + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public void CopyBindingRelationShip(BindableObject other) + { + if (null == other) + { + return; + } + + foreach (var property in properties) + { + RemoveBinding(property.Key); + } + + foreach (var property in other.properties) + { + if (null != property.Value.Binding) + { + var binding = property.Value.Binding; + other.RemoveBinding(property.Key); + SetBinding(property.Key, binding); + } + } + } + + /// /// Raised whenever the BindingContext property changes. /// /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API. @@ -188,6 +189,11 @@ namespace Tizen.NUI.Binding if (property == null) throw new ArgumentNullException(nameof(property)); + if (!IsBound && property.ValueGetter != null) + { + return property.ValueGetter(this); + } + BindablePropertyContext context = property.DefaultValueCreator != null ? GetOrCreateContext(property) : GetContext(property); if (context == null) @@ -231,18 +237,56 @@ namespace Tizen.NUI.Binding SetBinding(targetProperty, binding, false); } - private bool isCreateByXaml = false; - /// Only used by the IL of xaml, will never changed to not hidden. + /// Internal used, will never changed to not hidden. [EditorBrowsable(EditorBrowsableState.Never)] public virtual bool IsCreateByXaml { - get - { - return isCreateByXaml; - } - set + get; + set; + } + + /// This will be public opened in next ACR. + [EditorBrowsable(EditorBrowsableState.Never)] + public void EnforceNotifyBindedInstance(BindableProperty property) + { + if (null != property) { - 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 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); + } + } + } } } @@ -256,7 +300,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); } @@ -267,38 +317,33 @@ namespace Tizen.NUI.Binding throw new ArgumentNullException(nameof(property)); } - if (null == property.DefaultValueCreator) + object oldvalue = null; + BindablePropertyContext context = GetOrCreateContext(property); + if (null != context) { - BindablePropertyContext context = GetOrCreateContext(property); - if (null != context) - { - context.Value = value; - } + context.Attributes |= BindableContextAttributes.IsManuallySet; + oldvalue = context.Value; + context.Value = value; } - property.PropertyChanged?.Invoke(this, null, value); + property.PropertyChanged?.Invoke(this, oldvalue, value); OnPropertyChanged(property.PropertyName); OnPropertyChangedWithData(property); } } - internal void SetValueAndForceSendChangeSignal(BindableProperty property, object value) + private HashSet changedPropertiesSetExcludingStyle; + internal protected HashSet ChangedPropertiesSetExcludingStyle { - if (property == null) - throw new ArgumentNullException(nameof(property)); - - if (true == isCreateByXaml) + get { - if (property.IsReadOnly) - throw new InvalidOperationException(string.Format("The BindableProperty \"{0}\" is readonly.", property.PropertyName)); + if (null == changedPropertiesSetExcludingStyle) + { + changedPropertiesSetExcludingStyle = new HashSet(); + } - SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearDynamicResource, - SetValuePrivateFlags.ManuallySet | SetValuePrivateFlags.CheckAccess, true); - } - else - { - property.PropertyChanged?.Invoke(this, null, value); + return changedPropertiesSetExcludingStyle; } } @@ -424,9 +469,8 @@ namespace Tizen.NUI.Binding [EditorBrowsable(EditorBrowsableState.Never)] protected void UnapplyBindings() { - for (int i = 0, _propertiesCount = properties.Count; i < _propertiesCount; i++) + foreach (var context in properties.Values) { - BindablePropertyContext context = properties[i]; if (context.Binding == null) continue; @@ -453,10 +497,8 @@ namespace Tizen.NUI.Binding { var values = new object[2]; - for (var i = 0; i < properties.Count; i++) + foreach (var context in properties.Values) { - BindablePropertyContext context = properties[i]; - if (ReferenceEquals(context.Property, property0)) { values[0] = context.Value; @@ -491,10 +533,8 @@ namespace Tizen.NUI.Binding { var values = new object[3]; - for (var i = 0; i < properties.Count; i++) + foreach (var context in properties.Values) { - BindablePropertyContext context = properties[i]; - if (ReferenceEquals(context.Property, property0)) { values[0] = context.Value; @@ -533,9 +573,8 @@ namespace Tizen.NUI.Binding internal object[] GetValues(params BindableProperty[] properties) { var values = new object[properties.Length]; - for (var i = 0; i < this.properties.Count; i++) + foreach (var context in this.properties.Values) { - var context = this.properties[i]; var index = properties.IndexOf(context.Property); if (index < 0) continue; @@ -578,7 +617,7 @@ namespace Tizen.NUI.Binding if (fromStyle && !CanBeSetFromStyle(targetProperty)) return; - IsBinded = true; + IsBound = true; var context = GetOrCreateContext(targetProperty); if (fromStyle) @@ -643,7 +682,7 @@ namespace Tizen.NUI.Binding 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); } /// @@ -655,10 +694,10 @@ namespace Tizen.NUI.Binding [EditorBrowsable(EditorBrowsableState.Never)] internal void SetValueCore(BindableProperty property, object value, SetValueFlags attributes = SetValueFlags.None) { - SetValueCore(property, value, attributes, SetValuePrivateFlags.Default, false); + 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; @@ -716,7 +755,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 delayQueue = context.DelayedSetters; if (delayQueue != null) @@ -724,7 +763,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; @@ -736,7 +775,7 @@ namespace Tizen.NUI.Binding internal void ApplyBindings(bool skipBindingContext, bool fromBindingContextChanged) { - var prop = properties.ToArray(); + var prop = properties.Values.ToArray(); for (int i = 0, propLength = prop.Length; i < propLength; i++) { BindablePropertyContext context = prop[i]; @@ -752,12 +791,28 @@ namespace Tizen.NUI.Binding } } - internal bool IsBinded + /// + /// Check if object is bound or not. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool IsBound { get; set; } = false; + static void BindingContextPropertyChanged(BindableObject bindable, object oldvalue, object newvalue) + { + bindable.inheritedContext = null; + bindable.ApplyBindings(skipBindingContext: true, fromBindingContextChanged: true); + bindable.OnBindingContextChanged(); + + if (newvalue is BindableObject targetBindableObject) + { + targetBindableObject.IsBound = true; + } + } + static void BindingContextPropertyBindingChanging(BindableObject bindable, BindingBase oldBindingBase, BindingBase newBindingBase) { object context = bindable.inheritedContext; @@ -822,24 +877,12 @@ namespace Tizen.NUI.Binding else context.Attributes = BindableContextAttributes.IsDefaultValueCreated; - properties.Add(context); + properties.Add(property, context); return context; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - BindablePropertyContext GetContext(BindableProperty property) - { - List propertyList = properties; - - for (var i = 0; i < propertyList.Count; i++) - { - BindablePropertyContext context = propertyList[i]; - if (ReferenceEquals(context.Property, property)) - return context; - } - - return null; - } + BindablePropertyContext GetContext(BindableProperty property) => properties.TryGetValue(property, out var result) ? result : null; [MethodImpl(MethodImplOptions.AggressiveInlining)] BindablePropertyContext GetOrCreateContext(BindableProperty property) @@ -849,7 +892,11 @@ namespace Tizen.NUI.Binding { context = CreateAndAddContext(property); } - else if (property.DefaultValueCreator != null) + else if (property.ValueGetter != null) + { + context.Value = property.ValueGetter(this); //Update Value from dali + }//added by xiaohui.fang + else if (property.DefaultValueCreator != null) //This will be removed in the future. { context.Value = property.DefaultValueCreator(this); //Update Value from dali }//added by xb.teng @@ -878,11 +925,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; @@ -921,71 +967,36 @@ namespace Tizen.NUI.Binding PropertyToGroup.TryGetValue(property, out HashSet propertyGroup); - if (!silent) + if (!silent && (!same || raiseOnEqual)) { - if ((!same || raiseOnEqual)) - { - property.PropertyChanged?.Invoke(this, original, value); + 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; - - 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); } } } @@ -1047,30 +1058,53 @@ namespace Tizen.NUI.Binding } } - internal void AddChildBindableObject(BindableObject child) + internal void ReplaceBindingElement(Dictionary oldNameScope, Dictionary newNameScope) { - if (null != child) + var xElementToNameOfOld = new Dictionary(); + + foreach (var pair in oldNameScope) { - children.Add(child); - child.FlushBinding(); + xElementToNameOfOld.Add(pair.Value, pair.Key); } - } - internal void RemoveChildBindableObject(BindableObject child) - { - children.Remove(child); - } + foreach (var property in properties) + { + if (property.Value.Binding is Binding binding && null != binding.Source) + { + string xName; + xElementToNameOfOld.TryGetValue(binding.Source, out xName); - private List children = new List(); + if (null != xName) + { + var newObject = newNameScope[xName]; + binding.Unapply(); + binding.Source = newObject; + SetBinding(property.Key, binding); + } + } + } - private void FlushBinding() - { - ApplyBindings(skipBindingContext: true, fromBindingContextChanged: true); - OnBindingContextChanged(); + if (null != BindingContext) + { + string xName; + xElementToNameOfOld.TryGetValue(BindingContext, out xName); - foreach (var child in children) + if (null != xName) + { + var newObject = newNameScope[xName]; + BindingContext = newObject; + } + } + } + + internal void ClearBinding() + { + foreach (var property in properties) { - child.FlushBinding(); + if (null != property.Value.Binding) + { + property.Value.Binding.Unapply(); + } } } }