[NUI] Add Shadow BlurRadius and lighten View size (#1552)
authorJiyun Yang <ji.yang@samsung.com>
Thu, 23 Apr 2020 09:12:28 +0000 (18:12 +0900)
committerGitHub <noreply@github.com>
Thu, 23 Apr 2020 09:12:28 +0000 (18:12 +0900)
Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
18 files changed:
src/Tizen.NUI.Components/Controls/ButtonGroup.cs
src/Tizen.NUI.Components/Controls/Popup.cs
src/Tizen.NUI.Components/Style/PopupStyle.cs
src/Tizen.NUI.Components/Utils/StyleManager.cs
src/Tizen.NUI/src/public/BaseComponents/Style/Constants.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/TextLabel.cs
src/Tizen.NUI/src/public/BaseComponents/View.cs
src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs
src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs
src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs
src/Tizen.NUI/src/public/Rectangle.cs
src/Tizen.NUI/src/public/ViewProperty/BackgroundExtraData.cs [new file with mode: 0644]
src/Tizen.NUI/src/public/ViewProperty/ImageShadow.cs
src/Tizen.NUI/src/public/ViewProperty/Shadow.cs
src/Tizen.NUI/src/public/ViewProperty/ShadowBase.cs
src/Tizen.NUI/src/public/VisualConstants.cs

index 2afccfc..7f47b75 100755 (executable)
@@ -203,9 +203,9 @@ namespace Tizen.NUI.Components
                 var shadow = (ImageShadow)newValue;
                 foreach (Button btn in btGroup.itemGroup)
                 {
-                    btn.Style.ImageShadow = (ImageShadow)ImageShadow.Clone(shadow);
+                    btn.Style.ImageShadow = new ImageShadow(shadow);
                 }
-                btGroup.itemImageShadow = (ImageShadow)ImageShadow.Clone(shadow);
+                btGroup.itemImageShadow = new ImageShadow(shadow);
             }
         },
         defaultValueCreator: (bindable) =>
index ebba0fa..ef74941 100755 (executable)
@@ -186,8 +186,8 @@ namespace Tizen.NUI.Components
         {
             var instance = (Popup)bindable;
             ImageShadow shadow = (ImageShadow)newValue;
-            instance.btGroup.ItemImageShadow = (ImageShadow)ImageShadow.Clone(shadow);
-            instance.Style.Buttons.ImageShadow = (ImageShadow)ImageShadow.Clone(shadow);
+            instance.btGroup.ItemImageShadow = new ImageShadow(shadow);
+            instance.Style.Buttons.ImageShadow = new ImageShadow(shadow);
         },
         defaultValueCreator: (bindable) =>
         {
index 51eb137..2d6caf5 100755 (executable)
@@ -89,6 +89,7 @@ namespace Tizen.NUI.Components
             // TODO Apply proper shadow as a default for a Popup
             BoxShadow = new Shadow()
             {
+                BlurRadius = 5,
                 Offset = new Vector2(5, 5),
             };
 
index cf562ff..b176283 100755 (executable)
@@ -255,7 +255,7 @@ namespace Tizen.NUI.Components
             }
             catch
             {
-                Tizen.Log.Error("NUI", "Unknown device profile");
+                Tizen.Log.Error("NUI", "Unknown device profile\n");
                 return;
             }
 
index 28ef04d..6d04a79 100755 (executable)
@@ -83,12 +83,5 @@ namespace Tizen.NUI.Components
         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         DisabledSelected = Disabled | Selected,
-        /// <summary>
-        /// The SelectedPressed state.
-        /// </summary>
-        /// <since_tizen> 6 </since_tizen>
-        /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        PressedSelected = Pressed | Selected,
     }
 }
index 8043579..558fc89 100755 (executable)
@@ -151,16 +151,6 @@ namespace Tizen.NUI.BaseComponents
         }
 
         /// <summary>
-        /// PressedSelected State.
-        /// </summary>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public T PressedSelected
-        {
-            get;
-            set;
-        }
-
-        /// <summary>
         /// Other State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
@@ -201,10 +191,19 @@ namespace Tizen.NUI.BaseComponents
                     return DisabledSelected != null ? DisabledSelected : (Disabled != null ? Disabled : Other);
                 case ControlStates.SelectedFocused:
                     return SelectedFocused != null ? SelectedFocused : (Selected != null ? Selected : Other);
-                case ControlStates.PressedSelected:
-                    return PressedSelected != null ? PressedSelected : (Selected != null ? Selected : Other);
                 default:
+                {
+                    // Handle combined states
+                    if ((int)(state & ControlStates.Selected) != 0 && Selected != null)
+                    {
+                        return Selected;
+                    }
+                    else if ((int)(state & ControlStates.Pressed) != 0 && Pressed != null)
+                    {
+                        return Pressed;
+                    }
                     return Other;
+                }
             }
         }
         /// <summary>
@@ -224,7 +223,6 @@ namespace Tizen.NUI.BaseComponents
             DisabledSelected = selector.DisabledSelected;
             DisabledFocused = selector.DisabledFocused;
             SelectedFocused = selector.SelectedFocused;
-            PressedSelected = selector.PressedSelected;
             Other = selector.Other;
         }
 
@@ -241,9 +239,13 @@ namespace Tizen.NUI.BaseComponents
             DisabledSelected = (T)(other.DisabledSelected)?.Clone();
             DisabledFocused = (T)(other.DisabledFocused)?.Clone();
             SelectedFocused = (T)(other.SelectedFocused)?.Clone();
-            PressedSelected = (T)(other.PressedSelected)?.Clone();
             Other = (T)(other.Other)?.Clone();
         }
+
+        internal bool HasMultiValue()
+        {
+            return All == null;
+        }
     }
 
     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
@@ -273,11 +275,11 @@ namespace Tizen.NUI.BaseComponents
             }
         }
 
-        private void OnViewControlState(View obj, ControlStates state)
+        private void OnViewControlState(View obj, View.ControlStateChagedInfo controlStateChangedInfo)
         {
-            if (null != obj && null != GetValue(state))
+            if (null != obj && null != GetValue(controlStateChangedInfo.CurrentState))
             {
-                obj.SetValue(targetBindableProperty, GetValue(state));
+                obj.SetValue(targetBindableProperty, GetValue(controlStateChangedInfo.CurrentState));
             }
         }
 
index 840c748..0893fcf 100755 (executable)
@@ -760,12 +760,13 @@ namespace Tizen.NUI.BaseComponents
 
         /// A BindableProperty for ImageShadow
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty ImageShadowProperty = BindableProperty.Create(nameof(ImageShadow), typeof(Selector<ImageShadow>), typeof(ViewStyle), null, propertyChanged: (bindable, oldValue, newValue) =>
+        public static readonly BindableProperty ImageShadowSelectorProperty = BindableProperty.Create("ImageShadowSelector", typeof(Selector<ImageShadow>), typeof(ViewStyle), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var viewStyle = (ViewStyle)bindable;
-            viewStyle.imageShadow = SelectorHelper.CopyCloneable<ImageShadow>(newValue);
 
-            if (viewStyle.imageShadow != null) viewStyle.boxShadow = null;
+            viewStyle.imageShadow = (Selector<ImageShadow>)newValue;
+
+            viewStyle.boxShadow = null;
         },
         defaultValueCreator: (bindable) =>
         {
@@ -775,12 +776,13 @@ namespace Tizen.NUI.BaseComponents
 
         /// A BindableProperty for BoxShadow
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty BoxShadowProperty = BindableProperty.Create(nameof(BoxShadow), typeof(Selector<ImageShadow>), typeof(ViewStyle), null, propertyChanged: (bindable, oldValue, newValue) =>
+        public static readonly BindableProperty BoxShadowSelectorProperty = BindableProperty.Create("BoxShadowSelector", typeof(Selector<Shadow>), typeof(ViewStyle), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var viewStyle = (ViewStyle)bindable;
-            viewStyle.boxShadow = SelectorHelper.CopyCloneable<Shadow>(newValue);
 
-            if (viewStyle.boxShadow != null) viewStyle.imageShadow = null;
+            viewStyle.boxShadow = (Selector<Shadow>)newValue;
+
+            viewStyle.imageShadow = null;
         },
         defaultValueCreator: (bindable) =>
         {
@@ -790,10 +792,10 @@ namespace Tizen.NUI.BaseComponents
 
         /// A BindableProperty for CornerRadius
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CornerRadius), typeof(Selector<float?>), typeof(ViewStyle), null, propertyChanged: (bindable, oldValue, newValue) =>
+        public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create("CornerRadiusSelector", typeof(Selector<float?>), typeof(ViewStyle), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var viewStyle = (ViewStyle)bindable;
-            viewStyle.cornerRadius = SelectorHelper.CopyValue<float?>(newValue);
+            viewStyle.cornerRadius = (Selector<float?>)(newValue);
         },
         defaultValueCreator: (bindable) =>
         {
@@ -1404,27 +1406,24 @@ namespace Tizen.NUI.BaseComponents
         /// It is null by default.
         /// </summary>
         /// <remarks>
-        /// The mutually exclusive with "BoxShadow".
+        /// If BoxShadow is not null, the ImageShadow value will be ignored.
         /// </remarks>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public Selector<ImageShadow> ImageShadow
         {
-            get => (Selector<ImageShadow>)GetValue(ImageShadowProperty);
-            set => SetValue(ImageShadowProperty, value);
+            get => (Selector<ImageShadow>)GetValue(ImageShadowSelectorProperty);
+            set => SetValue(ImageShadowSelectorProperty, value);
         }
 
         /// <summary>
         /// Describes a box shaped shadow drawing for a View.
         /// It is null by default.
         /// </summary>
-        /// <remarks>
-        /// The mutually exclusive with "ImageShadow".
-        /// </remarks>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public Selector<Shadow> BoxShadow
         {
-            get => (Selector<Shadow>)GetValue(BoxShadowProperty);
-            set => SetValue(BoxShadowProperty, value);
+            get => (Selector<Shadow>)GetValue(BoxShadowSelectorProperty);
+            set => SetValue(BoxShadowSelectorProperty, value);
         }
 
         /// <summary>
index 76cbce9..35f38a3 100755 (executable)
@@ -1583,7 +1583,7 @@ namespace Tizen.NUI.BaseComponents
             TextShadow = instance;
         }
 
-        private void OnControlStateChangedForShadow(View obj, Components.ControlStates state)
+        private void OnControlStateChangedForShadow(View obj, ControlStateChagedInfo controlStateChangedInfo)
         {
             UpdateTextShadowVisual();
         }
index a31513f..77a944a 100755 (executable)
@@ -59,13 +59,7 @@ namespace Tizen.NUI.BaseComponents
         private bool _backgroundImageSynchronosLoading = false;
         private Dictionary<string, Transition> transDictionary = new Dictionary<string, Transition>();
         private string[] transitionNames;
-        private Rectangle backgroundImageBorder;
-
-        private CloneableViewSelector<ImageShadow> imageShadow;
-
-        private CloneableViewSelector<Shadow> boxShadow;
-
-        private ViewSelector<float?> cornerRadius;
+        private BackgroundExtraData backgroundExtraData;
 
         internal Size2D sizeSetExplicitly = new Size2D(); // Store size set by API, will be used in place of NaturalSize if not set.
 
@@ -127,6 +121,8 @@ namespace Tizen.NUI.BaseComponents
             {
                 SetVisible(false);
             }
+
+            backgroundExtraData = uiControl.backgroundExtraData == null ? null : new BackgroundExtraData(uiControl.backgroundExtraData);
         }
 
         internal View(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : this(cPtr, cMemoryOwn, shown)
@@ -167,7 +163,7 @@ namespace Tizen.NUI.BaseComponents
             }
         }
 
-        internal delegate void ControlStateChangesDelegate(View obj, ControlStates state);
+        internal delegate void ControlStateChangesDelegate(View obj, ControlStateChagedInfo controlStateChangedInfo);
         internal event ControlStateChangesDelegate ControlStateChangeEvent;
 
         private ControlStates controlStates;
@@ -206,9 +202,11 @@ namespace Tizen.NUI.BaseComponents
 
             controlStates = state;
 
-            ControlStateChangeEvent?.Invoke(this, state);
+            var changeInfo = new ControlStateChagedInfo(prevState, state, touchInfo);
+
+            ControlStateChangeEvent?.Invoke(this, changeInfo);
 
-            if (OnControlStateChanged(prevState, touchInfo))
+            if (OnControlStateChanged(changeInfo))
             {
                 foreach (View child in Children)
                 {
@@ -338,6 +336,9 @@ namespace Tizen.NUI.BaseComponents
         /// It is null by default.
         /// </summary>
         /// <remarks>
+        /// Gettter returns copied instance of current shadow.
+        /// </remarks>
+        /// <remarks>
         /// The mutually exclusive with "BoxShadow".
         /// </remarks>
         [EditorBrowsable(EditorBrowsableState.Never)]
@@ -345,8 +346,7 @@ namespace Tizen.NUI.BaseComponents
         {
             get
             {
-                var value = (ImageShadow)GetValue(ImageShadowProperty);
-                return value == null ? null : new ImageShadow(value, OnImageShadowChanged);
+                return (ImageShadow)GetValue(ImageShadowProperty);
             }
             set
             {
@@ -360,6 +360,9 @@ namespace Tizen.NUI.BaseComponents
         /// It is null by default.
         /// </summary>
         /// <remarks>
+        /// Gettter returns copied instance of current shadow.
+        /// </remarks>
+        /// <remarks>
         /// The mutually exclusive with "ImageShadow".
         /// </remarks>
         [EditorBrowsable(EditorBrowsableState.Never)]
@@ -367,8 +370,7 @@ namespace Tizen.NUI.BaseComponents
         {
             get
             {
-                var value = (Shadow)GetValue(BoxShadowProperty);
-                return value == null ? null : new Shadow(value, OnBoxShadowChanged);
+                return (Shadow)GetValue(BoxShadowProperty);
             }
             set
             {
@@ -387,8 +389,7 @@ namespace Tizen.NUI.BaseComponents
         {
             get
             {
-                float? value = (float?)GetValue(CornerRadiusProperty);
-                return value ?? 0;
+                return (float)GetValue(CornerRadiusProperty);
             }
             set
             {
@@ -2309,11 +2310,10 @@ namespace Tizen.NUI.BaseComponents
         /// <summary>
         /// Called after the View's ControlStates changed.
         /// </summary>
-        /// <param name="previousState">The previous state value</param>
-        /// <param name="touchInfo">The touch information in case the state has changed by touching.</param>
+        /// <param name="controlStateChangedInfo">The information including state changed variables.</param>
         /// <return>True if it needs to apply the state to children recursively.</return>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        protected virtual bool OnControlStateChanged(ControlStates previousState, Touch touchInfo)
+        protected virtual bool OnControlStateChanged(ControlStateChagedInfo controlStateChangedInfo)
         {
             //If need to apply the state to all child, return true;
             return true;
index 7a0f54d..277be24 100755 (executable)
@@ -53,15 +53,22 @@ namespace Tizen.NUI.BaseComponents
         public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create("BackgroundColor", typeof(Color), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
             var view = (View)bindable;
+
             if (newValue != null)
             {
-                Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new Tizen.NUI.PropertyValue((Color)newValue));
-
-                // Apply CornerRadius if needs
-                if (view.cornerRadius != null && view.cornerRadius.GetValue() != 0)
+                if (view.backgroundExtraData == null)
                 {
-                    view.ApplyCornerRadius();
+                    Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new PropertyValue((Color)newValue));
+                    return;
                 }
+
+                PropertyMap map = new PropertyMap();
+
+                map.Add(Visual.Property.Type, new PropertyValue((int)Visual.Type.Color))
+                   .Add(ColorVisualProperty.MixColor, new PropertyValue((Color)newValue))
+                   .Add(Visual.Property.CornerRadius, new PropertyValue(view.backgroundExtraData.CornerRadius));
+
+                Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new PropertyValue(map));
             }
         },
         defaultValueCreator: (bindable) =>
@@ -109,25 +116,38 @@ namespace Tizen.NUI.BaseComponents
             {
                 string url = (string)newValue;
 
-                if (Rectangle.IsNullOrZero(view.backgroundImageBorder))
+                if (string.IsNullOrEmpty(url))
                 {
-                    Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, string.IsNullOrEmpty(url) ? new PropertyValue() : new PropertyValue(url));
+                    // Clear background
+                    Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new PropertyValue());
+                    return;
+                }
 
-                    // Apply CornerRadius if needs
-                    if (view.cornerRadius != null && view.cornerRadius.GetValue() != 0)
-                    {
-                        view.ApplyCornerRadius();
-                    }
+                if (view.backgroundExtraData == null)
+                {
+                    Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new PropertyValue(url));
+                    view.BackgroundImageSynchronosLoading = view._backgroundImageSynchronosLoading;
+
+                    return;
+                }
+
+                PropertyMap map = new PropertyMap();
+
+                map.Add(ImageVisualProperty.URL, new PropertyValue(url))
+                   .Add(Visual.Property.CornerRadius, new PropertyValue(view.backgroundExtraData.CornerRadius))
+                   .Add(ImageVisualProperty.SynchronousLoading, new PropertyValue(view._backgroundImageSynchronosLoading));
+                
+                if (view.backgroundExtraData.BackgroundImageBorder != null)
+                {
+                    map.Add(Visual.Property.Type, new PropertyValue((int)Visual.Type.NPatch))
+                       .Add(NpatchImageVisualProperty.Border, new PropertyValue(view.backgroundExtraData.BackgroundImageBorder));
                 }
                 else
                 {
-                    var visual = new NPatchVisual();
-                    visual.URL = url;
-                    visual.Border = view.backgroundImageBorder;
-                    Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new PropertyValue(visual.OutputVisualMap));
+                    map.Add(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
                 }
 
-                view.BackgroundImageSynchronosLoading = view._backgroundImageSynchronosLoading;
+                Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new PropertyValue(map));
             }
         },
         defaultValueCreator: (bindable) =>
@@ -150,36 +170,44 @@ namespace Tizen.NUI.BaseComponents
         public static readonly BindableProperty BackgroundImageBorderProperty = BindableProperty.Create(nameof(BackgroundImageBorder), typeof(Rectangle), typeof(View), default(Rectangle), propertyChanged: (bindable, oldValue, newValue) =>
         {
             var view = (View)bindable;
-            string url = view.BackgroundImage;
-            view.backgroundImageBorder = (Rectangle)newValue;
 
-            if (string.IsNullOrEmpty(url))
+            bool isEmptyValue = Rectangle.IsNullOrZero((Rectangle)newValue);
+
+            var backgroundImageBorder = isEmptyValue ? null : (Rectangle)newValue;
+
+            (view.backgroundExtraData ?? (view.backgroundExtraData = new BackgroundExtraData())).BackgroundImageBorder = backgroundImageBorder;
+
+            if (isEmptyValue)
             {
                 return;
             }
 
-            if (Rectangle.IsNullOrZero(view.backgroundImageBorder))
-            {
-                Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new PropertyValue(url));
+            PropertyMap map = view.Background;
 
-                // Apply CornerRadius if needs
-                if (view.cornerRadius != null && view.cornerRadius.GetValue() != 0)
-                {
-                    view.ApplyCornerRadius();
-                }
+            if (map.Empty())
+            {
+                return;
             }
-            else
+
+            map[NpatchImageVisualProperty.Border] = new PropertyValue(backgroundImageBorder);
+
+            int visualType = 0;
+
+            map.Find(Visual.Property.Type)?.Get(out visualType);
+
+            if (visualType == (int)Visual.Type.Image)
             {
-                var visual = new NPatchVisual();
-                visual.URL = url;
-                visual.Border = view.backgroundImageBorder;
-                Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new PropertyValue(visual.OutputVisualMap));
+                map[Visual.Property.Type] = new PropertyValue((int)Visual.Type.NPatch);
             }
+
+            Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new PropertyValue(map));
+
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.backgroundImageBorder == null ? new Rectangle(view.OnBackgroundImageBorderChanged) : new Rectangle(view.OnBackgroundImageBorderChanged, view.backgroundImageBorder);
+
+            return view.backgroundExtraData?.BackgroundImageBorder;
         });
         /// <summary>
         /// BackgroundProperty
@@ -191,6 +219,8 @@ namespace Tizen.NUI.BaseComponents
             if (newValue != null)
             {
                 Tizen.NUI.Object.SetProperty(view.swigCPtr, View.Property.BACKGROUND, new Tizen.NUI.PropertyValue((PropertyMap)newValue));
+
+                view.backgroundExtraData = null;
             }
         },
         defaultValueCreator: (bindable) =>
@@ -1420,19 +1450,47 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly BindableProperty ImageShadowProperty = BindableProperty.Create(nameof(ImageShadow), typeof(ImageShadow), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
+            var shadow = (ImageShadow)newValue;
+
+            var view = (View)bindable;
+
+            view.SetValue(View.ImageShadowSelectorProperty, shadow == null ? null : new Selector<ImageShadow>() { All = shadow, });
+        },
+        defaultValueCreator: (bindable) =>
+        {
+            var view = (View)bindable;
+
+            if (view.viewStyle != null)
+            {
+                return view.viewStyle.ImageShadow?.GetValue(view.ControlState);
+            }
+
+            PropertyMap map = new PropertyMap();
+
+            Tizen.NUI.Object.GetProperty(view.swigCPtr, View.Property.SHADOW).Get(map);
+
+            var shadow = new ImageShadow(map);
+
+            return shadow.IsEmpty() ? null : shadow;
+        });
+
+        /// <summary>
+        /// ImageShadow Selector Property for binding to ViewStyle
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static readonly BindableProperty ImageShadowSelectorProperty = BindableProperty.Create("ImageShadowSelector", typeof(Selector<ImageShadow>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
+        {
             var view = (View)bindable;
-            bool hadShadowExtents = view.HasShadowExtents();
 
-            (view.imageShadow ?? (view.imageShadow = new CloneableViewSelector<ImageShadow>(view, view.OnControlStateChangedForShadow))).Set(newValue);
-            Tizen.NUI.Object.SetProperty(view.swigCPtr, Interop.ViewProperty.View_Property_SHADOW_get(), ImageShadow.ToPropertyValue(view.imageShadow.GetValue(), view));
+            var shadowSelector = (Selector<ImageShadow>)newValue;
 
-            view.boxShadow?.Clear();
-            view.UpdateRelayoutCallbackForShadow(hadShadowExtents);
+            view.UpdateShadow(shadowSelector?.GetValue(view.ControlState), shadowSelector == null ? false : shadowSelector.HasMultiValue());
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.imageShadow?.GetValue();
+
+            return view.viewStyle?.ImageShadow;
         });
 
         /// <summary>
@@ -1441,19 +1499,47 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly BindableProperty BoxShadowProperty = BindableProperty.Create(nameof(BoxShadow), typeof(Shadow), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
         {
+            var shadow = (Shadow)newValue;
+
             var view = (View)bindable;
-            bool hadShadowExtents = view.HasShadowExtents();
 
-            (view.boxShadow ?? (view.boxShadow = new CloneableViewSelector<Shadow>(view, view.OnControlStateChangedForShadow))).Set(newValue);
-            Tizen.NUI.Object.SetProperty(view.swigCPtr, Interop.ViewProperty.View_Property_SHADOW_get(), Shadow.ToPropertyValue(view.boxShadow.GetValue(), view));
+            view.SetValue(View.BoxShadowSelectorProperty, shadow == null ? null : new Selector<Shadow>() { All = shadow, });
+        },
+        defaultValueCreator: (bindable) =>
+        {
+            var view = (View)bindable;
 
-            view.imageShadow?.Clear();
-            view.UpdateRelayoutCallbackForShadow(hadShadowExtents);
+            if (view.viewStyle != null)
+            {
+                return view.viewStyle.BoxShadow?.GetValue(view.ControlState);
+            }
+
+            PropertyMap map = new PropertyMap();
+
+            Tizen.NUI.Object.GetProperty(view.swigCPtr, View.Property.SHADOW).Get(map);
+
+            var shadow = new Shadow(map);
+
+            return shadow.IsEmpty() ? null : shadow;
+        });
+
+        /// <summary>
+        /// BoxShadow Selector Property for binding to ViewStyle
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static readonly BindableProperty BoxShadowSelectorProperty = BindableProperty.Create("BoxShadowSelector", typeof(Selector<Shadow>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
+        {
+            var view = (View)bindable;
+
+            var shadowSelector = (Selector<Shadow>)newValue;
+
+            view.UpdateShadow(shadowSelector?.GetValue(view.ControlState), shadowSelector == null ? false : shadowSelector.HasMultiValue());
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.boxShadow?.GetValue();
+
+            return view.viewStyle?.BoxShadow;
         });
 
         /// <summary>
@@ -1464,17 +1550,32 @@ namespace Tizen.NUI.BaseComponents
         {
             var view = (View)bindable;
 
-            (view.cornerRadius ?? (view.cornerRadius = new ViewSelector<float?>(view, view.OnControlStateChangedForCornerRadius))).Set(newValue);
+            view.SetValue(View.CornerRadiusSelectorProperty, new Selector<float?>() { All = (float)newValue, });
+        },
+        defaultValueCreator: (bindable) =>
+        {
+            var view = (View)bindable;
+
+            return view.backgroundExtraData == null ? 0 : view.backgroundExtraData.CornerRadius;
+        });
 
-            view.ApplyCornerRadius();
+        /// <summary>
+        /// CornerRadius Selector Property
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static readonly BindableProperty CornerRadiusSelectorProperty = BindableProperty.Create("CornerRadiusSelector", typeof(Selector<float?>), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) =>
+        {
+            var view = (View)bindable;
 
-            // Update shadow visual
-            view.ApplyShadow();
+            var cornerRadiusSelector = (Selector<float?>)newValue;
+
+            view.UpdateCornerRadius(cornerRadiusSelector?.GetValue(view.ControlState) ?? 0, cornerRadiusSelector == null ? false : cornerRadiusSelector.HasMultiValue());
         },
         defaultValueCreator: (bindable) =>
         {
             var view = (View)bindable;
-            return view.cornerRadius?.GetValue();
+
+            return view.viewStyle?.CornerRadius;
         });
 
         /// <summary>
index 4680cd3..7c5b557 100755 (executable)
@@ -16,7 +16,9 @@
  */
 
 using System;
+using System.ComponentModel;
 using System.Runtime.InteropServices;
+using Tizen.NUI.Components;
 
 namespace Tizen.NUI.BaseComponents
 {
@@ -1054,6 +1056,40 @@ namespace Tizen.NUI.BaseComponents
             }
         }
 
+        /// <summary>
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public class ControlStateChagedInfo
+        {
+            /// <summary>
+            /// The previous control state.
+            /// </summary>
+            public ControlStateChagedInfo(ControlStates previousState, ControlStates currentState, Touch touch)
+            {
+                PreviousState = previousState;
+                CurrentState = currentState;
+                Touch = touch;
+            }
+
+            /// <summary>
+            /// The previous control state.
+            /// </summary>
+            public ControlStates PreviousState { get; }
+
+            /// <summary>
+            /// The current control state.
+            /// </summary>
+            public ControlStates CurrentState { get; }
+
+            /// <summary>
+            /// The touch information in case the state has changed by touching.
+            /// </summary>
+            /// <remarks>
+            /// The value is null if it is not the case.
+            /// </remarks>
+            public Touch Touch { get; }
+        }
+
         private EventHandlerWithReturnType<object, WheelEventArgs, bool> WindowWheelEventHandler;
         private void OnWindowWheelEvent(object sender, Window.WheelEventArgs e)
         {
index 92ff630..a784ee4 100755 (executable)
@@ -1259,60 +1259,116 @@ namespace Tizen.NUI.BaseComponents
             SizeModeFactor = new Vector3(x, y, z);
         }
 
-        private bool HasShadowExtents()
+        private void OnControlStateChangedForShadow(View obj, ControlStateChagedInfo controlStateChangedInfo)
         {
-            bool verifyImageShadow = imageShadow?.GetValue()?.HasValidSizeExtents() ?? false;
-            bool verifyBoxShadow = boxShadow?.GetValue()?.HasValidSizeExtents() ?? false;
-            return verifyImageShadow || verifyBoxShadow;
+            var boxShadowSelector = (Selector<Shadow>)GetValue(BoxShadowSelectorProperty);
+
+            if (boxShadowSelector != null)
+            {
+                ShadowBase prevShadow = boxShadowSelector.GetValue(controlStateChangedInfo.PreviousState);
+
+                var boxShadow = boxShadowSelector.GetValue(controlStateChangedInfo.CurrentState);
+
+                if (boxShadow == prevShadow)
+                {
+                    return;
+                }
+
+                Tizen.NUI.Object.SetProperty(swigCPtr, View.Property.SHADOW, boxShadow == null ? new PropertyValue() : boxShadow.ToPropertyValue(this));
+
+                return;
+            }
+
+            var imageShadowSelector = (Selector<ImageShadow>)GetValue(ImageShadowSelectorProperty);
+
+            if (imageShadowSelector != null)
+            {
+                ShadowBase prevShadow = imageShadowSelector?.GetValue(controlStateChangedInfo.PreviousState);
+
+                var imageShadow = imageShadowSelector.GetValue(controlStateChangedInfo.CurrentState);
+
+                if (imageShadow == prevShadow)
+                {
+                    return;
+                }
+
+                Tizen.NUI.Object.SetProperty(swigCPtr, View.Property.SHADOW, imageShadow == null ? new PropertyValue() : imageShadow.ToPropertyValue(this));
+            }
         }
 
-        private void UpdateRelayoutCallbackForShadow(bool hadShadowExtents)
+        private void UpdateShadow(ShadowBase shadow, bool needToListenStateChanged)
         {
-            bool hasShadowExtents = HasShadowExtents();
+            ControlStateChangeEvent -= OnControlStateChangedForShadow;
 
-            if (!hadShadowExtents && hasShadowExtents)
+            if (shadow == null)
             {
-                Relayout += OnRelayoutForShadow;
+                Tizen.NUI.Object.SetProperty(swigCPtr, View.Property.SHADOW, new PropertyValue());
             }
-            else if (hadShadowExtents && !hasShadowExtents)
+            else
             {
-                Relayout -= OnRelayoutForShadow;
+                Tizen.NUI.Object.SetProperty(swigCPtr, View.Property.SHADOW, shadow.ToPropertyValue(this));
             }
-        }
 
-        private void OnRelayoutForShadow(object sender, global::System.EventArgs e)
-        {
-            ApplyShadow();
+            if (needToListenStateChanged)
+            {
+                ControlStateChangeEvent += OnControlStateChangedForShadow;
+            }
         }
 
-        private void OnControlStateChangedForShadow(View obj, NUI.Components.ControlStates state)
+        private void OnControlStateChangedForCornerRadius(View obj, ControlStateChagedInfo controlStateChangedInfo)
         {
-            ApplyShadow();
-        }
+            var selector = (Selector<float?>)GetValue(CornerRadiusSelectorProperty);
 
-        private void ApplyShadow()
-        {
-            ShadowBase shadow = (boxShadow != null && !boxShadow.IsEmpty()) ? (ShadowBase)boxShadow.GetValue() : (ShadowBase)imageShadow?.GetValue();
-            Tizen.NUI.Object.SetProperty(swigCPtr, Interop.ViewProperty.View_Property_SHADOW_get(), ShadowBase.ToPropertyValue(shadow, this));
-        }
+            if (selector == null)
+            {
+                return;
+            }
 
-        private void OnControlStateChangedForCornerRadius(View obj, NUI.Components.ControlStates state)
-        {
-            ApplyCornerRadius();
-            ApplyShadow();
+            float? currentCornerRadius = selector.GetValue(controlStateChangedInfo.CurrentState);
+
+            if (selector.GetValue(controlStateChangedInfo.PreviousState) == currentCornerRadius)
+            {
+                UpdateCornerRadius(currentCornerRadius ?? 0, true);
+            }
         }
 
-        private void ApplyCornerRadius()
+        private void UpdateCornerRadius(float value, bool needToListenStateChanged)
         {
+            ControlStateChangeEvent -= OnControlStateChangedForCornerRadius;
+
+            if (needToListenStateChanged)
+            {
+                ControlStateChangeEvent += OnControlStateChangedForCornerRadius;
+            }
+
+            if (value != 0)
+            {
+                (backgroundExtraData ?? (backgroundExtraData = new BackgroundExtraData())).CornerRadius = value;
+            }
+
             Tizen.NUI.PropertyMap backgroundMap = new Tizen.NUI.PropertyMap();
             Tizen.NUI.Object.GetProperty(swigCPtr, View.Property.BACKGROUND).Get(backgroundMap);
 
             if (!backgroundMap.Empty())
             {
-                // TODO (NDalic.VISUAL_PROPERTY_MIX_COLOR + 3) to CornerRadius
-                backgroundMap[Visual.Property.CornerRadius] = new PropertyValue(cornerRadius.GetValue() ?? 0);
+                backgroundMap[Visual.Property.CornerRadius] = new PropertyValue(value);
                 Tizen.NUI.Object.SetProperty(swigCPtr, View.Property.BACKGROUND, new Tizen.NUI.PropertyValue(backgroundMap));
             }
+
+            UpdateShadowCornerRadius(value);
+        }
+
+        private void UpdateShadowCornerRadius(float value)
+        {
+            // TODO Update corner radius property only whe DALi supports visual property update.
+            PropertyMap map = new PropertyMap();
+
+            if (Tizen.NUI.Object.GetProperty(swigCPtr, View.Property.SHADOW).Get(map) && !map.Empty())
+            {
+                map[Visual.Property.CornerRadius] = new PropertyValue(value);
+
+                Tizen.NUI.Object.SetProperty(swigCPtr, View.Property.SHADOW, new PropertyValue(map));
+            }
         }
     }
 }
index 7bc4279..372f623 100755 (executable)
@@ -48,6 +48,10 @@ namespace Tizen.NUI
             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
         }
 
+        internal Rectangle(Rectangle other) : this(other.x, other.y, other.width, other.height)
+        {
+        }
+
         internal Rectangle(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
         {
         }
diff --git a/src/Tizen.NUI/src/public/ViewProperty/BackgroundExtraData.cs b/src/Tizen.NUI/src/public/ViewProperty/BackgroundExtraData.cs
new file mode 100644 (file)
index 0000000..621e531
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright(c) 2020 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    /// <summary>
+    /// The class storing Background extra properties such as CornerRadius, ImageBorder.
+    /// </summary>
+    internal class BackgroundExtraData
+    {
+        internal BackgroundExtraData()
+        {
+        }
+
+        internal BackgroundExtraData(BackgroundExtraData other)
+        {
+            BackgroundImageBorder = other.BackgroundImageBorder;
+            CornerRadius = other.CornerRadius;
+        }
+
+        private Rectangle backgroundImageBorder;
+
+        /// <summary></summary>
+        internal Rectangle BackgroundImageBorder
+        {
+            get => backgroundImageBorder;
+            set => backgroundImageBorder = new Rectangle(value);
+        }
+
+        /// <summary></summary>
+        internal float CornerRadius { get; set; }
+
+        internal bool Empty()
+        {
+            return CornerRadius == 0 && Rectangle.IsNullOrZero(BackgroundImageBorder);
+        }
+    }
+}
+
+
index f8f6978..98049d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2020 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.
@@ -24,139 +24,149 @@ namespace Tizen.NUI
     /// The Shadow composed of image for View
     /// </summary>
     [EditorBrowsable(EditorBrowsableState.Never)]
-    public class ImageShadow : ShadowBase, Tizen.NUI.Internal.ICloneable
+    public class ImageShadow : ShadowBase
     {
         private static readonly Rectangle noBorder = new Rectangle();
 
-        private string url;
-
-        private Rectangle border;
-
         /// <summary>
         /// Constructor
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public ImageShadow() : base()
         {
-            propertyMap[Visual.Property.Type] = new PropertyValue((int)Visual.Type.Image);
+            Border = noBorder;
         }
 
-        internal ImageShadow(ImageShadow other, PropertyChangedCallback callback = null) : base(other)
+        /// <summary>
+        /// Constructor
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public ImageShadow(string url, Rectangle border, Vector2 offset, Vector2 extents) : base(offset, extents)
         {
-            propertyMap[Visual.Property.Type] = new PropertyValue((int)Visual.Type.Image);
-
-            Url = other.Url;
-            Border = other.Border;
-            OnPropertyChanged = callback;
+            Url = url;
+            Border = border;
         }
 
         /// <summary>
-        /// The string conversion
+        /// Constructor
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static implicit operator ImageShadow(string value)
+        public ImageShadow(ImageShadow other) : this(other.Url, other.Border, other.Offset, other.Extents)
         {
-            ImageShadow imageShadow = new ImageShadow()
-            {
-                Url = value ?? "",
-            };
-            return imageShadow;
         }
 
         /// <summary>
-        /// Deep copy method
+        /// Constructor
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public object Clone()
+        internal ImageShadow(PropertyMap propertyMap) : base(propertyMap)
         {
-            return new ImageShadow() {
-                Offset = offset,
-                Extents = extents,
-                Url = url,
-                Border = border
-            };
         }
 
         /// <summary>
-        /// Deep copy method (static)
-        /// This provides nullity check.
+        /// The string conversion
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        static public object Clone(ImageShadow instance)
+        public static implicit operator ImageShadow(string value)
         {
-            return instance == null ? null : new ImageShadow() {
-                Offset = instance.offset,
-                Extents = instance.extents,
-                Url = instance.url,
-                Border = instance.border
+            return new ImageShadow()
+            {
+                Url = value
             };
         }
 
-        private void OnBorderChanged(int x, int y, int width, int height)
-        {
-            UpdateBorder();
-        }
+        /// <summary>
+        /// The url for the shadow image to load.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public string Url { get; set; }
 
-        private void UpdateUrl()
-        {
-            propertyMap[ImageVisualProperty.URL] = PropertyValue.CreateWithGuard(url);
-            OnPropertyChanged?.Invoke(this);
-        }
+        /// <summary>
+        /// Optional.<br />
+        /// The border area of the n-patch image.
+        /// Set left, right, bottom, top length of the border you don't want to stretch in the image.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Rectangle Border { get; set; }
 
-        private void UpdateBorder()
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override bool Equals(object other)
         {
-            if (Rectangle.IsNullOrZero(border))
+            if (!base.Equals(other))
             {
-                propertyMap[Visual.Property.Type] = new PropertyValue((int)Visual.Type.Image);
+                return false;
             }
-            else
+
+            var otherShadow = (ImageShadow)other;
+
+            if (!((Url == null) ? otherShadow.Url == null : Url.Equals(otherShadow.Url)))
             {
-                propertyMap[Visual.Property.Type] = new PropertyValue((int)Visual.Type.NPatch);
+                return false;
             }
 
-            propertyMap[ImageVisualProperty.Border] = PropertyValue.CreateWithGuard(border);
-            OnPropertyChanged?.Invoke(this);
+            return Border.Equals(otherShadow.Border);
         }
 
-        /// <summary>
-        /// The url for the shadow image to load.
-        /// </summary>
+        /// <inheritdoc/>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public string Url
+        public override int GetHashCode()
         {
-            get
+            unchecked
             {
-                return url;
-            }
-            set
-            {
-                url = value;
-                UpdateUrl();
+                int hash = base.GetHashCode();
+                hash = (hash * 7) + (Url == null ? 0 : Url.GetHashCode());
+                hash = (hash * 7) + (Border.GetHashCode());
+                return hash;
             }
         }
 
-        /// <summary>
-        /// Optional.<br />
-        /// The border area of the n-patch image.
-        /// Set left, right, bottom, top length of the border you don't want to stretch in the image.
-        /// </summary>
+        internal override bool IsEmpty()
+        {
+            return string.IsNullOrEmpty(Url);
+        }
+
+        /// <inheritdoc/>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public Rectangle Border
+        protected override PropertyMap GetPropertyMap()
         {
-            get
+            var map = base.GetPropertyMap();
+
+            map[Visual.Property.Type] = new PropertyValue((int)Visual.Type.Image);
+
+            if (Rectangle.IsNullOrZero(Border))
             {
-                return border;
+                map[Visual.Property.Type] = new PropertyValue((int)Visual.Type.Image);
             }
-            set
+            else
             {
-                border = new Rectangle(OnBorderChanged, value ?? noBorder);
-                UpdateBorder();
+                map[Visual.Property.Type] = new PropertyValue((int)Visual.Type.NPatch);
             }
+
+            map[ImageVisualProperty.Border] = PropertyValue.CreateWithGuard(Border);
+
+            map[ImageVisualProperty.URL] = PropertyValue.CreateWithGuard(Url);
+
+            return map;
         }
 
-        override internal bool IsValid()
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override bool SetPropertyMap(PropertyMap propertyMap)
         {
-            return !string.IsNullOrEmpty(url);
+            if (!base.SetPropertyMap(propertyMap))
+            {
+                return false;
+            }
+
+            Border = noBorder;
+            propertyMap.Find(ImageVisualProperty.Border)?.Get(Border);
+
+            string url = null;
+            propertyMap.Find(ImageVisualProperty.URL)?.Get(out url);
+            Url = url;
+
+            return true;
         }
     }
 }
index 58bd45f..72dfe8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2020 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.
@@ -24,116 +24,123 @@ namespace Tizen.NUI
     /// The platform provided shadow drawing for View
     /// </summary>
     [EditorBrowsable(EditorBrowsableState.Never)]
-    public class Shadow : ShadowBase, Tizen.NUI.Internal.ICloneable
+    public class Shadow : ShadowBase
     {
         private static readonly Color noColor = new Color(0, 0, 0, 0);
 
         private static readonly Color defaultColor = new Color(0, 0, 0, 0.5f);
 
-        private Color color;
-
-        private uint blurRadius;
-
-        /// <summary>
-        /// Constructor
-        /// </summary>
+        /// <summary></summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public Shadow() : base()
         {
-            propertyMap[Visual.Property.Type] = new PropertyValue((int)Visual.Type.Color);
-
+            BlurRadius = 0;
             Color = defaultColor;
         }
 
-        internal Shadow(Shadow other, PropertyChangedCallback callback = null) : base(other)
+        /// <summary></summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Shadow(float blurRadius, Vector2 offset, Color color, Vector2 extents) : base(offset, extents)
         {
-            propertyMap[Visual.Property.Type] = new PropertyValue((int)Visual.Type.Color);
+            BlurRadius = blurRadius;
+            Color = color;
+        }
 
-            Color = other.Color;
-            BlurRadius = other.BlurRadius;
-            OnPropertyChanged = callback;
+        /// <summary></summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Shadow(Shadow other) : this(other.BlurRadius, other.Offset, other.Color, other.Extents)
+        {
         }
 
-        /// <summary>
-        /// The boolean conversion
-        /// </summary>
+        /// <summary></summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static implicit operator Shadow(bool value)
+        internal Shadow(PropertyMap propertyMap) : base(propertyMap)
         {
-            Shadow shadow = new Shadow()
-            {
-                Color = value ? defaultColor : noColor,
-            };
-            return shadow;
         }
 
         /// <summary>
-        /// Deep copy method
+        /// The color for the shadow.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Color Color { get; set; }
+
+        /// <summary>
+        /// The blur radius value for the shadow. Bigger value, much blurry.
         /// </summary>
+        /// <remark>
+        /// Negative value is ignored. (no blur)
+        /// </remark>
+        public float BlurRadius { get; set; }
+
+        /// <inheritdoc/>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public object Clone()
+        public override bool Equals(object other)
         {
-            return new Shadow() {
-                Offset = offset,
-                Extents = extents,
-                Color = color,
-                BlurRadius = blurRadius
-            };
-        }
+            if (!base.Equals(other))
+            {
+                return false;
+            }
 
-        private void OnColorChanged(float r, float g, float b, float a)
-        {
-            UpdateColor();
+            var otherShadow = (Shadow)other;
+
+            if (!((Color == null) ? otherShadow.Color == null : Color.Equals(otherShadow.Color)))
+            {
+                return false;
+            }
+
+            return BlurRadius.Equals(otherShadow.BlurRadius);
         }
 
-        private void UpdateColor()
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public override int GetHashCode()
         {
-            propertyMap[ColorVisualProperty.MixColor] = PropertyValue.CreateWithGuard(color);
-            OnPropertyChanged?.Invoke(this);
+            unchecked
+            {
+                int hash = base.GetHashCode();
+                hash = (hash * 7) + (Color == null ? 0 : Color.GetHashCode());
+                hash = (hash * 7) + (BlurRadius.GetHashCode());
+                return hash;
+            }
         }
 
-        private void UpdateBlurRadius()
+        internal override bool IsEmpty()
         {
-            // TODO update blur radius value in the property map
-            OnPropertyChanged?.Invoke(this);
+            return (Color == null || Color.A == 0);
         }
 
-        /// <summary>
-        /// The color for the shadow.
-        /// </summary>
+        /// <inheritdoc/>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public Color Color
+        protected override PropertyMap GetPropertyMap()
         {
-            get
-            {
-                return color;
-            }
-            set
-            {
-                color = new Color(OnColorChanged, value ?? noColor);
-                UpdateColor();
-            }
+            var map = base.GetPropertyMap();
+
+            map[Visual.Property.Type] = new PropertyValue((int)Visual.Type.Color);
+
+            map[ColorVisualProperty.MixColor] = new PropertyValue(Color ?? noColor);
+
+            map[ColorVisualProperty.BlurRadius] = new PropertyValue(BlurRadius < 0 ? 0 : BlurRadius);
+
+            return map;
         }
 
-        /// <summary>
-        /// The blur radius value for the shadow. Bigger value, much blurry.
-        /// </summary>
-        private uint BlurRadius
+        /// <inheritdoc/>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override bool SetPropertyMap(PropertyMap propertyMap)
         {
-            get
+            if (!base.SetPropertyMap(propertyMap))
             {
-                return blurRadius;
+                return false;
             }
-            set
-            {
-                blurRadius = value;
-                UpdateBlurRadius();
-            }
-        }
 
-        override internal bool IsValid()
-        {
-            return color != null && color.A != 0;
+            Color = noColor;
+            propertyMap.Find(ColorVisualProperty.MixColor)?.Get(Color);
+
+            float blurRadius = 0;
+            propertyMap.Find(ColorVisualProperty.BlurRadius)?.Get(out blurRadius);
+            BlurRadius = blurRadius;
+
+            return true;
         }
     }
 }
index ecc0918..3c993a8 100644 (file)
@@ -15,7 +15,7 @@
  *
  */
 
- using System.ComponentModel;
+using System.ComponentModel;
 
 namespace Tizen.NUI
 {
@@ -25,164 +25,202 @@ namespace Tizen.NUI
     /// This class can be used to convert visual properties to map.
     /// </summary>
     [EditorBrowsable(EditorBrowsableState.Never)]
-    abstract public class ShadowBase
+    public abstract class ShadowBase
     {
-        internal delegate void PropertyChangedCallback(ShadowBase instance);
-
-        internal PropertyChangedCallback OnPropertyChanged = null;
-
         private static readonly Vector2 noOffset = new Vector2(0, 0);
 
         private static readonly Vector2 noExtents = new Vector2(0, 0);
 
-        private static readonly Vector2 absoluteTransformPolicy = new Vector2((int)VisualTransformPolicyType.Absolute, (int)VisualTransformPolicyType.Absolute);
-
-
-        /// <summary>
-        /// The location offset value from the View
-        /// </summary>
-        protected internal Vector2 offset;
-
-        /// <summary>
-        /// The size value in extension length
-        /// </summary>
-        protected internal Vector2 extents;
-
         /// <summary>
-        /// The output property map
+        /// Constructor
         /// </summary>
-        protected internal PropertyMap propertyMap;
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected ShadowBase() : this(noOffset, noExtents)
+        {
+        }
 
         /// <summary>
         /// Constructor
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public ShadowBase() : this(noOffset, noExtents)
+        protected ShadowBase(Vector2 offset, Vector2 extents)
+        {
+            Offset = offset;
+            Extents = extents;
+        }
+
+        /// <summary></summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        internal protected ShadowBase(PropertyMap propertyMap)
         {
+            Offset = noOffset;
+            Extents = noExtents;
+
+            if (propertyMap == null)
+            {
+                return;
+            }
+
+            SetPropertyMap(propertyMap);
         }
 
         /// <summary>
         /// Copy Constructor
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public ShadowBase(ShadowBase other) : this(other.offset, other.extents)
+        protected ShadowBase(ShadowBase other) : this(other.Offset, other.Extents)
         {
         }
 
         /// <summary>
-        /// Constructor
+        /// The position offset value (x, y) from the top left corner.
         /// </summary>
-        private ShadowBase(Vector2 offset, Vector2 extents)
-        {
-            propertyMap = new PropertyMap();
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Vector2 Offset { get; set; }
 
-            Offset = offset;
-            Extents = extents;
+        /// <summary>
+        /// The shadow will extend its size by specified amount of length.<br />
+        /// If the value is negative then the shadow will shrink.
+        /// For example, when View's size is (100, 100) and the Shadow's Extents is (5, -5),
+        /// the output shadow will have size (105, 95).
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Vector2 Extents { get; set; }
+
+        /// <summary></summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static bool operator ==(ShadowBase shadow1, ShadowBase shadow2)
+        {
+            return object.ReferenceEquals(shadow1, null) ? object.ReferenceEquals(shadow2, null) : shadow1.Equals(shadow2);
         }
 
-        private void OnOffsetOrSizeChanged(float x, float y)
+        /// <summary></summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static bool operator !=(ShadowBase shadow1, ShadowBase shadow2)
         {
-            OnPropertyChanged?.Invoke(this);
+            return !(shadow1 == shadow2);
         }
 
-        /// <summary>
-        /// The position offset value (x, y) from the top left corner.
-        /// </summary>
+        /// <inheritdoc/>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public Vector2 Offset
+        public override bool Equals(object other)
         {
-            get
+            if ((other == null) || ! this.GetType().Equals(other.GetType())) 
             {
-                return offset;
+                return false;
             }
-            set
+            
+            var otherShadow = (ShadowBase)other;
+
+            if (!((Offset == null) ? otherShadow.Offset == null : Offset.Equals(otherShadow.Offset)))
             {
-                offset = new Vector2(OnOffsetOrSizeChanged, value ?? noOffset);
-                OnPropertyChanged?.Invoke(this);
+                return false;
             }
+
+            return ((Extents == null) ? otherShadow.Extents == null : Extents.Equals(otherShadow.Extents));
         }
 
-        /// <summary>
-        /// The value indicates percentage of the container size. <br />
-        /// e.g. (0.5f, 1.0f) means 50% of the container's width and 100% of container's height.
-        /// </summary>
-        /// <Remarks> It is not guaranteed that this would work well. It will be removed in the next version.</Remarks>
+        /// <inheritdoc/>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public Vector2 Scale
+        public override int GetHashCode()
+        {
+            unchecked
+            {
+                int hash = Offset == null ? 0 : Offset.GetHashCode();
+                hash = (hash * 7) + (Extents == null ? 0 : Extents.GetHashCode());
+                return hash;
+            }
+        }
+
+        internal abstract bool IsEmpty();
+
+        internal PropertyValue ToPropertyValue(BaseComponents.View attachedView)
         {
-            get
+            if (IsEmpty())
             {
-                return new Vector2();
+                return new PropertyValue();
             }
-            set
+
+            var map = GetPropertyMap();
+
+            if (attachedView.CornerRadius > 0)
             {
+                map[Visual.Property.CornerRadius] = new PropertyValue(attachedView.CornerRadius);
             }
+
+            map[Visual.Property.Transform] = GetTransformMap();
+
+            return new PropertyValue(map);
+        }
+
+        /// <summary>
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected virtual PropertyMap GetPropertyMap()
+        {
+            PropertyMap map = new PropertyMap();
+
+            return map;
         }
 
         /// <summary>
-        /// The shadow will extend its size by specified amount of length.<br />
-        /// If the value is negative then the shadow will shrink.
-        /// For example, when View's size is (100, 100) and the Shadow's Extents is (5, -5),
-        /// the output shadow will have size (105, 95).
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public Vector2 Extents
+        protected virtual bool SetPropertyMap(PropertyMap propertyMap)
         {
-            get
+            if (propertyMap == null)
+            {
+                return false;
+            }
+
+            var transformProperty = propertyMap.Find(Visual.Property.Transform);
+
+            if (transformProperty == null)
             {
-                return extents;
+                // No transform map
+                return true;
             }
-            set
+
+            var transformMap = new PropertyMap();
+
+            if (transformProperty.Get(transformMap))
             {
-                extents = new Vector2(OnOffsetOrSizeChanged, value ?? noExtents);
-                OnPropertyChanged?.Invoke(this);
+                SetTransformMap(transformMap);
             }
+
+            return true;
         }
 
-        private PropertyValue GetTransformMap(BaseComponents.View attachedView)
+        private PropertyValue GetTransformMap()
         {
             var transformMap = new PropertyMap();
 
-            if (!offset.Equals(noOffset))
+            if (!Offset.Equals(noOffset))
             {
-                transformMap[(int)VisualTransformPropertyType.OffsetPolicy] = new PropertyValue(absoluteTransformPolicy);
-                transformMap[(int)VisualTransformPropertyType.Offset] = PropertyValue.CreateWithGuard(offset);
+                transformMap[(int)VisualTransformPropertyType.OffsetPolicy] = new PropertyValue(new Vector2((int)VisualTransformPolicyType.Absolute, (int)VisualTransformPolicyType.Absolute));
+                transformMap[(int)VisualTransformPropertyType.Offset] = PropertyValue.CreateWithGuard(Offset);
             }
 
-            if (!extents.Equals(noExtents))
+            if (!Extents.Equals(noExtents))
             {
-                var viewSize = new Vector2(attachedView.GetRelayoutSize(DimensionType.Width), attachedView.GetRelayoutSize(DimensionType.Height));
-                var shadowSize = viewSize + extents;
-
-                transformMap[(int)VisualTransformPropertyType.SizePolicy] = new PropertyValue(absoluteTransformPolicy);
-                transformMap[(int)VisualTransformPropertyType.Size] = PropertyValue.CreateWithGuard(shadowSize);
+                transformMap[(int)VisualTransformPropertyType.ExtraSize] = PropertyValue.CreateWithGuard(Extents);
             }
 
             return transformMap.Count() == 0 ? new PropertyValue() : new PropertyValue(transformMap);
         }
 
-        abstract internal bool IsValid();
-
-        internal bool HasValidSizeExtents()
-        {
-            return IsValid() && !extents.Equals(noExtents);
-        }
-
-        static internal PropertyValue ToPropertyValue(ShadowBase instance, BaseComponents.View attachedView)
+        /// <summary>
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        private void SetTransformMap(PropertyMap transformMap)
         {
-            if (instance == null || !instance.IsValid())
+            if (transformMap == null)
             {
-                return new PropertyValue();
+                return;
             }
 
-            if (attachedView.CornerRadius > 0)
-            {
-                instance.propertyMap[Visual.Property.CornerRadius] = new PropertyValue(attachedView.CornerRadius);
-            }
-
-            instance.propertyMap[Visual.Property.Transform] = instance.GetTransformMap(attachedView);
-
-            return new PropertyValue(instance.propertyMap);
+            transformMap.Find((int)VisualTransformPropertyType.Offset)?.Get(Offset);
+            transformMap.Find((int)VisualTransformPropertyType.ExtraSize)?.Get(Extents);
         }
     }
 }
index c03663b..16c4561 100755 (executable)
@@ -346,7 +346,12 @@ namespace Tizen.NUI
         /// <summary>
         /// Whether the width or the height size values are relative (percentage [0.0f to 1.0f] of the control) or absolute (in world units).
         /// </summary>
-        SizePolicy
+        SizePolicy,
+        /// <summary>
+        /// Extra size value that will be added to the computed visual size.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        ExtraSize,
     }
 
     /// <summary>
@@ -581,6 +586,11 @@ namespace Tizen.NUI
         /// </summary>
         /// <since_tizen> 5 </since_tizen>
         public static readonly int RenderIfTransparent = NDalic.COLOR_VISUAL_MIX_COLOR + 1;
+        /// <summary>
+        /// Then radius value for the area to blur.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static readonly int BlurRadius = NDalic.COLOR_VISUAL_MIX_COLOR + 2;
     }
 
     /// <summary>