*
*/
using System;
+using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.ComponentModel;
using Tizen.NUI.Binding;
/// An instance of ImageView can be created using a URL or an image instance.<br />
/// </summary>
/// <since_tizen> 3 </since_tizen>
- public class ImageView : View
+ public partial class ImageView : View
{
static ImageView() { }
- /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
- [EditorBrowsable(EditorBrowsableState.Never)]
- public static readonly BindableProperty ResourceUrlProperty = BindableProperty.Create(nameof(ImageView.ResourceUrl), typeof(string), typeof(ImageView), string.Empty, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- string url = (string)newValue;
- url = (url == null ? "" : url);
- if (imageView.IsCreateByXaml && url.Contains("*Resource*"))
- {
- string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
- url = url.Replace("*Resource*", resource);
- }
- imageView._resourceUrl = url;
- imageView.UpdateImage(ImageVisualProperty.URL, new PropertyValue(url));
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
- string ret = "";
-
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(imageView.swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap.Find(ImageVisualProperty.URL)?.Get(out ret);
- return ret;
- });
-
- /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
- [EditorBrowsable(EditorBrowsableState.Never)]
- public static readonly BindableProperty ImageProperty = BindableProperty.Create(nameof(ImageView.Image), typeof(PropertyMap), typeof(ImageView), null, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- if (newValue != null)
- {
- PropertyMap map = (PropertyMap)newValue;
- if (imageView.IsCreateByXaml)
- {
- string url = "", alphaMaskURL = "", auxiliaryImageURL = "";
- string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
- PropertyValue urlValue = map.Find(NDalic.ImageVisualUrl);
- bool ret = false;
- if (urlValue != null) ret = urlValue.Get(out url);
- PropertyMap mmap = new PropertyMap();
- if (ret && url.Contains("*Resource*"))
- {
- url = url.Replace("*Resource*", resource);
- mmap.Insert(NDalic.ImageVisualUrl, new PropertyValue(url));
- }
-
- ret = false;
- PropertyValue alphaMaskUrlValue = map.Find(NDalic.ImageVisualAlphaMaskUrl);
- if (alphaMaskUrlValue != null) ret = alphaMaskUrlValue.Get(out alphaMaskURL);
- if (ret && alphaMaskURL.Contains("*Resource*"))
- {
- alphaMaskURL = alphaMaskURL.Replace("*Resource*", resource);
- mmap.Insert(NDalic.ImageVisualUrl, new PropertyValue(alphaMaskURL));
- }
-
- ret = false;
- PropertyValue auxiliaryImageURLValue = map.Find(NDalic.ImageVisualAuxiliaryImageUrl);
- if (auxiliaryImageURLValue != null) ret = auxiliaryImageURLValue.Get(out auxiliaryImageURL);
- if (ret && auxiliaryImageURL.Contains("*Resource*"))
- {
- auxiliaryImageURL = auxiliaryImageURL.Replace("*Resource*", resource);
- mmap.Insert(NDalic.ImageVisualAuxiliaryImageUrl, new PropertyValue(auxiliaryImageURL));
- }
-
- map.Merge(mmap);
- }
- if (imageView._border == null)
- {
- Tizen.NUI.Object.SetProperty(imageView.swigCPtr, ImageView.Property.IMAGE, new Tizen.NUI.PropertyValue(map));
- }
- }
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
- if (imageView._border == null)
- {
- PropertyMap temp = new PropertyMap();
- Tizen.NUI.Object.GetProperty(imageView.swigCPtr, ImageView.Property.IMAGE).Get(temp);
- return temp;
- }
- else
- {
- return null;
- }
- });
-
- /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
- [EditorBrowsable(EditorBrowsableState.Never)]
- public static readonly BindableProperty PreMultipliedAlphaProperty = BindableProperty.Create(nameof(PreMultipliedAlpha), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- if (newValue != null)
- {
- Tizen.NUI.Object.SetProperty(imageView.swigCPtr, ImageView.Property.PreMultipliedAlpha, new Tizen.NUI.PropertyValue((bool)newValue));
- }
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
- bool temp = false;
- Tizen.NUI.Object.GetProperty(imageView.swigCPtr, ImageView.Property.PreMultipliedAlpha).Get(out temp);
- return temp;
- });
-
- /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
- [EditorBrowsable(EditorBrowsableState.Never)]
- public static readonly BindableProperty PixelAreaProperty = BindableProperty.Create(nameof(PixelArea), typeof(RelativeVector4), typeof(ImageView), null, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- if (newValue != null)
- {
- Tizen.NUI.Object.SetProperty(imageView.swigCPtr, ImageView.Property.PixelArea, new Tizen.NUI.PropertyValue((RelativeVector4)newValue));
- }
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
- Vector4 temp = new Vector4(0.0f, 0.0f, 0.0f, 0.0f);
- Tizen.NUI.Object.GetProperty(imageView.swigCPtr, ImageView.Property.PixelArea).Get(temp);
- RelativeVector4 relativeTemp = new RelativeVector4(temp.X, temp.Y, temp.Z, temp.W);
- return relativeTemp;
- });
-
- /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
- [EditorBrowsable(EditorBrowsableState.Never)]
- public static readonly BindableProperty BorderProperty = BindableProperty.Create(nameof(Border), typeof(Rectangle), typeof(ImageView), null, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- if (newValue != null)
- {
- imageView._border = new Rectangle((Rectangle)newValue);
- imageView.UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(imageView._border));
- }
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
- return imageView._border;
- });
-
- /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
- [EditorBrowsable(EditorBrowsableState.Never)]
- public static readonly BindableProperty BorderOnlyProperty = BindableProperty.Create(nameof(BorderOnly), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- if (newValue != null)
- {
- imageView.UpdateImage(NpatchImageVisualProperty.BorderOnly, new PropertyValue((bool)newValue));
- }
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
- bool ret = false;
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(imageView.swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap.Find(ImageVisualProperty.BorderOnly)?.Get(out ret);
- return ret;
- });
-
- /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
- [EditorBrowsable(EditorBrowsableState.Never)]
- public static readonly BindableProperty SynchronosLoadingProperty = BindableProperty.Create(nameof(SynchronosLoading), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- if (newValue != null)
- {
- imageView._synchronosLoading = (bool)newValue;
- imageView.UpdateImage(NpatchImageVisualProperty.SynchronousLoading, new PropertyValue((bool)newValue));
- }
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
- return imageView._synchronosLoading;
- });
-
- /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
- [EditorBrowsable(EditorBrowsableState.Never)]
- public static readonly BindableProperty OrientationCorrectionProperty = BindableProperty.Create(nameof(OrientationCorrection), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- if (newValue != null)
- {
- imageView.UpdateImage(ImageVisualProperty.OrientationCorrection, new PropertyValue((bool)newValue));
- }
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
-
- bool ret = false;
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(imageView.swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap?.Find(ImageVisualProperty.OrientationCorrection)?.Get(out ret);
-
- return ret;
- });
-
- internal static readonly BindableProperty ResourceUrlSelectorProperty = BindableProperty.Create("ResourceUrlSelector", typeof(Selector<string>), typeof(ImageView), null, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- imageView.resourceUrlSelector.Update(imageView, (Selector<string>)newValue, true);
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
- return imageView.resourceUrlSelector.Get(imageView);
- });
-
- internal static readonly BindableProperty BorderSelectorProperty = BindableProperty.Create("BorderSelector", typeof(Selector<Rectangle>), typeof(ImageView), null, propertyChanged: (bindable, oldValue, newValue) =>
- {
- var imageView = (ImageView)bindable;
- imageView.borderSelector.Update(imageView, (Selector<Rectangle>)newValue, true);
- },
- defaultValueCreator: (bindable) =>
- {
- var imageView = (ImageView)bindable;
- return imageView.borderSelector.Get(imageView);
- });
-
private EventHandler<ResourceReadyEventArgs> _resourceReadyEventHandler;
private ResourceReadyEventCallbackType _resourceReadyEventCallback;
private EventHandler<ResourceLoadedEventArgs> _resourceLoadedEventHandler;
private _resourceLoadedCallbackType _resourceLoadedCallback;
+ /// <summary>
+ /// Convert non-null string that some keyword change as application specific directory.
+ /// </summary>
+ /// <param name="value">Inputed and replaced after this function finished</param>
+ /// <returns>Replaced url</returns>
+ private static string ConvertResourceUrl(ref string value)
+ {
+ value ??= "";
+ if (value.StartsWith("*Resource*"))
+ {
+ string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
+ value = value.Replace("*Resource*", resource);
+ }
+ return value;
+ }
+
+ // Collection of image-sensitive properties.
+ private static readonly List<int> cachedImagePropertyKeyList = new List<int> {
+ Visual.Property.Type,
+ ImageVisualProperty.URL,
+ ImageVisualProperty.AlphaMaskURL,
+ ImageVisualProperty.CropToMask,
+ Visual.Property.VisualFittingMode,
+ ImageVisualProperty.DesiredWidth,
+ ImageVisualProperty.DesiredHeight,
+ ImageVisualProperty.ReleasePolicy,
+ ImageVisualProperty.WrapModeU,
+ ImageVisualProperty.WrapModeV,
+ ImageVisualProperty.SynchronousLoading,
+ Visual.Property.PremultipliedAlpha,
+ ImageVisualProperty.OrientationCorrection,
+ ImageVisualProperty.FastTrackUploading,
+ NpatchImageVisualProperty.Border,
+ NpatchImageVisualProperty.BorderOnly,
+ };
+ internal PropertyMap cachedImagePropertyMap;
+ internal bool imagePropertyUpdatedFlag = false;
+
+ private bool imagePropertyUpdateProcessAttachedFlag = false;
private Rectangle _border;
private string _resourceUrl = "";
- private bool _synchronosLoading = false;
- private string _alphaMaskUrl = null;
private int _desired_width = -1;
private int _desired_height = -1;
- private readonly TriggerableSelector<string> resourceUrlSelector = new TriggerableSelector<string>(ResourceUrlProperty);
- private readonly TriggerableSelector<Rectangle> borderSelector = new TriggerableSelector<Rectangle>(BorderProperty);
+ private bool _fastTrackUploading = false;
+ private TriggerableSelector<string> resourceUrlSelector;
+ private TriggerableSelector<Rectangle> borderSelector;
- /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
- [EditorBrowsable(EditorBrowsableState.Never)]
- public ImageViewStyle Style => new ImageViewStyle(this);
+ private RelativeVector4 internalPixelArea;
/// <summary>
/// Creates an initialized ImageView.
/// </summary>
/// <param name="url">The URL of the image resource to display.</param>
/// <since_tizen> 3 </since_tizen>
- public ImageView(string url) : this(Interop.ImageView.New(url), true)
+ public ImageView(string url) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
{
- ResourceUrl = url;
+ _resourceUrl = url;
+
+ // Update cached property. Note that we should not re-create new visual.
+ using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
+ {
+ UpdateImage(ImageVisualProperty.URL, urlValue, false);
+ }
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
/// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
/// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
[EditorBrowsable(EditorBrowsableState.Never)]
- public ImageView(string url, bool shown) : this(Interop.ImageView.New(url), true)
+ public ImageView(string url, bool shown) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
{
- ResourceUrl = url;
+ _resourceUrl = url;
+
+ // Update cached property. Note that we should not re-create new visual.
+ using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
+ {
+ UpdateImage(ImageVisualProperty.URL, urlValue, false);
+ }
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
SetVisible(shown);
}
- internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(url, Uint16Pair.getCPtr(size)), true)
+ internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size)), true)
{
- ResourceUrl = url;
+ _resourceUrl = url;
+ _desired_width = size?.GetWidth() ?? -1;
+ _desired_height = size?.GetHeight() ?? -1;
+
+ // Update cached property. Note that we should not re-create new visual.
+ using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
+ {
+ UpdateImage(ImageVisualProperty.URL, urlValue, false);
+ }
+ using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
+ {
+ UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
+ }
+ using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
+ {
+ UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
+ }
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
if (!shown)
}
}
- internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(Interop.ImageView.Upcast(cPtr), cMemoryOwn, viewStyle)
+ internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
{
if (!shown)
{
}
}
- internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(Interop.ImageView.Upcast(cPtr), cMemoryOwn, null)
+ internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
{
if (!shown)
{
if (_resourceReadyEventHandler == null)
{
_resourceReadyEventCallback = OnResourceReady;
- ResourceReadySignal(this).Connect(_resourceReadyEventCallback);
+ ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
+ resourceReadySignal?.Connect(_resourceReadyEventCallback);
+ resourceReadySignal?.Dispose();
}
_resourceReadyEventHandler += value;
{
_resourceReadyEventHandler -= value;
- if (_resourceReadyEventHandler == null && ResourceReadySignal(this).Empty() == false)
+ ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
+ if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
{
- ResourceReadySignal(this).Disconnect(_resourceReadyEventCallback);
+ resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
}
+ resourceReadySignal?.Dispose();
}
}
if (_resourceLoadedEventHandler == null)
{
_resourceLoadedCallback = OnResourceLoaded;
- this.ResourceReadySignal(this).Connect(_resourceLoadedCallback);
+ ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
+ resourceReadySignal?.Connect(_resourceLoadedCallback);
+ resourceReadySignal?.Dispose();
}
_resourceLoadedEventHandler += value;
remove
{
_resourceLoadedEventHandler -= value;
-
- if (_resourceLoadedEventHandler == null && this.ResourceReadySignal(this).Empty() == false)
+ ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
+ if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
{
- this.ResourceReadySignal(this).Disconnect(_resourceLoadedCallback);
+ resourceReadySignal?.Disconnect(_resourceLoadedCallback);
}
+ resourceReadySignal?.Dispose();
}
}
}
/// <summary>
+ /// Enumeration for MaskingMode of image.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public enum MaskingModeType
+ {
+ /// <summary>
+ /// Applies alpha masking on rendering time.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ MaskingOnRendering,
+ /// <summary>
+ /// Applies alpha masking on loading time.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ MaskingOnLoading
+ }
+
+ /// <summary>
/// ImageView ResourceUrl, type string.
/// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
/// When it is set as null, it gives empty string ("") to be read.
set
{
SetValue(ResourceUrlProperty, value);
- resourceUrlSelector.UpdateIfNeeds(this, value);
NotifyPropertyChanged();
}
}
/// <summary>
- /// This will be deprecated, please use Image instead. <br />
+ /// This will be deprecated, Use Image instead. <br />
/// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
/// </summary>
/// <since_tizen> 3 </since_tizen>
- [Obsolete("Please do not use! This will be deprecated! Please use Image property instead!")]
+ [Obsolete("Do not use this, that will be deprecated. Use Image property instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public PropertyMap ImageMap
{
get
{
+ return GetValue(ImageMapProperty) as PropertyMap;
+ }
+ set
+ {
+ SetValue(ImageMapProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+ private PropertyMap InternalImageMap
+ {
+ get
+ {
if (_border == null)
{
- PropertyMap temp = new PropertyMap();
- GetProperty(ImageView.Property.IMAGE).Get(temp);
- return temp;
+ // Sync as current properties
+ UpdateImage();
+
+ // Get current properties force.
+ PropertyMap returnValue = new PropertyMap();
+ PropertyValue image = GetProperty(ImageView.Property.IMAGE);
+ image?.Get(returnValue);
+ image?.Dispose();
+
+ // Update cached property map
+ if (returnValue != null)
+ {
+ MergeCachedImageVisualProperty(returnValue);
+ }
+ return returnValue;
}
else
{
{
if (_border == null)
{
- SetProperty(ImageView.Property.IMAGE, new Tizen.NUI.PropertyValue(value));
+ PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
+ SetProperty(ImageView.Property.IMAGE, setValue);
+
+ // Image properties are changed hardly. We should ignore lazy UpdateImage
+ imagePropertyUpdatedFlag = false;
+ cachedImagePropertyMap?.Dispose();
+ cachedImagePropertyMap = null;
+ MergeCachedImageVisualProperty(value);
+
NotifyPropertyChanged();
+ setValue?.Dispose();
}
}
}
/// <summary>
- /// ImageView Image, type PropertyMap
+ /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
/// </summary>
+ /// <remarks>
+ /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
+ /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
+ /// you can also use <see cref="Visual.Property"/>. <br />
+ /// See <see cref="Visual.Property"/> for a detailed description. <br />
+ /// </remarks>
+ /// <example>
+ /// The following example demonstrates how to use the Image property.
+ /// <code>
+ /// PropertyMap map = new PropertyMap();
+ /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
+ /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
+ /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
+ /// imageview.Image = map;
+ /// </code>
+ /// </example>
/// <since_tizen> 4 </since_tizen>
public PropertyMap Image
{
{
get
{
- RelativeVector4 temp = (RelativeVector4)GetValue(PixelAreaProperty);
- return new RelativeVector4(OnPixelAreaChanged, temp.X, temp.Y, temp.Z, temp.W);
+ return (RelativeVector4)GetValue(PixelAreaProperty);
}
set
{
set
{
SetValue(BorderProperty, value);
- borderSelector.UpdateIfNeeds(this, value);
NotifyPropertyChanged();
}
}
}
/// <summary>
- /// Gets or sets whether to synchronos loading the resourceurl of image.<br />
+ /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
/// </summary>
/// <since_tizen> 3 </since_tizen>
+ [Obsolete("This has been deprecated since API9 and will be removed in API11. Use SynchronousLoading instead.")]
public bool SynchronosLoading
{
get
{
- return (bool)GetValue(SynchronosLoadingProperty);
+ return SynchronousLoading;
}
set
{
- SetValue(SynchronosLoadingProperty, value);
+ SynchronousLoading = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
+ /// </summary>
+ /// <remarks>
+ /// Changing this property make this ImageView load image synchronously at the next loading
+ /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
+ /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
+ /// </remarks>
+ /// <since_tizen> 9 </since_tizen>
+ public bool SynchronousLoading
+ {
+ get
+ {
+ return (bool)GetValue(SynchronousLoadingProperty);
+ }
+ set
+ {
+ SetValue(SynchronousLoadingProperty, value);
NotifyPropertyChanged();
}
}
}
/// <summary>
+ /// Gets or sets whether to apply mask on GPU or not.<br />
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public MaskingModeType MaskingMode
+ {
+ get
+ {
+ return (MaskingModeType)GetValue(MaskingModeProperty);
+ }
+ set
+ {
+ SetValue(MaskingModeProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+
+ private MaskingModeType InternalMaskingMode
+ {
+ get
+ {
+ int ret = (int)MaskingModeType.MaskingOnLoading;
+
+ PropertyValue maskingMode = GetCachedImageVisualProperty(ImageVisualProperty.MaskingMode);
+ maskingMode?.Get(out ret);
+ maskingMode?.Dispose();
+
+ return (MaskingModeType)ret;
+ }
+ set
+ {
+ MaskingModeType ret = value;
+ PropertyValue setValue = new PropertyValue((int)ret);
+ UpdateImage(ImageVisualProperty.MaskingMode, setValue);
+ setValue?.Dispose();
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether to apply fast track uploading or not.<br />
+ /// </summary>
+ /// <remarks>
+ /// If we use fast track uploading feature, It can upload texture without event-thead dependency. But also,<br />
+ /// - Texture size is invalid until ResourceReady signal comes.<br />
+ /// - Texture cannot be cached (We always try to load new image).<br />
+ /// - Seamless visual change didn't supported.<br />
+ /// - Alpha masking didn't supported. If you try, It will load as normal case.<br />
+ /// - Synchronous loading didn't supported. If you try, It will load as normal case.<br />
+ /// - Reload action didn't supported. If you try, It will load as normal case.<br />
+ /// - Atlas loading didn't supported. If you try, It will load as normal case.<br />
+ /// - Custom shader didn't supported. If you try, It will load as normal case.
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool FastTrackUploading
+ {
+ get
+ {
+ return (bool)GetValue(FastTrackUploadingProperty);
+ }
+ set
+ {
+ SetValue(FastTrackUploadingProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+
+ private bool InternalFastTrackUploading
+ {
+ get
+ {
+ PropertyValue fastTrackUploading = GetCachedImageVisualProperty(ImageVisualProperty.FastTrackUploading);
+ fastTrackUploading?.Get(out _fastTrackUploading);
+ fastTrackUploading?.Dispose();
+
+ return _fastTrackUploading;
+ }
+ set
+ {
+ if (_fastTrackUploading != value)
+ {
+ _fastTrackUploading = value;
+
+ PropertyValue setValue = new PropertyValue(_fastTrackUploading);
+ UpdateImage(ImageVisualProperty.FastTrackUploading, setValue);
+ setValue?.Dispose();
+
+ if (_fastTrackUploading && !string.IsNullOrEmpty(_resourceUrl))
+ {
+ // Special case. If user set FastTrackUploading mean, user want to upload image As-Soon-As-Possible.
+ // Create ImageVisual synchronously.
+ UpdateImage();
+ }
+ }
+ }
+ }
+
+ /// <summary>
/// Gets the loading state of the visual resource.
/// </summary>
/// <since_tizen> 5 </since_tizen>
{
get
{
- return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(swigCPtr, (int)Property.IMAGE);
+ return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
}
}
/// Downcasts a handle to imageView handle.
/// </summary>
/// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
- /// Please do not use! this will be deprecated!
- /// Instead please use as keyword.
+ /// Do not use this, that will be deprecated. Use as keyword instead.
/// <since_tizen> 3 </since_tizen>
- [Obsolete("Please do not use! This will be deprecated! Please use as keyword instead! " +
+ [Obsolete("Do not use this, that will be deprecated. Use as keyword instead. " +
"Like: " +
"BaseHandle handle = new ImageView(imagePath); " +
"ImageView image = handle as ImageView")]
if (url.Contains(".json"))
{
- Tizen.Log.Fatal("NUI", "[ERROR] Please DO NOT set lottie file in ImageView! This is temporary checking, will be removed soon!");
+ Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
return;
}
- Interop.ImageView.SetImage(swigCPtr, url);
+ Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
- ResourceUrl = url;
+ _resourceUrl = url;
+ // Update cached property. Note that we should not re-create new visual.
+ using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
+ {
+ UpdateImage(ImageVisualProperty.URL, urlValue, false);
+ }
+ imagePropertyUpdatedFlag = false;
}
/// <summary>
/// <since_tizen> 3 </since_tizen>
public new bool IsResourceReady()
{
- bool ret = Interop.View.IsResourceReady(swigCPtr);
+ bool ret = Interop.View.IsResourceReady(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending)
throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
/// <since_tizen> 5 </since_tizen>
public void Reload()
{
- this.DoAction(ImageView.Property.IMAGE, Property.ActionReload, new PropertyValue(0));
+ // Sync as current properties
+ UpdateImage();
+
+
+ Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionReload);
}
/// <summary>
/// <since_tizen> 5 </since_tizen>
public void Play()
{
- this.DoAction(ImageView.Property.IMAGE, Property.ActionPlay, new PropertyValue(0));
+ // Sync as current properties
+ UpdateImage();
+
+
+ Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPlay);
}
/// <summary>
/// <since_tizen> 5 </since_tizen>
public void Pause()
{
- this.DoAction(ImageView.Property.IMAGE, Property.ActionPause, new PropertyValue(0));
+ // Sync as current properties
+ UpdateImage();
+
+
+ Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPause);
}
/// <summary>
/// <since_tizen> 5 </since_tizen>
public void Stop()
{
- this.DoAction(ImageView.Property.IMAGE, Property.ActionStop, new PropertyValue(0));
+ // Sync as current properties
+ UpdateImage();
+
+
+
+ Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionStop);
}
/// <summary>
{
get
{
+ return GetValue(AlphaMaskURLProperty) as string;
+ }
+ set
+ {
+ SetValue(AlphaMaskURLProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+
+ private string InternalAlphaMaskURL
+ {
+ get
+ {
string ret = "";
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap?.Find(ImageVisualProperty.AlphaMaskURL)?.Get(out ret);
- _alphaMaskUrl = ret;
+ PropertyValue maskUrl = GetCachedImageVisualProperty(ImageVisualProperty.AlphaMaskURL);
+ maskUrl?.Get(out ret);
+ maskUrl?.Dispose();
+
return ret;
}
set
{
- if (value == null)
+ PropertyValue setValue = new PropertyValue(value ?? "");
+ UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
+ // When we never set CropToMask property before, we should set default value as true.
+ using (PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask))
{
- value = "";
+ if (cropToMask == null)
+ {
+ using PropertyValue setCropValue = new PropertyValue(true);
+ UpdateImage(ImageVisualProperty.CropToMask, setCropValue);
+ }
}
-
- _alphaMaskUrl = value;
- UpdateImage(ImageVisualProperty.AlphaMaskURL, new PropertyValue(value));
+ setValue?.Dispose();
}
}
{
get
{
+ return (bool)GetValue(CropToMaskProperty);
+ }
+ set
+ {
+ SetValue(CropToMaskProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+ private bool InternalCropToMask
+ {
+ get
+ {
bool ret = false;
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap?.Find(ImageVisualProperty.CropToMask)?.Get(out ret);
+
+ PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask);
+ cropToMask?.Get(out ret);
+ cropToMask?.Dispose();
return ret;
}
set
{
- UpdateImage(ImageVisualProperty.CropToMask, new PropertyValue(value));
+ PropertyValue setValue = new PropertyValue(value);
+ UpdateImage(ImageVisualProperty.CropToMask, setValue);
+ setValue?.Dispose();
}
}
- internal VisualFittingModeType CovertFittingModetoVisualFittingMode(FittingModeType value)
+ /// <summary>
+ /// Actions property value for Reload image.
+ /// </summary>
+ internal static readonly int ActionReload = Interop.ImageView.ImageVisualActionReloadGet();
+
+ /// <summary>
+ /// Actions property value to Play animated images.
+ /// </summary>
+ internal static readonly int ActionPlay = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
+
+ /// <summary>
+ /// Actions property value to Pause animated images.
+ /// </summary>
+ internal static readonly int ActionPause = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
+
+ /// <summary>
+ /// Actions property value to Stop animated images.
+ /// </summary>
+ internal static readonly int ActionStop = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
+
+ internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
{
switch (value)
{
case FittingModeType.FitHeight:
return VisualFittingModeType.FitHeight;
case FittingModeType.FitWidth:
- return VisualFittingModeType.FitHeight;
+ return VisualFittingModeType.FitWidth;
default:
return VisualFittingModeType.Fill;
}
}
}
+ internal override LayoutItem CreateDefaultLayout()
+ {
+ return new ImageLayout();
+ }
+
/// <summary>
/// Gets or sets fitting options used when resizing images to fit.<br />
/// If not supplied, the default is FittingModeType.Fill.<br />
{
get
{
- int ret = (int)VisualFittingModeType.Fill;
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap?.Find(Visual.Property.VisualFittingMode)?.Get(out ret);
- return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
+ return (FittingModeType)GetValue(FittingModeProperty);
}
set
{
- VisualFittingModeType ret = CovertFittingModetoVisualFittingMode(value);
- UpdateImage(Visual.Property.VisualFittingMode, new PropertyValue((int)ret));
+ SetValue(FittingModeProperty, value);
+ NotifyPropertyChanged();
}
}
+ private FittingModeType InternalFittingMode
+ {
+ get
+ {
+ int ret = (int)VisualFittingModeType.Fill;
+ PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
+ fittingMode?.Get(out ret);
+ fittingMode?.Dispose();
- /// <summary>
- /// Gets or sets the desired image width.<br />
+ return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
+ }
+ set
+ {
+ VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
+ PropertyValue setValue = new PropertyValue((int)ret);
+ UpdateImage(Visual.Property.VisualFittingMode, setValue);
+ setValue?.Dispose();
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the desired image width.<br />
/// If not specified, the actual image width is used.<br />
/// For normal quad images only.<br />
/// Optional.
{
get
{
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap?.Find(ImageVisualProperty.DesiredWidth)?.Get(out _desired_width);
+ return (int)GetValue(DesiredWidthProperty);
+ }
+ set
+ {
+ SetValue(DesiredWidthProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+ private int InternalDesiredWidth
+ {
+ get
+ {
+ // Sync as current properties only if both _desired_width and _desired_height are setuped.
+ if (_desired_width != -1 && _desired_height != -1)
+ {
+ UpdateImage();
+ }
+ PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
+ desirewidth?.Get(out _desired_width);
+ desirewidth?.Dispose();
return _desired_width;
}
if (_desired_width != value)
{
_desired_width = value;
- UpdateImage(0, null);
+ PropertyValue setValue = new PropertyValue(value);
+ UpdateImage(ImageVisualProperty.DesiredWidth, setValue, false);
+ setValue?.Dispose();
}
}
}
{
get
{
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap?.Find(ImageVisualProperty.DesiredHeight)?.Get(out _desired_height);
+ return (int)GetValue(DesiredHeightProperty);
+ }
+ set
+ {
+ SetValue(DesiredHeightProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+ private int InternalDesiredHeight
+ {
+ get
+ {
+ // Sync as current properties only if both _desired_width and _desired_height are setuped.
+ if (_desired_width != -1 && _desired_height != -1)
+ {
+ UpdateImage();
+ }
+ PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
+ desireheight?.Get(out _desired_height);
+ desireheight?.Dispose();
return _desired_height;
}
if (_desired_height != value)
{
_desired_height = value;
- UpdateImage(0, null);
+ PropertyValue setValue = new PropertyValue(value);
+ UpdateImage(ImageVisualProperty.DesiredHeight, setValue, false);
+ setValue?.Dispose();
}
}
}
{
get
{
+ return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
+ }
+ set
+ {
+ SetValue(ReleasePolicyProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+
+ private ReleasePolicyType InternalReleasePolicy
+ {
+ get
+ {
int ret = (int)ReleasePolicyType.Detached;
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap?.Find(ImageVisualProperty.ReleasePolicy)?.Get(out ret);
+
+ PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
+ releasePoli?.Get(out ret);
+ releasePoli?.Dispose();
+
return (ReleasePolicyType)ret;
}
set
{
- UpdateImage(ImageVisualProperty.ReleasePolicy, new PropertyValue((int)value));
+ PropertyValue setValue = new PropertyValue((int)value);
+ UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
+ setValue?.Dispose();
}
}
{
get
{
+ return (WrapModeType)GetValue(WrapModeUProperty);
+ }
+ set
+ {
+ SetValue(WrapModeUProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+
+ private WrapModeType InternalWrapModeU
+ {
+ get
+ {
int ret = (int)WrapModeType.Default;
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap?.Find(ImageVisualProperty.WrapModeU)?.Get(out ret);
+
+ PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
+ wrapModeU?.Get(out ret);
+ wrapModeU?.Dispose();
return (WrapModeType)ret;
}
set
{
- UpdateImage(ImageVisualProperty.WrapModeU, new PropertyValue((int)value));
+ PropertyValue setValue = new PropertyValue((int)value);
+ UpdateImage(ImageVisualProperty.WrapModeU, setValue);
+ setValue?.Dispose();
}
}
{
get
{
+ return (WrapModeType)GetValue(WrapModeVProperty);
+ }
+ set
+ {
+ SetValue(WrapModeVProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+
+ private WrapModeType InternalWrapModeV
+ {
+ get
+ {
int ret = (int)WrapModeType.Default;
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap?.Find(ImageVisualProperty.WrapModeV)?.Get(out ret);
+
+ PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
+ wrapModeV?.Get(out ret);
+ wrapModeV?.Dispose();
return (WrapModeType)ret;
}
set
{
- UpdateImage(ImageVisualProperty.WrapModeV, new PropertyValue((int)value));
+ PropertyValue setValue = new PropertyValue((int)value);
+ UpdateImage(ImageVisualProperty.WrapModeV, setValue);
+ setValue?.Dispose();
}
}
/// <summary>
- /// Get attribues, it is abstract function and must be override.
+ /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
/// </summary>
- /// <since_tizen> 6 </since_tizen>
- /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
+ /// <remarks>
+ /// This is false by default.
+ /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
+ /// to preserve the aspect ratio of the image resource.
+ /// AdjustViewSize works only if ImageView is added to a View having Layout.
+ /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
+ /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
+ /// </remarks>
+ /// <since_tizen> 9 </since_tizen>
+ public bool AdjustViewSize
+ {
+ get
+ {
+ return (bool)GetValue(AdjustViewSizeProperty);
+ }
+ set
+ {
+ SetValue(AdjustViewSizeProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+ private bool adjustViewSize = false;
+
+ /// <summary>
+ /// ImageView PlaceHolderUrl, type string.
+ /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
+ /// When it is set as null, it gives empty string ("") to be read.
+ /// </summary>
+ /// <since_tizen> 11 </since_tizen>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public string PlaceHolderUrl
+ {
+ get
+ {
+ return (string)GetValue(PlaceHolderUrlProperty);
+ }
+ set
+ {
+ SetValue(PlaceHolderUrlProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether the image use TransitionEffect or not<br />
+ /// </summary>
+ /// <since_tizen> 11 </since_tizen>
[EditorBrowsable(EditorBrowsableState.Never)]
- protected override ViewStyle GetViewStyle()
+ public bool TransitionEffect
+ {
+ get
+ {
+ return (bool)GetValue(TransitionEffectProperty);
+ }
+ set
+ {
+ SetValue(TransitionEffectProperty, value);
+ NotifyPropertyChanged();
+ }
+ }
+
+ internal Selector<string> ResourceUrlSelector
+ {
+ get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
+ set
+ {
+ resourceUrlSelector?.Reset(this);
+ if (value == null) return;
+
+ if (value.HasAll()) SetResourceUrl(value.All);
+ else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
+ }
+ }
+
+ /// <summary>
+ /// Get attributes, it is abstract function and must be override.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override ViewStyle CreateViewStyle()
{
return new ImageViewStyle();
}
{
if (url.Contains(".json"))
{
- Tizen.Log.Fatal("NUI", "[ERROR] Please DO NOT set lottie file in ImageView! This is temporary checking, will be removed soon!");
+ Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
return;
}
- Interop.ImageView.SetImage(swigCPtr, url, Uint16Pair.getCPtr(size));
+ Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
- ResourceUrl = url;
+ _resourceUrl = url;
+ _desired_width = size?.GetWidth() ?? -1;
+ _desired_height = size?.GetHeight() ?? -1;
+
+ // Update cached property. Note that we should not re-create new visual.
+ using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
+ {
+ UpdateImage(ImageVisualProperty.URL, urlValue, false);
+ }
+ using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
+ {
+ UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
+ }
+ using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
+ {
+ UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
+ }
+ imagePropertyUpdatedFlag = false;
}
internal ViewResourceReadySignal ResourceReadySignal(View view)
{
base.ApplyCornerRadius();
- UpdateImage(0, null);
+ if (backgroundExtraData == null) return;
+
+
+ // Update corner radius properties to image by ActionUpdateProperty
+ if (backgroundExtraData.CornerRadius != null)
+ {
+ Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
+ }
+ Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
+ }
+
+ internal override void ApplyBorderline()
+ {
+ base.ApplyBorderline();
+
+ if (backgroundExtraData == null) return;
+
+
+ // Update borderline properties to image by ActionUpdateProperty
+ Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
+ Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
+ Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
}
internal ResourceLoadingStatusType GetResourceStatus()
{
- return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.swigCPtr, Property.IMAGE);
+ return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
}
/// <summary>
return;
}
+ internalPixelArea?.Dispose();
+
if (type == DisposeTypes.Explicit)
{
//Called by User
//You should release all of your own disposable objects here.
_border?.Dispose();
_border = null;
- borderSelector.Reset(this);
- resourceUrlSelector.Reset(this);
+ borderSelector?.Reset(this);
+ resourceUrlSelector?.Reset(this);
+ imagePropertyUpdatedFlag = false;
+ if (imagePropertyUpdateProcessAttachedFlag)
+ {
+ ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
+ imagePropertyUpdateProcessAttachedFlag = false;
+ }
+ cachedImagePropertyMap?.Dispose();
+ cachedImagePropertyMap = null;
}
base.Dispose(type);
// Callback for View ResourceReady signal
private void OnResourceReady(IntPtr data)
{
+ if (!CheckResourceReady())
+ {
+ return;
+ }
+
ResourceReadyEventArgs e = new ResourceReadyEventArgs();
if (data != null)
{
}
}
- private void UpdateImageMap(PropertyMap fromMap)
+ private void SetResourceUrl(string value)
{
- PropertyMap imageMap = new PropertyMap();
- Tizen.NUI.Object.GetProperty(swigCPtr, ImageView.Property.IMAGE).Get(imageMap);
- imageMap.Merge(fromMap);
-
- SetProperty(ImageView.Property.IMAGE, new PropertyValue(imageMap));
+ if (_resourceUrl != ConvertResourceUrl(ref value))
+ {
+ _resourceUrl = value;
+ if (string.IsNullOrEmpty(_resourceUrl))
+ {
+ // Special case. If we set ResourceUrl as empty, Unregist visual.
+ RemoveImage();
+ }
+ else
+ {
+ using (PropertyValue setValue = new PropertyValue(value))
+ {
+ UpdateImage(ImageVisualProperty.URL, setValue);
+ }
+ // Special case. If we set GeneratedUrl, or FastTrackUploading, Create ImageVisual synchronously.
+ if (value.StartsWith("dali://") || value.StartsWith("enbuf://") || _fastTrackUploading)
+ {
+ UpdateImage();
+ }
+ }
+ }
}
- private void UpdateImage(int key, PropertyValue value)
+ private void SetBorder(Rectangle value)
{
- PropertyMap temp = new PropertyMap();
-
- if (_alphaMaskUrl != null)
+ if (value == null)
+ {
+ return;
+ }
+ if (_border != value)
{
- temp.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(_alphaMaskUrl));
+ _border = new Rectangle(value);
+ UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
}
+ }
- if (_resourceUrl == "")
+ /// <summary>
+ /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
+ /// </summary>
+ private void RemoveImage()
+ {
+ // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
+ // Unregist and detach process only if previous resourceUrl was not empty
+ string currentResourceUrl = "";
+ PropertyValue currentResourceUrlValue = GetCachedImageVisualProperty(ImageVisualProperty.URL);
+ if ((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
{
- temp.Insert(ImageVisualProperty.URL, new PropertyValue(_resourceUrl));
- SetProperty(ImageView.Property.IMAGE, new PropertyValue(temp));
- return;
+ PropertyValue emptyValue = new PropertyValue();
+
+ // Remove current registed Image.
+ SetProperty(ImageView.Property.IMAGE, emptyValue);
+
+ // Image visual is not exist anymore. We should ignore lazy UpdateImage
+ imagePropertyUpdatedFlag = false;
+ if (imagePropertyUpdateProcessAttachedFlag)
+ {
+ ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
+ imagePropertyUpdateProcessAttachedFlag = false;
+ }
+ // Update resourceUrl as empty value
+ cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
+
+ emptyValue?.Dispose();
}
+ currentResourceUrlValue?.Dispose();
+ }
- if (_border == null)
+ /// <summary>
+ /// Lazy call to UpdateImage.
+ /// Collect Properties need to be update, and set properties that starts the Processing.
+ ///
+ /// If you want to update cachedImagePropertyMap, but don't want to request new visual creation, make requiredVisualCreation value as false.
+ /// (Example : if we change SynchronousLoading property from 'true' to 'false', or if we call this function during UpdateImage)
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual void UpdateImage(int key, PropertyValue value, bool requiredVisualCreation = true)
+ {
+ // Update image property map value as inputed value.
+ if (key != 0)
{
- temp.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
+ if (!HasBody())
+ {
+ // Throw exception if ImageView is disposed.
+ throw new global::System.InvalidOperationException("[NUI][ImageVIew] Someone try to change disposed ImageView's property.\n");
+ }
+
+ if (cachedImagePropertyMap == null)
+ {
+ cachedImagePropertyMap = new PropertyMap();
+ }
+
+ // To optimization, we don't check URL duplicate case. We already checked before.
+ if (key != ImageVisualProperty.URL)
+ {
+ using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
+ {
+ if (oldValue != null && oldValue.EqualTo(value))
+ {
+ // Ignore UpdateImage query when we try to update equality value.
+ return;
+ }
+ }
+ }
+ imagePropertyUpdatedFlag = true;
+ cachedImagePropertyMap[key] = value;
+
+ // Lazy update only if visual creation required, and _resourceUrl is not empty, and ProcessAttachedFlag is false.
+ if (requiredVisualCreation && !string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
+ {
+ imagePropertyUpdateProcessAttachedFlag = true;
+ ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
+ // Call process hardly.
+ ProcessorController.Instance.Awake();
+ }
}
- else
+ }
+
+ /// <summary>
+ /// Callback function to Lazy UpdateImage.
+ /// </summary>
+ private void UpdateImage(object source, EventArgs e)
+ {
+ // Note : To allow event attachment during UpdateImage, let we make flag as false before call UpdateImage().
+ imagePropertyUpdateProcessAttachedFlag = false;
+ UpdateImage();
+ }
+
+ /// <summary>
+ /// Update image-relative properties synchronously.
+ /// After call this API, All image properties updated.
+ /// </summary>
+ /// <remarks>
+ /// Current version ImageView property update asynchronously.
+ /// If you want to guarantee that ImageView property setuped,
+ /// Please call this ImageView.UpdateImage() API.
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual void UpdateImage()
+ {
+ if (!imagePropertyUpdatedFlag) return;
+
+ imagePropertyUpdatedFlag = false;
+
+ if (cachedImagePropertyMap == null)
{
- temp.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.NPatch));
- temp.Insert(NpatchImageVisualProperty.Border, new PropertyValue(_border));
+ cachedImagePropertyMap = new PropertyMap();
}
- temp.Insert(NpatchImageVisualProperty.SynchronousLoading, new PropertyValue(_synchronosLoading));
+ // Checkup the cached visual type is AnimatedImage.
+ // It is trick to know that this code is running on AnimatedImageView.UpdateImage() with resourceURLs or not.
+ int visualType = (int)Visual.Type.Invalid;
+ if (!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage)))
+ {
+ // If ResourceUrl is not setuped, don't set property. fast return.
+ if (string.IsNullOrEmpty(_resourceUrl))
+ {
+ return;
+ }
+ if (_border == null)
+ {
+ PropertyValue image = new PropertyValue((int)Visual.Type.Image);
+ cachedImagePropertyMap[Visual.Property.Type] = image;
+ image?.Dispose();
+ }
+ else
+ {
+ PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
+ cachedImagePropertyMap[Visual.Property.Type] = nPatch;
+ nPatch?.Dispose();
+ PropertyValue border = new PropertyValue(_border);
+ cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
+ border?.Dispose();
+ }
+ }
- if (backgroundExtraData != null && backgroundExtraData.CornerRadius > 0)
+ if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
{
- temp.Insert(Visual.Property.CornerRadius, new PropertyValue(backgroundExtraData.CornerRadius));
+ using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
+ using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
+ {
+ cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
+ cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
+ }
}
- if (value != null)
+ if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
{
- temp.Insert(key, value);
+ using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
+ using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
+ using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
+ {
+ cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
+ cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
+ cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
+ }
}
// Do Fitting Buffer when desired dimension is set
+ // TODO : Couldn't we do this job in dali-engine side.
if (_desired_width != -1 && _desired_height != -1)
{
if (_resourceUrl != null)
{
- Size2D imageSize = ImageLoading.GetOriginalImageSize(_resourceUrl);
-
- int adjustedDesiredWidth, adjustedDesiredHeight;
- float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
- float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
- if( aspectOfImageSize > aspectOfDesiredSize)
+ Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
+ if (imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0)
{
- adjustedDesiredWidth = _desired_width;
- adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
+ int adjustedDesiredWidth, adjustedDesiredHeight;
+ float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
+ float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
+ if (aspectOfImageSize > aspectOfDesiredSize)
+ {
+ adjustedDesiredWidth = _desired_width;
+ adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
+ }
+ else
+ {
+ adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
+ adjustedDesiredHeight = _desired_height;
+ }
+
+ PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
+ cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
+ returnWidth?.Dispose();
+ PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
+ cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
+ returnHeight?.Dispose();
+ PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
+ cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
+ scaleToFit?.Dispose();
}
- else
+ imageSize?.Dispose();
+ }
+ }
+
+ UpdateImageMap();
+ }
+
+ /// <summary>
+ /// Merge our collected properties, and set IMAGE property internally.
+ /// </summary>
+ private void UpdateImageMap()
+ {
+ // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
+ using (PropertyMap imageMap = new PropertyMap())
+ {
+ using (PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
+ {
+ returnValue?.Get(imageMap);
+ }
+ if (cachedImagePropertyMap != null)
+ {
+ imageMap?.Merge(cachedImagePropertyMap);
+ }
+ using (PropertyValue setValue = new PropertyValue(imageMap))
+ {
+ SetProperty(ImageView.Property.IMAGE, setValue);
+ }
+
+ // Update cached image property.
+ MergeCachedImageVisualProperty(imageMap);
+ }
+ }
+
+ /// <summary>
+ /// Get image visual property by key.
+ /// If we found value in local Cached result, return that.
+ /// Else, get synced native map and return that.
+ /// If there is no matched value, return null.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual PropertyValue GetImageVisualProperty(int key)
+ {
+ PropertyValue ret = GetCachedImageVisualProperty(key);
+ if (ret == null)
+ {
+ // If we cannot find result form cached map, Get value from native engine.
+ ret = Image?.Find(key);
+ }
+ return ret;
+ }
+
+ /// <summary>
+ /// Get image visual property from NUI cached image map by key.
+ /// If there is no matched value, return null.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual PropertyValue GetCachedImageVisualProperty(int key)
+ {
+ return cachedImagePropertyMap?.Find(key);
+ }
+
+ /// <summary>
+ /// Update NUI cached image visual property map by inputed property map.
+ /// </summary>
+ /// <remarks>
+ /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
+ /// </remarks>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
+ {
+ if (map == null) return;
+ if (cachedImagePropertyMap == null)
+ {
+ cachedImagePropertyMap = new PropertyMap();
+ }
+ foreach (var key in cachedImagePropertyKeyList)
+ {
+ PropertyValue value = map.Find(key);
+ if (value != null)
+ {
+ // Update-or-Insert new value
+ cachedImagePropertyMap[key] = value;
+ if (key == ImageVisualProperty.URL)
{
- adjustedDesiredWidth = imageSize.Width * _desired_height/ imageSize.Height;
- adjustedDesiredHeight = _desired_height;
+ // Special case. If key is Url, update _resourceUrl here.
+ value.Get(out _resourceUrl);
}
- temp.Insert(ImageVisualProperty.DesiredWidth, new PropertyValue(adjustedDesiredWidth));
- temp.Insert(ImageVisualProperty.DesiredHeight, new PropertyValue(adjustedDesiredHeight));
- temp.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill));
}
}
+ }
- UpdateImageMap(temp);
-
- temp.Dispose();
- temp = null;
+ /// <summary>
+ /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
+ /// So before get base.GetNaturalSize(), we should synchronous image properties
+ /// </summary>
+ internal override Vector3 GetNaturalSize()
+ {
+ // Sync as current properties
+ UpdateImage();
+ return base.GetNaturalSize();
}
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override bool CheckResourceReady()
+ {
+ // If we have some properties to be updated, this signal is old thing.
+ // We need to ignore current signal, and wait next.
+ return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
+ }
private void OnResourceLoaded(IntPtr view)
{
+ if (!CheckResourceReady())
+ {
+ return;
+ }
ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
- e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.swigCPtr, Property.IMAGE);
+ e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
if (_resourceLoadedEventHandler != null)
{
internal static readonly int IMAGE = Interop.ImageView.ImageGet();
internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
- internal static readonly int ActionReload = Interop.ImageView.ImageVisualActionReloadGet();
- internal static readonly int ActionPlay = Interop.ImageView.ImageVisualActionPlayGet();
- internal static readonly int ActionPause = Interop.ImageView.ImageVisualActionPauseGet();
- internal static readonly int ActionStop = Interop.ImageView.ImageVisualActionStopGet();
+ internal static readonly int PlaceHolderUrl = Interop.ImageView.PlaceHolderImageGet();
+ internal static readonly int TransitionEffect = Interop.ImageView.TransitionEffectGet();
}
private enum ImageType
{
PixelArea = new RelativeVector4(x, y, z, w);
}
+
+ private class ImageLayout : LayoutItem
+ {
+ /// <summary>
+ /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
+ /// If this is set to be true, then the width or height, which is not set by user explicitly, can be adjusted to preserve the aspect ratio of the image resource.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool AdjustViewSize
+ {
+ get
+ {
+ return (Owner as ImageView)?.AdjustViewSize ?? false;
+ }
+ set
+ {
+ if (Owner is ImageView imageView)
+ {
+ imageView.AdjustViewSize = value;
+ }
+ }
+ }
+
+ /// <inheritdoc/>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
+ {
+ // To not change the view size by DALi
+ Owner.WidthResizePolicy = ResizePolicyType.Fixed;
+ Owner.HeightResizePolicy = ResizePolicyType.Fixed;
+
+ float specWidth = widthMeasureSpec.Size.AsDecimal();
+ float specHeight = heightMeasureSpec.Size.AsDecimal();
+ float naturalWidth = Owner.NaturalSize.Width;
+ float naturalHeight = Owner.NaturalSize.Height;
+ float minWidth = Owner.MinimumSize.Width;
+ float maxWidth = Owner.MaximumSize.Width;
+ float minHeight = Owner.MinimumSize.Height;
+ float maxHeight = Owner.MaximumSize.Height;
+ float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
+
+ // Assume that the new width and height are given from the view's suggested size by default.
+ float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
+ float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
+
+ // The width and height measure specs are going to be used to set measured size.
+ // Mark that the measure specs are changed by default to update measure specs later.
+ bool widthSpecChanged = true;
+ bool heightSpecChanged = true;
+
+ if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
+ {
+ newWidth = specWidth;
+ widthSpecChanged = false;
+
+ if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
+ {
+ if ((AdjustViewSize) && (aspectRatio > 0))
+ {
+ newHeight = newWidth * aspectRatio;
+ }
+ }
+ }
+
+ if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
+ {
+ newHeight = specHeight;
+ heightSpecChanged = false;
+
+ if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
+ {
+ if ((AdjustViewSize) && (aspectRatio > 0))
+ {
+ newWidth = newHeight / aspectRatio;
+ }
+ }
+ }
+
+ if (widthSpecChanged)
+ {
+ widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
+ }
+
+ if (heightSpecChanged)
+ {
+ heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
+ }
+
+ MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
+ MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
+
+ SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
+ ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));
+ }
+ }
}
}