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 private EventHandler<ResourceReadyEventArgs> _resourceReadyEventHandler;
36 private ResourceReadyEventCallbackType _resourceReadyEventCallback;
37 private EventHandler<ResourceLoadedEventArgs> _resourceLoadedEventHandler;
38 private _resourceLoadedCallbackType _resourceLoadedCallback;
41 /// Convert non-null string that some keyword change as application specific directory.
43 /// <param name="value">Inputed and replaced after this function finished</param>
44 /// <returns>Replaced url</returns>
45 private static string ConvertResourceUrl(ref string value)
48 if (value.StartsWith("*Resource*"))
50 string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
51 value = value.Replace("*Resource*", resource);
56 // Collection of image-sensitive properties.
57 private static readonly List<int> cachedImagePropertyKeyList = new List<int> {
59 ImageVisualProperty.URL,
60 ImageVisualProperty.AlphaMaskURL,
61 ImageVisualProperty.CropToMask,
62 Visual.Property.VisualFittingMode,
63 ImageVisualProperty.DesiredWidth,
64 ImageVisualProperty.DesiredHeight,
65 ImageVisualProperty.ReleasePolicy,
66 ImageVisualProperty.WrapModeU,
67 ImageVisualProperty.WrapModeV,
68 ImageVisualProperty.SynchronousLoading,
69 Visual.Property.MixColor,
70 Visual.Property.PremultipliedAlpha,
71 ImageVisualProperty.OrientationCorrection,
72 ImageVisualProperty.FastTrackUploading,
73 NpatchImageVisualProperty.Border,
74 NpatchImageVisualProperty.BorderOnly,
76 internal PropertyMap cachedImagePropertyMap;
77 internal bool imagePropertyUpdatedFlag = false;
79 private bool imagePropertyUpdateProcessAttachedFlag = false;
80 private Rectangle _border;
81 private string _resourceUrl = "";
82 private int _desired_width = -1;
83 private int _desired_height = -1;
84 private bool _fastTrackUploading = false;
85 private TriggerableSelector<string> resourceUrlSelector;
86 private TriggerableSelector<Rectangle> borderSelector;
88 private RelativeVector4 internalPixelArea;
91 /// Creates an initialized ImageView.
93 /// <since_tizen> 3 </since_tizen>
94 public ImageView() : this(Interop.ImageView.New(), true)
96 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
99 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
100 [EditorBrowsable(EditorBrowsableState.Never)]
101 public ImageView(ViewStyle viewStyle) : this(Interop.ImageView.New(), true, viewStyle)
106 /// Creates an initialized ImageView with setting the status of shown or hidden.
108 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
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(bool shown) : this(Interop.ImageView.New(), true)
113 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
118 /// Creates an initialized ImageView from a URL to an image resource.<br />
119 /// If the string is empty, ImageView will not display anything.<br />
121 /// <param name="url">The URL of the image resource to display.</param>
122 /// <since_tizen> 3 </since_tizen>
123 public ImageView(string url) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
127 // Update cached property. Note that we should not re-create new visual.
128 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
130 UpdateImage(ImageVisualProperty.URL, urlValue, false);
132 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
137 /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden.
139 /// <param name="url">The URL of the image resource to display.</param>
140 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
141 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
142 [EditorBrowsable(EditorBrowsableState.Never)]
143 public ImageView(string url, bool shown) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
147 // Update cached property. Note that we should not re-create new visual.
148 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
150 UpdateImage(ImageVisualProperty.URL, urlValue, false);
152 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
156 internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size)), true)
159 _desired_width = size?.GetWidth() ?? -1;
160 _desired_height = size?.GetHeight() ?? -1;
162 // Update cached property. Note that we should not re-create new visual.
163 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
165 UpdateImage(ImageVisualProperty.URL, urlValue, false);
167 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
169 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
171 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
173 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
175 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
183 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
191 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
199 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
200 private delegate void ResourceReadyEventCallbackType(IntPtr data);
201 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
202 private delegate void _resourceLoadedCallbackType(IntPtr view);
205 /// An event for ResourceReady signal which can be used to subscribe or unsubscribe the event handler.<br />
206 /// This signal is emitted after all resources required by a control are loaded and ready.<br />
207 /// Most resources are only loaded when the control is placed on the stage.<br />
209 /// <since_tizen> 3 </since_tizen>
210 public event EventHandler<ResourceReadyEventArgs> ResourceReady
214 if (_resourceReadyEventHandler == null)
216 _resourceReadyEventCallback = OnResourceReady;
217 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
218 resourceReadySignal?.Connect(_resourceReadyEventCallback);
219 resourceReadySignal?.Dispose();
222 _resourceReadyEventHandler += value;
227 _resourceReadyEventHandler -= value;
229 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
230 if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
232 resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
234 resourceReadySignal?.Dispose();
238 internal event EventHandler<ResourceLoadedEventArgs> ResourceLoaded
242 if (_resourceLoadedEventHandler == null)
244 _resourceLoadedCallback = OnResourceLoaded;
245 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
246 resourceReadySignal?.Connect(_resourceLoadedCallback);
247 resourceReadySignal?.Dispose();
250 _resourceLoadedEventHandler += value;
254 _resourceLoadedEventHandler -= value;
255 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
256 if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
258 resourceReadySignal?.Disconnect(_resourceLoadedCallback);
260 resourceReadySignal?.Dispose();
265 /// Enumeration for LoadingStatus of image.
267 /// <since_tizen> 5 </since_tizen>
268 public enum LoadingStatusType
271 /// Loading preparing status.
273 /// <since_tizen> 5 </since_tizen>
276 /// Loading ready status.
278 /// <since_tizen> 5 </since_tizen>
281 /// Loading failed status.
283 /// <since_tizen> 5 </since_tizen>
288 /// Enumeration for MaskingMode of image.
290 [EditorBrowsable(EditorBrowsableState.Never)]
291 public enum MaskingModeType
294 /// Applies alpha masking on rendering time.
296 [EditorBrowsable(EditorBrowsableState.Never)]
299 /// Applies alpha masking on loading time.
301 [EditorBrowsable(EditorBrowsableState.Never)]
306 /// ImageView ResourceUrl, type string.
307 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
308 /// When it is set as null, it gives empty string ("") to be read.
310 /// <since_tizen> 3 </since_tizen>
311 public string ResourceUrl
315 return (string)GetValue(ResourceUrlProperty);
319 SetValue(ResourceUrlProperty, value);
320 NotifyPropertyChanged();
325 /// This will be deprecated, Use Image instead. <br />
326 /// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
328 /// <since_tizen> 3 </since_tizen>
329 [Obsolete("Do not use this, that will be deprecated. Use Image property instead.")]
330 [EditorBrowsable(EditorBrowsableState.Never)]
331 public PropertyMap ImageMap
335 return GetValue(ImageMapProperty) as PropertyMap;
339 SetValue(ImageMapProperty, value);
340 NotifyPropertyChanged();
343 private PropertyMap InternalImageMap
349 // Sync as current properties
352 // Get current properties force.
353 PropertyMap returnValue = new PropertyMap();
354 PropertyValue image = GetProperty(ImageView.Property.IMAGE);
355 image?.Get(returnValue);
358 // Update cached property map
359 if (returnValue != null)
361 MergeCachedImageVisualProperty(returnValue);
374 PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
375 SetProperty(ImageView.Property.IMAGE, setValue);
377 // Image properties are changed hardly. We should ignore lazy UpdateImage
378 imagePropertyUpdatedFlag = false;
379 cachedImagePropertyMap?.Dispose();
380 cachedImagePropertyMap = null;
381 MergeCachedImageVisualProperty(value);
383 NotifyPropertyChanged();
390 /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
393 /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
394 /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
395 /// you can also use <see cref="Visual.Property"/>. <br />
396 /// See <see cref="Visual.Property"/> for a detailed description. <br />
399 /// The following example demonstrates how to use the Image property.
401 /// PropertyMap map = new PropertyMap();
402 /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
403 /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
404 /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
405 /// imageview.Image = map;
408 /// <since_tizen> 4 </since_tizen>
409 public PropertyMap Image
415 return (PropertyMap)GetValue(ImageProperty);
426 SetValue(ImageProperty, value);
427 NotifyPropertyChanged();
433 /// ImageView PreMultipliedAlpha, type Boolean.<br />
434 /// Image must be initialized.<br />
436 /// <since_tizen> 3 </since_tizen>
437 public bool PreMultipliedAlpha
441 return (bool)GetValue(PreMultipliedAlphaProperty);
445 SetValue(PreMultipliedAlphaProperty, value);
446 NotifyPropertyChanged();
451 /// ImageView PixelArea, type Vector4 (Animatable property).<br />
452 /// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].<br />
455 /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
457 /// <since_tizen> 3 </since_tizen>
458 public RelativeVector4 PixelArea
462 return (RelativeVector4)GetValue(PixelAreaProperty);
466 SetValue(PixelAreaProperty, value);
467 NotifyPropertyChanged();
472 /// The border of the image in the order: left, right, bottom, top.<br />
473 /// If set, ImageMap will be ignored.<br />
474 /// For N-Patch images only.<br />
478 /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
480 /// <since_tizen> 3 </since_tizen>
481 public Rectangle Border
485 Rectangle temp = (Rectangle)GetValue(BorderProperty);
492 return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
497 SetValue(BorderProperty, value);
498 NotifyPropertyChanged();
503 /// Gets or sets whether to draw the borders only (if true).<br />
504 /// If not specified, the default is false.<br />
505 /// For N-Patch images only.<br />
508 /// <since_tizen> 3 </since_tizen>
509 public bool BorderOnly
513 return (bool)GetValue(BorderOnlyProperty);
517 SetValue(BorderOnlyProperty, value);
518 NotifyPropertyChanged();
523 /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
525 /// <since_tizen> 3 </since_tizen>
526 [Obsolete("This has been deprecated since API9 and will be removed in API11. Use SynchronousLoading instead.")]
527 public bool SynchronosLoading
531 return SynchronousLoading;
535 SynchronousLoading = value;
540 /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
543 /// Changing this property make this ImageView load image synchronously at the next loading
544 /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
545 /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
547 /// <since_tizen> 9 </since_tizen>
548 public bool SynchronousLoading
552 return (bool)GetValue(SynchronousLoadingProperty);
556 SetValue(SynchronousLoadingProperty, value);
557 NotifyPropertyChanged();
562 /// Gets or sets whether to automatically correct the orientation of an image.<br />
564 /// <since_tizen> 5 </since_tizen>
565 public bool OrientationCorrection
569 return (bool)GetValue(OrientationCorrectionProperty);
573 SetValue(OrientationCorrectionProperty, value);
574 NotifyPropertyChanged();
579 /// Gets or sets whether to apply mask on GPU or not.<br />
581 [EditorBrowsable(EditorBrowsableState.Never)]
582 public MaskingModeType MaskingMode
586 return (MaskingModeType)GetValue(MaskingModeProperty);
590 SetValue(MaskingModeProperty, value);
591 NotifyPropertyChanged();
595 private MaskingModeType InternalMaskingMode
599 int ret = (int)MaskingModeType.MaskingOnLoading;
601 PropertyValue maskingMode = GetCachedImageVisualProperty(ImageVisualProperty.MaskingMode);
602 maskingMode?.Get(out ret);
603 maskingMode?.Dispose();
605 return (MaskingModeType)ret;
609 MaskingModeType ret = value;
610 PropertyValue setValue = new PropertyValue((int)ret);
611 UpdateImage(ImageVisualProperty.MaskingMode, setValue);
617 /// Gets or sets whether to apply fast track uploading or not.<br />
620 /// If we use fast track uploading feature, It can upload texture without event-thead dependency. But also,<br />
621 /// - Texture size is invalid until ResourceReady signal comes.<br />
622 /// - Texture cannot be cached (We always try to load new image).<br />
623 /// - Seamless visual change didn't supported.<br />
624 /// - Alpha masking didn't supported. If you try, It will load as normal case.<br />
625 /// - Synchronous loading didn't supported. If you try, It will load as normal case.<br />
626 /// - Reload action didn't supported. If you try, It will load as normal case.<br />
627 /// - Atlas loading didn't supported. If you try, It will load as normal case.<br />
628 /// - Custom shader didn't supported. If you try, It will load as normal case.
630 [EditorBrowsable(EditorBrowsableState.Never)]
631 public bool FastTrackUploading
635 return (bool)GetValue(FastTrackUploadingProperty);
639 SetValue(FastTrackUploadingProperty, value);
640 NotifyPropertyChanged();
644 private bool InternalFastTrackUploading
648 PropertyValue fastTrackUploading = GetCachedImageVisualProperty(ImageVisualProperty.FastTrackUploading);
649 fastTrackUploading?.Get(out _fastTrackUploading);
650 fastTrackUploading?.Dispose();
652 return _fastTrackUploading;
656 if (_fastTrackUploading != value)
658 _fastTrackUploading = value;
660 PropertyValue setValue = new PropertyValue(_fastTrackUploading);
661 UpdateImage(ImageVisualProperty.FastTrackUploading, setValue);
664 if (_fastTrackUploading && !string.IsNullOrEmpty(_resourceUrl))
666 // Special case. If user set FastTrackUploading mean, user want to upload image As-Soon-As-Possible.
667 // Create ImageVisual synchronously.
675 /// Gets the loading state of the visual resource.
677 /// <since_tizen> 5 </since_tizen>
678 public ImageView.LoadingStatusType LoadingStatus
682 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
687 /// Downcasts a handle to imageView handle.
689 /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
690 /// Do not use this, that will be deprecated. Use as keyword instead.
691 /// <since_tizen> 3 </since_tizen>
692 [Obsolete("Do not use this, that will be deprecated. Use as keyword instead. " +
694 "BaseHandle handle = new ImageView(imagePath); " +
695 "ImageView image = handle as ImageView")]
696 [EditorBrowsable(EditorBrowsableState.Never)]
697 public static ImageView DownCast(BaseHandle handle)
701 throw new ArgumentNullException(nameof(handle));
703 ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
704 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
709 /// Sets this ImageView from the given URL.<br />
710 /// If the URL is empty, ImageView will not display anything.<br />
712 /// <param name="url">The URL to the image resource to display.</param>
713 /// <exception cref="ArgumentNullException"> Thrown when url is null. </exception>
714 /// <since_tizen> 3 </since_tizen>
715 public void SetImage(string url)
719 throw new ArgumentNullException(nameof(url));
722 if (url.Contains(".json"))
724 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
728 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url));
729 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
732 // Update cached property. Note that we should not re-create new visual.
733 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
735 UpdateImage(ImageVisualProperty.URL, urlValue, false);
737 imagePropertyUpdatedFlag = false;
741 /// Queries if all resources required by a control are loaded and ready.<br />
742 /// Most resources are only loaded when the control is placed on the stage.<br />
743 /// True if the resources are loaded and ready, false otherwise.<br />
745 /// <since_tizen> 3 </since_tizen>
746 public new bool IsResourceReady()
748 bool ret = Interop.View.IsResourceReady(SwigCPtr);
749 if (NDalicPINVOKE.SWIGPendingException.Pending)
750 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
755 /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
757 /// <since_tizen> 5 </since_tizen>
760 // Sync as current properties
764 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionReload);
768 /// Plays the animated GIF. This is also the default playback mode.
770 /// <since_tizen> 5 </since_tizen>
773 // Sync as current properties
777 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPlay);
781 /// Pauses the animated GIF.
783 /// <since_tizen> 5 </since_tizen>
786 // Sync as current properties
790 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPause);
794 /// Stops the animated GIF.
796 /// <since_tizen> 5 </since_tizen>
799 // Sync as current properties
804 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionStop);
808 /// Gets or sets the URL of the alpha mask.<br />
811 /// <since_tizen> 6</since_tizen>
812 [EditorBrowsable(EditorBrowsableState.Never)]
813 public string AlphaMaskURL
817 return GetValue(AlphaMaskURLProperty) as string;
821 SetValue(AlphaMaskURLProperty, value);
822 NotifyPropertyChanged();
826 private string InternalAlphaMaskURL
832 PropertyValue maskUrl = GetCachedImageVisualProperty(ImageVisualProperty.AlphaMaskURL);
833 maskUrl?.Get(out ret);
840 PropertyValue setValue = new PropertyValue(value ?? "");
841 UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
842 // When we never set CropToMask property before, we should set default value as true.
843 using (PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask))
845 if (cropToMask == null)
847 using PropertyValue setCropValue = new PropertyValue(true);
848 UpdateImage(ImageVisualProperty.CropToMask, setCropValue);
857 /// Whether to crop image to mask or scale mask to fit image.
859 /// <since_tizen> 6 </since_tizen>
860 public bool CropToMask
864 return (bool)GetValue(CropToMaskProperty);
868 SetValue(CropToMaskProperty, value);
869 NotifyPropertyChanged();
872 private bool InternalCropToMask
878 PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask);
879 cropToMask?.Get(out ret);
880 cropToMask?.Dispose();
886 PropertyValue setValue = new PropertyValue(value);
887 UpdateImage(ImageVisualProperty.CropToMask, setValue);
893 /// Actions property value for Reload image.
895 internal static readonly int ActionReload = Interop.ImageView.ImageVisualActionReloadGet();
898 /// Actions property value to Play animated images.
900 internal static readonly int ActionPlay = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
903 /// Actions property value to Pause animated images.
905 internal static readonly int ActionPause = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
908 /// Actions property value to Stop animated images.
910 internal static readonly int ActionStop = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
912 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
916 case FittingModeType.ShrinkToFit:
917 return VisualFittingModeType.FitKeepAspectRatio;
918 case FittingModeType.ScaleToFill:
919 return VisualFittingModeType.OverFitKeepAspectRatio;
920 case FittingModeType.Center:
921 return VisualFittingModeType.Center;
922 case FittingModeType.Fill:
923 return VisualFittingModeType.Fill;
924 case FittingModeType.FitHeight:
925 return VisualFittingModeType.FitHeight;
926 case FittingModeType.FitWidth:
927 return VisualFittingModeType.FitWidth;
929 return VisualFittingModeType.Fill;
933 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
937 case VisualFittingModeType.FitKeepAspectRatio:
938 return FittingModeType.ShrinkToFit;
939 case VisualFittingModeType.OverFitKeepAspectRatio:
940 return FittingModeType.ScaleToFill;
941 case VisualFittingModeType.Center:
942 return FittingModeType.Center;
943 case VisualFittingModeType.Fill:
944 return FittingModeType.Fill;
945 case VisualFittingModeType.FitHeight:
946 return FittingModeType.FitHeight;
947 case VisualFittingModeType.FitWidth:
948 return FittingModeType.FitWidth;
950 return FittingModeType.ShrinkToFit;
954 internal override LayoutItem CreateDefaultLayout()
956 return new ImageLayout();
960 /// Gets or sets fitting options used when resizing images to fit.<br />
961 /// If not supplied, the default is FittingModeType.Fill.<br />
962 /// For normal quad images only.<br />
965 /// <since_tizen> 6 </since_tizen>
966 [EditorBrowsable(EditorBrowsableState.Never)]
967 public FittingModeType FittingMode
971 return (FittingModeType)GetValue(FittingModeProperty);
975 SetValue(FittingModeProperty, value);
976 NotifyPropertyChanged();
980 private FittingModeType InternalFittingMode
984 int ret = (int)VisualFittingModeType.Fill;
986 PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
987 fittingMode?.Get(out ret);
988 fittingMode?.Dispose();
990 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
994 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
995 PropertyValue setValue = new PropertyValue((int)ret);
996 UpdateImage(Visual.Property.VisualFittingMode, setValue);
1002 /// Gets or sets the desired image width.<br />
1003 /// If not specified, the actual image width is used.<br />
1004 /// For normal quad images only.<br />
1007 /// <since_tizen> 6 </since_tizen>
1008 [EditorBrowsable(EditorBrowsableState.Never)]
1009 public int DesiredWidth
1013 return (int)GetValue(DesiredWidthProperty);
1017 SetValue(DesiredWidthProperty, value);
1018 NotifyPropertyChanged();
1021 private int InternalDesiredWidth
1025 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1026 if (_desired_width != -1 && _desired_height != -1)
1030 PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
1031 desirewidth?.Get(out _desired_width);
1032 desirewidth?.Dispose();
1034 return _desired_width;
1038 if (_desired_width != value)
1040 _desired_width = value;
1041 PropertyValue setValue = new PropertyValue(value);
1042 UpdateImage(ImageVisualProperty.DesiredWidth, setValue, false);
1043 setValue?.Dispose();
1049 /// Gets or sets the desired image height.<br />
1050 /// If not specified, the actual image height is used.<br />
1051 /// For normal quad images only.<br />
1054 /// <since_tizen> 6 </since_tizen>
1055 [EditorBrowsable(EditorBrowsableState.Never)]
1056 public int DesiredHeight
1060 return (int)GetValue(DesiredHeightProperty);
1064 SetValue(DesiredHeightProperty, value);
1065 NotifyPropertyChanged();
1068 private int InternalDesiredHeight
1072 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1073 if (_desired_width != -1 && _desired_height != -1)
1077 PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
1078 desireheight?.Get(out _desired_height);
1079 desireheight?.Dispose();
1081 return _desired_height;
1085 if (_desired_height != value)
1087 _desired_height = value;
1088 PropertyValue setValue = new PropertyValue(value);
1089 UpdateImage(ImageVisualProperty.DesiredHeight, setValue, false);
1090 setValue?.Dispose();
1096 /// Gets or sets ReleasePolicy for image.<br />
1097 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
1099 [EditorBrowsable(EditorBrowsableState.Never)]
1100 public ReleasePolicyType ReleasePolicy
1104 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
1108 SetValue(ReleasePolicyProperty, value);
1109 NotifyPropertyChanged();
1113 private ReleasePolicyType InternalReleasePolicy
1117 int ret = (int)ReleasePolicyType.Detached;
1119 PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
1120 releasePoli?.Get(out ret);
1121 releasePoli?.Dispose();
1123 return (ReleasePolicyType)ret;
1127 PropertyValue setValue = new PropertyValue((int)value);
1128 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
1129 setValue?.Dispose();
1134 /// Gets or sets the wrap mode for the u coordinate.<br />
1135 /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
1136 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1137 /// For normal quad images only.<br />
1140 /// <since_tizen> 6 </since_tizen>
1141 [EditorBrowsable(EditorBrowsableState.Never)]
1142 public WrapModeType WrapModeU
1146 return (WrapModeType)GetValue(WrapModeUProperty);
1150 SetValue(WrapModeUProperty, value);
1151 NotifyPropertyChanged();
1155 private WrapModeType InternalWrapModeU
1159 int ret = (int)WrapModeType.Default;
1161 PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
1162 wrapModeU?.Get(out ret);
1163 wrapModeU?.Dispose();
1165 return (WrapModeType)ret;
1169 PropertyValue setValue = new PropertyValue((int)value);
1170 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
1171 setValue?.Dispose();
1176 /// Gets or sets the wrap mode for the v coordinate.<br />
1177 /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
1178 /// 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 />
1179 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1180 /// For normal quad images only.
1183 /// <since_tizen> 6 </since_tizen>
1184 [EditorBrowsable(EditorBrowsableState.Never)]
1185 public WrapModeType WrapModeV
1189 return (WrapModeType)GetValue(WrapModeVProperty);
1193 SetValue(WrapModeVProperty, value);
1194 NotifyPropertyChanged();
1198 private WrapModeType InternalWrapModeV
1202 int ret = (int)WrapModeType.Default;
1204 PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
1205 wrapModeV?.Get(out ret);
1206 wrapModeV?.Dispose();
1208 return (WrapModeType)ret;
1212 PropertyValue setValue = new PropertyValue((int)value);
1213 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1214 setValue?.Dispose();
1219 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1222 /// This is false by default.
1223 /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1224 /// to preserve the aspect ratio of the image resource.
1225 /// AdjustViewSize works only if ImageView is added to a View having Layout.
1226 /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1227 /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1229 /// <since_tizen> 9 </since_tizen>
1230 public bool AdjustViewSize
1234 return (bool)GetValue(AdjustViewSizeProperty);
1238 SetValue(AdjustViewSizeProperty, value);
1239 NotifyPropertyChanged();
1242 private bool adjustViewSize = false;
1245 /// ImageView PlaceHolderUrl, type string.
1246 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
1247 /// When it is set as null, it gives empty string ("") to be read.
1249 /// <since_tizen> 11 </since_tizen>
1250 [EditorBrowsable(EditorBrowsableState.Never)]
1251 public string PlaceHolderUrl
1255 return (string)GetValue(PlaceHolderUrlProperty);
1259 SetValue(PlaceHolderUrlProperty, value);
1260 NotifyPropertyChanged();
1265 /// Gets or sets whether the image use TransitionEffect or not<br />
1267 /// <since_tizen> 11 </since_tizen>
1268 [EditorBrowsable(EditorBrowsableState.Never)]
1269 public bool TransitionEffect
1273 return (bool)GetValue(TransitionEffectProperty);
1277 SetValue(TransitionEffectProperty, value);
1278 NotifyPropertyChanged();
1283 /// The mixed color value for the image.
1287 /// The property cascade chaining set is not recommended.
1291 /// This way is recommended for setting the property
1293 /// var imageView = new ImageView();
1294 /// imageView.ImageColor = new Color(0.5f, 0.1f, 0.0f, 1.0f);
1296 /// This way to set the property is prohibited
1298 /// imageView.ImageColor.R = 0.5f; //This does not guarantee a proper operation
1301 [EditorBrowsable(EditorBrowsableState.Never)]
1302 public Color ImageColor
1306 return (Color)GetValue(ImageColorProperty);
1310 SetValue(ImageColorProperty, value);
1311 NotifyPropertyChanged();
1315 internal Selector<string> ResourceUrlSelector
1317 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1320 resourceUrlSelector?.Reset(this);
1321 if (value == null) return;
1323 if (value.HasAll()) SetResourceUrl(value.All);
1324 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1329 /// Get attributes, it is abstract function and must be override.
1331 [EditorBrowsable(EditorBrowsableState.Never)]
1332 protected override ViewStyle CreateViewStyle()
1334 return new ImageViewStyle();
1337 internal void SetImage(string url, Uint16Pair size)
1339 if (url.Contains(".json"))
1341 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1345 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
1346 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1349 _desired_width = size?.GetWidth() ?? -1;
1350 _desired_height = size?.GetHeight() ?? -1;
1352 // Update cached property. Note that we should not re-create new visual.
1353 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
1355 UpdateImage(ImageVisualProperty.URL, urlValue, false);
1357 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
1359 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
1361 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
1363 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
1365 imagePropertyUpdatedFlag = false;
1368 internal ViewResourceReadySignal ResourceReadySignal(View view)
1370 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1371 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1375 internal override void ApplyCornerRadius()
1377 base.ApplyCornerRadius();
1379 if (backgroundExtraData == null) return;
1381 // Update corner radius properties to image by ActionUpdateProperty
1382 if (backgroundExtraDataUpdatedFlag.HasFlag(BackgroundExtraDataUpdatedFlag.ContentsCornerRadius))
1384 if (backgroundExtraData.CornerRadius != null)
1386 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1388 Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1392 internal override void ApplyBorderline()
1394 base.ApplyBorderline();
1396 if (backgroundExtraData == null) return;
1398 if (backgroundExtraDataUpdatedFlag.HasFlag(BackgroundExtraDataUpdatedFlag.ContentsBorderline))
1400 // Update borderline properties to image by ActionUpdateProperty
1401 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
1402 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
1403 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
1407 internal ResourceLoadingStatusType GetResourceStatus()
1409 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1413 /// you can override it to clean-up your own resources.
1415 /// <param name="type">DisposeTypes</param>
1416 /// <since_tizen> 3 </since_tizen>
1417 protected override void Dispose(DisposeTypes type)
1424 internalPixelArea?.Dispose();
1426 if (type == DisposeTypes.Explicit)
1429 //Release your own managed resources here.
1430 //You should release all of your own disposable objects here.
1433 borderSelector?.Reset(this);
1434 resourceUrlSelector?.Reset(this);
1435 imagePropertyUpdatedFlag = false;
1436 if (imagePropertyUpdateProcessAttachedFlag)
1438 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1439 imagePropertyUpdateProcessAttachedFlag = false;
1441 cachedImagePropertyMap?.Dispose();
1442 cachedImagePropertyMap = null;
1448 /// This will not be public opened.
1449 [EditorBrowsable(EditorBrowsableState.Never)]
1450 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1452 Interop.ImageView.DeleteImageView(swigCPtr);
1455 // Callback for View ResourceReady signal
1456 private void OnResourceReady(IntPtr data)
1458 if (!CheckResourceReady())
1463 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1464 if (data != IntPtr.Zero)
1466 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1469 if (_resourceReadyEventHandler != null)
1471 _resourceReadyEventHandler(this, e);
1475 private void SetResourceUrl(string value)
1477 if (_resourceUrl != ConvertResourceUrl(ref value))
1479 _resourceUrl = value;
1480 if (string.IsNullOrEmpty(_resourceUrl))
1482 // Special case. If we set ResourceUrl as empty, Unregist visual.
1487 using (PropertyValue setValue = new PropertyValue(value))
1489 UpdateImage(ImageVisualProperty.URL, setValue);
1491 // Special case. If we set GeneratedUrl, or FastTrackUploading, Create ImageVisual synchronously.
1492 if (value.StartsWith("dali://") || value.StartsWith("enbuf://") || _fastTrackUploading)
1500 private void SetBorder(Rectangle value)
1506 if (_border != value)
1508 _border = new Rectangle(value);
1509 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1514 /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1516 private void RemoveImage()
1518 // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1519 // Unregist and detach process only if previous resourceUrl was not empty
1520 string currentResourceUrl = "";
1521 PropertyValue currentResourceUrlValue = GetCachedImageVisualProperty(ImageVisualProperty.URL);
1522 if ((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1524 PropertyValue emptyValue = new PropertyValue();
1526 // Remove current registed Image.
1527 SetProperty(ImageView.Property.IMAGE, emptyValue);
1529 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1530 imagePropertyUpdatedFlag = false;
1531 if (imagePropertyUpdateProcessAttachedFlag)
1533 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1534 imagePropertyUpdateProcessAttachedFlag = false;
1536 // Update resourceUrl as empty value
1537 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1539 emptyValue?.Dispose();
1541 currentResourceUrlValue?.Dispose();
1545 /// Lazy call to UpdateImage.
1546 /// Collect Properties need to be update, and set properties that starts the Processing.
1548 /// If you want to update cachedImagePropertyMap, but don't want to request new visual creation, make requiredVisualCreation value as false.
1549 /// (Example : if we change SynchronousLoading property from 'true' to 'false', or if we call this function during UpdateImage)
1551 [EditorBrowsable(EditorBrowsableState.Never)]
1552 protected virtual void UpdateImage(int key, PropertyValue value, bool requiredVisualCreation = true)
1554 // Update image property map value as inputed value.
1559 // Throw exception if ImageView is disposed.
1560 throw new global::System.InvalidOperationException("[NUI][ImageVIew] Someone try to change disposed ImageView's property.\n");
1563 if (cachedImagePropertyMap == null)
1565 cachedImagePropertyMap = new PropertyMap();
1568 // To optimization, we don't check URL duplicate case. We already checked before.
1569 if (key != ImageVisualProperty.URL)
1571 using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1573 if (oldValue != null && oldValue.EqualTo(value))
1575 // Ignore UpdateImage query when we try to update equality value.
1580 imagePropertyUpdatedFlag = true;
1581 cachedImagePropertyMap[key] = value;
1583 // Lazy update only if visual creation required, and _resourceUrl is not empty, and ProcessAttachedFlag is false.
1584 if (requiredVisualCreation && !string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1586 imagePropertyUpdateProcessAttachedFlag = true;
1587 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1588 // Call process hardly.
1589 ProcessorController.Instance.Awake();
1595 /// Callback function to Lazy UpdateImage.
1597 private void UpdateImage(object source, EventArgs e)
1599 // Note : To allow event attachment during UpdateImage, let we make flag as false before call UpdateImage().
1600 imagePropertyUpdateProcessAttachedFlag = false;
1605 /// Update image-relative properties synchronously.
1606 /// After call this API, All image properties updated.
1609 /// Current version ImageView property update asynchronously.
1610 /// If you want to guarantee that ImageView property setuped,
1611 /// Please call this ImageView.UpdateImage() API.
1613 [EditorBrowsable(EditorBrowsableState.Never)]
1614 protected virtual void UpdateImage()
1616 if (!imagePropertyUpdatedFlag) return;
1618 imagePropertyUpdatedFlag = false;
1620 if (cachedImagePropertyMap == null)
1622 cachedImagePropertyMap = new PropertyMap();
1625 // Checkup the cached visual type is AnimatedImage.
1626 // It is trick to know that this code is running on AnimatedImageView.UpdateImage() with resourceURLs or not.
1627 int visualType = (int)Visual.Type.Invalid;
1628 if (!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage)))
1630 // If ResourceUrl is not setuped, don't set property. fast return.
1631 if (string.IsNullOrEmpty(_resourceUrl))
1635 if (_border == null)
1637 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1638 cachedImagePropertyMap[Visual.Property.Type] = image;
1643 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1644 cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1646 PropertyValue border = new PropertyValue(_border);
1647 cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1652 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1654 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1655 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1657 cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1658 cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1662 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1664 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1665 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1666 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1668 cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1669 cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1670 cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1674 // We already applied background extra data now.
1675 backgroundExtraDataUpdatedFlag &= ~BackgroundExtraDataUpdatedFlag.ContentsCornerRadius;
1676 backgroundExtraDataUpdatedFlag &= ~BackgroundExtraDataUpdatedFlag.ContentsBorderline;
1678 // Do Fitting Buffer when desired dimension is set
1679 // TODO : Couldn't we do this job in dali-engine side.
1680 if (_desired_width != -1 && _desired_height != -1)
1682 if (_resourceUrl != null)
1684 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1685 if (imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0)
1687 int adjustedDesiredWidth, adjustedDesiredHeight;
1688 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1689 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1690 if (aspectOfImageSize > aspectOfDesiredSize)
1692 adjustedDesiredWidth = _desired_width;
1693 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1697 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1698 adjustedDesiredHeight = _desired_height;
1701 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1702 cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1703 returnWidth?.Dispose();
1704 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1705 cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1706 returnHeight?.Dispose();
1707 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1708 cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1709 scaleToFit?.Dispose();
1711 imageSize?.Dispose();
1719 /// Merge our collected properties, and set IMAGE property internally.
1721 private void UpdateImageMap()
1723 // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1724 using (PropertyMap imageMap = new PropertyMap())
1726 using (PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1728 returnValue?.Get(imageMap);
1730 if (cachedImagePropertyMap != null)
1732 imageMap?.Merge(cachedImagePropertyMap);
1734 using (PropertyValue setValue = new PropertyValue(imageMap))
1736 SetProperty(ImageView.Property.IMAGE, setValue);
1739 // Update cached image property.
1740 MergeCachedImageVisualProperty(imageMap);
1745 /// Get image visual property by key.
1746 /// If we found value in local Cached result, return that.
1747 /// Else, get synced native map and return that.
1748 /// If there is no matched value, return null.
1750 [EditorBrowsable(EditorBrowsableState.Never)]
1751 protected virtual PropertyValue GetImageVisualProperty(int key)
1753 PropertyValue ret = GetCachedImageVisualProperty(key);
1756 // If we cannot find result form cached map, Get value from native engine.
1757 ret = Image?.Find(key);
1763 /// Get image visual property from NUI cached image map by key.
1764 /// If there is no matched value, return null.
1766 [EditorBrowsable(EditorBrowsableState.Never)]
1767 protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1769 return cachedImagePropertyMap?.Find(key);
1773 /// Update NUI cached image visual property map by inputed property map.
1776 /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1778 [EditorBrowsable(EditorBrowsableState.Never)]
1779 protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1781 if (map == null) return;
1782 if (cachedImagePropertyMap == null)
1784 cachedImagePropertyMap = new PropertyMap();
1786 foreach (var key in cachedImagePropertyKeyList)
1788 PropertyValue value = map.Find(key);
1791 // Update-or-Insert new value
1792 cachedImagePropertyMap[key] = value;
1793 if (key == ImageVisualProperty.URL)
1795 // Special case. If key is Url, update _resourceUrl here.
1796 value.Get(out _resourceUrl);
1803 /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1804 /// So before get base.GetNaturalSize(), we should synchronous image properties
1806 internal override Vector3 GetNaturalSize()
1808 // Sync as current properties
1810 return base.GetNaturalSize();
1813 [EditorBrowsable(EditorBrowsableState.Never)]
1814 protected override bool CheckResourceReady()
1816 // If we have some properties to be updated, this signal is old thing.
1817 // We need to ignore current signal, and wait next.
1818 return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1821 private void OnResourceLoaded(IntPtr view)
1823 if (!CheckResourceReady())
1827 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1828 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1830 if (_resourceLoadedEventHandler != null)
1832 _resourceLoadedEventHandler(this, e);
1837 /// Event arguments of resource ready.
1839 /// <since_tizen> 3 </since_tizen>
1840 public class ResourceReadyEventArgs : EventArgs
1845 /// The view whose resource is ready.
1847 /// <since_tizen> 3 </since_tizen>
1861 internal class ResourceLoadedEventArgs : EventArgs
1863 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1864 public ResourceLoadingStatusType Status
1877 internal new class Property
1879 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1880 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1881 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1882 internal static readonly int PlaceHolderUrl = Interop.ImageView.PlaceHolderImageGet();
1883 internal static readonly int TransitionEffect = Interop.ImageView.TransitionEffectGet();
1886 private enum ImageType
1889 /// For Normal Image.
1894 /// For normal image, with synchronous loading and orientation correction property
1899 /// For nine-patch image
1904 private void OnBorderChanged(int x, int y, int width, int height)
1906 Border = new Rectangle(x, y, width, height);
1908 private void OnPixelAreaChanged(float x, float y, float z, float w)
1910 PixelArea = new RelativeVector4(x, y, z, w);
1913 private class ImageLayout : LayoutItem
1916 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1917 /// 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.
1919 [EditorBrowsable(EditorBrowsableState.Never)]
1920 public bool AdjustViewSize
1924 return (Owner as ImageView)?.AdjustViewSize ?? false;
1928 if (Owner is ImageView imageView)
1930 imageView.AdjustViewSize = value;
1936 [EditorBrowsable(EditorBrowsableState.Never)]
1937 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1939 // To not change the view size by DALi
1940 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1941 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1943 float specWidth = widthMeasureSpec.Size.AsDecimal();
1944 float specHeight = heightMeasureSpec.Size.AsDecimal();
1945 float naturalWidth = Owner.NaturalSize.Width;
1946 float naturalHeight = Owner.NaturalSize.Height;
1947 float minWidth = Owner.MinimumSize.Width;
1948 float maxWidth = Owner.MaximumSize.Width;
1949 float minHeight = Owner.MinimumSize.Height;
1950 float maxHeight = Owner.MaximumSize.Height;
1951 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1953 // Assume that the new width and height are given from the view's suggested size by default.
1954 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1955 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1957 // The width and height measure specs are going to be used to set measured size.
1958 // Mark that the measure specs are changed by default to update measure specs later.
1959 bool widthSpecChanged = true;
1960 bool heightSpecChanged = true;
1962 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1964 newWidth = specWidth;
1965 widthSpecChanged = false;
1967 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1969 if ((AdjustViewSize) && (aspectRatio > 0))
1971 newHeight = newWidth * aspectRatio;
1976 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1978 newHeight = specHeight;
1979 heightSpecChanged = false;
1981 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1983 if ((AdjustViewSize) && (aspectRatio > 0))
1985 newWidth = newHeight / aspectRatio;
1990 if (widthSpecChanged)
1992 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1995 if (heightSpecChanged)
1997 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
2000 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
2001 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
2003 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
2004 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));