From: Jiyun Yang Date: Tue, 21 Jan 2020 03:49:47 +0000 (+0900) Subject: [NUI] Support Shadow Size Extents (#1334) X-Git-Tag: submit/tizen_5.5/20200121.151316~1^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=886a1204533783036a5257178d8c24d026f9029e;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git [NUI] Support Shadow Size Extents (#1334) Signed-off-by: Jiyun Yang --- diff --git a/src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs b/src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs index f5d7d32..bd2096b 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs @@ -37,6 +37,19 @@ namespace Tizen.NUI.BaseComponents return selector; } + /// Default Contructor + [EditorBrowsable(EditorBrowsableState.Never)] + public Selector() + { + } + + /// Contructor with T + [EditorBrowsable(EditorBrowsableState.Never)] + public Selector(T value) : this() + { + All = value; + } + /// /// All State. /// @@ -199,6 +212,22 @@ namespace Tizen.NUI.BaseComponents SelectedFocused = selector.SelectedFocused; Other = selector.Other; } + + internal void Clone(Selector other) where U : T, Tizen.NUI.Internal.ICloneable + { + // TODO Apply constraint to the Selector (not to Clone method) + + All = (T)(other.All)?.Clone(); + Normal = (T)(other.Normal)?.Clone(); + Focused = (T)(other.Focused)?.Clone(); + Pressed = (T)(other.Pressed)?.Clone(); + Disabled = (T)(other.Disabled)?.Clone(); + Selected = (T)(other.Selected)?.Clone(); + DisabledSelected = (T)(other.DisabledSelected)?.Clone(); + DisabledFocused = (T)(other.DisabledFocused)?.Clone(); + SelectedFocused = (T)(other.SelectedFocused)?.Clone(); + Other = (T)(other.Other)?.Clone(); + } } /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. @@ -240,7 +269,79 @@ namespace Tizen.NUI.BaseComponents private BindableProperty targetBindableProperty; } - internal static class SelectorHelper where T : class, Tizen.NUI.ICloneable + /// + /// A class that helps binding a non-selector property in View to selector property in ViewStyle. + /// + internal class ViewSelector where T : class, Tizen.NUI.Internal.ICloneable + { + private Selector selector; + private View view; + private View.ControlStateChangesDelegate controlStateChanged; + + internal ViewSelector(View view, View.ControlStateChangesDelegate controlStateChanged) + { + if (view == null || controlStateChanged == null) + { + throw new global::System.ArgumentNullException(); + } + this.view = view; + this.controlStateChanged = controlStateChanged; + this.selector = null; + } + + internal T GetValue() + { + return selector == null ? null : selector.GetValue(view.ControlState); + } + + internal void Clone(object value) + { + bool hadMultiValue = HasMultiValue(); + var type = value?.GetType(); + + if (type == typeof(T)) + { + selector = new Selector(); + selector.All = (T)((T)value).Clone(); + } + else if (type == typeof(Selector)) + { + selector = new Selector(); + selector.Clone((Selector)value); + } + else + { + selector = null; + } + + if (hadMultiValue != HasMultiValue()) + { + if (hadMultiValue) view.ControlStateChangeEvent -= controlStateChanged; + else view.ControlStateChangeEvent += controlStateChanged; + } + } + + internal void Clear() + { + if (HasMultiValue()) + { + view.ControlStateChangeEvent -= controlStateChanged; + } + selector = null; + } + + internal bool IsEmpty() + { + return selector == null; + } + + private bool HasMultiValue() + { + return (selector != null && selector.All == null); + } + } + + internal static class SelectorHelper where T : class, Tizen.NUI.Internal.ICloneable { /// /// For the object type of T or Selector T, convert it to Selector T and return the cloned one. @@ -253,15 +354,13 @@ namespace Tizen.NUI.BaseComponents if (type == typeof(Selector)) { var result = new Selector(); - result.Clone((Selector)value); + result.Clone((Selector)value); return result; } if (type == typeof(T)) { - var result = new Selector(); - result.Clone((T)value); - return result; + return new Selector((T)((T)value).Clone()); } return null; diff --git a/src/Tizen.NUI/src/public/BaseComponents/View.cs b/src/Tizen.NUI/src/public/BaseComponents/View.cs index 4d9bb86..0b8c8f4 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/View.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/View.cs @@ -60,9 +60,9 @@ namespace Tizen.NUI.BaseComponents private string[] transitionNames; private Rectangle backgroundImageBorder; - private ImageShadow imageShadow; + private ViewSelector imageShadow; - private Shadow boxShadow; + private ViewSelector boxShadow; static View() {} diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs index 2696fc8..1e65b76 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs @@ -1281,14 +1281,18 @@ namespace Tizen.NUI.BaseComponents public static readonly BindableProperty ImageShadowProperty = BindableProperty.Create(nameof(ImageShadow), typeof(ImageShadow), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) => { var view = (View)bindable; - view.imageShadow = SelectorHelper.Clone(newValue, view); - Tizen.NUI.Object.SetProperty(view.swigCPtr, Interop.ViewProperty.View_Property_SHADOW_get(), ImageShadow.ToPropertyValue(view.imageShadow)); + bool hadShadowExtents = view.HasShadowExtents(); - if (view.imageShadow != null) view.boxShadow = null; + (view.imageShadow ?? (view.imageShadow = new ViewSelector(view, view.OnControlStateChangedForShadow))).Clone(newValue); + Tizen.NUI.Object.SetProperty(view.swigCPtr, Interop.ViewProperty.View_Property_SHADOW_get(), ImageShadow.ToPropertyValue(view.imageShadow.GetValue(), view)); + + view.boxShadow?.Clear(); + view.UpdateRelayoutCallbackForShadow(hadShadowExtents); }, defaultValueCreator: (bindable) => { - return ((View)bindable).imageShadow; + var view = (View)bindable; + return view.imageShadow?.GetValue(); }); /// @@ -1298,14 +1302,18 @@ namespace Tizen.NUI.BaseComponents public static readonly BindableProperty BoxShadowProperty = BindableProperty.Create(nameof(BoxShadow), typeof(Shadow), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) => { var view = (View)bindable; - view.boxShadow = SelectorHelper.Clone(newValue, view); - Tizen.NUI.Object.SetProperty(view.swigCPtr, Interop.ViewProperty.View_Property_SHADOW_get(), Shadow.ToPropertyValue(view.boxShadow)); + bool hadShadowExtents = view.HasShadowExtents(); - if (view.boxShadow != null) view.imageShadow = null; + (view.boxShadow ?? (view.boxShadow = new ViewSelector(view, view.OnControlStateChangedForShadow))).Clone(newValue); + Tizen.NUI.Object.SetProperty(view.swigCPtr, Interop.ViewProperty.View_Property_SHADOW_get(), Shadow.ToPropertyValue(view.boxShadow.GetValue(), view)); + + view.imageShadow?.Clear(); + view.UpdateRelayoutCallbackForShadow(hadShadowExtents); }, defaultValueCreator: (bindable) => { - return ((View)bindable).boxShadow; + var view = (View)bindable; + return view.boxShadow?.GetValue(); }); /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API. diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs index aa1f38c..6d6d632 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs @@ -1246,5 +1246,42 @@ namespace Tizen.NUI.BaseComponents { SizeModeFactor = new Vector3(x, y, z); } + + private bool HasShadowExtents() + { + bool verifyImageShadow = imageShadow?.GetValue()?.HasValidSizeExtents() ?? false; + bool verifyBoxShadow = boxShadow?.GetValue()?.HasValidSizeExtents() ?? false; + return verifyImageShadow || verifyBoxShadow; + } + + private void UpdateRelayoutCallbackForShadow(bool hadShadowExtents) + { + bool hasShadowExtents = HasShadowExtents(); + + if (!hadShadowExtents && hasShadowExtents) + { + Relayout += OnRelayoutForShadow; + } + else if (hadShadowExtents && !hasShadowExtents) + { + Relayout -= OnRelayoutForShadow; + } + } + + private void OnRelayoutForShadow(object sender, global::System.EventArgs e) + { + UpdateShadowVisual(); + } + + private void OnControlStateChangedForShadow(View obj, NUI.Components.ControlStates state) + { + UpdateShadowVisual(); + } + + private void UpdateShadowVisual() + { + 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)); + } } } diff --git a/src/Tizen.NUI/src/public/ViewProperty/ICloneable.cs b/src/Tizen.NUI/src/public/ViewProperty/ICloneable.cs index 4304e7e..83ef182 100644 --- a/src/Tizen.NUI/src/public/ViewProperty/ICloneable.cs +++ b/src/Tizen.NUI/src/public/ViewProperty/ICloneable.cs @@ -17,7 +17,7 @@ using System.ComponentModel; -namespace Tizen.NUI +namespace Tizen.NUI.Internal { /// diff --git a/src/Tizen.NUI/src/public/ViewProperty/ImageShadow.cs b/src/Tizen.NUI/src/public/ViewProperty/ImageShadow.cs index 9032365..bd60a24 100644 --- a/src/Tizen.NUI/src/public/ViewProperty/ImageShadow.cs +++ b/src/Tizen.NUI/src/public/ViewProperty/ImageShadow.cs @@ -24,8 +24,10 @@ namespace Tizen.NUI /// The Shadow composed of image for View /// [EditorBrowsable(EditorBrowsableState.Never)] - public class ImageShadow : ShadowBase, Tizen.NUI.ICloneable + public class ImageShadow : ShadowBase, Tizen.NUI.Internal.ICloneable { + private static readonly Rectangle noBorder = new Rectangle(); + private string url; private Rectangle border; @@ -69,7 +71,7 @@ namespace Tizen.NUI { return new ImageShadow() { Offset = offset, - Scale = scale, + Extents = extents, Url = url, Border = border }; @@ -84,7 +86,7 @@ namespace Tizen.NUI { return instance == null ? null : new ImageShadow() { Offset = instance.offset, - Scale = instance.scale, + Extents = instance.extents, Url = instance.url, Border = instance.border }; @@ -138,7 +140,7 @@ namespace Tizen.NUI } set { - border = value == null? null : new Rectangle(OnBorderChanged, value); + border = new Rectangle(OnBorderChanged, value ?? noBorder); UpdateBorder(); } } diff --git a/src/Tizen.NUI/src/public/ViewProperty/Shadow.cs b/src/Tizen.NUI/src/public/ViewProperty/Shadow.cs index 6f79f92..58bd45f 100644 --- a/src/Tizen.NUI/src/public/ViewProperty/Shadow.cs +++ b/src/Tizen.NUI/src/public/ViewProperty/Shadow.cs @@ -24,7 +24,7 @@ namespace Tizen.NUI /// The platform provided shadow drawing for View /// [EditorBrowsable(EditorBrowsableState.Never)] - public class Shadow : ShadowBase, Tizen.NUI.ICloneable + public class Shadow : ShadowBase, Tizen.NUI.Internal.ICloneable { private static readonly Color noColor = new Color(0, 0, 0, 0); @@ -75,7 +75,7 @@ namespace Tizen.NUI { return new Shadow() { Offset = offset, - Scale = scale, + Extents = extents, Color = color, BlurRadius = blurRadius }; @@ -110,7 +110,7 @@ namespace Tizen.NUI } set { - color = value == null? null : new Color(OnColorChanged, value); + color = new Color(OnColorChanged, value ?? noColor); UpdateColor(); } } diff --git a/src/Tizen.NUI/src/public/ViewProperty/ShadowBase.cs b/src/Tizen.NUI/src/public/ViewProperty/ShadowBase.cs index 06ac918..a2428a7 100644 --- a/src/Tizen.NUI/src/public/ViewProperty/ShadowBase.cs +++ b/src/Tizen.NUI/src/public/ViewProperty/ShadowBase.cs @@ -33,7 +33,7 @@ namespace Tizen.NUI private static readonly Vector2 noOffset = new Vector2(0, 0); - private static readonly Vector2 noScale = new Vector2(1, 1); + private static readonly Vector2 noExtents = new Vector2(0, 0); private static readonly Vector2 absoluteTransformPolicy = new Vector2((int)VisualTransformPolicyType.Absolute, (int)VisualTransformPolicyType.Absolute); @@ -44,9 +44,9 @@ namespace Tizen.NUI protected internal Vector2 offset; /// - /// The size value in scale + /// The size value in extension length /// - protected internal Vector2 scale; + protected internal Vector2 extents; /// /// The output property map @@ -57,7 +57,7 @@ namespace Tizen.NUI /// Constructor /// [EditorBrowsable(EditorBrowsableState.Never)] - public ShadowBase() : this(noOffset, noScale) + public ShadowBase() : this(noOffset, noExtents) { } @@ -65,27 +65,22 @@ namespace Tizen.NUI /// Copy Constructor /// [EditorBrowsable(EditorBrowsableState.Never)] - public ShadowBase(ShadowBase other) : this(other.offset, other.scale) + public ShadowBase(ShadowBase other) : this(other.offset, other.extents) { } /// /// Constructor /// - protected internal ShadowBase(Vector2 offset, Vector2 scale) + private ShadowBase(Vector2 offset, Vector2 extents) { propertyMap = new PropertyMap(); Offset = offset; - Scale = scale; + Extents = extents; } - private void OnOffsetChanged(float x, float y) - { - OnPropertyChanged?.Invoke(this); - } - - private void OnScaleChanged(float widht, float height) + private void OnOffsetOrSizeChanged(float x, float y) { OnPropertyChanged?.Invoke(this); } @@ -102,7 +97,7 @@ namespace Tizen.NUI } set { - offset = new Vector2(OnOffsetChanged, value ?? noOffset); + offset = new Vector2(OnOffsetOrSizeChanged, value ?? noOffset); OnPropertyChanged?.Invoke(this); } } @@ -111,21 +106,40 @@ namespace Tizen.NUI /// The value indicates percentage of the container size.
/// e.g. (0.5f, 1.0f) means 50% of the container's width and 100% of container's height. /// + /// It is not guaranteed that this would work well. It will be removed in the next version. [EditorBrowsable(EditorBrowsableState.Never)] public Vector2 Scale { get { - return scale; + return new Vector2(); + } + set + { + } + } + + /// + /// The shadow will extend its size by specified amount of length.
+ /// 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). + ///
+ [EditorBrowsable(EditorBrowsableState.Never)] + public Vector2 Extents + { + get + { + return extents; } set { - scale = new Vector2(OnScaleChanged, value ?? noScale); + extents = new Vector2(OnOffsetOrSizeChanged, value ?? noExtents); OnPropertyChanged?.Invoke(this); } } - private PropertyValue GetTransformMap() + private PropertyValue GetTransformMap(BaseComponents.View attachedView) { var transformMap = new PropertyMap(); @@ -135,9 +149,13 @@ namespace Tizen.NUI transformMap[(int)VisualTransformPropertyType.Offset] = PropertyValue.CreateWithGuard(offset); } - if (!scale.Equals(noScale)) + if (!extents.Equals(noExtents)) { - transformMap[(int)VisualTransformPropertyType.Size] = PropertyValue.CreateWithGuard(scale); + 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); } return transformMap.Count() == 0 ? new PropertyValue() : new PropertyValue(transformMap); @@ -145,14 +163,19 @@ namespace Tizen.NUI abstract internal bool IsValid(); - static internal PropertyValue ToPropertyValue(ShadowBase instance) + internal bool HasValidSizeExtents() + { + return IsValid() && !extents.Equals(noExtents); + } + + static internal PropertyValue ToPropertyValue(ShadowBase instance, BaseComponents.View attachedView) { if (instance == null || !instance.IsValid()) { return new PropertyValue(); } - instance.propertyMap[Visual.Property.Transform] = instance.GetTransformMap(); + instance.propertyMap[Visual.Property.Transform] = instance.GetTransformMap(attachedView); return new PropertyValue(instance.propertyMap); } diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/PopupSample.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/PopupSample.cs index f0bcbac..56106cc 100755 --- a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/PopupSample.cs +++ b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/PopupSample.cs @@ -68,8 +68,7 @@ namespace Tizen.NUI.Samples Url = CommonResource.GetFHResourcePath() + "11. Popup/popup_background_shadow.png", Border = new Rectangle(24, 24, 24, 24), Offset = new Vector2(-24, -24), - // TODO We do not have shadow extents now, so replace it to scale value - Scale = new Vector2(1080f/1032f, 448f/400f), + Extents = new Vector2(48, 48), }; // Background @@ -124,8 +123,7 @@ namespace Tizen.NUI.Samples Url = CommonResource.GetFHResourcePath() + "11. Popup/popup_background_shadow.png", Border = new Rectangle(24, 24, 24, 24), Offset = new Vector2(-24, -24), - // TODO We do not have shadow extents now, so replace it to scale value - Scale = new Vector2(1080f/1032f, 448f/400f), + Extents = new Vector2(48, 48), }, Title = new TextLabelStyle {