[NUI] Improve performance in theme and styles (#2704)
authorJiyun Yang <ji.yang@samsung.com>
Tue, 9 Mar 2021 03:19:34 +0000 (12:19 +0900)
committerjykeon <44285706+jykeon@users.noreply.github.com>
Wed, 10 Mar 2021 04:44:29 +0000 (13:44 +0900)
* [NUI] Improve performance: Make selectors lazily generated.

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
* [NUI] Improve performance: Remove redundant clone

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
* [NUI] Improve performance: Add dirty style property set

This may reduce time of ViewStyle.Clone() and View.ApplyStyle().
But may increase runtime memory.

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
16 files changed:
src/Tizen.NUI/src/public/BaseComponents/ImageView.cs
src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs
src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyle.cs
src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyleBindableProperty.cs
src/Tizen.NUI/src/public/BaseComponents/TextField.cs
src/Tizen.NUI/src/public/BaseComponents/TextFieldBindableProperty.cs
src/Tizen.NUI/src/public/BaseComponents/TextFieldSelectorData.cs
src/Tizen.NUI/src/public/BaseComponents/TextLabel.cs
src/Tizen.NUI/src/public/BaseComponents/TextLabelBindableProperty.cs
src/Tizen.NUI/src/public/BaseComponents/TextLabelSelectorData.cs
src/Tizen.NUI/src/public/BaseComponents/View.cs
src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs
src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs
src/Tizen.NUI/src/public/BaseComponents/ViewSelectorData.cs [changed mode: 0755->0644]
src/Tizen.NUI/src/public/ViewProperty/BackgroundExtraData.cs
src/Tizen.NUI/src/public/XamlBinding/BindableObject.cs

index 0087ad6..581951b 100755 (executable)
@@ -241,7 +241,7 @@ namespace Tizen.NUI.BaseComponents
         defaultValueCreator: (bindable) =>
         {
             var imageView = (ImageView)bindable;
-            return imageView.resourceUrlSelector.Get(imageView);
+            return imageView.GetSelector<string>(imageView.resourceUrlSelector, ImageView.ResourceUrlProperty);
         });
 
         internal static readonly BindableProperty BorderSelectorProperty = BindableProperty.Create("BorderSelector", typeof(Selector<Rectangle>), typeof(ImageView), null, propertyChanged: (bindable, oldValue, newValue) =>
@@ -252,7 +252,7 @@ namespace Tizen.NUI.BaseComponents
         defaultValueCreator: (bindable) =>
         {
             var imageView = (ImageView)bindable;
-            return imageView.borderSelector.Get(imageView);
+            return imageView.GetSelector<Rectangle>(imageView.borderSelector, ImageView.BorderProperty);
         });
 
         private EventHandler<ResourceReadyEventArgs> _resourceReadyEventHandler;
@@ -453,7 +453,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(ResourceUrlProperty, value);
-                resourceUrlSelector.UpdateIfNeeds(this, value);
+                resourceUrlSelector.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -588,7 +588,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(BorderProperty, value);
-                borderSelector.UpdateIfNeeds(this, value);
+                borderSelector.Reset(this);
                 NotifyPropertyChanged();
             }
         }
index 79dd26a..0467fd3 100755 (executable)
@@ -378,58 +378,24 @@ namespace Tizen.NUI.BaseComponents
     [EditorBrowsable(EditorBrowsableState.Never)]
     public class TriggerableSelector<T>
     {
-        /// <summary>
-        /// Create an TriggerableSelector.
-        /// </summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public delegate T ValueGetter(View view);
-
         private readonly BindableProperty targetBindableProperty;
-        private readonly ValueGetter propertyGetter;
-        private bool dirty = true;
         private Selector<T> selector;
 
         /// <summary>
         /// Create an TriggerableSelector.
         /// </summary>
         /// <param name="targetBindableProperty">The TriggerableSelector will change this bindable property value when the view's ControlState has changed.</param>
-        /// <param name="propertyGetter">It is optional value in case the target bindable property getter is not proper to use.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public TriggerableSelector(BindableProperty targetBindableProperty, ValueGetter propertyGetter = null)
+        public TriggerableSelector(BindableProperty targetBindableProperty)
         {
             this.targetBindableProperty = targetBindableProperty;
-            this.propertyGetter = propertyGetter;
         }
 
         /// <summary>
         /// Return the containing selector. It can be null.
         /// </summary>
-        /// <exception cref="ArgumentNullException"> Thrown when view is null. </exception>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public Selector<T> Get(View view)
-        {
-            if (!dirty) return selector;
-            if (null == view)
-            {
-                throw new ArgumentNullException(nameof(view));
-            }
-
-            T value = default;
-
-            if (propertyGetter != null)
-            {
-                value = propertyGetter(view);
-            }
-            else
-            {
-                value = (T)view.GetValue(targetBindableProperty);
-            }
-
-            Selector<T> converted = value == null ? null : new Selector<T>(value);
-            Update(view, converted);
-
-            return selector;
-        }
+        public Selector<T> Get() => selector;
 
         /// <summary>
         /// Update containing selector from the other selector.
@@ -453,7 +419,7 @@ namespace Tizen.NUI.BaseComponents
                 return;
             }
 
-            selector = otherSelector.Clone();
+            selector = otherSelector;
 
             if (otherSelector.HasMultiValue())
             {
@@ -467,26 +433,6 @@ namespace Tizen.NUI.BaseComponents
         }
 
         /// <summary>
-        /// Update containing selector value from a single value.
-        /// Note that, it updates lazily if possible.
-        /// If you need to udpate directly, please use <seealso cref="Update" />.
-        /// </summary>
-        /// <param name="view">The View that is affected by this TriggerableSelector.</param>
-        /// <param name="value">The copy target.</param>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public void UpdateIfNeeds(View view, T value)
-        {
-            if (selector != null && selector.HasMultiValue())
-            {
-                Selector<T> converted = value == null ? null : new Selector<T>(value);
-                Update(view, converted);
-                return;
-            }
-
-            dirty = true;
-        }
-
-        /// <summary>
         /// Reset selector and listeners.
         /// </summary>
         /// <param name="view">The View that is affected by this TriggerableSelector.</param>
@@ -497,9 +443,7 @@ namespace Tizen.NUI.BaseComponents
             {
                 view.ControlStateChangeEventInternal -= OnViewControlState;
             }
-            selector?.Clear();
             selector = null;
-            dirty = false;
         }
 
         private void OnViewControlState(object obj, View.ControlStateChangedEventArgs controlStateChangedInfo)
index 368d30d..176520c 100755 (executable)
@@ -16,6 +16,7 @@
  */
 using System;
 using System.ComponentModel;
+using System.Collections.Generic;
 using Tizen.NUI.Binding;
 
 namespace Tizen.NUI.BaseComponents
@@ -394,6 +395,11 @@ namespace Tizen.NUI.BaseComponents
         public bool SolidNull { get; set; } = false;
 
         /// <summary>
+        /// HashSet of dirty properties. Internal use only.
+        /// </summary>
+        internal HashSet<BindableProperty> DirtyProperties { get; private set; }
+
+        /// <summary>
         /// Set style's bindable properties from the view.
         /// </summary>
         /// <param name="view">The view that includes property data.</param>
@@ -432,9 +438,7 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public void Merge(ViewStyle other)
         {
-            AllowNullCopy = other?.SolidNull ?? false;
             CopyFrom(other);
-            AllowNullCopy = false;
         }
 
         /// <summary>
@@ -447,6 +451,43 @@ namespace Tizen.NUI.BaseComponents
             global::System.GC.SuppressFinalize(this);
         }
 
+        /// <summary>Copy properties of other ViewStyle to this.</summary>
+        /// <param name="other">The other BindableProperty merge to this.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override void CopyFrom(BindableObject other)
+        {
+            var source = other as ViewStyle;
+
+            if (source == null || source.DirtyProperties == null || source.DirtyProperties.Count == 0)
+            {
+                return;
+            }
+
+            BindableProperty.GetBindablePropertysOfType(GetType(), out var thisBindableProperties);
+
+            if (thisBindableProperties == null)
+            {
+                return;
+            }
+
+            foreach (var sourceProperty in source.DirtyProperties)
+            {
+                var sourceValue = source.GetValue(sourceProperty);
+
+                if (sourceValue == null)
+                {
+                    continue;
+                }
+
+                thisBindableProperties.TryGetValue(sourceProperty.PropertyName, out var destinationProperty);
+
+                if (destinationProperty != null)
+                {
+                    SetValue(destinationProperty, sourceValue);
+                }
+            }
+        }
+
         /// <summary>
         /// Release instance.
         /// </summary>
@@ -476,6 +517,20 @@ namespace Tizen.NUI.BaseComponents
             disposed = true;
         }
 
+        /// <summary>
+        /// Method that is called when a bound property is changed.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void OnPropertyChangedWithData(BindableProperty property)
+        {
+            base.OnPropertyChangedWithData(property);
+
+            if (property != null)
+            {
+                (DirtyProperties ?? (DirtyProperties = new HashSet<BindableProperty>())).Add(property);
+            }
+        }
+
         internal ViewStyle CreateInstance()
         {
             return (ViewStyle)Activator.CreateInstance(GetType());
index 28699fd..8804149 100755 (executable)
@@ -33,7 +33,7 @@ namespace Tizen.NUI.BaseComponents
             }
             else
             {
-                viewStyle.backgroundImageSelector = ((Selector<string>)newValue).Clone();
+                viewStyle.backgroundImageSelector = (Selector<string>)newValue;
                 viewStyle.backgroundColorSelector = null;
             }
         },
@@ -65,7 +65,7 @@ namespace Tizen.NUI.BaseComponents
         /// <summary> Bindable property of Opacity. Please do not open it. </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly BindableProperty OpacitySelectorProperty = BindableProperty.Create("OpacitySelector", typeof(Selector<float?>), typeof(ViewStyle), null,
-            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).opacitySelector = ((Selector<float?>)newValue)?.Clone(),
+            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).opacitySelector = (Selector<float?>)newValue,
             defaultValueCreator: (bindable) => ((ViewStyle)bindable).opacitySelector
         );
 
@@ -248,7 +248,7 @@ namespace Tizen.NUI.BaseComponents
         /// <summary> Bindable property of Padding. Please do not open it. </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly BindableProperty PaddingProperty = BindableProperty.Create(nameof(Padding), typeof(Extents), typeof(ViewStyle), null,
-            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).padding = (Extents)((Extents)newValue)?.Clone(),
+            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).padding = (Extents)newValue,
             defaultValueCreator: (bindable) => ((ViewStyle)bindable).padding
         );
 
@@ -293,7 +293,7 @@ namespace Tizen.NUI.BaseComponents
         /// <summary> Bindable property of Margin. Please do not open it. </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly BindableProperty MarginProperty = BindableProperty.Create(nameof(Margin), typeof(Extents), typeof(ViewStyle), null,
-            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).margin = (Extents)((Extents)newValue)?.Clone(),
+            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).margin = (Extents)newValue,
             defaultValueCreator: (bindable) => ((ViewStyle)bindable).margin
         );
 
@@ -309,7 +309,7 @@ namespace Tizen.NUI.BaseComponents
             }
             else
             {
-                viewStyle.backgroundColorSelector = ((Selector<Color>)newValue).Clone();
+                viewStyle.backgroundColorSelector = (Selector<Color>)newValue;
                 viewStyle.backgroundImageSelector = null;
             }
 
@@ -322,14 +322,14 @@ namespace Tizen.NUI.BaseComponents
         /// <summary> Bindable property of ColorSelector. Please do not open it. </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly BindableProperty ColorSelectorProperty = BindableProperty.Create("ColorSelector", typeof(Selector<Color>), typeof(ViewStyle), null,
-            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).colorSelector = ((Selector<Color>)newValue)?.Clone(),
+            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).colorSelector = (Selector<Color>)newValue,
             defaultValueCreator: (bindable) => ((ViewStyle)bindable).colorSelector
         );
 
         /// <summary> Bindable property of BackgroundImageBorder. Please do not open it. </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly BindableProperty BackgroundImageBorderSelectorProperty = BindableProperty.Create("BackgroundImageBorderSelector", typeof(Selector<Rectangle>), typeof(ViewStyle), null,
-            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).backgroundImageBorderSelector = ((Selector<Rectangle>)newValue)?.Clone(),
+            propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).backgroundImageBorderSelector = (Selector<Rectangle>)newValue,
             defaultValueCreator: (bindable) => ((ViewStyle)bindable).backgroundImageBorderSelector
         );
 
@@ -339,7 +339,7 @@ namespace Tizen.NUI.BaseComponents
         {
             var viewStyle = (ViewStyle)bindable;
 
-            viewStyle.imageShadow = ((Selector<ImageShadow>)newValue)?.Clone();
+            viewStyle.imageShadow = (Selector<ImageShadow>)newValue;
 
             if (viewStyle.imageShadow != null)
             {
@@ -358,7 +358,7 @@ namespace Tizen.NUI.BaseComponents
         {
             var viewStyle = (ViewStyle)bindable;
 
-            viewStyle.boxShadow = ((Selector<Shadow>)newValue)?.Clone();
+            viewStyle.boxShadow = (Selector<Shadow>)newValue;
 
             if (viewStyle.boxShadow != null)
             {
index 9a21d84..c0495bd 100755 (executable)
@@ -118,7 +118,7 @@ namespace Tizen.NUI.BaseComponents
             }
             set
             {
-                selectorData?.TranslatableText.UpdateIfNeeds(this, value);
+                selectorData?.TranslatableText?.Reset(this);
                 SetValue(TranslatableTextProperty, value);
             }
         }
@@ -157,7 +157,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(TranslatablePlaceholderTextProperty, value);
-                selectorData?.TranslatablePlaceholderText.UpdateIfNeeds(this, value);
+                selectorData?.TranslatablePlaceholderText?.Reset(this);
             }
         }
         private string translatablePlaceholderText
@@ -191,7 +191,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValueAndForceSendChangeSignal(TextProperty, value);
-                selectorData?.Text.UpdateIfNeeds(this, value);
+                selectorData?.Text?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -243,7 +243,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(FontFamilyProperty, value);
-                selectorData?.FontFamily.UpdateIfNeeds(this, value);
+                selectorData?.FontFamily?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -278,7 +278,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(PointSizeProperty, value);
-                selectorData?.PointSize.UpdateIfNeeds(this, value);
+                selectorData?.PointSize?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -369,7 +369,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(TextColorProperty, value);
-                selectorData?.TextColor.UpdateIfNeeds(this, value);
+                selectorData?.TextColor?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -391,7 +391,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(PlaceholderTextColorProperty, value);
-                selectorData?.PlaceholderTextColor.UpdateIfNeeds(this, value);
+                selectorData?.PlaceholderTextColor?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -469,7 +469,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(PrimaryCursorColorProperty, value);
-                selectorData?.PrimaryCursorColor.UpdateIfNeeds(this, value);
+                selectorData?.PrimaryCursorColor?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -1047,7 +1047,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(PixelSizeProperty, value);
-                selectorData?.PixelSize.UpdateIfNeeds(this, value);
+                selectorData?.PixelSize?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -1372,17 +1372,7 @@ namespace Tizen.NUI.BaseComponents
             }
         }
 
-        private TextFieldSelectorData SelectorData
-        {
-            get
-            {
-                if (selectorData == null)
-                {
-                    selectorData = new TextFieldSelectorData();
-                }
-                return selectorData;
-            }
-        }
+        private TextFieldSelectorData EnsureSelectorData() => selectorData ?? (selectorData = new TextFieldSelectorData());
 
         /// <summary>
         /// Get the InputMethodContext instance.
index 415a53b..9c58900 100755 (executable)
@@ -994,92 +994,125 @@ namespace Tizen.NUI.BaseComponents
         internal static readonly BindableProperty TranslatableTextSelectorProperty = BindableProperty.Create("TranslatableTextSelector", typeof(Selector<string>), typeof(TextField), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textField = (TextField)bindable;
-            textField.SelectorData.TranslatableText.Update(textField, (Selector<string>)newValue, true);
+            textField.EnsureSelectorData().EnsureTranslatableText().Update(textField, (Selector<string>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textField = (TextField)bindable;
-            return textField.SelectorData.TranslatableText.Get(textField);
+            return textField.GetSelector<string>(textField.selectorData?.TranslatableText, TextField.TranslatableTextProperty);
         });
         internal static readonly BindableProperty TranslatablePlaceholderTextSelectorProperty = BindableProperty.Create("TranslatablePlaceholderTextSelector", typeof(Selector<string>), typeof(TextField), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textField = (TextField)bindable;
-            textField.SelectorData.TranslatablePlaceholderText.Update(textField, (Selector<string>)newValue, true);
+            textField.EnsureSelectorData().EnsureTranslatablePlaceholderText().Update(textField, (Selector<string>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textField = (TextField)bindable;
-            return textField.SelectorData.TranslatablePlaceholderText.Get(textField);
+            return textField.GetSelector<string>(textField.selectorData?.TranslatablePlaceholderText, TextField.TranslatablePlaceholderTextProperty);
         });
         internal static readonly BindableProperty TextSelectorProperty = BindableProperty.Create("TextSelector", typeof(Selector<string>), typeof(TextField), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textField = (TextField)bindable;
-            textField.SelectorData.Text.Update(textField, (Selector<string>)newValue, true);
+            textField.EnsureSelectorData().EnsureText().Update(textField, (Selector<string>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textField = (TextField)bindable;
-            return textField.SelectorData.Text.Get(textField);
+            return textField.GetSelector<string>(textField.selectorData?.Text, TextField.TextProperty);
         });
         internal static readonly BindableProperty FontFamilySelectorProperty = BindableProperty.Create("FontFamilySelector", typeof(Selector<string>), typeof(TextField), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textField = (TextField)bindable;
-            textField.SelectorData.FontFamily.Update(textField, (Selector<string>)newValue, true);
+            textField.EnsureSelectorData().EnsureFontFamily().Update(textField, (Selector<string>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textField = (TextField)bindable;
-            return textField.SelectorData.FontFamily.Get(textField);
+            return textField.GetSelector<string>(textField.selectorData?.FontFamily, TextField.FontFamilyProperty);
         });
         internal static readonly BindableProperty PointSizeSelectorProperty = BindableProperty.Create("PointSizeSelector", typeof(Selector<float?>), typeof(TextField), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textField = (TextField)bindable;
-            textField.SelectorData.PointSize.Update(textField, (Selector<float?>)newValue, true);
+            textField.EnsureSelectorData().EnsurePointSize().Update(textField, (Selector<float?>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textField = (TextField)bindable;
-            return textField.SelectorData.PointSize.Get(textField);
+            return textField.GetSelector<float?>(textField.selectorData?.PointSize, TextField.PointSizeProperty);
         });
         internal static readonly BindableProperty PixelSizeSelectorProperty = BindableProperty.Create("PixelSizeSelector", typeof(Selector<float?>), typeof(TextField), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textField = (TextField)bindable;
-            textField.SelectorData.PixelSize.Update(textField, (Selector<float?>)newValue, true);
+            textField.EnsureSelectorData().EnsurePixelSize().Update(textField, (Selector<float?>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textField = (TextField)bindable;
-            return textField.SelectorData.PixelSize.Get(textField);
+            return textField.GetSelector<float?>(textField.selectorData?.PixelSize, TextField.PixelSizeProperty);
         });
         internal static readonly BindableProperty TextColorSelectorProperty = BindableProperty.Create("TextColorSelector", typeof(Selector<Color>), typeof(TextField), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textField = (TextField)bindable;
-            textField.SelectorData.TextColor.Update(textField, (Selector<Color>)newValue, true);
+            textField.EnsureSelectorData().EnsureTextColor().Update(textField, (Selector<Color>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textField = (TextField)bindable;
-            return textField.SelectorData.TextColor.Get(textField);
+            var selector =  textField.selectorData?.TextColor?.Get();
+            if (selector != null)
+            {
+                return selector;
+            }
+
+            Color color = new Color();
+            if (!textField.GetProperty(TextField.Property.TextColor).Get(color))
+            {
+                return null;
+            }
+            return new Selector<Color>(color);
         });
         internal static readonly BindableProperty PlaceholderTextColorSelectorProperty = BindableProperty.Create("PlaceholderTextColorSelector", typeof(Selector<Vector4>), typeof(TextField), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textField = (TextField)bindable;
-            textField.SelectorData.PlaceholderTextColor.Update(textField, (Selector<Vector4>)newValue, true);
+            textField.EnsureSelectorData().EnsurePlaceholderTextColor().Update(textField, (Selector<Vector4>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textField = (TextField)bindable;
-            return textField.SelectorData.PlaceholderTextColor.Get(textField);
+            var selector =  textField.selectorData?.PlaceholderTextColor?.Get();
+            if (selector != null)
+            {
+                return selector;
+            }
+
+            Color color = new Color();
+            if (!textField.GetProperty(TextField.Property.PlaceholderTextColor).Get(color))
+            {
+                return null;
+            }
+            return new Selector<Color>(color);
         });
         internal static readonly BindableProperty PrimaryCursorColorSelectorProperty = BindableProperty.Create("PrimaryCursorColorSelector", typeof(Selector<Vector4>), typeof(TextField), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textField = (TextField)bindable;
-            textField.SelectorData.PrimaryCursorColor.Update(textField, (Selector<Vector4>)newValue, true);
+            textField.EnsureSelectorData().EnsurePrimaryCursorColor().Update(textField, (Selector<Vector4>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textField = (TextField)bindable;
-            return textField.SelectorData.PrimaryCursorColor.Get(textField);
+            var selector =  textField.selectorData?.PrimaryCursorColor?.Get();
+            if (selector != null)
+            {
+                return selector;
+            }
+
+            Color color = new Color();
+            if (!textField.GetProperty(TextField.Property.PrimaryCursorColor).Get(color))
+            {
+                return null;
+            }
+            return new Selector<Color>(color);
         });
         #endregion
     }
index 5445aaa..6cc9984 100755 (executable)
@@ -22,54 +22,37 @@ namespace Tizen.NUI.BaseComponents
     /// </summary>
     internal class TextFieldSelectorData
     {
-        public TriggerableSelector<string> TranslatableText { get; } = new TriggerableSelector<string>(TextField.TranslatableTextProperty);
-        public TriggerableSelector<string> Text { get; } = new TriggerableSelector<string>(TextField.TextProperty);
-        public TriggerableSelector<string> FontFamily { get; } = new TriggerableSelector<string>(TextField.FontFamilyProperty);
-        public TriggerableSelector<Color> TextColor { get; } = new TriggerableSelector<Color>(TextField.TextColorProperty, GetTextColor);
-        public TriggerableSelector<float?> PointSize { get; } = new TriggerableSelector<float?>(TextField.PointSizeProperty);
-        public TriggerableSelector<float?> PixelSize { get; } = new TriggerableSelector<float?>(TextField.PixelSizeProperty);
-        public TriggerableSelector<string> TranslatablePlaceholderText { get; } = new TriggerableSelector<string>(TextField.TranslatablePlaceholderTextProperty);
-        public TriggerableSelector<Vector4> PlaceholderTextColor { get; } = new TriggerableSelector<Vector4>(TextField.PlaceholderTextColorProperty, delegate (View view)
-        {
-            Vector4 color = new Vector4();
-            if (view.GetProperty(TextField.Property.PlaceholderTextColor).Get(color))
-            {
-                return color;
-            }
-            return null;
-        });
+        public TriggerableSelector<string> TranslatableText { get; private set; }
+        public TriggerableSelector<string> Text { get; private set; }
+        public TriggerableSelector<string> FontFamily { get; private set; }
+        public TriggerableSelector<Color> TextColor { get; private set; }
+        public TriggerableSelector<float?> PointSize { get; private set; }
+        public TriggerableSelector<float?> PixelSize { get; private set; }
+        public TriggerableSelector<string> TranslatablePlaceholderText { get; private set; }
+        public TriggerableSelector<Vector4> PlaceholderTextColor { get; private set; }
+        public TriggerableSelector<Vector4> PrimaryCursorColor { get; private set; }
 
-        public TriggerableSelector<Vector4> PrimaryCursorColor { get; } = new TriggerableSelector<Vector4>(TextField.PrimaryCursorColorProperty, delegate (View view)
-        {
-            Vector4 color = new Vector4(0.0f, 0.0f, 0.0f, 0.0f);
-            if (view.GetProperty(TextField.Property.PrimaryCursorColor).Get(color))
-            {
-                return color;
-            }
-            return null;
-        });
+        public TriggerableSelector<string> EnsureTranslatableText() => TranslatableText ?? (TranslatableText = new TriggerableSelector<string>(TextField.TranslatableTextProperty));
+        public TriggerableSelector<string> EnsureText() => Text ?? (Text = new TriggerableSelector<string>(TextField.TextProperty));
+        public TriggerableSelector<string> EnsureFontFamily() => FontFamily ?? (FontFamily = new TriggerableSelector<string>(TextField.FontFamilyProperty));
+        public TriggerableSelector<Color> EnsureTextColor() => TextColor ?? (TextColor = new TriggerableSelector<Color>(TextField.TextColorProperty));
+        public TriggerableSelector<float?> EnsurePointSize() => PointSize ?? (PointSize = new TriggerableSelector<float?>(TextField.PointSizeProperty));
+        public TriggerableSelector<float?> EnsurePixelSize() => PixelSize ?? (PixelSize = new TriggerableSelector<float?>(TextField.PixelSizeProperty));
+        public TriggerableSelector<string> EnsureTranslatablePlaceholderText() => TranslatablePlaceholderText ?? (TranslatablePlaceholderText = new TriggerableSelector<string>(TextField.TranslatablePlaceholderTextProperty));
+        public TriggerableSelector<Vector4> EnsurePlaceholderTextColor() =>  PlaceholderTextColor ?? (PlaceholderTextColor = new TriggerableSelector<Vector4>(TextField.PlaceholderTextColorProperty));
+        public TriggerableSelector<Vector4> EnsurePrimaryCursorColor() => PrimaryCursorColor ?? (PrimaryCursorColor = new TriggerableSelector<Vector4>(TextField.PrimaryCursorColorProperty));
 
         public void Reset(View view)
         {
-            TranslatableText.Reset(view);
-            Text.Reset(view);
-            FontFamily.Reset(view);
-            TextColor.Reset(view);
-            PointSize.Reset(view);
-            PixelSize.Reset(view);
-            TranslatablePlaceholderText.Reset(view);
-            PlaceholderTextColor.Reset(view);
-            PrimaryCursorColor.Reset(view);
-        }
-
-        private static Color GetTextColor(View view)
-        {
-            Color color = new Color();
-            if (view.GetProperty(TextField.Property.TextColor).Get(color))
-            {
-                return color;
-            }
-            return null;
+            TranslatableText?.Reset(view);
+            Text?.Reset(view);
+            FontFamily?.Reset(view);
+            TextColor?.Reset(view);
+            PointSize?.Reset(view);
+            PixelSize?.Reset(view);
+            TranslatablePlaceholderText?.Reset(view);
+            PlaceholderTextColor?.Reset(view);
+            PrimaryCursorColor?.Reset(view);
         }
     }
 }
index 664dd4c..d8271bf 100755 (executable)
@@ -183,7 +183,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(TranslatableTextProperty, value);
-                selectorData?.TranslatableText.UpdateIfNeeds(this, value);
+                selectorData?.TranslatableText?.Reset(this);
             }
         }
         private string translatableText
@@ -232,7 +232,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(TextProperty, value);
-                selectorData?.Text.UpdateIfNeeds(this, value);
+                selectorData?.Text?.Reset(this);
                 NotifyPropertyChangedAndRequestLayout();
             }
         }
@@ -251,7 +251,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(FontFamilyProperty, value);
-                selectorData?.FontFamily.UpdateIfNeeds(this, value);
+                selectorData?.FontFamily?.Reset(this);
                 NotifyPropertyChangedAndRequestLayout();
             }
         }
@@ -288,7 +288,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(PointSizeProperty, value);
-                selectorData?.PointSize.UpdateIfNeeds(this, value);
+                selectorData?.PointSize?.Reset(this);
                 NotifyPropertyChangedAndRequestLayout();
             }
         }
@@ -367,7 +367,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(TextColorProperty, value);
-                selectorData?.TextColor.UpdateIfNeeds(this, value);
+                selectorData?.TextColor?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -684,7 +684,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(TextShadowProperty, value);
-                selectorData?.TextShadow.UpdateIfNeeds(this, value);
+                selectorData?.TextShadow?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -739,7 +739,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(PixelSizeProperty, value);
-                selectorData?.PixelSize.UpdateIfNeeds(this, value);
+                selectorData?.PixelSize?.Reset(this);
                 NotifyPropertyChangedAndRequestLayout();
             }
         }
@@ -970,17 +970,7 @@ namespace Tizen.NUI.BaseComponents
             }
         }
 
-        private TextLabelSelectorData SelectorData
-        {
-            get
-            {
-                if (selectorData == null)
-                {
-                    selectorData = new TextLabelSelectorData();
-                }
-                return selectorData;
-            }
-        }
+        private TextLabelSelectorData EnsureSelectorData() => selectorData ?? (selectorData = new TextLabelSelectorData());
 
         /// <summary>
         /// Downcasts a handle to textLabel handle
index 790d493..ca559ce 100755 (executable)
@@ -566,74 +566,85 @@ namespace Tizen.NUI.BaseComponents
         internal static readonly BindableProperty TranslatableTextSelectorProperty = BindableProperty.Create("TranslatableTextSelector", typeof(Selector<string>), typeof(TextLabel), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textLabel = (TextLabel)bindable;
-            textLabel.SelectorData.TranslatableText.Update(textLabel, (Selector<string>)newValue, true);
+            textLabel.EnsureSelectorData().EnsureTranslatableText().Update(textLabel, (Selector<string>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textLabel = (TextLabel)bindable;
-            return textLabel.SelectorData.TranslatableText.Get(textLabel);
+            return textLabel.GetSelector<string>(textLabel.selectorData?.TranslatableText, TextLabel.TranslatableTextProperty);
         });
         internal static readonly BindableProperty TextSelectorProperty = BindableProperty.Create("TextSelector", typeof(Selector<string>), typeof(TextLabel), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textLabel = (TextLabel)bindable;
-            textLabel.SelectorData.Text.Update(textLabel, (Selector<string>)newValue, true);
+            textLabel.EnsureSelectorData().EnsureText().Update(textLabel, (Selector<string>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textLabel = (TextLabel)bindable;
-            return textLabel.SelectorData.Text.Get(textLabel);
+            return textLabel.GetSelector<string>(textLabel.selectorData?.Text, TextLabel.TextProperty);
         });
         internal static readonly BindableProperty FontFamilySelectorProperty = BindableProperty.Create("FontFamilySelector", typeof(Selector<string>), typeof(TextLabel), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textLabel = (TextLabel)bindable;
-            textLabel.SelectorData.FontFamily.Update(textLabel, (Selector<string>)newValue, true);
+            textLabel.EnsureSelectorData().EnsureFontFamily().Update(textLabel, (Selector<string>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textLabel = (TextLabel)bindable;
-            return textLabel.SelectorData.FontFamily.Get(textLabel);
+            return textLabel.GetSelector<string>(textLabel.selectorData?.FontFamily, TextLabel.FontFamilyProperty);
         });
         internal static readonly BindableProperty PointSizeSelectorProperty = BindableProperty.Create("PointSizeSelector", typeof(Selector<float?>), typeof(TextLabel), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textLabel = (TextLabel)bindable;
-            textLabel.SelectorData.PointSize.Update(textLabel, (Selector<float?>)newValue, true);
+            textLabel.EnsureSelectorData().EnsurePointSize().Update(textLabel, (Selector<float?>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textLabel = (TextLabel)bindable;
-            return textLabel.SelectorData.PointSize.Get(textLabel);
+            return textLabel.GetSelector<float?>(textLabel.selectorData?.PointSize, TextLabel.PointSizeProperty);
         });
         internal static readonly BindableProperty TextColorSelectorProperty = BindableProperty.Create("TextColorSelector", typeof(Selector<Color>), typeof(TextLabel), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textLabel = (TextLabel)bindable;
-            textLabel.SelectorData.TextColor.Update(textLabel, (Selector<Color>)newValue, true);
+            textLabel.EnsureSelectorData().EnsureTextColor().Update(textLabel, (Selector<Color>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textLabel = (TextLabel)bindable;
-            return textLabel.SelectorData.TextColor.Get(textLabel);
+            var selector =  textLabel.selectorData?.TextColor?.Get();
+            if (selector != null)
+            {
+                return selector;
+            }
+
+            Color color = new Color();
+            if (!textLabel.GetProperty(TextLabel.Property.TextColor).Get(color))
+            {
+                return null;
+            }
+            return new Selector<Color>(color);
         });
 
         internal static readonly BindableProperty TextShadowSelectorProperty = BindableProperty.Create("TextShadowSelector", typeof(Selector<TextShadow>), typeof(TextLabel), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textLabel = (TextLabel)bindable;
-            textLabel.SelectorData.TextShadow.Update(textLabel, (Selector<TextShadow>)newValue, true);
+            textLabel.EnsureSelectorData().EnsureTextShadow().Update(textLabel, (Selector<TextShadow>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textLabel = (TextLabel)bindable;
-            return textLabel.SelectorData.TextShadow.Get(textLabel);
+            return textLabel.GetSelector<TextShadow>(textLabel.selectorData?.TextShadow, TextLabel.TextShadowProperty);
         });
 
         internal static readonly BindableProperty PixelSizeSelectorProperty = BindableProperty.Create("PixelSizeSelector", typeof(Selector<float?>), typeof(TextLabel), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var textLabel = (TextLabel)bindable;
-            ((TextLabel)bindable).SelectorData.PixelSize.Update(textLabel, (Selector<float?>)newValue, true);
+            ((TextLabel)bindable).EnsureSelectorData().EnsurePixelSize().Update(textLabel, (Selector<float?>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var textLabel = (TextLabel)bindable;
-            return textLabel.SelectorData.PixelSize.Get(textLabel);
+            return textLabel.GetSelector<float?>(textLabel.selectorData?.PixelSize, TextLabel.PixelSizeProperty);
         });
         #endregion
 
index 5f78bec..09f7699 100755 (executable)
@@ -22,33 +22,31 @@ namespace Tizen.NUI.BaseComponents
     /// </summary>
     internal class TextLabelSelectorData
     {
-        public TriggerableSelector<string> TranslatableText { get; } = new TriggerableSelector<string>(TextLabel.TranslatableTextProperty);
-        public TriggerableSelector<string> Text { get; } = new TriggerableSelector<string>(TextLabel.TextProperty);
-        public TriggerableSelector<string> FontFamily { get; } = new TriggerableSelector<string>(TextLabel.FontFamilyProperty);
-        public TriggerableSelector<Color> TextColor { get; } = new TriggerableSelector<Color>(TextLabel.TextColorProperty, GetTextColor);
-        public TriggerableSelector<float?> PointSize { get; } = new TriggerableSelector<float?>(TextLabel.PointSizeProperty);
-        public TriggerableSelector<float?> PixelSize { get; } = new TriggerableSelector<float?>(TextLabel.PixelSizeProperty);
-        public TriggerableSelector<TextShadow> TextShadow { get; } = new TriggerableSelector<TextShadow>(TextLabel.TextShadowProperty);
+        public TriggerableSelector<string> TranslatableText { get; private set; }
+        public TriggerableSelector<string> Text { get; private set; }
+        public TriggerableSelector<string> FontFamily { get; private set; }
+        public TriggerableSelector<Color> TextColor { get; private set; }
+        public TriggerableSelector<float?> PointSize { get; private set; }
+        public TriggerableSelector<float?> PixelSize { get; private set; }
+        public TriggerableSelector<TextShadow> TextShadow { get; private set; }
 
-        public virtual void Reset(View view)
-        {
-            TranslatableText.Reset(view);
-            Text.Reset(view);
-            FontFamily.Reset(view);
-            TextColor.Reset(view);
-            PointSize.Reset(view);
-            PixelSize.Reset(view);
-            TextShadow.Reset(view);
-        }
+        public TriggerableSelector<string> EnsureTranslatableText() => TranslatableText ?? (TranslatableText = new TriggerableSelector<string>(TextLabel.TranslatableTextProperty));
+        public TriggerableSelector<string> EnsureText() => Text ?? (Text = new TriggerableSelector<string>(TextLabel.TextProperty));
+        public TriggerableSelector<string> EnsureFontFamily() => FontFamily ?? (FontFamily = new TriggerableSelector<string>(TextLabel.FontFamilyProperty));
+        public TriggerableSelector<Color> EnsureTextColor() => TextColor ?? (TextColor = new TriggerableSelector<Color>(TextLabel.TextColorProperty));
+        public TriggerableSelector<float?> EnsurePointSize() => PointSize ?? (PointSize = new TriggerableSelector<float?>(TextLabel.PointSizeProperty));
+        public TriggerableSelector<float?> EnsurePixelSize() => PixelSize ?? (PixelSize = new TriggerableSelector<float?>(TextLabel.PixelSizeProperty));
+        public TriggerableSelector<TextShadow> EnsureTextShadow() => TextShadow ?? (TextShadow = new TriggerableSelector<TextShadow>(TextLabel.TextShadowProperty));
 
-        private static Color GetTextColor(View view)
+        public virtual void Reset(View view)
         {
-            Color color = new Color();
-            if (view.GetProperty(TextLabel.Property.TextColor).Get(color))
-            {
-                return color;
-            }
-            return null;
+            TranslatableText?.Reset(view);
+            Text?.Reset(view);
+            FontFamily?.Reset(view);
+            TextColor?.Reset(view);
+            PointSize?.Reset(view);
+            PixelSize?.Reset(view);
+            TextShadow?.Reset(view);
         }
     }
 }
index e967580..ece7367 100755 (executable)
@@ -168,6 +168,9 @@ namespace Tizen.NUI.BaseComponents
 
         /// <summary>
         /// Get/Set the control state.
+        /// Note that the ControlState only available for the classes derived from Control.
+        /// If the classes that are not derived from Control (such as View, ImageView and TextLabel) want to use this system,
+        /// please set <see cref="EnableControlState"/> to true.
         /// </summary>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
@@ -311,8 +314,8 @@ namespace Tizen.NUI.BaseComponents
                 SetValue(BackgroundColorProperty, value);
                 if (selectorData != null)
                 {
-                    selectorData.BackgroundImage.Reset(this);
-                    selectorData.BackgroundColor.UpdateIfNeeds(this, value);
+                    selectorData.BackgroundImage?.Reset(this);
+                    selectorData.BackgroundColor?.Reset(this);
                 }
                 NotifyPropertyChanged();
             }
@@ -333,8 +336,8 @@ namespace Tizen.NUI.BaseComponents
                 SetValue(BackgroundImageProperty, value);
                 if (selectorData != null)
                 {
-                    selectorData.BackgroundColor.Reset(this);
-                    selectorData.BackgroundImage.UpdateIfNeeds(this, value);
+                    selectorData.BackgroundColor?.Reset(this);
+                    selectorData.BackgroundImage?.Reset(this);
                 }
                 NotifyPropertyChanged();
             }
@@ -354,7 +357,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(BackgroundImageBorderProperty, value);
-                selectorData?.BackgroundImageBorder.UpdateIfNeeds(this, value);
+                selectorData?.BackgroundImageBorder?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -408,8 +411,8 @@ namespace Tizen.NUI.BaseComponents
                 SetValue(ImageShadowProperty, value);
                 if (selectorData != null)
                 {
-                    selectorData.BoxShadow.Reset(this);
-                    selectorData.ImageShadow.UpdateIfNeeds(this, value);
+                    selectorData.BoxShadow?.Reset(this);
+                    selectorData.ImageShadow?.Reset(this);
                 }
                 NotifyPropertyChanged();
             }
@@ -447,8 +450,8 @@ namespace Tizen.NUI.BaseComponents
                 SetValue(BoxShadowProperty, value);
                 if (selectorData != null)
                 {
-                    selectorData.ImageShadow.Reset(this);
-                    selectorData.BoxShadow.UpdateIfNeeds(this, value);
+                    selectorData.ImageShadow?.Reset(this);
+                    selectorData.BoxShadow?.Reset(this);
                 }
                 NotifyPropertyChanged();
             }
@@ -1078,7 +1081,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(OpacityProperty, value);
-                selectorData?.Opacity.UpdateIfNeeds(this, value);
+                selectorData?.Opacity?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -2381,7 +2384,7 @@ namespace Tizen.NUI.BaseComponents
             set
             {
                 SetValue(ColorProperty, value);
-                selectorData?.Color.UpdateIfNeeds(this, value);
+                selectorData?.Color?.Reset(this);
                 NotifyPropertyChanged();
             }
         }
@@ -2567,7 +2570,6 @@ namespace Tizen.NUI.BaseComponents
         }
 
         /// <summary>
-        /// If this property is set to true, the View can have a touch related ControlState (such as Pressed) when touch.
         /// By default, it is false in View, true in Control.
         /// Note that if the value is true, the View will be a touch receptor.
         /// </summary>
@@ -2678,31 +2680,36 @@ namespace Tizen.NUI.BaseComponents
 
             this.viewStyle = viewStyle;
 
-            Dictionary<string, BindableProperty> bindablePropertyOfView;
-            Type viewType = GetType();
+            if (viewStyle.DirtyProperties == null || viewStyle.DirtyProperties.Count == 0)
+            {
+                // Nothing to apply
+                return;
+            }
+
+            BindableProperty.GetBindablePropertysOfType(GetType(), out var bindablePropertyOfView);
 
-            Dictionary<string, BindableProperty> bindablePropertyOfStyle;
-            Type styleType = viewStyle.GetType();
+            if (bindablePropertyOfView == null)
+            {
+                return;
+            }
 
-            BindableProperty.GetBindablePropertysOfType(viewType, out bindablePropertyOfView);
-            BindableProperty.GetBindablePropertysOfType(styleType, out bindablePropertyOfStyle);
+            var dirtyProperties = new BindableProperty[viewStyle.DirtyProperties.Count];
+            viewStyle.DirtyProperties.CopyTo(dirtyProperties);
 
-            if (null != bindablePropertyOfView && null != bindablePropertyOfStyle)
+            foreach (var sourceProperty in dirtyProperties)
             {
-                foreach (KeyValuePair<string, BindableProperty> keyValuePair in bindablePropertyOfStyle)
+                var sourceValue = viewStyle.GetValue(sourceProperty);
+
+                if (sourceValue == null)
                 {
-                    BindableProperty viewProperty;
-                    bindablePropertyOfView.TryGetValue(keyValuePair.Key, out viewProperty);
+                    continue;
+                }
 
-                    if (null != viewProperty && viewProperty != StyleNameProperty)
-                    {
-                        object value = viewStyle.GetValue(keyValuePair.Value);
+                bindablePropertyOfView.TryGetValue(sourceProperty.PropertyName, out var destinationProperty);
 
-                        if (null != value)
-                        {
-                            SetValue(viewProperty, value);
-                        }
-                    }
+                if (destinationProperty != null)
+                {
+                    SetValue(destinationProperty, sourceValue);
                 }
             }
         }
index 485a8b9..ebd1d80 100755 (executable)
@@ -1779,58 +1779,93 @@ namespace Tizen.NUI.BaseComponents
         internal static readonly BindableProperty BackgroundImageSelectorProperty = BindableProperty.Create("BackgroundImageSelector", typeof(Selector<string>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var view = (View)bindable;
-            view.SelectorData.BackgroundImage.Update(view, (Selector<string>)newValue, true);
-            if (newValue != null) view.SelectorData.BackgroundColor.Reset(view);
+            view.EnsureSelectorData().EnsureBackgroundImage().Update(view, (Selector<string>)newValue, true);
+            if (newValue != null) view.EnsureSelectorData().BackgroundColor?.Reset(view);
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.SelectorData.BackgroundImage.Get(view);
+            var selector = view.selectorData?.BackgroundImage?.Get();
+            if (selector != null)
+            {
+                return selector;
+            }
+
+            string backgroundImage = null;
+            view.Background.Find(ImageVisualProperty.URL)?.Get(out backgroundImage);
+            return backgroundImage == null ? null : new Selector<string>(backgroundImage);
         });
 
         internal static readonly BindableProperty BackgroundColorSelectorProperty = BindableProperty.Create("BackgroundColorSelector", typeof(Selector<Color>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var view = (View)bindable;
-            view.SelectorData.BackgroundColor.Update(view, (Selector<Color>)newValue, true);
-            if (newValue != null) view.SelectorData.BackgroundImage.Reset(view);
+            view.EnsureSelectorData().EnsureBackgroundColor().Update(view, (Selector<Color>)newValue, true);
+            if (newValue != null) view.EnsureSelectorData().BackgroundImage?.Reset(view);
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.SelectorData.BackgroundColor.Get(view);
+            var selector = view.selectorData?.BackgroundColor?.Get();
+            if (selector != null)
+            {
+                return selector;
+            }
+
+            var background = view.Background;
+            int visualType = 0;
+            background.Find(Visual.Property.Type)?.Get(out visualType);
+            if (visualType != (int)Visual.Type.Color)
+            {
+                return null;
+            }
+
+            Color backgroundColor = new Color();
+            background.Find(ColorVisualProperty.MixColor)?.Get(backgroundColor);
+            return new Selector<Color>(backgroundColor);
         });
 
         internal static readonly BindableProperty BackgroundImageBorderSelectorProperty = BindableProperty.Create("BackgroundImageBorderSelector", typeof(Selector<Rectangle>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var view = (View)bindable;
-            view.SelectorData.BackgroundImageBorder.Update(view, (Selector<Rectangle>)newValue, true);
+            view.EnsureSelectorData().EnsureBackgroundImageBorder().Update(view, (Selector<Rectangle>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.SelectorData.BackgroundImageBorder.Get(view);
+            return view.GetSelector<Rectangle>(view.selectorData?.BackgroundImageBorder, View.BackgroundImageBorderProperty);
         });
 
         internal static readonly BindableProperty ColorSelectorProperty = BindableProperty.Create("ColorSelector", typeof(Selector<Color>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var view = (View)bindable;
-            view.SelectorData.Color.Update(view, (Selector<Color>)newValue, true);
+            view.EnsureSelectorData().EnsureColor().Update(view, (Selector<Color>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.SelectorData.Color.Get(view);
+            var selector = view.selectorData?.Color?.Get();
+            if (selector != null)
+            {
+                return selector;
+            }
+
+            Color color = new Color();
+            if (!view.GetProperty(Interop.ActorProperty.ColorGet()).Get(color))
+            {
+                return null;
+            }
+            return new Selector<Color>(color);
         });
 
         internal static readonly BindableProperty OpacitySelectorProperty = BindableProperty.Create("OpacitySelector", typeof(Selector<float?>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var view = (View)bindable;
-            view.SelectorData.Opacity.Update(view, (Selector<float?>)newValue, true);
+            view.EnsureSelectorData().EnsureOpacity().Update(view, (Selector<float?>)newValue, true);
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.SelectorData.Opacity.Get(view);
+            return view.GetSelector<float?>(view.selectorData?.Opacity, View.OpacityProperty);
         });
 
         /// <summary>
@@ -1840,13 +1875,13 @@ namespace Tizen.NUI.BaseComponents
         public static readonly BindableProperty ImageShadowSelectorProperty = BindableProperty.Create("ImageShadowSelector", typeof(Selector<ImageShadow>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var view = (View)bindable;
-            view.SelectorData.ImageShadow.Update(view, (Selector<ImageShadow>)newValue, true);
-            if (newValue != null) view.SelectorData.BoxShadow.Reset(view);
+            view.EnsureSelectorData().EnsureImageShadow().Update(view, (Selector<ImageShadow>)newValue, true);
+            if (newValue != null) view.EnsureSelectorData().BoxShadow?.Reset(view);
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.SelectorData.ImageShadow.Get(view);
+            return view.GetSelector<ImageShadow>(view.selectorData?.ImageShadow, View.ImageShadowProperty);
         });
 
         /// <summary>
@@ -1856,13 +1891,13 @@ namespace Tizen.NUI.BaseComponents
         public static readonly BindableProperty BoxShadowSelectorProperty = BindableProperty.Create("BoxShadowSelector", typeof(Selector<Shadow>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var view = (View)bindable;
-            view.SelectorData.BoxShadow.Update(view, (Selector<Shadow>)newValue, true);
-            if (newValue != null) view.SelectorData.ImageShadow.Reset(view);
+            view.EnsureSelectorData().EnsureBoxShadow().Update(view, (Selector<Shadow>)newValue, true);
+            if (newValue != null) view.EnsureSelectorData().ImageShadow?.Reset(view);
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.SelectorData.BoxShadow.Get(view);
+            return view.GetSelector<Shadow>(view.selectorData?.BoxShadow, View.BoxShadowProperty);
         });
         #endregion
     }
index e6032e7..fa69534 100755 (executable)
@@ -27,6 +27,7 @@ namespace Tizen.NUI.BaseComponents
     public partial class View
     {
         private ViewSelectorData selectorData;
+
         internal string styleName;
 
         /// <summary>
@@ -335,18 +336,6 @@ namespace Tizen.NUI.BaseComponents
             }
         }
 
-        private ViewSelectorData SelectorData
-        {
-            get
-            {
-                if (selectorData == null)
-                {
-                    selectorData = new ViewSelectorData();
-                }
-                return selectorData;
-            }
-        }
-
         internal void Raise()
         {
             var parentChildren = GetParent()?.Children;
@@ -1098,6 +1087,21 @@ namespace Tizen.NUI.BaseComponents
         }
 
         /// <summary>
+        /// Get selector value from the triggerable selector or related property.
+        /// </summary>
+        internal Selector<T> GetSelector<T>(TriggerableSelector<T> triggerableSelector, NUI.Binding.BindableProperty relatedProperty)
+        {
+            var selector = triggerableSelector?.Get();
+            if (selector != null)
+            {
+                return selector;
+            }
+
+            var value = (T)GetValue(relatedProperty);
+            return value == null ? null : new Selector<T>(value);
+        }
+
+        /// <summary>
         /// you can override it to clean-up your own resources.
         /// </summary>
         /// <param name="type">DisposeTypes</param>
@@ -1374,5 +1378,7 @@ namespace Tizen.NUI.BaseComponents
             if (style != null) ApplyStyle(style.Clone());   // Use given style
             else if (ThemeManager.ThemeApplied) UpdateStyle(); // Use style in the current theme
         }
+
+        private ViewSelectorData EnsureSelectorData() => selectorData ?? (selectorData = new ViewSelectorData());
     }
 }
old mode 100755 (executable)
new mode 100644 (file)
index 0032a01..4801fab
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2021 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.
 namespace Tizen.NUI.BaseComponents
 {
     /// <summary>
-    /// The class storing extra data for a View to optimize size of it.
+    /// The class storing extra selector properties of view that is rared used.
     /// </summary>
     internal class ViewSelectorData
     {
-        public TriggerableSelector<Color> BackgroundColor { get; } = new TriggerableSelector<Color>(View.BackgroundColorProperty, delegate (View view)
-        {
-            var background = view.Background;
-            int visualType = 0;
-            background.Find(Visual.Property.Type)?.Get(out visualType);
+        internal ViewSelectorData() { }
 
-            if (visualType == (int)Visual.Type.Color)
-            {
-                Color backgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.0f);
-                background.Find(ColorVisualProperty.MixColor)?.Get(backgroundColor);
-                return backgroundColor;
-            }
-            return null;
-        });
-        public TriggerableSelector<string> BackgroundImage { get; } = new TriggerableSelector<string>(View.BackgroundImageProperty, delegate (View view)
-        {
-            string backgroundImage = null;
-            view.Background.Find(ImageVisualProperty.URL)?.Get(out backgroundImage);
-            return backgroundImage;
-        });
-        public TriggerableSelector<Rectangle> BackgroundImageBorder { get; } = new TriggerableSelector<Rectangle>(View.BackgroundImageBorderProperty);
-        public TriggerableSelector<Color> Color { get; } = new TriggerableSelector<Color>(View.ColorProperty, delegate (View view)
-        {
-            Color color = new Color();
-            if (view.GetProperty(Interop.ActorProperty.ColorGet()).Get(color))
-            {
-                return color;
-            }
-            return null;
-        });
-        public TriggerableSelector<float?> Opacity { get; } = new TriggerableSelector<float?>(View.OpacityProperty);
-        public TriggerableSelector<ImageShadow> ImageShadow { get; } = new TriggerableSelector<ImageShadow>(View.ImageShadowProperty);
-        public TriggerableSelector<Shadow> BoxShadow { get; } = new TriggerableSelector<Shadow>(View.BoxShadowProperty);
+        public TriggerableSelector<Color> BackgroundColor { get;  private set; }
+        public TriggerableSelector<string> BackgroundImage { get;  private set; }
+        public TriggerableSelector<Rectangle> BackgroundImageBorder { get;  private set; }
+        public TriggerableSelector<Color> Color { get;  private set; }
+        public TriggerableSelector<float?> Opacity { get;  private set; }
+        public TriggerableSelector<ImageShadow> ImageShadow { get;  private set; }
+        public TriggerableSelector<Shadow> BoxShadow { get;  private set; }
+
+        public TriggerableSelector<Color> EnsureBackgroundColor() => BackgroundColor ?? (BackgroundColor = new TriggerableSelector<Color>(View.BackgroundColorProperty));
+        public TriggerableSelector<string> EnsureBackgroundImage() => BackgroundImage ?? (BackgroundImage = new TriggerableSelector<string>(View.BackgroundImageProperty));
+        public TriggerableSelector<Rectangle> EnsureBackgroundImageBorder() => BackgroundImageBorder ?? (BackgroundImageBorder = new TriggerableSelector<Rectangle>(View.BackgroundImageBorderProperty));      
+        public TriggerableSelector<Color> EnsureColor() => Color ?? (Color = new TriggerableSelector<Color>(View.ColorProperty));
+        public TriggerableSelector<float?> EnsureOpacity() => Opacity ?? (Opacity = new TriggerableSelector<float?>(View.OpacityProperty));
+        public TriggerableSelector<ImageShadow> EnsureImageShadow() => ImageShadow ?? (ImageShadow = new TriggerableSelector<ImageShadow>(View.ImageShadowProperty));
+        public TriggerableSelector<Shadow> EnsureBoxShadow() => BoxShadow ?? (BoxShadow = new TriggerableSelector<Shadow>(View.BoxShadowProperty));
 
         public void Reset(View view)
         {
-            BackgroundColor.Reset(view);
-            BackgroundImage.Reset(view);
-            BackgroundImageBorder.Reset(view);
-            Color.Reset(view);
-            Opacity.Reset(view);
-            ImageShadow.Reset(view);
-            BoxShadow.Reset(view);
+            BackgroundColor?.Reset(view);
+            BackgroundImage?.Reset(view);
+            BackgroundImageBorder?.Reset(view);
+            Color?.Reset(view);
+            Opacity?.Reset(view);
+            ImageShadow?.Reset(view);
+            BoxShadow?.Reset(view);
         }
     }
 }
+
+
index ba4efd8..79c8264 100755 (executable)
@@ -52,12 +52,6 @@ namespace Tizen.NUI
         /// </summary>
         internal VisualTransformPolicyType CornerRadiusPolicy { get; set; } = VisualTransformPolicyType.Absolute;
 
-        internal bool Empty()
-        {
-            return CornerRadius == 0 && Rectangle.IsNullOrZero(BackgroundImageBorder);
-        }
-
-
         [EditorBrowsable(EditorBrowsableState.Never)]
         protected virtual void Dispose(bool disposing)
         {
index 66de5e5..6e393d4 100755 (executable)
@@ -67,10 +67,6 @@ namespace Tizen.NUI.Binding
         [EditorBrowsable(EditorBrowsableState.Never)]
         public event PropertyChangedEventHandler PropertyChanged;
 
-        /// <summary>Whether to allow null value when <seealso cref="CopyFrom"/>.</summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        protected static bool AllowNullCopy { get; set; } = false;
-
         /// <summary>Copy properties of other ViewStyle to this.</summary>
         /// <param name="other">The other BindableProperty merge to this.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
@@ -94,7 +90,7 @@ namespace Tizen.NUI.Binding
                     {
                         object value = other.GetValue(bindableProperty);
 
-                        if (AllowNullCopy || null != value)
+                        if (null != value)
                         {
                             SetValue(keyValuePair.Value, value);
                         }
@@ -244,6 +240,7 @@ namespace Tizen.NUI.Binding
                 property.PropertyChanged?.Invoke(this, null, value);
 
                 OnPropertyChanged(property.PropertyName);
+                OnPropertyChangedWithData(property);
             }
         }
 
@@ -358,6 +355,12 @@ namespace Tizen.NUI.Binding
         [EditorBrowsable(EditorBrowsableState.Never)]
         protected virtual void OnPropertyChanging([CallerMemberName] string propertyName = null)
             => PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
+        
+        /// <summary>
+        /// Method that is called when a bound property is changed.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected virtual void OnPropertyChangedWithData(BindableProperty property) { }
 
         /// <summary>
         /// Unapplies all previously set bindings.
@@ -744,6 +747,7 @@ namespace Tizen.NUI.Binding
             if (!same)
             {
                 OnPropertyChanged(property.PropertyName);
+                OnPropertyChangedWithData(property);
                 property.PropertyChanged?.Invoke(this, original, newValue);
             }
         }
@@ -881,6 +885,8 @@ namespace Tizen.NUI.Binding
 
                     OnPropertyChanged(property.PropertyName);
                 }
+
+                OnPropertyChangedWithData(property);
             }
         }