2 * Copyright(c) 2019 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using System.ComponentModel;
21 using Tizen.NUI.Binding;
23 namespace Tizen.NUI.BaseComponents
27 /// ImageView is a class for displaying an image resource.<br />
28 /// An instance of ImageView can be created using a URL or an image instance.<br />
30 /// <since_tizen> 3 </since_tizen>
31 public partial class ImageView : View
33 static ImageView() { }
35 static internal new void Preload()
37 // Do not call View.Preload(), since we already call it
40 // Do nothing. Just call for load static values.
41 var temporalCachedImagePropertyKeyList = cachedImagePropertyKeyList;
44 private EventHandler<ResourceReadyEventArgs> _resourceReadyEventHandler;
45 private ResourceReadyEventCallbackType _resourceReadyEventCallback;
46 private EventHandler<ResourceLoadedEventArgs> _resourceLoadedEventHandler;
47 private _resourceLoadedCallbackType _resourceLoadedCallback;
50 /// Convert non-null string that some keyword change as application specific directory.
52 /// <param name="value">Inputed and replaced after this function finished</param>
53 /// <returns>Replaced url</returns>
54 private static string ConvertResourceUrl(ref string value)
57 if (value.StartsWith("*Resource*"))
59 string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
60 value = value.Replace("*Resource*", resource);
65 // Collection of image-sensitive properties.
66 private static readonly List<int> cachedImagePropertyKeyList = new List<int> {
68 ImageVisualProperty.URL,
69 ImageVisualProperty.AlphaMaskURL,
70 ImageVisualProperty.CropToMask,
71 Visual.Property.VisualFittingMode,
72 ImageVisualProperty.DesiredWidth,
73 ImageVisualProperty.DesiredHeight,
74 ImageVisualProperty.ReleasePolicy,
75 ImageVisualProperty.WrapModeU,
76 ImageVisualProperty.WrapModeV,
77 ImageVisualProperty.SynchronousLoading,
78 Visual.Property.MixColor,
79 Visual.Property.Opacity,
80 Visual.Property.PremultipliedAlpha,
81 ImageVisualProperty.OrientationCorrection,
82 ImageVisualProperty.FastTrackUploading,
83 NpatchImageVisualProperty.Border,
84 NpatchImageVisualProperty.BorderOnly,
86 internal PropertyMap cachedImagePropertyMap;
87 internal bool imagePropertyUpdatedFlag = false;
89 private bool imagePropertyUpdateProcessAttachedFlag = false;
90 private Rectangle _border;
91 private string _resourceUrl = "";
92 private int _desired_width = -1;
93 private int _desired_height = -1;
94 private bool _fastTrackUploading = false;
95 private TriggerableSelector<string> resourceUrlSelector;
96 private TriggerableSelector<Rectangle> borderSelector;
98 private RelativeVector4 internalPixelArea;
101 /// Creates an initialized ImageView.
103 /// <since_tizen> 3 </since_tizen>
104 public ImageView() : this(Interop.ImageView.New(), true)
106 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
109 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
110 [EditorBrowsable(EditorBrowsableState.Never)]
111 public ImageView(ViewStyle viewStyle) : this(Interop.ImageView.New(), true, viewStyle)
116 /// Creates an initialized ImageView with setting the status of shown or hidden.
118 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
119 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
120 [EditorBrowsable(EditorBrowsableState.Never)]
121 public ImageView(bool shown) : this(Interop.ImageView.New(), true)
123 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
128 /// Creates an initialized ImageView from a URL to an image resource.<br />
129 /// If the string is empty, ImageView will not display anything.<br />
131 /// <param name="url">The URL of the image resource to display.</param>
132 /// <since_tizen> 3 </since_tizen>
133 public ImageView(string url) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
137 // Update cached property. Note that we should not re-create new visual.
138 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
140 UpdateImage(ImageVisualProperty.URL, urlValue, false);
142 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
147 /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden.
149 /// <param name="url">The URL of the image resource to display.</param>
150 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
151 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
152 [EditorBrowsable(EditorBrowsableState.Never)]
153 public ImageView(string url, bool shown) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
157 // Update cached property. Note that we should not re-create new visual.
158 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
160 UpdateImage(ImageVisualProperty.URL, urlValue, false);
162 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
166 internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size)), true)
169 _desired_width = size?.GetWidth() ?? -1;
170 _desired_height = size?.GetHeight() ?? -1;
172 // Update cached property. Note that we should not re-create new visual.
173 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
175 UpdateImage(ImageVisualProperty.URL, urlValue, false);
177 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
179 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
181 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
183 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
185 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
193 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
201 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
209 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
210 private delegate void ResourceReadyEventCallbackType(IntPtr data);
211 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
212 private delegate void _resourceLoadedCallbackType(IntPtr view);
215 /// An event for ResourceReady signal which can be used to subscribe or unsubscribe the event handler.<br />
216 /// This signal is emitted after all resources required by a control are loaded and ready.<br />
217 /// Most resources are only loaded when the control is placed on the stage.<br />
219 /// <since_tizen> 3 </since_tizen>
220 public event EventHandler<ResourceReadyEventArgs> ResourceReady
224 if (_resourceReadyEventHandler == null)
226 _resourceReadyEventCallback = OnResourceReady;
227 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
228 resourceReadySignal?.Connect(_resourceReadyEventCallback);
229 resourceReadySignal?.Dispose();
232 _resourceReadyEventHandler += value;
237 _resourceReadyEventHandler -= value;
239 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
240 if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
242 resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
244 resourceReadySignal?.Dispose();
248 internal event EventHandler<ResourceLoadedEventArgs> ResourceLoaded
252 if (_resourceLoadedEventHandler == null)
254 _resourceLoadedCallback = OnResourceLoaded;
255 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
256 resourceReadySignal?.Connect(_resourceLoadedCallback);
257 resourceReadySignal?.Dispose();
260 _resourceLoadedEventHandler += value;
264 _resourceLoadedEventHandler -= value;
265 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
266 if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
268 resourceReadySignal?.Disconnect(_resourceLoadedCallback);
270 resourceReadySignal?.Dispose();
275 /// Enumeration for LoadingStatus of image.
277 /// <since_tizen> 5 </since_tizen>
278 public enum LoadingStatusType
281 /// Loading preparing status.
283 /// <since_tizen> 5 </since_tizen>
286 /// Loading ready status.
288 /// <since_tizen> 5 </since_tizen>
291 /// Loading failed status.
293 /// <since_tizen> 5 </since_tizen>
298 /// Enumeration for MaskingMode of image.
300 [EditorBrowsable(EditorBrowsableState.Never)]
301 public enum MaskingModeType
304 /// Applies alpha masking on rendering time.
306 [EditorBrowsable(EditorBrowsableState.Never)]
309 /// Applies alpha masking on loading time.
311 [EditorBrowsable(EditorBrowsableState.Never)]
316 /// ImageView ResourceUrl, type string.
317 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
318 /// When it is set as null, it gives empty string ("") to be read.
320 /// <since_tizen> 3 </since_tizen>
321 public string ResourceUrl
325 return (string)GetValue(ResourceUrlProperty);
329 SetValue(ResourceUrlProperty, value);
330 NotifyPropertyChanged();
335 /// This will be deprecated, Use Image instead. <br />
336 /// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
338 /// <since_tizen> 3 </since_tizen>
339 [Obsolete("Do not use this, that will be deprecated. Use Image property instead.")]
340 [EditorBrowsable(EditorBrowsableState.Never)]
341 public PropertyMap ImageMap
345 return GetValue(ImageMapProperty) as PropertyMap;
349 SetValue(ImageMapProperty, value);
350 NotifyPropertyChanged();
353 private PropertyMap InternalImageMap
359 // Sync as current properties
362 // Get current properties force.
363 PropertyMap returnValue = new PropertyMap();
364 PropertyValue image = GetProperty(ImageView.Property.IMAGE);
365 image?.Get(returnValue);
368 // Update cached property map
369 if (returnValue != null)
371 MergeCachedImageVisualProperty(returnValue);
384 PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
385 SetProperty(ImageView.Property.IMAGE, setValue);
387 // Image properties are changed hardly. We should ignore lazy UpdateImage
388 imagePropertyUpdatedFlag = false;
389 cachedImagePropertyMap?.Dispose();
390 cachedImagePropertyMap = null;
391 MergeCachedImageVisualProperty(value);
393 NotifyPropertyChanged();
400 /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
403 /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
404 /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
405 /// you can also use <see cref="Visual.Property"/>. <br />
406 /// See <see cref="Visual.Property"/> for a detailed description. <br />
409 /// The following example demonstrates how to use the Image property.
411 /// PropertyMap map = new PropertyMap();
412 /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
413 /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
414 /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
415 /// imageview.Image = map;
418 /// <since_tizen> 4 </since_tizen>
419 public PropertyMap Image
425 return (PropertyMap)GetValue(ImageProperty);
436 SetValue(ImageProperty, value);
437 NotifyPropertyChanged();
443 /// ImageView PreMultipliedAlpha, type Boolean.<br />
444 /// Image must be initialized.<br />
446 /// <since_tizen> 3 </since_tizen>
447 public bool PreMultipliedAlpha
451 return (bool)GetValue(PreMultipliedAlphaProperty);
455 SetValue(PreMultipliedAlphaProperty, value);
456 NotifyPropertyChanged();
461 /// ImageView PixelArea, type Vector4 (Animatable property).<br />
462 /// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].<br />
465 /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
467 /// <since_tizen> 3 </since_tizen>
468 public RelativeVector4 PixelArea
472 return (RelativeVector4)GetValue(PixelAreaProperty);
476 SetValue(PixelAreaProperty, value);
477 NotifyPropertyChanged();
482 /// The border of the image in the order: left, right, bottom, top.<br />
483 /// If set, ImageMap will be ignored.<br />
484 /// For N-Patch images only.<br />
488 /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
490 /// <since_tizen> 3 </since_tizen>
491 public Rectangle Border
495 Rectangle temp = (Rectangle)GetValue(BorderProperty);
502 return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
507 SetValue(BorderProperty, value);
508 NotifyPropertyChanged();
513 /// Gets or sets whether to draw the borders only (if true).<br />
514 /// If not specified, the default is false.<br />
515 /// For N-Patch images only.<br />
518 /// <since_tizen> 3 </since_tizen>
519 public bool BorderOnly
523 return (bool)GetValue(BorderOnlyProperty);
527 SetValue(BorderOnlyProperty, value);
528 NotifyPropertyChanged();
533 /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
535 /// <since_tizen> 3 </since_tizen>
536 [Obsolete("This has been deprecated since API9 and will be removed in API11. Use SynchronousLoading instead.")]
537 public bool SynchronosLoading
541 return SynchronousLoading;
545 SynchronousLoading = value;
550 /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
553 /// Changing this property make this ImageView load image synchronously at the next loading
554 /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
555 /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
557 /// <since_tizen> 9 </since_tizen>
558 public bool SynchronousLoading
562 return (bool)GetValue(SynchronousLoadingProperty);
566 SetValue(SynchronousLoadingProperty, value);
567 NotifyPropertyChanged();
572 /// Gets or sets whether to automatically correct the orientation of an image.<br />
574 /// <since_tizen> 5 </since_tizen>
575 public bool OrientationCorrection
579 return (bool)GetValue(OrientationCorrectionProperty);
583 SetValue(OrientationCorrectionProperty, value);
584 NotifyPropertyChanged();
589 /// Gets or sets whether to apply mask on GPU or not.<br />
591 [EditorBrowsable(EditorBrowsableState.Never)]
592 public MaskingModeType MaskingMode
596 return (MaskingModeType)GetValue(MaskingModeProperty);
600 SetValue(MaskingModeProperty, value);
601 NotifyPropertyChanged();
605 private MaskingModeType InternalMaskingMode
609 int ret = (int)MaskingModeType.MaskingOnLoading;
611 PropertyValue maskingMode = GetCachedImageVisualProperty(ImageVisualProperty.MaskingMode);
612 maskingMode?.Get(out ret);
613 maskingMode?.Dispose();
615 return (MaskingModeType)ret;
619 MaskingModeType ret = value;
620 PropertyValue setValue = new PropertyValue((int)ret);
621 UpdateImage(ImageVisualProperty.MaskingMode, setValue);
627 /// Gets or sets whether to apply fast track uploading or not.<br />
630 /// If we use fast track uploading feature, It can upload texture without event-thead dependency. But also,<br />
631 /// - Texture size is invalid until ResourceReady signal comes.<br />
632 /// - Texture cannot be cached (We always try to load new image).<br />
633 /// - Seamless visual change didn't supported.<br />
634 /// - Alpha masking didn't supported. If you try, It will load as normal case.<br />
635 /// - Synchronous loading didn't supported. If you try, It will load as normal case.<br />
636 /// - Reload action didn't supported. If you try, It will load as normal case.<br />
637 /// - Atlas loading didn't supported. If you try, It will load as normal case.<br />
638 /// - Custom shader didn't supported. If you try, It will load as normal case.
640 [EditorBrowsable(EditorBrowsableState.Never)]
641 public bool FastTrackUploading
645 return (bool)GetValue(FastTrackUploadingProperty);
649 SetValue(FastTrackUploadingProperty, value);
650 NotifyPropertyChanged();
654 private bool InternalFastTrackUploading
658 PropertyValue fastTrackUploading = GetCachedImageVisualProperty(ImageVisualProperty.FastTrackUploading);
659 fastTrackUploading?.Get(out _fastTrackUploading);
660 fastTrackUploading?.Dispose();
662 return _fastTrackUploading;
666 if (_fastTrackUploading != value)
668 _fastTrackUploading = value;
670 PropertyValue setValue = new PropertyValue(_fastTrackUploading);
671 UpdateImage(ImageVisualProperty.FastTrackUploading, setValue);
674 if (_fastTrackUploading && !string.IsNullOrEmpty(_resourceUrl))
676 // Special case. If user set FastTrackUploading mean, user want to upload image As-Soon-As-Possible.
677 // Create ImageVisual synchronously.
685 /// Gets the loading state of the visual resource.
687 /// <since_tizen> 5 </since_tizen>
688 public ImageView.LoadingStatusType LoadingStatus
692 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
697 /// Downcasts a handle to imageView handle.
699 /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
700 /// Do not use this, that will be deprecated. Use as keyword instead.
701 /// <since_tizen> 3 </since_tizen>
702 [Obsolete("Do not use this, that will be deprecated. Use as keyword instead. " +
704 "BaseHandle handle = new ImageView(imagePath); " +
705 "ImageView image = handle as ImageView")]
706 [EditorBrowsable(EditorBrowsableState.Never)]
707 public static ImageView DownCast(BaseHandle handle)
711 throw new ArgumentNullException(nameof(handle));
713 ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
714 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
719 /// Sets this ImageView from the given URL.<br />
720 /// If the URL is empty, ImageView will not display anything.<br />
722 /// <param name="url">The URL to the image resource to display.</param>
723 /// <exception cref="ArgumentNullException"> Thrown when url is null. </exception>
724 /// <since_tizen> 3 </since_tizen>
725 public void SetImage(string url)
729 throw new ArgumentNullException(nameof(url));
732 if (url.Contains(".json"))
734 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
738 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url));
739 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
742 // Update cached property. Note that we should not re-create new visual.
743 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
745 UpdateImage(ImageVisualProperty.URL, urlValue, false);
747 imagePropertyUpdatedFlag = false;
751 /// Queries if all resources required by a control are loaded and ready.<br />
752 /// Most resources are only loaded when the control is placed on the stage.<br />
753 /// True if the resources are loaded and ready, false otherwise.<br />
755 /// <since_tizen> 3 </since_tizen>
756 public new bool IsResourceReady()
758 bool ret = Interop.View.IsResourceReady(SwigCPtr);
759 if (NDalicPINVOKE.SWIGPendingException.Pending)
760 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
765 /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
767 /// <since_tizen> 5 </since_tizen>
770 // Sync as current properties
774 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionReload);
778 /// Plays the animated GIF. This is also the default playback mode.
780 /// <since_tizen> 5 </since_tizen>
783 // Sync as current properties
787 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPlay);
791 /// Pauses the animated GIF.
793 /// <since_tizen> 5 </since_tizen>
796 // Sync as current properties
800 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPause);
804 /// Stops the animated GIF.
806 /// <since_tizen> 5 </since_tizen>
809 // Sync as current properties
814 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionStop);
818 /// Gets or sets the URL of the alpha mask.<br />
821 /// <since_tizen> 6</since_tizen>
822 [EditorBrowsable(EditorBrowsableState.Never)]
823 public string AlphaMaskURL
827 return GetValue(AlphaMaskURLProperty) as string;
831 SetValue(AlphaMaskURLProperty, value);
832 NotifyPropertyChanged();
836 private string InternalAlphaMaskURL
842 PropertyValue maskUrl = GetCachedImageVisualProperty(ImageVisualProperty.AlphaMaskURL);
843 maskUrl?.Get(out ret);
850 PropertyValue setValue = new PropertyValue(value ?? "");
851 UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
852 // When we never set CropToMask property before, we should set default value as true.
853 using (PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask))
855 if (cropToMask == null)
857 using PropertyValue setCropValue = new PropertyValue(true);
858 UpdateImage(ImageVisualProperty.CropToMask, setCropValue);
867 /// Whether to crop image to mask or scale mask to fit image.
869 /// <since_tizen> 6 </since_tizen>
870 public bool CropToMask
874 return (bool)GetValue(CropToMaskProperty);
878 SetValue(CropToMaskProperty, value);
879 NotifyPropertyChanged();
882 private bool InternalCropToMask
888 PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask);
889 cropToMask?.Get(out ret);
890 cropToMask?.Dispose();
896 PropertyValue setValue = new PropertyValue(value);
897 UpdateImage(ImageVisualProperty.CropToMask, setValue);
903 /// Actions property value for Reload image.
905 internal static readonly int ActionReload = Interop.ImageView.ImageVisualActionReloadGet();
908 /// Actions property value to Play animated images.
910 internal static readonly int ActionPlay = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
913 /// Actions property value to Pause animated images.
915 internal static readonly int ActionPause = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
918 /// Actions property value to Stop animated images.
920 internal static readonly int ActionStop = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
922 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
926 case FittingModeType.ShrinkToFit:
927 return VisualFittingModeType.FitKeepAspectRatio;
928 case FittingModeType.ScaleToFill:
929 return VisualFittingModeType.OverFitKeepAspectRatio;
930 case FittingModeType.Center:
931 return VisualFittingModeType.Center;
932 case FittingModeType.Fill:
933 return VisualFittingModeType.Fill;
934 case FittingModeType.FitHeight:
935 return VisualFittingModeType.FitHeight;
936 case FittingModeType.FitWidth:
937 return VisualFittingModeType.FitWidth;
939 return VisualFittingModeType.Fill;
943 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
947 case VisualFittingModeType.FitKeepAspectRatio:
948 return FittingModeType.ShrinkToFit;
949 case VisualFittingModeType.OverFitKeepAspectRatio:
950 return FittingModeType.ScaleToFill;
951 case VisualFittingModeType.Center:
952 return FittingModeType.Center;
953 case VisualFittingModeType.Fill:
954 return FittingModeType.Fill;
955 case VisualFittingModeType.FitHeight:
956 return FittingModeType.FitHeight;
957 case VisualFittingModeType.FitWidth:
958 return FittingModeType.FitWidth;
960 return FittingModeType.ShrinkToFit;
964 internal override LayoutItem CreateDefaultLayout()
966 return new ImageLayout();
970 /// Gets or sets fitting options used when resizing images to fit.<br />
971 /// If not supplied, the default is FittingModeType.Fill.<br />
972 /// For normal quad images only.<br />
975 /// <since_tizen> 6 </since_tizen>
976 [EditorBrowsable(EditorBrowsableState.Never)]
977 public FittingModeType FittingMode
981 return (FittingModeType)GetValue(FittingModeProperty);
985 SetValue(FittingModeProperty, value);
986 NotifyPropertyChanged();
990 private FittingModeType InternalFittingMode
994 int ret = (int)VisualFittingModeType.Fill;
996 PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
997 fittingMode?.Get(out ret);
998 fittingMode?.Dispose();
1000 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
1004 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
1005 PropertyValue setValue = new PropertyValue((int)ret);
1006 UpdateImage(Visual.Property.VisualFittingMode, setValue);
1007 setValue?.Dispose();
1012 /// Gets or sets the desired image width.<br />
1013 /// If not specified, the actual image width is used.<br />
1014 /// For normal quad images only.<br />
1017 /// <since_tizen> 6 </since_tizen>
1018 [EditorBrowsable(EditorBrowsableState.Never)]
1019 public int DesiredWidth
1023 return (int)GetValue(DesiredWidthProperty);
1027 SetValue(DesiredWidthProperty, value);
1028 NotifyPropertyChanged();
1031 private int InternalDesiredWidth
1035 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1036 if (_desired_width != -1 && _desired_height != -1)
1040 PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
1041 desirewidth?.Get(out _desired_width);
1042 desirewidth?.Dispose();
1044 return _desired_width;
1048 if (_desired_width != value)
1050 _desired_width = value;
1051 PropertyValue setValue = new PropertyValue(value);
1052 UpdateImage(ImageVisualProperty.DesiredWidth, setValue, false);
1053 setValue?.Dispose();
1059 /// Gets or sets the desired image height.<br />
1060 /// If not specified, the actual image height is used.<br />
1061 /// For normal quad images only.<br />
1064 /// <since_tizen> 6 </since_tizen>
1065 [EditorBrowsable(EditorBrowsableState.Never)]
1066 public int DesiredHeight
1070 return (int)GetValue(DesiredHeightProperty);
1074 SetValue(DesiredHeightProperty, value);
1075 NotifyPropertyChanged();
1078 private int InternalDesiredHeight
1082 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1083 if (_desired_width != -1 && _desired_height != -1)
1087 PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
1088 desireheight?.Get(out _desired_height);
1089 desireheight?.Dispose();
1091 return _desired_height;
1095 if (_desired_height != value)
1097 _desired_height = value;
1098 PropertyValue setValue = new PropertyValue(value);
1099 UpdateImage(ImageVisualProperty.DesiredHeight, setValue, false);
1100 setValue?.Dispose();
1106 /// Gets or sets ReleasePolicy for image.<br />
1107 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
1109 [EditorBrowsable(EditorBrowsableState.Never)]
1110 public ReleasePolicyType ReleasePolicy
1114 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
1118 SetValue(ReleasePolicyProperty, value);
1119 NotifyPropertyChanged();
1123 private ReleasePolicyType InternalReleasePolicy
1127 int ret = (int)ReleasePolicyType.Detached;
1129 PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
1130 releasePoli?.Get(out ret);
1131 releasePoli?.Dispose();
1133 return (ReleasePolicyType)ret;
1137 PropertyValue setValue = new PropertyValue((int)value);
1138 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
1139 setValue?.Dispose();
1144 /// Gets or sets the wrap mode for the u coordinate.<br />
1145 /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
1146 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1147 /// For normal quad images only.<br />
1150 /// <since_tizen> 6 </since_tizen>
1151 [EditorBrowsable(EditorBrowsableState.Never)]
1152 public WrapModeType WrapModeU
1156 return (WrapModeType)GetValue(WrapModeUProperty);
1160 SetValue(WrapModeUProperty, value);
1161 NotifyPropertyChanged();
1165 private WrapModeType InternalWrapModeU
1169 int ret = (int)WrapModeType.Default;
1171 PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
1172 wrapModeU?.Get(out ret);
1173 wrapModeU?.Dispose();
1175 return (WrapModeType)ret;
1179 PropertyValue setValue = new PropertyValue((int)value);
1180 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
1181 setValue?.Dispose();
1186 /// Gets or sets the wrap mode for the v coordinate.<br />
1187 /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
1188 /// 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.<br />
1189 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1190 /// For normal quad images only.
1193 /// <since_tizen> 6 </since_tizen>
1194 [EditorBrowsable(EditorBrowsableState.Never)]
1195 public WrapModeType WrapModeV
1199 return (WrapModeType)GetValue(WrapModeVProperty);
1203 SetValue(WrapModeVProperty, value);
1204 NotifyPropertyChanged();
1208 private WrapModeType InternalWrapModeV
1212 int ret = (int)WrapModeType.Default;
1214 PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
1215 wrapModeV?.Get(out ret);
1216 wrapModeV?.Dispose();
1218 return (WrapModeType)ret;
1222 PropertyValue setValue = new PropertyValue((int)value);
1223 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1224 setValue?.Dispose();
1229 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1232 /// This is false by default.
1233 /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1234 /// to preserve the aspect ratio of the image resource.
1235 /// AdjustViewSize works only if ImageView is added to a View having Layout.
1236 /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1237 /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1239 /// <since_tizen> 9 </since_tizen>
1240 public bool AdjustViewSize
1244 return (bool)GetValue(AdjustViewSizeProperty);
1248 SetValue(AdjustViewSizeProperty, value);
1249 NotifyPropertyChanged();
1252 private bool adjustViewSize = false;
1255 /// ImageView PlaceHolderUrl, type string.
1256 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
1257 /// When it is set as null, it gives empty string ("") to be read.
1259 /// <since_tizen> 11 </since_tizen>
1260 [EditorBrowsable(EditorBrowsableState.Never)]
1261 public string PlaceHolderUrl
1265 return (string)GetValue(PlaceHolderUrlProperty);
1269 SetValue(PlaceHolderUrlProperty, value);
1270 NotifyPropertyChanged();
1275 /// Gets or sets whether the image use TransitionEffect or not<br />
1277 /// <since_tizen> 11 </since_tizen>
1278 [EditorBrowsable(EditorBrowsableState.Never)]
1279 public bool TransitionEffect
1283 return (bool)GetValue(TransitionEffectProperty);
1287 SetValue(TransitionEffectProperty, value);
1288 NotifyPropertyChanged();
1293 /// The mixed color value for the image.
1297 /// The property cascade chaining set is not recommended.
1301 /// This way is recommended for setting the property
1303 /// var imageView = new ImageView();
1304 /// imageView.ImageColor = new Color(0.5f, 0.1f, 0.0f, 1.0f);
1306 /// This way to set the property is prohibited
1308 /// imageView.ImageColor.R = 0.5f; //This does not guarantee a proper operation
1311 [EditorBrowsable(EditorBrowsableState.Never)]
1312 public Color ImageColor
1316 return (Color)GetValue(ImageColorProperty);
1320 SetValue(ImageColorProperty, value);
1321 NotifyPropertyChanged();
1325 internal Selector<string> ResourceUrlSelector
1327 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1330 resourceUrlSelector?.Reset(this);
1331 if (value == null) return;
1333 if (value.HasAll()) SetResourceUrl(value.All);
1334 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1339 /// Get attributes, it is abstract function and must be override.
1341 [EditorBrowsable(EditorBrowsableState.Never)]
1342 protected override ViewStyle CreateViewStyle()
1344 return new ImageViewStyle();
1347 internal void SetImage(string url, Uint16Pair size)
1349 if (url.Contains(".json"))
1351 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1355 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
1356 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1359 _desired_width = size?.GetWidth() ?? -1;
1360 _desired_height = size?.GetHeight() ?? -1;
1362 // Update cached property. Note that we should not re-create new visual.
1363 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
1365 UpdateImage(ImageVisualProperty.URL, urlValue, false);
1367 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
1369 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
1371 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
1373 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
1375 imagePropertyUpdatedFlag = false;
1378 internal ViewResourceReadySignal ResourceReadySignal(View view)
1380 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1381 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1385 internal override void ApplyCornerRadius()
1387 base.ApplyCornerRadius();
1389 if (backgroundExtraData == null) return;
1391 // Update corner radius properties to image by ActionUpdateProperty
1392 if (backgroundExtraDataUpdatedFlag.HasFlag(BackgroundExtraDataUpdatedFlag.ContentsCornerRadius))
1394 if (backgroundExtraData.CornerRadius != null)
1396 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1398 Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1402 internal override void ApplyBorderline()
1404 base.ApplyBorderline();
1406 if (backgroundExtraData == null) return;
1408 if (backgroundExtraDataUpdatedFlag.HasFlag(BackgroundExtraDataUpdatedFlag.ContentsBorderline))
1410 // Update borderline properties to image by ActionUpdateProperty
1411 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
1412 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
1413 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
1417 internal ResourceLoadingStatusType GetResourceStatus()
1419 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1423 /// you can override it to clean-up your own resources.
1425 /// <param name="type">DisposeTypes</param>
1426 /// <since_tizen> 3 </since_tizen>
1427 protected override void Dispose(DisposeTypes type)
1434 internalPixelArea?.Dispose();
1436 if (type == DisposeTypes.Explicit)
1439 //Release your own managed resources here.
1440 //You should release all of your own disposable objects here.
1443 borderSelector?.Reset(this);
1444 resourceUrlSelector?.Reset(this);
1445 imagePropertyUpdatedFlag = false;
1446 if (imagePropertyUpdateProcessAttachedFlag)
1448 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1449 imagePropertyUpdateProcessAttachedFlag = false;
1451 cachedImagePropertyMap?.Dispose();
1452 cachedImagePropertyMap = null;
1458 /// This will not be public opened.
1459 [EditorBrowsable(EditorBrowsableState.Never)]
1460 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1462 Interop.ImageView.DeleteImageView(swigCPtr);
1465 // Callback for View ResourceReady signal
1466 private void OnResourceReady(IntPtr data)
1468 if (!CheckResourceReady())
1473 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1474 if (data != IntPtr.Zero)
1476 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1479 if (_resourceReadyEventHandler != null)
1481 _resourceReadyEventHandler(this, e);
1485 private void SetResourceUrl(string value)
1487 if (_resourceUrl != ConvertResourceUrl(ref value))
1489 _resourceUrl = value;
1490 if (string.IsNullOrEmpty(_resourceUrl))
1492 // Special case. If we set ResourceUrl as empty, Unregist visual.
1497 using (PropertyValue setValue = new PropertyValue(value))
1499 UpdateImage(ImageVisualProperty.URL, setValue);
1501 // Special case. If we set GeneratedUrl, or FastTrackUploading, Create ImageVisual synchronously.
1502 if (value.StartsWith("dali://") || value.StartsWith("enbuf://") || _fastTrackUploading)
1510 private void SetBorder(Rectangle value)
1516 if (_border != value)
1518 _border = new Rectangle(value);
1519 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1524 /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1526 private void RemoveImage()
1528 // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1529 // Unregist and detach process only if previous resourceUrl was not empty
1530 string currentResourceUrl = "";
1531 PropertyValue currentResourceUrlValue = GetCachedImageVisualProperty(ImageVisualProperty.URL);
1532 if ((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1534 PropertyValue emptyValue = new PropertyValue();
1536 // Remove current registed Image.
1537 SetProperty(ImageView.Property.IMAGE, emptyValue);
1539 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1540 imagePropertyUpdatedFlag = false;
1541 if (imagePropertyUpdateProcessAttachedFlag)
1543 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1544 imagePropertyUpdateProcessAttachedFlag = false;
1546 // Update resourceUrl as empty value
1547 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1549 emptyValue?.Dispose();
1551 currentResourceUrlValue?.Dispose();
1555 /// Lazy call to UpdateImage.
1556 /// Collect Properties need to be update, and set properties that starts the Processing.
1558 /// If you want to update cachedImagePropertyMap, but don't want to request new visual creation, make requiredVisualCreation value as false.
1559 /// (Example : if we change SynchronousLoading property from 'true' to 'false', or if we call this function during UpdateImage)
1561 [EditorBrowsable(EditorBrowsableState.Never)]
1562 protected virtual void UpdateImage(int key, PropertyValue value, bool requiredVisualCreation = true)
1564 // Update image property map value as inputed value.
1569 // Throw exception if ImageView is disposed.
1570 throw new global::System.InvalidOperationException("[NUI][ImageVIew] Someone try to change disposed ImageView's property.\n");
1573 if (cachedImagePropertyMap == null)
1575 cachedImagePropertyMap = new PropertyMap();
1578 // To optimization, we don't check URL duplicate case. We already checked before.
1579 if (key != ImageVisualProperty.URL)
1581 using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1583 if (oldValue != null && oldValue.EqualTo(value))
1585 // Ignore UpdateImage query when we try to update equality value.
1590 imagePropertyUpdatedFlag = true;
1591 cachedImagePropertyMap[key] = value;
1593 // Lazy update only if visual creation required, and _resourceUrl is not empty, and ProcessAttachedFlag is false.
1594 if (requiredVisualCreation && !string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1596 imagePropertyUpdateProcessAttachedFlag = true;
1597 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1598 // Call process hardly.
1599 ProcessorController.Instance.Awake();
1605 /// Callback function to Lazy UpdateImage.
1607 private void UpdateImage(object source, EventArgs e)
1609 // Note : To allow event attachment during UpdateImage, let we make flag as false before call UpdateImage().
1610 imagePropertyUpdateProcessAttachedFlag = false;
1615 /// Update image-relative properties synchronously.
1616 /// After call this API, All image properties updated.
1619 /// Current version ImageView property update asynchronously.
1620 /// If you want to guarantee that ImageView property setuped,
1621 /// Please call this ImageView.UpdateImage() API.
1623 [EditorBrowsable(EditorBrowsableState.Never)]
1624 protected virtual void UpdateImage()
1626 if (!imagePropertyUpdatedFlag) return;
1628 imagePropertyUpdatedFlag = false;
1630 if (cachedImagePropertyMap == null)
1632 cachedImagePropertyMap = new PropertyMap();
1635 // Checkup the cached visual type is AnimatedImage.
1636 // It is trick to know that this code is running on AnimatedImageView.UpdateImage() with resourceURLs or not.
1637 int visualType = (int)Visual.Type.Invalid;
1638 if (!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage)))
1640 // If ResourceUrl is not setuped, don't set property. fast return.
1641 if (string.IsNullOrEmpty(_resourceUrl))
1645 if (_border == null)
1647 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1648 cachedImagePropertyMap[Visual.Property.Type] = image;
1653 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1654 cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1656 PropertyValue border = new PropertyValue(_border);
1657 cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1662 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1664 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1665 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1667 cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1668 cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1672 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1674 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1675 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1676 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1678 cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1679 cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1680 cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1684 // We already applied background extra data now.
1685 backgroundExtraDataUpdatedFlag &= ~BackgroundExtraDataUpdatedFlag.ContentsCornerRadius;
1686 backgroundExtraDataUpdatedFlag &= ~BackgroundExtraDataUpdatedFlag.ContentsBorderline;
1688 // Do Fitting Buffer when desired dimension is set
1689 // TODO : Couldn't we do this job in dali-engine side.
1690 if (_desired_width != -1 && _desired_height != -1)
1692 if (_resourceUrl != null)
1694 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1695 if (imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0)
1697 int adjustedDesiredWidth, adjustedDesiredHeight;
1698 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1699 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1700 if (aspectOfImageSize > aspectOfDesiredSize)
1702 adjustedDesiredWidth = _desired_width;
1703 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1707 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1708 adjustedDesiredHeight = _desired_height;
1711 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1712 cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1713 returnWidth?.Dispose();
1714 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1715 cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1716 returnHeight?.Dispose();
1717 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1718 cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1719 scaleToFit?.Dispose();
1721 imageSize?.Dispose();
1729 /// Merge our collected properties, and set IMAGE property internally.
1731 private void UpdateImageMap()
1733 // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1734 using (PropertyMap imageMap = new PropertyMap())
1736 using (PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1738 returnValue?.Get(imageMap);
1740 if (cachedImagePropertyMap != null)
1742 imageMap?.Merge(cachedImagePropertyMap);
1744 using (PropertyValue setValue = new PropertyValue(imageMap))
1746 SetProperty(ImageView.Property.IMAGE, setValue);
1749 // Update cached image property.
1750 MergeCachedImageVisualProperty(imageMap);
1755 /// Get image visual property by key.
1756 /// If we found value in local Cached result, return that.
1757 /// Else, get synced native map and return that.
1758 /// If there is no matched value, return null.
1760 [EditorBrowsable(EditorBrowsableState.Never)]
1761 protected virtual PropertyValue GetImageVisualProperty(int key)
1763 PropertyValue ret = GetCachedImageVisualProperty(key);
1766 // If we cannot find result form cached map, Get value from native engine.
1767 ret = Image?.Find(key);
1773 /// Get image visual property from NUI cached image map by key.
1774 /// If there is no matched value, return null.
1776 [EditorBrowsable(EditorBrowsableState.Never)]
1777 protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1779 return cachedImagePropertyMap?.Find(key);
1783 /// Update NUI cached image visual property map by inputed property map.
1786 /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1788 [EditorBrowsable(EditorBrowsableState.Never)]
1789 protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1791 if (map == null) return;
1792 if (cachedImagePropertyMap == null)
1794 cachedImagePropertyMap = new PropertyMap();
1796 foreach (var key in cachedImagePropertyKeyList)
1798 PropertyValue value = map.Find(key);
1801 // Update-or-Insert new value
1802 cachedImagePropertyMap[key] = value;
1803 if (key == ImageVisualProperty.URL)
1805 // Special case. If key is Url, update _resourceUrl here.
1806 value.Get(out _resourceUrl);
1813 /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1814 /// So before get base.GetNaturalSize(), we should synchronous image properties
1816 internal override Vector3 GetNaturalSize()
1818 // Sync as current properties
1820 return base.GetNaturalSize();
1823 [EditorBrowsable(EditorBrowsableState.Never)]
1824 protected override bool CheckResourceReady()
1826 // If we have some properties to be updated, this signal is old thing.
1827 // We need to ignore current signal, and wait next.
1828 return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1831 private void OnResourceLoaded(IntPtr view)
1833 if (!CheckResourceReady())
1837 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1838 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1840 if (_resourceLoadedEventHandler != null)
1842 _resourceLoadedEventHandler(this, e);
1847 /// Event arguments of resource ready.
1849 /// <since_tizen> 3 </since_tizen>
1850 public class ResourceReadyEventArgs : EventArgs
1855 /// The view whose resource is ready.
1857 /// <since_tizen> 3 </since_tizen>
1871 internal class ResourceLoadedEventArgs : EventArgs
1873 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1874 public ResourceLoadingStatusType Status
1887 internal new class Property
1889 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1890 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1891 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1892 internal static readonly int PlaceHolderUrl = Interop.ImageView.PlaceHolderImageGet();
1893 internal static readonly int TransitionEffect = Interop.ImageView.TransitionEffectGet();
1895 internal static void Preload()
1897 // Do nothing. Just call for load static values.
1901 private enum ImageType
1904 /// For Normal Image.
1909 /// For normal image, with synchronous loading and orientation correction property
1914 /// For nine-patch image
1919 private void OnBorderChanged(int x, int y, int width, int height)
1921 Border = new Rectangle(x, y, width, height);
1923 private void OnPixelAreaChanged(float x, float y, float z, float w)
1925 PixelArea = new RelativeVector4(x, y, z, w);
1928 private class ImageLayout : LayoutItem
1931 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1932 /// 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.
1934 [EditorBrowsable(EditorBrowsableState.Never)]
1935 public bool AdjustViewSize
1939 return (Owner as ImageView)?.AdjustViewSize ?? false;
1943 if (Owner is ImageView imageView)
1945 imageView.AdjustViewSize = value;
1951 [EditorBrowsable(EditorBrowsableState.Never)]
1952 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1954 // To not change the view size by DALi
1955 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1956 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1958 float specWidth = widthMeasureSpec.Size.AsDecimal();
1959 float specHeight = heightMeasureSpec.Size.AsDecimal();
1960 float naturalWidth = Owner.NaturalSize.Width;
1961 float naturalHeight = Owner.NaturalSize.Height;
1962 float minWidth = Owner.MinimumSize.Width;
1963 float maxWidth = Owner.MaximumSize.Width;
1964 float minHeight = Owner.MinimumSize.Height;
1965 float maxHeight = Owner.MaximumSize.Height;
1966 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1968 // Assume that the new width and height are given from the view's suggested size by default.
1969 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1970 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1972 // The width and height measure specs are going to be used to set measured size.
1973 // Mark that the measure specs are changed by default to update measure specs later.
1974 bool widthSpecChanged = true;
1975 bool heightSpecChanged = true;
1977 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1979 newWidth = specWidth;
1980 widthSpecChanged = false;
1982 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1984 if ((AdjustViewSize) && (aspectRatio > 0))
1986 newHeight = newWidth * aspectRatio;
1991 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1993 newHeight = specHeight;
1994 heightSpecChanged = false;
1996 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1998 if ((AdjustViewSize) && (aspectRatio > 0))
2000 newWidth = newHeight / aspectRatio;
2005 if (widthSpecChanged)
2007 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
2010 if (heightSpecChanged)
2012 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
2015 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
2016 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
2018 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
2019 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));