return selector;
}
+ /// Default Contructor
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Selector()
+ {
+ }
+
+ /// Contructor with T
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Selector(T value) : this()
+ {
+ All = value;
+ }
+
/// <summary>
/// All State.
/// </summary>
SelectedFocused = selector.SelectedFocused;
Other = selector.Other;
}
+
+ internal void Clone<U>(Selector<U> 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.
private BindableProperty targetBindableProperty;
}
- internal static class SelectorHelper<T> where T : class, Tizen.NUI.ICloneable
+ /// <summary>
+ /// A class that helps binding a non-selector property in View to selector property in ViewStyle.
+ /// </summary>
+ internal class ViewSelector<T> where T : class, Tizen.NUI.Internal.ICloneable
+ {
+ private Selector<T> 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<T>();
+ selector.All = (T)((T)value).Clone();
+ }
+ else if (type == typeof(Selector<T>))
+ {
+ selector = new Selector<T>();
+ selector.Clone<T>((Selector<T>)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<T> where T : class, Tizen.NUI.Internal.ICloneable
{
/// <summary>
/// For the object type of T or Selector T, convert it to Selector T and return the cloned one.
if (type == typeof(Selector<T>))
{
var result = new Selector<T>();
- result.Clone((Selector<T>)value);
+ result.Clone<T>((Selector<T>)value);
return result;
}
if (type == typeof(T))
{
- var result = new Selector<T>();
- result.Clone((T)value);
- return result;
+ return new Selector<T>((T)((T)value).Clone());
}
return null;
private string[] transitionNames;
private Rectangle backgroundImageBorder;
- private ImageShadow imageShadow;
+ private ViewSelector<ImageShadow> imageShadow;
- private Shadow boxShadow;
+ private ViewSelector<Shadow> boxShadow;
internal Size2D sizeSetExplicitly = new Size2D(); // Store size set by API, will be used in place of NaturalSize if not set.
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<ImageShadow>.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<ImageShadow>(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();
});
/// <summary>
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<Shadow>.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<Shadow>(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();
});
/// <summary>
{
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));
+ }
}
}
using System.ComponentModel;
-namespace Tizen.NUI
+namespace Tizen.NUI.Internal
{
/// <summary>
/// The Shadow composed of image for View
/// </summary>
[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;
{
return new ImageShadow() {
Offset = offset,
- Scale = scale,
+ Extents = extents,
Url = url,
Border = border
};
{
return instance == null ? null : new ImageShadow() {
Offset = instance.offset,
- Scale = instance.scale,
+ Extents = instance.extents,
Url = instance.url,
Border = instance.border
};
}
set
{
- border = value == null? null : new Rectangle(OnBorderChanged, value);
+ border = new Rectangle(OnBorderChanged, value ?? noBorder);
UpdateBorder();
}
}
/// The platform provided shadow drawing for View
/// </summary>
[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);
{
return new Shadow() {
Offset = offset,
- Scale = scale,
+ Extents = extents,
Color = color,
BlurRadius = blurRadius
};
}
set
{
- color = value == null? null : new Color(OnColorChanged, value);
+ color = new Color(OnColorChanged, value ?? noColor);
UpdateColor();
}
}
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);
protected internal Vector2 offset;
/// <summary>
- /// The size value in scale
+ /// The size value in extension length
/// </summary>
- protected internal Vector2 scale;
+ protected internal Vector2 extents;
/// <summary>
/// The output property map
/// Constructor
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
- public ShadowBase() : this(noOffset, noScale)
+ public ShadowBase() : this(noOffset, noExtents)
{
}
/// Copy Constructor
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
- public ShadowBase(ShadowBase other) : this(other.offset, other.scale)
+ public ShadowBase(ShadowBase other) : this(other.offset, other.extents)
{
}
/// <summary>
/// Constructor
/// </summary>
- 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);
}
}
set
{
- offset = new Vector2(OnOffsetChanged, value ?? noOffset);
+ offset = new Vector2(OnOffsetOrSizeChanged, value ?? noOffset);
OnPropertyChanged?.Invoke(this);
}
}
/// 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>
[EditorBrowsable(EditorBrowsableState.Never)]
public Vector2 Scale
{
get
{
- return scale;
+ return new Vector2();
+ }
+ set
+ {
+ }
+ }
+
+ /// <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
+ {
+ 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();
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);
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);
}
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
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
{