/* * Copyright(c) 2019 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ using System; using System.Runtime.InteropServices; using System.ComponentModel; using Tizen.NUI.Binding; namespace Tizen.NUI.BaseComponents { /// /// ImageView is a class for displaying an image resource.
/// An instance of ImageView can be created using a URL or an image instance.
///
/// 3 public 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; if (newValue is Selector selector) { imageView.ResourceUrlSelector = selector; } else { imageView.resourceUrlSelector?.Reset(imageView); imageView.SetResourceUrl((string)newValue); } }, defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) => { var imageView = (ImageView)bindable; string ret = ""; PropertyMap imageMap = new PropertyMap(); Tizen.NUI.Object.GetProperty((HandleRef)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: (BindableProperty.BindingPropertyChangedDelegate)((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.StartsWith("*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.StartsWith("*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.StartsWith("*Resource*")) { auxiliaryImageURL = auxiliaryImageURL.Replace("*Resource*", resource); mmap.Insert(NDalic.ImageVisualAuxiliaryImageUrl, new PropertyValue(auxiliaryImageURL)); } map.Merge(mmap); } if (imageView._border == null) { Tizen.NUI.Object.SetProperty((HandleRef)imageView.SwigCPtr, ImageView.Property.IMAGE, new Tizen.NUI.PropertyValue(map)); } } }), defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) => { var imageView = (ImageView)bindable; if (imageView._border == null) { PropertyMap temp = new PropertyMap(); Tizen.NUI.Object.GetProperty((HandleRef)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: (BindableProperty.BindingPropertyChangedDelegate)((bindable, oldValue, newValue) => { var imageView = (ImageView)bindable; if (newValue != null) { Tizen.NUI.Object.SetProperty((HandleRef)imageView.SwigCPtr, ImageView.Property.PreMultipliedAlpha, new Tizen.NUI.PropertyValue((bool)newValue)); } }), defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) => { var imageView = (ImageView)bindable; bool temp = false; Tizen.NUI.Object.GetProperty((HandleRef)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: (BindableProperty.BindingPropertyChangedDelegate)((bindable, oldValue, newValue) => { var imageView = (ImageView)bindable; if (newValue != null) { Tizen.NUI.Object.SetProperty((HandleRef)imageView.SwigCPtr, ImageView.Property.PixelArea, new Tizen.NUI.PropertyValue((RelativeVector4)newValue)); } }), defaultValueCreator: (BindableProperty.CreateDefaultValueDelegate)((bindable) => { var imageView = (ImageView)bindable; Vector4 temp = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); Tizen.NUI.Object.GetProperty((HandleRef)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; imageView.borderSelector?.Reset(imageView); if (newValue is Selector selector) { if (selector.HasAll()) imageView.SetBorder(selector.All); else imageView.borderSelector = new TriggerableSelector(imageView, selector, imageView.SetBorder, true); } else { imageView.SetBorder((Rectangle)newValue); } }, 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: (BindableProperty.CreateDefaultValueDelegate)((bindable) => { var imageView = (ImageView)bindable; bool ret = false; PropertyMap imageMap = new PropertyMap(); Tizen.NUI.Object.GetProperty((HandleRef)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(SynchronousLoading), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) => { var imageView = (ImageView)bindable; if (newValue != null) { imageView._synchronousLoading = (bool)newValue; imageView.UpdateImage(NpatchImageVisualProperty.SynchronousLoading, new PropertyValue((bool)newValue)); } }, defaultValueCreator: (bindable) => { var imageView = (ImageView)bindable; return imageView._synchronousLoading; }); /// This will be public opened in tizen_7.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty SynchronousLoadingProperty = BindableProperty.Create(nameof(SynchronousLoading), typeof(bool), typeof(ImageView), false, propertyChanged: (bindable, oldValue, newValue) => { var imageView = (ImageView)bindable; if (newValue != null) { imageView._synchronousLoading = (bool)newValue; imageView.UpdateImage(NpatchImageVisualProperty.SynchronousLoading, new PropertyValue((bool)newValue)); } }, defaultValueCreator: (bindable) => { var imageView = (ImageView)bindable; return imageView._synchronousLoading; }); /// 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: (BindableProperty.CreateDefaultValueDelegate)((bindable) => { var imageView = (ImageView)bindable; bool ret = false; PropertyMap imageMap = new PropertyMap(); Tizen.NUI.Object.GetProperty((HandleRef)imageView.SwigCPtr, ImageView.Property.IMAGE).Get(imageMap); imageMap?.Find(ImageVisualProperty.OrientationCorrection)?.Get(out ret); return ret; })); private EventHandler _resourceReadyEventHandler; private ResourceReadyEventCallbackType _resourceReadyEventCallback; private EventHandler _resourceLoadedEventHandler; private _resourceLoadedCallbackType _resourceLoadedCallback; private Rectangle _border; private string _resourceUrl = ""; private bool _synchronousLoading = false; private string _alphaMaskUrl = null; private int _desired_width = -1; private int _desired_height = -1; private bool _cropToMask = false; private VisualFittingModeType _fittingMode = VisualFittingModeType.Fill; private TriggerableSelector resourceUrlSelector; private TriggerableSelector borderSelector; /// /// Creates an initialized ImageView. /// /// 3 public ImageView() : this(Interop.ImageView.New(), true) { if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } /// 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(ViewStyle viewStyle) : this(Interop.ImageView.New(), true, viewStyle) { } /// /// Creates an initialized ImageView with setting the status of shown or hidden. /// /// false : Not displayed (hidden), true : displayed (shown) /// 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(bool shown) : this(Interop.ImageView.New(), true) { if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); SetVisible(shown); } /// /// Creates an initialized ImageView from a URL to an image resource.
/// If the string is empty, ImageView will not display anything.
///
/// The URL of the image resource to display. /// 3 public ImageView(string url) : this(Interop.ImageView.New(url), true) { ResourceUrl = url; if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); } /// /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden. /// /// The URL of the image resource to display. /// false : Not displayed (hidden), true : displayed (shown) /// 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) { ResourceUrl = url; 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) { ResourceUrl = url; if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); if (!shown) { SetVisible(false); } } internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle) { if (!shown) { SetVisible(false); } } internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null) { if (!shown) { SetVisible(false); } } [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void ResourceReadyEventCallbackType(IntPtr data); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void _resourceLoadedCallbackType(IntPtr view); /// /// An event for ResourceReady signal which can be used to subscribe or unsubscribe the event handler.
/// This signal is emitted after all resources required by a control are loaded and ready.
/// Most resources are only loaded when the control is placed on the stage.
///
/// 3 public event EventHandler ResourceReady { add { if (_resourceReadyEventHandler == null) { _resourceReadyEventCallback = OnResourceReady; ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this); resourceReadySignal?.Connect(_resourceReadyEventCallback); resourceReadySignal?.Dispose(); } _resourceReadyEventHandler += value; } remove { _resourceReadyEventHandler -= value; ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this); if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false) { resourceReadySignal?.Disconnect(_resourceReadyEventCallback); } resourceReadySignal?.Dispose(); } } internal event EventHandler ResourceLoaded { add { if (_resourceLoadedEventHandler == null) { _resourceLoadedCallback = OnResourceLoaded; ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this); resourceReadySignal?.Connect(_resourceLoadedCallback); resourceReadySignal?.Dispose(); } _resourceLoadedEventHandler += value; } remove { _resourceLoadedEventHandler -= value; ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this); if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false) { resourceReadySignal?.Disconnect(_resourceLoadedCallback); } resourceReadySignal?.Dispose(); } } /// /// Enumeration for LoadingStatus of image. /// /// 5 public enum LoadingStatusType { /// /// Loading preparing status. /// /// 5 Preparing, /// /// Loading ready status. /// /// 5 Ready, /// /// Loading failed status. /// /// 5 Failed } /// /// 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. /// /// 3 public string ResourceUrl { get { return (string)GetValue(ResourceUrlProperty); } set { SetValue(ResourceUrlProperty, value); NotifyPropertyChanged(); } } /// /// This will be deprecated, please use Image instead.
/// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise. ///
/// 3 [Obsolete("Please do not use! This will be deprecated! Please use Image property instead!")] [EditorBrowsable(EditorBrowsableState.Never)] public PropertyMap ImageMap { get { if (_border == null) { PropertyMap returnValue = new PropertyMap(); PropertyValue image = GetProperty(ImageView.Property.IMAGE); image?.Get(returnValue); image?.Dispose(); return returnValue; } else { return null; } } set { if (_border == null) { PropertyValue setValue = new Tizen.NUI.PropertyValue(value); SetProperty(ImageView.Property.IMAGE, setValue); NotifyPropertyChanged(); setValue?.Dispose(); } } } /// /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise. /// /// /// This PropertyMap use a .
/// See for a detailed description.
/// you can also use .
/// See for a detailed description.
///
/// /// The following example demonstrates how to use the Image property. /// /// 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; /// /// /// 4 public PropertyMap Image { get { if (_border == null) { return (PropertyMap)GetValue(ImageProperty); } else { return null; } } set { if (_border == null) { SetValue(ImageProperty, value); NotifyPropertyChanged(); } } } /// /// ImageView PreMultipliedAlpha, type Boolean.
/// Image must be initialized.
///
/// 3 public bool PreMultipliedAlpha { get { return (bool)GetValue(PreMultipliedAlphaProperty); } set { SetValue(PreMultipliedAlphaProperty, value); NotifyPropertyChanged(); } } /// /// ImageView PixelArea, type Vector4 (Animatable property).
/// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].
///
/// /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible. /// /// 3 public RelativeVector4 PixelArea { get { RelativeVector4 temp = (RelativeVector4)GetValue(PixelAreaProperty); return new RelativeVector4(OnPixelAreaChanged, temp.X, temp.Y, temp.Z, temp.W); } set { SetValue(PixelAreaProperty, value); NotifyPropertyChanged(); } } /// /// The border of the image in the order: left, right, bottom, top.
/// If set, ImageMap will be ignored.
/// For N-Patch images only.
/// Optional. ///
/// /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible. /// /// 3 public Rectangle Border { get { Rectangle temp = (Rectangle)GetValue(BorderProperty); if (null == temp) { return null; } else { return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height); } } set { SetValue(BorderProperty, value); NotifyPropertyChanged(); } } /// /// Gets or sets whether to draw the borders only (if true).
/// If not specified, the default is false.
/// For N-Patch images only.
/// Optional. ///
/// 3 public bool BorderOnly { get { return (bool)GetValue(BorderOnlyProperty); } set { SetValue(BorderOnlyProperty, value); NotifyPropertyChanged(); } } /// /// Gets or sets whether to synchronous loading the resourceurl of image.
///
/// 3 [Obsolete("Deprecated since API level 9 and will be removed in API level 11. Please use SynchronousLoading instead!")] public bool SynchronosLoading { get { return SynchronousLoading; } set { SynchronousLoading = value; } } /// /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.
///
/// /// Changing this property make this ImageView load image synchronously at the next loading /// by following operation: , , /// and by some properties those cause reloading: , and etc. /// /// 9 public bool SynchronousLoading { get { return (bool)GetValue(SynchronousLoadingProperty); } set { SetValue(SynchronousLoadingProperty, value); NotifyPropertyChanged(); } } /// /// Gets or sets whether to automatically correct the orientation of an image.
///
/// 5 public bool OrientationCorrection { get { return (bool)GetValue(OrientationCorrectionProperty); } set { SetValue(OrientationCorrectionProperty, value); NotifyPropertyChanged(); } } /// /// Gets the loading state of the visual resource. /// /// 5 public ImageView.LoadingStatusType LoadingStatus { get { return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE); } } /// /// Downcasts a handle to imageView handle. /// /// Thrown when handle is null. /// Please do not use! this will be deprecated! /// Instead please use as keyword. /// 3 [Obsolete("Please do not use! This will be deprecated! Please use as keyword instead! " + "Like: " + "BaseHandle handle = new ImageView(imagePath); " + "ImageView image = handle as ImageView")] [EditorBrowsable(EditorBrowsableState.Never)] public static ImageView DownCast(BaseHandle handle) { if (null == handle) { throw new ArgumentNullException(nameof(handle)); } ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView; if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Sets this ImageView from the given URL.
/// If the URL is empty, ImageView will not display anything.
///
/// The URL to the image resource to display. /// Thrown when url is null. /// 3 public void SetImage(string url) { if (null == url) { throw new ArgumentNullException(nameof(url)); } 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!"); return; } Interop.ImageView.SetImage(SwigCPtr, url); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); ResourceUrl = url; } /// /// Queries if all resources required by a control are loaded and ready.
/// Most resources are only loaded when the control is placed on the stage.
/// True if the resources are loaded and ready, false otherwise.
///
/// 3 public new bool IsResourceReady() { bool ret = Interop.View.IsResourceReady(SwigCPtr); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } /// /// Forcefully reloads the image. All the visuals using this image will reload to the latest image. /// /// 5 public void Reload() { PropertyValue attributes = new PropertyValue(0); this.DoAction(ImageView.Property.IMAGE, ActionReload, attributes); attributes?.Dispose(); } /// /// Plays the animated GIF. This is also the default playback mode. /// /// 5 public void Play() { PropertyValue attributes = new PropertyValue(0); this.DoAction(ImageView.Property.IMAGE, ActionPlay, attributes); attributes?.Dispose(); } /// /// Pauses the animated GIF. /// /// 5 public void Pause() { PropertyValue attributes = new PropertyValue(0); this.DoAction(ImageView.Property.IMAGE, ActionPause, attributes); attributes?.Dispose(); } /// /// Stops the animated GIF. /// /// 5 public void Stop() { PropertyValue attributes = new PropertyValue(0); this.DoAction(ImageView.Property.IMAGE, ActionStop, attributes); attributes?.Dispose(); } /// /// Gets or sets the URL of the alpha mask.
/// Optional. ///
/// 6 [EditorBrowsable(EditorBrowsableState.Never)] public string AlphaMaskURL { get { string ret = ""; PropertyMap imageMap = new PropertyMap(); PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); image?.Get(imageMap); PropertyValue maskUrl = imageMap?.Find(ImageVisualProperty.AlphaMaskURL); maskUrl?.Get(out ret); _alphaMaskUrl = ret; imageMap?.Dispose(); image?.Dispose(); maskUrl?.Dispose(); return ret; } set { if (value == null) { value = ""; } _alphaMaskUrl = value; PropertyValue setValue = new PropertyValue(value); UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue); setValue?.Dispose(); } } /// /// Whether to crop image to mask or scale mask to fit image. /// /// 6 public bool CropToMask { get { bool ret = _cropToMask; PropertyMap imageMap = new PropertyMap(); PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); image?.Get(imageMap); PropertyValue cropUrl = imageMap?.Find(ImageVisualProperty.CropToMask); cropUrl?.Get(out ret); _cropToMask = ret; imageMap?.Dispose(); image?.Dispose(); cropUrl?.Dispose(); return ret; } set { _cropToMask = value; PropertyValue setValue = new PropertyValue(value); UpdateImage(ImageVisualProperty.CropToMask, setValue); setValue.Dispose(); } } /// /// Actions property value for Reload image. /// private int ActionReload { get; set; } = Interop.ImageView.ImageVisualActionReloadGet(); /// /// Actions property value to Play animated images. /// This property can be redefined by child class if it use different value. /// [EditorBrowsable(EditorBrowsableState.Never)] protected int ActionPlay { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet(); /// /// Actions property value to Pause animated images. /// This property can be redefined by child class if it use different value. /// [EditorBrowsable(EditorBrowsableState.Never)] protected int ActionPause { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet(); /// /// Actions property value to Stop animated images. /// This property can be redefined by child class if it use different value. /// [EditorBrowsable(EditorBrowsableState.Never)] protected int ActionStop { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet(); internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value) { switch (value) { case FittingModeType.ShrinkToFit: return VisualFittingModeType.FitKeepAspectRatio; case FittingModeType.ScaleToFill: return VisualFittingModeType.OverFitKeepAspectRatio; case FittingModeType.Center: return VisualFittingModeType.Center; case FittingModeType.Fill: return VisualFittingModeType.Fill; case FittingModeType.FitHeight: return VisualFittingModeType.FitHeight; case FittingModeType.FitWidth: return VisualFittingModeType.FitWidth; default: return VisualFittingModeType.Fill; } } internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value) { switch (value) { case VisualFittingModeType.FitKeepAspectRatio: return FittingModeType.ShrinkToFit; case VisualFittingModeType.OverFitKeepAspectRatio: return FittingModeType.ScaleToFill; case VisualFittingModeType.Center: return FittingModeType.Center; case VisualFittingModeType.Fill: return FittingModeType.Fill; case VisualFittingModeType.FitHeight: return FittingModeType.FitHeight; case VisualFittingModeType.FitWidth: return FittingModeType.FitWidth; default: return FittingModeType.ShrinkToFit; } } internal override LayoutItem CreateDefaultLayout() { return new ImageLayout(); } /// /// Gets or sets fitting options used when resizing images to fit.
/// If not supplied, the default is FittingModeType.Fill.
/// For normal quad images only.
/// Optional. ///
/// 6 [EditorBrowsable(EditorBrowsableState.Never)] public FittingModeType FittingMode { get { int ret = (int)_fittingMode; PropertyMap imageMap = new PropertyMap(); PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); image?.Get(imageMap); PropertyValue fittingMode = imageMap?.Find(Visual.Property.VisualFittingMode); fittingMode?.Get(out ret); _fittingMode = (VisualFittingModeType)ret; imageMap?.Dispose(); image?.Dispose(); fittingMode?.Dispose(); return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret); } set { VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value); PropertyValue setValue = new PropertyValue((int)ret); if(_fittingMode != ret) { _fittingMode = ret; UpdateImage(Visual.Property.VisualFittingMode, setValue); } setValue?.Dispose(); } } /// /// Gets or sets the desired image width.
/// If not specified, the actual image width is used.
/// For normal quad images only.
/// Optional. ///
/// 6 [EditorBrowsable(EditorBrowsableState.Never)] public int DesiredWidth { get { PropertyMap imageMap = new PropertyMap(); PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); image?.Get(imageMap); PropertyValue desireWidth = imageMap?.Find(ImageVisualProperty.DesiredWidth); desireWidth?.Get(out _desired_width); imageMap?.Dispose(); image?.Dispose(); desireWidth?.Dispose(); return _desired_width; } set { if (_desired_width != value) { _desired_width = value; UpdateImage(0, null); } } } /// /// Gets or sets the desired image height.
/// If not specified, the actual image height is used.
/// For normal quad images only.
/// Optional. ///
/// 6 [EditorBrowsable(EditorBrowsableState.Never)] public int DesiredHeight { get { PropertyMap imageMap = new PropertyMap(); PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); image?.Get(imageMap); PropertyValue desireheight = imageMap?.Find(ImageVisualProperty.DesiredHeight); desireheight?.Get(out _desired_height); imageMap?.Dispose(); image?.Dispose(); desireheight?.Dispose(); return _desired_height; } set { if (_desired_height != value) { _desired_height = value; UpdateImage(0, null); } } } /// /// Gets or sets ReleasePolicy for image.
/// If not supplied, the default is ReleasePolicyType.Detached.
///
[EditorBrowsable(EditorBrowsableState.Never)] public ReleasePolicyType ReleasePolicy { get { int ret = (int)ReleasePolicyType.Detached; PropertyMap imageMap = new PropertyMap(); PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); image?.Get(imageMap); PropertyValue releasePoli = imageMap?.Find(ImageVisualProperty.ReleasePolicy); releasePoli?.Get(out ret); imageMap?.Dispose(); image?.Dispose(); releasePoli?.Dispose(); return (ReleasePolicyType)ret; } set { PropertyValue setValue = new PropertyValue((int)value); UpdateImage(ImageVisualProperty.ReleasePolicy, setValue); setValue?.Dispose(); } } /// /// Gets or sets the wrap mode for the u coordinate.
/// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.
/// If not specified, the default is WrapModeType.Default(CLAMP).
/// For normal quad images only.
/// Optional. ///
/// 6 [EditorBrowsable(EditorBrowsableState.Never)] public WrapModeType WrapModeU { get { int ret = (int)WrapModeType.Default; PropertyMap imageMap = new PropertyMap(); PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); image?.Get(imageMap); PropertyValue warpModeU = imageMap?.Find(ImageVisualProperty.WrapModeU); warpModeU?.Get(out ret); imageMap?.Dispose(); image?.Dispose(); warpModeU?.Dispose(); return (WrapModeType)ret; } set { PropertyValue setValue = new PropertyValue((int)value); UpdateImage(ImageVisualProperty.WrapModeU, setValue); setValue?.Dispose(); } } /// /// Gets or sets the wrap mode for the v coordinate.
/// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.
/// The first two elements indicate the top-left position of the area, and the last two elements are the areas of the width and the height respectively.
/// If not specified, the default is WrapModeType.Default(CLAMP).
/// For normal quad images only. /// Optional. ///
/// 6 [EditorBrowsable(EditorBrowsableState.Never)] public WrapModeType WrapModeV { get { int ret = (int)WrapModeType.Default; PropertyMap imageMap = new PropertyMap(); PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); image?.Get(imageMap); PropertyValue wrapModeV = imageMap?.Find(ImageVisualProperty.WrapModeV); wrapModeV?.Get(out ret); imageMap?.Dispose(); image?.Dispose(); wrapModeV?.Dispose(); return (WrapModeType)ret; } set { PropertyValue setValue = new PropertyValue((int)value); UpdateImage(ImageVisualProperty.WrapModeV, setValue); setValue?.Dispose(); } } /// /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource. /// /// /// 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). /// /// 9 public bool AdjustViewSize { get; set; } = false; internal Selector ResourceUrlSelector { get => GetSelector(resourceUrlSelector, ImageView.ResourceUrlProperty); set { resourceUrlSelector?.Reset(this); if (value == null) return; if (value.HasAll()) SetResourceUrl(value.All); else resourceUrlSelector = new TriggerableSelector(this, value, SetResourceUrl, true); } } /// /// Get attributes, it is abstract function and must be override. /// [EditorBrowsable(EditorBrowsableState.Never)] protected override ViewStyle CreateViewStyle() { return new ImageViewStyle(); } internal void SetImage(string url, Uint16Pair size) { 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!"); return; } Interop.ImageView.SetImage(SwigCPtr, url, Uint16Pair.getCPtr(size)); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); ResourceUrl = url; } internal ViewResourceReadySignal ResourceReadySignal(View view) { ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false); if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); return ret; } internal override void ApplyCornerRadius() { base.ApplyCornerRadius(); UpdateImage(0, null); } internal override void ApplyBorderline() { base.ApplyBorderline(); // Apply borderline to IMAGE. if (backgroundExtraData != null) { var borderlineColor = backgroundExtraData.BorderlineColor == null ? new PropertyValue(Color.Black) : new PropertyValue(backgroundExtraData.BorderlineColor); // Apply to the image visual PropertyMap imageMap = new PropertyMap(); PropertyValue imageValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); if (imageValue.Get(imageMap) && !imageMap.Empty()) { imageMap[Visual.Property.BorderlineWidth] = new PropertyValue(backgroundExtraData.BorderlineWidth); imageMap[Visual.Property.BorderlineColor] = borderlineColor; imageMap[Visual.Property.BorderlineOffset] = new PropertyValue(backgroundExtraData.BorderlineOffset); var temp = new PropertyValue(imageMap); Tizen.NUI.Object.SetProperty(SwigCPtr, ImageView.Property.IMAGE, temp); temp.Dispose(); } imageMap.Dispose(); imageValue.Dispose(); borderlineColor.Dispose(); } UpdateImage(0, null); } internal ResourceLoadingStatusType GetResourceStatus() { return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE); } /// /// you can override it to clean-up your own resources. /// /// DisposeTypes /// 3 protected override void Dispose(DisposeTypes type) { if (disposed) { return; } if (type == DisposeTypes.Explicit) { //Called by User //Release your own managed resources here. //You should release all of your own disposable objects here. _border?.Dispose(); _border = null; borderSelector?.Reset(this); resourceUrlSelector?.Reset(this); } base.Dispose(type); } /// This will not be public opened. [EditorBrowsable(EditorBrowsableState.Never)] protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr) { Interop.ImageView.DeleteImageView(swigCPtr); } // Callback for View ResourceReady signal private void OnResourceReady(IntPtr data) { ResourceReadyEventArgs e = new ResourceReadyEventArgs(); if (data != null) { e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View; } if (_resourceReadyEventHandler != null) { _resourceReadyEventHandler(this, e); } } private void SetResourceUrl(string value) { value = (value == null ? "" : value); if (value.StartsWith("*Resource*")) { string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource; value = value.Replace("*Resource*", resource); } _resourceUrl = value; UpdateImage(ImageVisualProperty.URL, new PropertyValue(value)); } private void SetBorder(Rectangle value) { if (value == null) { return; } _border = new Rectangle(value); UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border)); } private void UpdateImageMap(PropertyMap fromMap) { PropertyMap imageMap = new PropertyMap(); PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE); image?.Get(imageMap); imageMap?.Merge(fromMap); PropertyValue setValue = new PropertyValue(imageMap); SetProperty(ImageView.Property.IMAGE, setValue); imageMap?.Dispose(); image?.Dispose(); setValue?.Dispose(); } private void UpdateImage(int key, PropertyValue value) { PropertyMap imageMap = new PropertyMap(); if (_alphaMaskUrl != null) { PropertyValue alphaMaskUrl = new PropertyValue(_alphaMaskUrl); imageMap?.Insert(ImageVisualProperty.AlphaMaskURL, alphaMaskUrl); alphaMaskUrl?.Dispose(); } if(key != ImageVisualProperty.CropToMask) { PropertyValue cropToMask = new PropertyValue(_cropToMask); imageMap?.Insert(ImageVisualProperty.CropToMask, cropToMask); cropToMask?.Dispose(); } if (string.IsNullOrEmpty(_resourceUrl)) { PropertyValue resourceUrl = new PropertyValue(_resourceUrl); imageMap?.Insert(ImageVisualProperty.URL, resourceUrl); PropertyValue setValue = new PropertyValue(imageMap); SetProperty(ImageView.Property.IMAGE, setValue); resourceUrl?.Dispose(); setValue?.Dispose(); return; } if (_border == null) { PropertyValue image = new PropertyValue((int)Visual.Type.Image); imageMap?.Insert(Visual.Property.Type, image); image?.Dispose(); } else { PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch); imageMap?.Insert(Visual.Property.Type, nPatch); nPatch?.Dispose(); PropertyValue border = new PropertyValue(_border); imageMap?.Insert(NpatchImageVisualProperty.Border, border); border?.Dispose(); } if(key != Visual.Property.VisualFittingMode && _fittingMode != VisualFittingModeType.Fill) { PropertyValue fittingMode = new PropertyValue((int)_fittingMode); imageMap?.Insert(Visual.Property.VisualFittingMode, fittingMode); fittingMode?.Dispose(); } PropertyValue synchronousLoading = new PropertyValue(_synchronousLoading); imageMap?.Insert(NpatchImageVisualProperty.SynchronousLoading, synchronousLoading); synchronousLoading?.Dispose(); if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null) { using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius)) using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy)) { imageMap.Insert(Visual.Property.CornerRadius, cornerRadius); imageMap.Insert(Visual.Property.CornerRadiusPolicy, new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy))); } } if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f) { using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth)) using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor)) using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset)) { imageMap.Insert(Visual.Property.BorderlineWidth, borderlineWidth); imageMap.Insert(Visual.Property.BorderlineColor, borderlineColor); imageMap.Insert(Visual.Property.BorderlineOffset, borderlineOffset); } } if (value != null) { imageMap?.Insert(key, value); } // Do Fitting Buffer when desired dimension is set if (_desired_width != -1 && _desired_height != -1) { if (_resourceUrl != null) { Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true); if( imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0 ) { 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); imageMap?.Insert(ImageVisualProperty.DesiredWidth, returnWidth); returnWidth?.Dispose(); PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight); imageMap?.Insert(ImageVisualProperty.DesiredHeight, returnHeight); returnHeight?.Dispose(); PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill); imageMap?.Insert(ImageVisualProperty.FittingMode, scaleToFit); scaleToFit?.Dispose(); } else { Tizen.Log.Fatal("NUI", "[ERROR] Can't use DesiredSize when ImageLoading is failed."); } imageSize?.Dispose(); } } UpdateImageMap(imageMap); imageMap?.Dispose(); imageMap = null; } private void OnResourceLoaded(IntPtr view) { ResourceLoadedEventArgs e = new ResourceLoadedEventArgs(); e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE); if (_resourceLoadedEventHandler != null) { _resourceLoadedEventHandler(this, e); } } /// /// Event arguments of resource ready. /// /// 3 public class ResourceReadyEventArgs : EventArgs { private View _view; /// /// The view whose resource is ready. /// /// 3 public View View { get { return _view; } set { _view = value; } } } internal class ResourceLoadedEventArgs : EventArgs { private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid; public ResourceLoadingStatusType Status { get { return status; } set { status = value; } } } internal new class Property { internal static readonly int IMAGE = Interop.ImageView.ImageGet(); internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet(); internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet(); } private enum ImageType { /// /// For Normal Image. /// Normal = 0, /// /// For normal image, with synchronous loading and orientation correction property /// Specific = 1, /// /// For nine-patch image /// Npatch = 2, } private void OnBorderChanged(int x, int y, int width, int height) { Border = new Rectangle(x, y, width, height); } private void OnPixelAreaChanged(float x, float y, float z, float w) { PixelArea = new RelativeVector4(x, y, z, w); } private class ImageLayout : LayoutItem { /// /// 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. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool AdjustViewSize { get { return (Owner as ImageView)?.AdjustViewSize ?? false; } set { if (Owner is ImageView imageView) { imageView.AdjustViewSize = value; } } } /// [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)); } } } }