Merge remote-tracking branch 'origin/master' into tizen
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / ImageView.cs
1 /*
2 * Copyright(c) 2019 Samsung Electronics Co., Ltd.
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 *
16 */
17 using System;
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using System.ComponentModel;
21 using Tizen.NUI.Binding;
22
23 namespace Tizen.NUI.BaseComponents
24 {
25
26     /// <summary>
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 />
29     /// </summary>
30     /// <since_tizen> 3 </since_tizen>
31     public partial class ImageView : View
32     {
33         static ImageView() { }
34
35         private EventHandler<ResourceReadyEventArgs> _resourceReadyEventHandler;
36         private ResourceReadyEventCallbackType _resourceReadyEventCallback;
37         private EventHandler<ResourceLoadedEventArgs> _resourceLoadedEventHandler;
38         private _resourceLoadedCallbackType _resourceLoadedCallback;
39
40         /// <summary>
41         /// Convert non-null string that some keyword change as application specific directory.
42         /// </summary>
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)
46         {
47             value ??= "";
48             if (value.StartsWith("*Resource*"))
49             {
50                 string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
51                 value = value.Replace("*Resource*", resource);
52             }
53             return value;
54         }
55
56         // Collection of image-sensitive properties.
57         private static readonly List<int> cachedImagePropertyKeyList = new List<int> {
58             Visual.Property.Type,
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.PremultipliedAlpha,
70             ImageVisualProperty.OrientationCorrection,
71             NpatchImageVisualProperty.Border,
72             NpatchImageVisualProperty.BorderOnly,
73         };
74         internal PropertyMap cachedImagePropertyMap;
75         internal bool imagePropertyUpdatedFlag = false;
76
77         private bool imagePropertyUpdateProcessAttachedFlag = false;
78         private Rectangle _border;
79         private string _resourceUrl = "";
80         private int _desired_width = -1;
81         private int _desired_height = -1;
82         private TriggerableSelector<string> resourceUrlSelector;
83         private TriggerableSelector<Rectangle> borderSelector;
84
85         private RelativeVector4 internalPixelArea;
86
87         /// <summary>
88         /// Creates an initialized ImageView.
89         /// </summary>
90         /// <since_tizen> 3 </since_tizen>
91         public ImageView() : this(Interop.ImageView.New(), true)
92         {
93             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
94         }
95
96         /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
97         [EditorBrowsable(EditorBrowsableState.Never)]
98         public ImageView(ViewStyle viewStyle) : this(Interop.ImageView.New(), true, viewStyle)
99         {
100         }
101
102         /// <summary>
103         /// Creates an initialized ImageView with setting the status of shown or hidden.
104         /// </summary>
105         /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
106         /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
107         [EditorBrowsable(EditorBrowsableState.Never)]
108         public ImageView(bool shown) : this(Interop.ImageView.New(), true)
109         {
110             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
111             SetVisible(shown);
112         }
113
114         /// <summary>
115         /// Creates an initialized ImageView from a URL to an image resource.<br />
116         /// If the string is empty, ImageView will not display anything.<br />
117         /// </summary>
118         /// <param name="url">The URL of the image resource to display.</param>
119         /// <since_tizen> 3 </since_tizen>
120         public ImageView(string url) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
121         {
122             _resourceUrl = url;
123             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
124
125         }
126
127         /// <summary>
128         /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden.
129         /// </summary>
130         /// <param name="url">The URL of the image resource to display.</param>
131         /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
132         /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
133         [EditorBrowsable(EditorBrowsableState.Never)]
134         public ImageView(string url, bool shown) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
135         {
136             _resourceUrl = url;
137             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
138             SetVisible(shown);
139         }
140
141         internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size)), true)
142         {
143             _resourceUrl = url;
144             _desired_width = size?.GetWidth() ?? -1;
145             _desired_height = size?.GetHeight() ?? -1;
146             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
147
148             if (!shown)
149             {
150                 SetVisible(false);
151             }
152         }
153
154         internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
155         {
156             if (!shown)
157             {
158                 SetVisible(false);
159             }
160         }
161
162         internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
163         {
164             if (!shown)
165             {
166                 SetVisible(false);
167             }
168         }
169
170         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
171         private delegate void ResourceReadyEventCallbackType(IntPtr data);
172         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
173         private delegate void _resourceLoadedCallbackType(IntPtr view);
174
175         /// <summary>
176         /// An event for ResourceReady signal which can be used to subscribe or unsubscribe the event handler.<br />
177         /// This signal is emitted after all resources required by a control are loaded and ready.<br />
178         /// Most resources are only loaded when the control is placed on the stage.<br />
179         /// </summary>
180         /// <since_tizen> 3 </since_tizen>
181         public event EventHandler<ResourceReadyEventArgs> ResourceReady
182         {
183             add
184             {
185                 if (_resourceReadyEventHandler == null)
186                 {
187                     _resourceReadyEventCallback = OnResourceReady;
188                     ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
189                     resourceReadySignal?.Connect(_resourceReadyEventCallback);
190                     resourceReadySignal?.Dispose();
191                 }
192
193                 _resourceReadyEventHandler += value;
194             }
195
196             remove
197             {
198                 _resourceReadyEventHandler -= value;
199
200                 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
201                 if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
202                 {
203                     resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
204                 }
205                 resourceReadySignal?.Dispose();
206             }
207         }
208
209         internal event EventHandler<ResourceLoadedEventArgs> ResourceLoaded
210         {
211             add
212             {
213                 if (_resourceLoadedEventHandler == null)
214                 {
215                     _resourceLoadedCallback = OnResourceLoaded;
216                     ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
217                     resourceReadySignal?.Connect(_resourceLoadedCallback);
218                     resourceReadySignal?.Dispose();
219                 }
220
221                 _resourceLoadedEventHandler += value;
222             }
223             remove
224             {
225                 _resourceLoadedEventHandler -= value;
226                 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
227                 if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
228                 {
229                     resourceReadySignal?.Disconnect(_resourceLoadedCallback);
230                 }
231                 resourceReadySignal?.Dispose();
232             }
233         }
234
235         /// <summary>
236         /// Enumeration for LoadingStatus of image.
237         /// </summary>
238         /// <since_tizen> 5 </since_tizen>
239         public enum LoadingStatusType
240         {
241             /// <summary>
242             /// Loading preparing status.
243             /// </summary>
244             /// <since_tizen> 5 </since_tizen>
245             Preparing,
246             /// <summary>
247             /// Loading ready status.
248             /// </summary>
249             /// <since_tizen> 5 </since_tizen>
250             Ready,
251             /// <summary>
252             /// Loading failed status.
253             /// </summary>
254             /// <since_tizen> 5 </since_tizen>
255             Failed
256         }
257
258         /// <summary>
259         /// Enumeration for MaskingMode of image.
260         /// </summary>
261         [EditorBrowsable(EditorBrowsableState.Never)]
262         public enum MaskingModeType
263         {
264             /// <summary>
265             /// Applies alpha masking on rendering time.
266             /// </summary>
267             [EditorBrowsable(EditorBrowsableState.Never)]
268             MaskingOnRendering,
269             /// <summary>
270             /// Applies alpha masking on loading time.
271             /// </summary>
272             [EditorBrowsable(EditorBrowsableState.Never)]
273             MaskingOnLoading
274         }
275
276         /// <summary>
277         /// ImageView ResourceUrl, type string.
278         /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
279         /// When it is set as null, it gives empty string ("") to be read.
280         /// </summary>
281         /// <since_tizen> 3 </since_tizen>
282         public string ResourceUrl
283         {
284             get
285             {
286                 return (string)GetValue(ResourceUrlProperty);
287             }
288             set
289             {
290                 SetValue(ResourceUrlProperty, value);
291                 NotifyPropertyChanged();
292             }
293         }
294
295         /// <summary>
296         /// This will be deprecated, Use Image instead. <br />
297         /// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
298         /// </summary>
299         /// <since_tizen> 3 </since_tizen>
300         [Obsolete("Do not use this, that will be deprecated. Use Image property instead.")]
301         [EditorBrowsable(EditorBrowsableState.Never)]
302         public PropertyMap ImageMap
303         {
304             get
305             {
306                 return GetValue(ImageMapProperty) as PropertyMap;
307             }
308             set
309             {
310                 SetValue(ImageMapProperty, value);
311                 NotifyPropertyChanged();
312             }
313         }
314         private PropertyMap InternalImageMap
315         {
316             get
317             {
318                 if (_border == null)
319                 {
320                     // Sync as current properties
321                     UpdateImage();
322
323                     // Get current properties force.
324                     PropertyMap returnValue = new PropertyMap();
325                     PropertyValue image = GetProperty(ImageView.Property.IMAGE);
326                     image?.Get(returnValue);
327                     image?.Dispose();
328
329                     // Update cached property map
330                     if(returnValue != null)
331                     {
332                         MergeCachedImageVisualProperty(returnValue);
333                     }
334                     return returnValue;
335                 }
336                 else
337                 {
338                     return null;
339                 }
340             }
341             set
342             {
343                 if (_border == null)
344                 {
345                     PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
346                     SetProperty(ImageView.Property.IMAGE, setValue);
347
348                     // Image properties are changed hardly. We should ignore lazy UpdateImage
349                     imagePropertyUpdatedFlag = false;
350                     cachedImagePropertyMap?.Dispose();
351                     cachedImagePropertyMap = null;
352                     MergeCachedImageVisualProperty(value);
353
354                     NotifyPropertyChanged();
355                     setValue?.Dispose();
356                 }
357             }
358         }
359
360         /// <summary>
361         /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
362         /// </summary>
363         /// <remarks>
364         /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
365         /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
366         /// you can also use <see cref="Visual.Property"/>. <br />
367         /// See <see cref="Visual.Property"/> for a detailed description. <br />
368         /// </remarks>
369         /// <example>
370         /// The following example demonstrates how to use the Image property.
371         /// <code>
372         /// PropertyMap map = new PropertyMap();
373         /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
374         /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
375         /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
376         /// imageview.Image = map;
377         /// </code>
378         /// </example>
379         /// <since_tizen> 4 </since_tizen>
380         public PropertyMap Image
381         {
382             get
383             {
384                 if (_border == null)
385                 {
386                     return (PropertyMap)GetValue(ImageProperty);
387                 }
388                 else
389                 {
390                     return null;
391                 }
392             }
393             set
394             {
395                 if (_border == null)
396                 {
397                     SetValue(ImageProperty, value);
398                     NotifyPropertyChanged();
399                 }
400             }
401         }
402
403         /// <summary>
404         /// ImageView PreMultipliedAlpha, type Boolean.<br />
405         /// Image must be initialized.<br />
406         /// </summary>
407         /// <since_tizen> 3 </since_tizen>
408         public bool PreMultipliedAlpha
409         {
410             get
411             {
412                 return (bool)GetValue(PreMultipliedAlphaProperty);
413             }
414             set
415             {
416                 SetValue(PreMultipliedAlphaProperty, value);
417                 NotifyPropertyChanged();
418             }
419         }
420
421         /// <summary>
422         /// ImageView PixelArea, type Vector4 (Animatable property).<br />
423         /// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].<br />
424         /// </summary>
425         /// <remarks>
426         /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
427         /// </remarks>
428         /// <since_tizen> 3 </since_tizen>
429         public RelativeVector4 PixelArea
430         {
431             get
432             {
433                 return (RelativeVector4)GetValue(PixelAreaProperty);
434             }
435             set
436             {
437                 SetValue(PixelAreaProperty, value);
438                 NotifyPropertyChanged();
439             }
440         }
441
442         /// <summary>
443         /// The border of the image in the order: left, right, bottom, top.<br />
444         /// If set, ImageMap will be ignored.<br />
445         /// For N-Patch images only.<br />
446         /// Optional.
447         /// </summary>
448         /// <remarks>
449         /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
450         /// </remarks>
451         /// <since_tizen> 3 </since_tizen>
452         public Rectangle Border
453         {
454             get
455             {
456                 Rectangle temp = (Rectangle)GetValue(BorderProperty);
457                 if (null == temp)
458                 {
459                     return null;
460                 }
461                 else
462                 {
463                     return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
464                 }
465             }
466             set
467             {
468                 SetValue(BorderProperty, value);
469                 NotifyPropertyChanged();
470             }
471         }
472
473         /// <summary>
474         /// Gets or sets whether to draw the borders only (if true).<br />
475         /// If not specified, the default is false.<br />
476         /// For N-Patch images only.<br />
477         /// Optional.
478         /// </summary>
479         /// <since_tizen> 3 </since_tizen>
480         public bool BorderOnly
481         {
482             get
483             {
484                 return (bool)GetValue(BorderOnlyProperty);
485             }
486             set
487             {
488                 SetValue(BorderOnlyProperty, value);
489                 NotifyPropertyChanged();
490             }
491         }
492
493         /// <summary>
494         /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
495         /// </summary>
496         /// <since_tizen> 3 </since_tizen>
497         [Obsolete("This has been deprecated since API9 and will be removed in API11. Use SynchronousLoading instead.")]
498         public bool SynchronosLoading
499         {
500             get
501             {
502                 return SynchronousLoading;
503             }
504             set
505             {
506                 SynchronousLoading = value;
507             }
508         }
509
510         /// <summary>
511         /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
512         /// </summary>
513         /// <remarks>
514         /// Changing this property make this ImageView load image synchronously at the next loading
515         /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
516         /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
517         /// </remarks>
518         /// <since_tizen> 9 </since_tizen>
519         public bool SynchronousLoading
520         {
521             get
522             {
523                 return (bool)GetValue(SynchronousLoadingProperty);
524             }
525             set
526             {
527                 SetValue(SynchronousLoadingProperty, value);
528                 NotifyPropertyChanged();
529             }
530         }
531
532         /// <summary>
533         /// Gets or sets whether to automatically correct the orientation of an image.<br />
534         /// </summary>
535         /// <since_tizen> 5 </since_tizen>
536         public bool OrientationCorrection
537         {
538             get
539             {
540                 return (bool)GetValue(OrientationCorrectionProperty);
541             }
542             set
543             {
544                 SetValue(OrientationCorrectionProperty, value);
545                 NotifyPropertyChanged();
546             }
547         }
548
549         /// <summary>
550         /// Gets or sets whether to apply mask on GPU or not.<br />
551         /// </summary>
552         [EditorBrowsable(EditorBrowsableState.Never)]
553         public MaskingModeType MaskingMode
554         {
555             get
556             {
557                 return (MaskingModeType)GetValue(MaskingModeProperty);
558             }
559             set
560             {
561                 SetValue(MaskingModeProperty, value);
562                 NotifyPropertyChanged();
563             }
564         }
565
566         private MaskingModeType InternalMaskingMode
567         {
568             get
569             {
570                 int ret = (int)MaskingModeType.MaskingOnLoading;
571
572                 PropertyValue maskingMode = GetCachedImageVisualProperty(ImageVisualProperty.MaskingMode);
573                 maskingMode?.Get(out ret);
574                 maskingMode?.Dispose();
575
576                 return (MaskingModeType)ret;
577             }
578             set
579             {
580                 MaskingModeType ret = value;
581                 PropertyValue setValue = new PropertyValue((int)ret);
582                 UpdateImage(ImageVisualProperty.MaskingMode, setValue);
583                 setValue?.Dispose();
584             }
585         }
586
587         /// <summary>
588         /// Gets the loading state of the visual resource.
589         /// </summary>
590         /// <since_tizen> 5 </since_tizen>
591         public ImageView.LoadingStatusType LoadingStatus
592         {
593             get
594             {
595                 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
596             }
597         }
598
599         /// <summary>
600         /// Downcasts a handle to imageView handle.
601         /// </summary>
602         /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
603         /// Do not use this, that will be deprecated. Use as keyword instead.
604         /// <since_tizen> 3 </since_tizen>
605         [Obsolete("Do not use this, that will be deprecated. Use as keyword instead. " +
606         "Like: " +
607         "BaseHandle handle = new ImageView(imagePath); " +
608         "ImageView image = handle as ImageView")]
609         [EditorBrowsable(EditorBrowsableState.Never)]
610         public static ImageView DownCast(BaseHandle handle)
611         {
612             if (null == handle)
613             {
614                 throw new ArgumentNullException(nameof(handle));
615             }
616             ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
617             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
618             return ret;
619         }
620
621         /// <summary>
622         /// Sets this ImageView from the given URL.<br />
623         /// If the URL is empty, ImageView will not display anything.<br />
624         /// </summary>
625         /// <param name="url">The URL to the image resource to display.</param>
626         /// <exception cref="ArgumentNullException"> Thrown when url is null. </exception>
627         /// <since_tizen> 3 </since_tizen>
628         public void SetImage(string url)
629         {
630             if (null == url)
631             {
632                 throw new ArgumentNullException(nameof(url));
633             }
634
635             if (url.Contains(".json"))
636             {
637                 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
638                 return;
639             }
640
641             Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url));
642             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
643
644             _resourceUrl = url;
645         }
646
647         /// <summary>
648         /// Queries if all resources required by a control are loaded and ready.<br />
649         /// Most resources are only loaded when the control is placed on the stage.<br />
650         /// True if the resources are loaded and ready, false otherwise.<br />
651         /// </summary>
652         /// <since_tizen> 3 </since_tizen>
653         public new bool IsResourceReady()
654         {
655             bool ret = Interop.View.IsResourceReady(SwigCPtr);
656             if (NDalicPINVOKE.SWIGPendingException.Pending)
657                 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
658             return ret;
659         }
660
661         /// <summary>
662         /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
663         /// </summary>
664         /// <since_tizen> 5 </since_tizen>
665         public void Reload()
666         {
667             // Sync as current properties
668             UpdateImage();
669
670
671             Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionReload);
672         }
673
674         /// <summary>
675         /// Plays the animated GIF. This is also the default playback mode.
676         /// </summary>
677         /// <since_tizen> 5 </since_tizen>
678         public void Play()
679         {
680             // Sync as current properties
681             UpdateImage();
682
683
684             Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPlay);
685         }
686
687         /// <summary>
688         /// Pauses the animated GIF.
689         /// </summary>
690         /// <since_tizen> 5 </since_tizen>
691         public void Pause()
692         {
693             // Sync as current properties
694             UpdateImage();
695
696
697             Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPause);
698         }
699
700         /// <summary>
701         /// Stops the animated GIF.
702         /// </summary>
703         /// <since_tizen> 5 </since_tizen>
704         public void Stop()
705         {
706             // Sync as current properties
707             UpdateImage();
708
709
710
711             Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionStop);
712         }
713
714         /// <summary>
715         /// Gets or sets the URL of the alpha mask.<br />
716         /// Optional.
717         /// </summary>
718         /// <since_tizen> 6</since_tizen>
719         [EditorBrowsable(EditorBrowsableState.Never)]
720         public string AlphaMaskURL
721         {
722             get
723             {
724                 return GetValue(AlphaMaskURLProperty) as string;
725             }
726             set
727             {
728                 SetValue(AlphaMaskURLProperty, value);
729                 NotifyPropertyChanged();
730             }
731         }
732
733         private string InternalAlphaMaskURL
734         {
735             get
736             {
737                 string ret = "";
738
739                 PropertyValue maskUrl = GetCachedImageVisualProperty(ImageVisualProperty.AlphaMaskURL);
740                 maskUrl?.Get(out ret);
741                 maskUrl?.Dispose();
742
743                 return ret;
744             }
745             set
746             {
747                 PropertyValue setValue = new PropertyValue(value ?? "");
748                 UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
749                 // When we never set CropToMask property before, we should set default value as true.
750                 using(PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask))
751                 {
752                     if(cropToMask == null)
753                     {
754                         using PropertyValue setCropValue = new PropertyValue(true);
755                         UpdateImage(ImageVisualProperty.CropToMask, setCropValue);
756                     }
757                 }
758                 setValue?.Dispose();
759             }
760         }
761
762
763         /// <summary>
764         ///  Whether to crop image to mask or scale mask to fit image.
765         /// </summary>
766         /// <since_tizen> 6 </since_tizen>
767         public bool CropToMask
768         {
769             get
770             {
771                 return (bool)GetValue(CropToMaskProperty);
772             }
773             set
774             {
775                 SetValue(CropToMaskProperty, value);
776                 NotifyPropertyChanged();
777             }
778         }
779         private bool InternalCropToMask
780         {
781             get
782             {
783                 bool ret = false;
784
785                 PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask);
786                 cropToMask?.Get(out ret);
787                 cropToMask?.Dispose();
788
789                 return ret;
790             }
791             set
792             {
793                 PropertyValue setValue = new PropertyValue(value);
794                 UpdateImage(ImageVisualProperty.CropToMask, setValue);
795                 setValue?.Dispose();
796             }
797         }
798
799         /// <summary>
800         /// Actions property value for Reload image.
801         /// </summary>
802         private int ActionReload { get; set; } = Interop.ImageView.ImageVisualActionReloadGet();
803
804         /// <summary>
805         /// Actions property value to Play animated images.
806         /// This property can be redefined by child class if it use different value.
807         /// </summary>
808         [EditorBrowsable(EditorBrowsableState.Never)]
809         protected int ActionPlay { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
810
811         /// <summary>
812         /// Actions property value to Pause animated images.
813         /// This property can be redefined by child class if it use different value.
814         /// </summary>
815         [EditorBrowsable(EditorBrowsableState.Never)]
816         protected int ActionPause { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
817
818         /// <summary>
819         /// Actions property value to Stop animated images.
820         /// This property can be redefined by child class if it use different value.
821         /// </summary>
822         [EditorBrowsable(EditorBrowsableState.Never)]
823         protected int ActionStop { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
824
825         internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
826         {
827             switch (value)
828             {
829                 case FittingModeType.ShrinkToFit:
830                     return VisualFittingModeType.FitKeepAspectRatio;
831                 case FittingModeType.ScaleToFill:
832                     return VisualFittingModeType.OverFitKeepAspectRatio;
833                 case FittingModeType.Center:
834                     return VisualFittingModeType.Center;
835                 case FittingModeType.Fill:
836                     return VisualFittingModeType.Fill;
837                 case FittingModeType.FitHeight:
838                     return VisualFittingModeType.FitHeight;
839                 case FittingModeType.FitWidth:
840                     return VisualFittingModeType.FitWidth;
841                 default:
842                     return VisualFittingModeType.Fill;
843             }
844         }
845
846         internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
847         {
848             switch (value)
849             {
850                 case VisualFittingModeType.FitKeepAspectRatio:
851                     return FittingModeType.ShrinkToFit;
852                 case VisualFittingModeType.OverFitKeepAspectRatio:
853                     return FittingModeType.ScaleToFill;
854                 case VisualFittingModeType.Center:
855                     return FittingModeType.Center;
856                 case VisualFittingModeType.Fill:
857                     return FittingModeType.Fill;
858                 case VisualFittingModeType.FitHeight:
859                     return FittingModeType.FitHeight;
860                 case VisualFittingModeType.FitWidth:
861                     return FittingModeType.FitWidth;
862                 default:
863                     return FittingModeType.ShrinkToFit;
864             }
865         }
866
867         internal override LayoutItem CreateDefaultLayout()
868         {
869             return new ImageLayout();
870         }
871
872         /// <summary>
873         /// Gets or sets fitting options used when resizing images to fit.<br />
874         /// If not supplied, the default is FittingModeType.Fill.<br />
875         /// For normal quad images only.<br />
876         /// Optional.
877         /// </summary>
878         /// <since_tizen> 6 </since_tizen>
879         [EditorBrowsable(EditorBrowsableState.Never)]
880         public FittingModeType FittingMode
881         {
882             get
883             {
884                 return (FittingModeType)GetValue(FittingModeProperty);
885             }
886             set
887             {
888                 SetValue(FittingModeProperty, value);
889                 NotifyPropertyChanged();
890             }
891         }
892
893         private FittingModeType InternalFittingMode
894         {
895             get
896             {
897                 int ret = (int)VisualFittingModeType.Fill;
898
899                 PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
900                 fittingMode?.Get(out ret);
901                 fittingMode?.Dispose();
902
903                 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
904             }
905             set
906             {
907                 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
908                 PropertyValue setValue = new PropertyValue((int)ret);
909                 UpdateImage(Visual.Property.VisualFittingMode, setValue);
910                 setValue?.Dispose();
911             }
912         }
913
914         /// <summary>
915         /// Gets or sets the desired image width.<br />
916         /// If not specified, the actual image width is used.<br />
917         /// For normal quad images only.<br />
918         /// Optional.
919         /// </summary>
920         /// <since_tizen> 6 </since_tizen>
921         [EditorBrowsable(EditorBrowsableState.Never)]
922         public int DesiredWidth
923         {
924             get
925             {
926                 return (int)GetValue(DesiredWidthProperty);
927             }
928             set
929             {
930                 SetValue(DesiredWidthProperty, value);
931                 NotifyPropertyChanged();
932             }
933         }
934         private int InternalDesiredWidth
935         {
936             get
937             {
938                 // Sync as current properties only if both _desired_width and _desired_height are setuped.
939                 if(_desired_width != -1 && _desired_height != -1)
940                 {
941                     UpdateImage();
942                 }
943                 PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
944                 desirewidth?.Get(out _desired_width);
945                 desirewidth?.Dispose();
946
947                 return _desired_width;
948             }
949             set
950             {
951                 if (_desired_width != value)
952                 {
953                     _desired_width = value;
954                     PropertyValue setValue = new PropertyValue(value);
955                     UpdateImage(ImageVisualProperty.DesiredWidth, setValue);
956                     setValue?.Dispose();
957                 }
958             }
959         }
960
961         /// <summary>
962         /// Gets or sets the desired image height.<br />
963         /// If not specified, the actual image height is used.<br />
964         /// For normal quad images only.<br />
965         /// Optional.
966         /// </summary>
967         /// <since_tizen> 6 </since_tizen>
968         [EditorBrowsable(EditorBrowsableState.Never)]
969         public int DesiredHeight
970         {
971             get
972             {
973                 return (int)GetValue(DesiredHeightProperty);
974             }
975             set
976             {
977                 SetValue(DesiredHeightProperty, value);
978                 NotifyPropertyChanged();
979             }
980         }
981         private int InternalDesiredHeight
982         {
983             get
984             {
985                 // Sync as current properties only if both _desired_width and _desired_height are setuped.
986                 if(_desired_width != -1 && _desired_height != -1)
987                 {
988                     UpdateImage();
989                 }
990                 PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
991                 desireheight?.Get(out _desired_height);
992                 desireheight?.Dispose();
993
994                 return _desired_height;
995             }
996             set
997             {
998                 if (_desired_height != value)
999                 {
1000                     _desired_height = value;
1001                     PropertyValue setValue = new PropertyValue(value);
1002                     UpdateImage(ImageVisualProperty.DesiredHeight, setValue);
1003                     setValue?.Dispose();
1004                 }
1005             }
1006         }
1007
1008         /// <summary>
1009         /// Gets or sets ReleasePolicy for image.<br />
1010         /// If not supplied, the default is ReleasePolicyType.Detached.<br />
1011         /// </summary>
1012         [EditorBrowsable(EditorBrowsableState.Never)]
1013         public ReleasePolicyType ReleasePolicy
1014         {
1015             get
1016             {
1017                 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
1018             }
1019             set
1020             {
1021                 SetValue(ReleasePolicyProperty, value);
1022                 NotifyPropertyChanged();
1023             }
1024         }
1025         
1026         private ReleasePolicyType InternalReleasePolicy
1027         {
1028             get
1029             {
1030                 int ret = (int)ReleasePolicyType.Detached;
1031
1032                 PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
1033                 releasePoli?.Get(out ret);
1034                 releasePoli?.Dispose();
1035
1036                 return (ReleasePolicyType)ret;
1037             }
1038             set
1039             {
1040                 PropertyValue setValue = new PropertyValue((int)value);
1041                 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
1042                 setValue?.Dispose();
1043             }
1044         }
1045
1046         /// <summary>
1047         /// Gets or sets the wrap mode for the u coordinate.<br />
1048         /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
1049         /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1050         /// For normal quad images only.<br />
1051         /// Optional.
1052         /// </summary>
1053         /// <since_tizen> 6 </since_tizen>
1054         [EditorBrowsable(EditorBrowsableState.Never)]
1055         public WrapModeType WrapModeU
1056         {
1057             get
1058             {
1059                 return (WrapModeType)GetValue(WrapModeUProperty);
1060             }
1061             set
1062             {
1063                 SetValue(WrapModeUProperty, value);
1064                 NotifyPropertyChanged();
1065             }
1066         }
1067
1068         private WrapModeType InternalWrapModeU
1069         {
1070             get
1071             {
1072                 int ret = (int)WrapModeType.Default;
1073
1074                 PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
1075                 wrapModeU?.Get(out ret);
1076                 wrapModeU?.Dispose();
1077
1078                 return (WrapModeType)ret;
1079             }
1080             set
1081             {
1082                 PropertyValue setValue = new PropertyValue((int)value);
1083                 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
1084                 setValue?.Dispose();
1085             }
1086         }
1087
1088         /// <summary>
1089         /// Gets or sets the wrap mode for the v coordinate.<br />
1090         /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
1091         /// 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 />
1092         /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1093         /// For normal quad images only.
1094         /// Optional.
1095         /// </summary>
1096         /// <since_tizen> 6 </since_tizen>
1097         [EditorBrowsable(EditorBrowsableState.Never)]
1098         public WrapModeType WrapModeV
1099         {
1100             get
1101             {
1102                 return (WrapModeType)GetValue(WrapModeVProperty);
1103             }
1104             set
1105             {
1106                 SetValue(WrapModeVProperty, value);
1107                 NotifyPropertyChanged();
1108             }
1109         }
1110
1111         private WrapModeType InternalWrapModeV
1112         {
1113             get
1114             {
1115                 int ret = (int)WrapModeType.Default;
1116
1117                 PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
1118                 wrapModeV?.Get(out ret);
1119                 wrapModeV?.Dispose();
1120
1121                 return (WrapModeType)ret;
1122             }
1123             set
1124             {
1125                 PropertyValue setValue = new PropertyValue((int)value);
1126                 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1127                 setValue?.Dispose();
1128             }
1129         }
1130
1131         /// <summary>
1132         /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1133         /// </summary>
1134         /// <remarks>
1135         /// This is false by default.
1136         /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1137         /// to preserve the aspect ratio of the image resource.
1138         /// AdjustViewSize works only if ImageView is added to a View having Layout.
1139         /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1140         ///      If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1141         /// </remarks>
1142         /// <since_tizen> 9 </since_tizen>
1143         public bool AdjustViewSize
1144         {
1145             get
1146             {
1147                 return (bool)GetValue(AdjustViewSizeProperty);
1148             }
1149             set
1150             {
1151                 SetValue(AdjustViewSizeProperty, value);
1152                 NotifyPropertyChanged();
1153             }
1154         }
1155         private bool adjustViewSize = false;
1156
1157         /// <summary>
1158         /// ImageView PlaceHolderUrl, type string.
1159         /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
1160         /// When it is set as null, it gives empty string ("") to be read.
1161         /// </summary>
1162         /// <since_tizen> 11 </since_tizen>
1163         [EditorBrowsable(EditorBrowsableState.Never)]
1164         public string PlaceHolderUrl
1165         {
1166             get
1167             {
1168                 return (string)GetValue(PlaceHolderUrlProperty);
1169             }
1170             set
1171             {
1172                 SetValue(PlaceHolderUrlProperty, value);
1173                 NotifyPropertyChanged();
1174             }
1175         }
1176
1177         /// <summary>
1178         /// Gets or sets whether the image use TransitionEffect or not<br />
1179         /// </summary>
1180         /// <since_tizen> 11 </since_tizen>
1181         [EditorBrowsable(EditorBrowsableState.Never)]
1182         public bool TransitionEffect
1183         {
1184             get
1185             {
1186                 return (bool)GetValue(TransitionEffectProperty);
1187             }
1188             set
1189             {
1190                 SetValue(TransitionEffectProperty, value);
1191                 NotifyPropertyChanged();
1192             }
1193         }
1194
1195         internal Selector<string> ResourceUrlSelector
1196         {
1197             get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1198             set
1199             {
1200                 resourceUrlSelector?.Reset(this);
1201                 if (value == null) return;
1202
1203                 if (value.HasAll()) SetResourceUrl(value.All);
1204                 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1205             }
1206         }
1207
1208         /// <summary>
1209         /// Get attributes, it is abstract function and must be override.
1210         /// </summary>
1211         [EditorBrowsable(EditorBrowsableState.Never)]
1212         protected override ViewStyle CreateViewStyle()
1213         {
1214             return new ImageViewStyle();
1215         }
1216
1217         internal void SetImage(string url, Uint16Pair size)
1218         {
1219             if (url.Contains(".json"))
1220             {
1221                 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1222                 return;
1223             }
1224
1225             Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
1226             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1227
1228             _resourceUrl = url;
1229             _desired_width = size?.GetWidth() ?? -1;
1230             _desired_height = size?.GetHeight() ?? -1;
1231         }
1232
1233         internal ViewResourceReadySignal ResourceReadySignal(View view)
1234         {
1235             ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1236             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1237             return ret;
1238         }
1239
1240         internal override void ApplyCornerRadius()
1241         {
1242             base.ApplyCornerRadius();
1243
1244             if (backgroundExtraData == null) return;
1245
1246
1247             // Update corner radius properties to image by ActionUpdateProperty
1248             if (backgroundExtraData.CornerRadius != null)
1249             {
1250                 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1251             }
1252             Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1253         }
1254
1255         internal override void ApplyBorderline()
1256         {
1257             base.ApplyBorderline();
1258
1259             if (backgroundExtraData == null) return;
1260
1261
1262             // Update borderline properties to image by ActionUpdateProperty
1263             Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
1264             Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
1265             Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
1266         }
1267
1268         internal ResourceLoadingStatusType GetResourceStatus()
1269         {
1270             return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1271         }
1272
1273         /// <summary>
1274         /// you can override it to clean-up your own resources.
1275         /// </summary>
1276         /// <param name="type">DisposeTypes</param>
1277         /// <since_tizen> 3 </since_tizen>
1278         protected override void Dispose(DisposeTypes type)
1279         {
1280             if (disposed)
1281             {
1282                 return;
1283             }
1284
1285             internalPixelArea?.Dispose();
1286
1287             if (type == DisposeTypes.Explicit)
1288             {
1289                 //Called by User
1290                 //Release your own managed resources here.
1291                 //You should release all of your own disposable objects here.
1292                 _border?.Dispose();
1293                 _border = null;
1294                 borderSelector?.Reset(this);
1295                 resourceUrlSelector?.Reset(this);
1296                 imagePropertyUpdatedFlag = false;
1297                 if (imagePropertyUpdateProcessAttachedFlag)
1298                 {
1299                     ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1300                     imagePropertyUpdateProcessAttachedFlag = false;
1301                 }
1302                 cachedImagePropertyMap?.Dispose();
1303                 cachedImagePropertyMap = null;
1304             }
1305
1306             base.Dispose(type);
1307         }
1308
1309         /// This will not be public opened.
1310         [EditorBrowsable(EditorBrowsableState.Never)]
1311         protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1312         {
1313             Interop.ImageView.DeleteImageView(swigCPtr);
1314         }
1315
1316         // Callback for View ResourceReady signal
1317         private void OnResourceReady(IntPtr data)
1318         {
1319             if(!CheckResourceReady())
1320             {
1321                 return;
1322             }
1323
1324             ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1325             if (data != null)
1326             {
1327                 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1328             }
1329
1330             if (_resourceReadyEventHandler != null)
1331             {
1332                 _resourceReadyEventHandler(this, e);
1333             }
1334         }
1335
1336         private void SetResourceUrl(string value)
1337         {
1338             if(_resourceUrl != ConvertResourceUrl(ref value))
1339             {
1340                 _resourceUrl = value;
1341                 if(string.IsNullOrEmpty(_resourceUrl))
1342                 {
1343                     // Special case. If we set ResourceUrl as empty, Unregist visual.
1344                     RemoveImage();
1345                 }
1346                 else
1347                 {
1348                     using(PropertyValue setValue = new PropertyValue(value))
1349                     {
1350                         UpdateImage(ImageVisualProperty.URL, setValue);
1351                     }
1352                     // Special case. If we set GeneratedUrl, Create ImageVisual synchronously.
1353                     if(value.StartsWith("dali://") || value.StartsWith("enbuf://"))
1354                     {
1355                         UpdateImage();
1356                     }
1357                 }
1358             }
1359         }
1360
1361         private void SetBorder(Rectangle value)
1362         {
1363             if (value == null)
1364             {
1365                 return;
1366             }
1367             if(_border != value)
1368             {
1369                 _border = new Rectangle(value);
1370                 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1371             }
1372         }
1373
1374         /// <summary>
1375         /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1376         /// </summary>
1377         private void RemoveImage()
1378         {
1379             // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1380             // Unregist and detach process only if previous resourceUrl was not empty
1381             string currentResourceUrl = "";
1382             PropertyValue currentResourceUrlValue = GetCachedImageVisualProperty(ImageVisualProperty.URL);
1383             if((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1384             {
1385                 PropertyValue emptyValue = new PropertyValue();
1386
1387                 // Remove current registed Image.
1388                 SetProperty(ImageView.Property.IMAGE, emptyValue);
1389
1390                 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1391                 imagePropertyUpdatedFlag = false;
1392                 if(imagePropertyUpdateProcessAttachedFlag)
1393                 {
1394                     ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1395                     imagePropertyUpdateProcessAttachedFlag = false;
1396                 }
1397                 // Update resourceUrl as empty value
1398                 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1399
1400                 emptyValue?.Dispose();
1401             }
1402             currentResourceUrlValue?.Dispose();
1403         }
1404
1405         /// <summary>
1406         /// Lazy call to UpdateImage.
1407         /// Collect Properties need to be update, and set properties that starts the Processing.
1408         /// </summary>
1409         [EditorBrowsable(EditorBrowsableState.Never)]
1410         protected virtual void UpdateImage(int key, PropertyValue value)
1411         {
1412             // Update image property map value as inputed value.
1413             if (key != 0)
1414             {
1415                 if (cachedImagePropertyMap == null)
1416                 {
1417                     cachedImagePropertyMap = new PropertyMap();
1418                 }
1419
1420                 // To optimization, we don't check URL duplicate case. We already checked before.
1421                 if (key != ImageVisualProperty.URL)
1422                 {
1423                     using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1424                     {
1425                         if (oldValue != null && oldValue.EqualTo(value))
1426                         {
1427                             // Ignore UpdateImage query when we try to update equality value.
1428                             return;
1429                         }
1430                     }
1431                 }
1432                 imagePropertyUpdatedFlag = true;
1433                 cachedImagePropertyMap[key] = value;
1434
1435                 // Lazy update only if _resourceUrl is not empty and ProcessAttachedFlag is false.
1436                 if (!string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1437                 {
1438                     imagePropertyUpdateProcessAttachedFlag = true;
1439                     ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1440                     // Call process hardly.
1441                     ProcessorController.Instance.Awake();
1442                 }
1443             }
1444         }
1445
1446         /// <summary>
1447         /// Callback function to Lazy UpdateImage.
1448         /// </summary>
1449         private void UpdateImage(object source, EventArgs e)
1450         {
1451             UpdateImage();
1452             imagePropertyUpdateProcessAttachedFlag = false;
1453         }
1454
1455         /// <summary>
1456         /// Update image-relative properties synchronously.
1457         /// After call this API, All image properties updated.
1458         /// </summary>
1459         /// <remarks>
1460         /// Current version ImageView property update asynchronously.
1461         /// If you want to guarantee that ImageView property setuped,
1462         /// Please call this ImageView.UpdateImage() API.
1463         /// </remarks>
1464         [EditorBrowsable(EditorBrowsableState.Never)]
1465         protected virtual void UpdateImage()
1466         {
1467             if(!imagePropertyUpdatedFlag) return;
1468
1469             imagePropertyUpdatedFlag = false;
1470
1471             if(cachedImagePropertyMap == null)
1472             {
1473                 cachedImagePropertyMap = new PropertyMap();
1474             }
1475
1476             // Checkup the cached visual type is AnimatedImage.
1477             // It is trick to know that this code is running on AnimatedImageView.UpdateImage() / LottieAnimationView.UpdateImage() or not.
1478             int visualType = (int)Visual.Type.Invalid;
1479             if(!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage || visualType == (int)Visual.Type.AnimatedVectorImage)))
1480             {
1481                 // If ResourceUrl is not setuped, don't set property. fast return.
1482                 if(string.IsNullOrEmpty(_resourceUrl))
1483                 {
1484                     return;
1485                 }
1486                 if (_border == null)
1487                 {
1488                     PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1489                     cachedImagePropertyMap[Visual.Property.Type] = image;
1490                     image?.Dispose();
1491                 }
1492                 else
1493                 {
1494                     PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1495                     cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1496                     nPatch?.Dispose();
1497                     PropertyValue border = new PropertyValue(_border);
1498                     cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1499                     border?.Dispose();
1500                 }
1501             }
1502
1503             if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1504             {
1505                 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1506                 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1507                 {
1508                     cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1509                     cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1510                 }
1511             }
1512
1513             if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1514             {
1515                 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1516                 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1517                 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1518                 {
1519                     cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1520                     cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1521                     cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1522                 }
1523             }
1524
1525             // Do Fitting Buffer when desired dimension is set
1526             if (_desired_width != -1 && _desired_height != -1)
1527             {
1528                 if (_resourceUrl != null)
1529                 {
1530                     Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1531                     if( imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0  && _desired_height > 0 )
1532                     {
1533                         int adjustedDesiredWidth, adjustedDesiredHeight;
1534                         float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1535                         float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1536                         if (aspectOfImageSize > aspectOfDesiredSize)
1537                         {
1538                             adjustedDesiredWidth = _desired_width;
1539                             adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1540                         }
1541                         else
1542                         {
1543                             adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1544                             adjustedDesiredHeight = _desired_height;
1545                         }
1546
1547                         PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1548                         cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1549                         returnWidth?.Dispose();
1550                         PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1551                         cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1552                         returnHeight?.Dispose();
1553                         PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1554                         cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1555                         scaleToFit?.Dispose();
1556                     }
1557                     else
1558                     {
1559                         Tizen.Log.Fatal("NUI", "[ERROR] Can't use DesiredSize when ImageLoading is failed.");
1560                     }
1561                     imageSize?.Dispose();
1562                 }
1563             }
1564
1565             UpdateImageMap();
1566         }
1567
1568         /// <summary>
1569         /// Merge our collected properties, and set IMAGE property internally.
1570         /// </summary>
1571         private void UpdateImageMap()
1572         {
1573             // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1574             using(PropertyMap imageMap = new PropertyMap())
1575             {
1576                 using(PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1577                 {
1578                     returnValue?.Get(imageMap);
1579                 }
1580                 if(cachedImagePropertyMap != null)
1581                 {
1582                     imageMap?.Merge(cachedImagePropertyMap);
1583                 }
1584                 using(PropertyValue setValue = new PropertyValue(imageMap))
1585                 {
1586                     SetProperty(ImageView.Property.IMAGE, setValue);
1587                 }
1588
1589                 // Update cached image property.
1590                 MergeCachedImageVisualProperty(imageMap);
1591             }
1592         }
1593
1594         /// <summary>
1595         /// Get image visual property by key.
1596         /// If we found value in local Cached result, return that.
1597         /// Else, get synced native map and return that.
1598         /// If there is no matched value, return null.
1599         /// </summary>
1600         [EditorBrowsable(EditorBrowsableState.Never)]
1601         protected virtual PropertyValue GetImageVisualProperty(int key)
1602         {
1603             PropertyValue ret = GetCachedImageVisualProperty(key);
1604             if(ret == null)
1605             {
1606                 // If we cannot find result form cached map, Get value from native engine.
1607                 ret = Image?.Find(key);
1608             }
1609             return ret;
1610         }
1611
1612         /// <summary>
1613         /// Get image visual property from NUI cached image map by key.
1614         /// If there is no matched value, return null.
1615         /// </summary>
1616         [EditorBrowsable(EditorBrowsableState.Never)]
1617         protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1618         {
1619             return cachedImagePropertyMap?.Find(key);
1620         }
1621
1622         /// <summary>
1623         /// Update NUI cached image visual property map by inputed property map.
1624         /// </summary>
1625         /// <remarks>
1626         /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1627         /// </remarks>
1628         [EditorBrowsable(EditorBrowsableState.Never)]
1629         protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1630         {
1631             if(map == null) return;
1632             if(cachedImagePropertyMap == null)
1633             {
1634                 cachedImagePropertyMap = new PropertyMap();
1635             }
1636             foreach(var key in cachedImagePropertyKeyList)
1637             {
1638                 PropertyValue value = map.Find(key);
1639                 if(value != null)
1640                 {
1641                     // Update-or-Insert new value
1642                     cachedImagePropertyMap[key] = value;
1643                 }
1644             }
1645         }
1646
1647         /// <summary>
1648         /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1649         /// So before get base.GetNaturalSize(), we should synchronous image properties
1650         /// </summary>
1651         internal override Vector3 GetNaturalSize()
1652         {
1653             // Sync as current properties
1654             UpdateImage();
1655             return base.GetNaturalSize();
1656         }
1657
1658         [EditorBrowsable(EditorBrowsableState.Never)]
1659         protected override bool CheckResourceReady()
1660         {
1661             // If we have some properties to be updated, this signal is old thing.
1662             // We need to ignore current signal, and wait next.
1663             return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1664         }
1665
1666         private void OnResourceLoaded(IntPtr view)
1667         {
1668             if(!CheckResourceReady())
1669             {
1670                 return;
1671             }
1672             ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1673             e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1674
1675             if (_resourceLoadedEventHandler != null)
1676             {
1677                 _resourceLoadedEventHandler(this, e);
1678             }
1679         }
1680
1681         /// <summary>
1682         /// Event arguments of resource ready.
1683         /// </summary>
1684         /// <since_tizen> 3 </since_tizen>
1685         public class ResourceReadyEventArgs : EventArgs
1686         {
1687             private View _view;
1688
1689             /// <summary>
1690             /// The view whose resource is ready.
1691             /// </summary>
1692             /// <since_tizen> 3 </since_tizen>
1693             public View View
1694             {
1695                 get
1696                 {
1697                     return _view;
1698                 }
1699                 set
1700                 {
1701                     _view = value;
1702                 }
1703             }
1704         }
1705
1706         internal class ResourceLoadedEventArgs : EventArgs
1707         {
1708             private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1709             public ResourceLoadingStatusType Status
1710             {
1711                 get
1712                 {
1713                     return status;
1714                 }
1715                 set
1716                 {
1717                     status = value;
1718                 }
1719             }
1720         }
1721
1722         internal new class Property
1723         {
1724             internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1725             internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1726             internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1727             internal static readonly int PlaceHolderUrl = Interop.ImageView.PlaceHolderImageGet();
1728             internal static readonly int TransitionEffect = Interop.ImageView.TransitionEffectGet();
1729         }
1730
1731         private enum ImageType
1732         {
1733             /// <summary>
1734             /// For Normal Image.
1735             /// </summary>
1736             Normal = 0,
1737
1738             /// <summary>
1739             /// For normal image, with synchronous loading and orientation correction property
1740             /// </summary>
1741             Specific = 1,
1742
1743             /// <summary>
1744             /// For nine-patch image
1745             /// </summary>
1746             Npatch = 2,
1747         }
1748
1749         private void OnBorderChanged(int x, int y, int width, int height)
1750         {
1751             Border = new Rectangle(x, y, width, height);
1752         }
1753         private void OnPixelAreaChanged(float x, float y, float z, float w)
1754         {
1755             PixelArea = new RelativeVector4(x, y, z, w);
1756         }
1757
1758         private class ImageLayout : LayoutItem
1759         {
1760             /// <summary>
1761             /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1762             /// 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.
1763             /// </summary>
1764             [EditorBrowsable(EditorBrowsableState.Never)]
1765             public bool AdjustViewSize
1766             {
1767                 get
1768                 {
1769                     return (Owner as ImageView)?.AdjustViewSize ?? false;
1770                 }
1771                 set
1772                 {
1773                     if (Owner is ImageView imageView)
1774                     {
1775                         imageView.AdjustViewSize = value;
1776                     }
1777                 }
1778             }
1779
1780             /// <inheritdoc/>
1781             [EditorBrowsable(EditorBrowsableState.Never)]
1782             protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1783             {
1784                 // To not change the view size by DALi
1785                 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1786                 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1787
1788                 float specWidth = widthMeasureSpec.Size.AsDecimal();
1789                 float specHeight = heightMeasureSpec.Size.AsDecimal();
1790                 float naturalWidth = Owner.NaturalSize.Width;
1791                 float naturalHeight = Owner.NaturalSize.Height;
1792                 float minWidth = Owner.MinimumSize.Width;
1793                 float maxWidth = Owner.MaximumSize.Width;
1794                 float minHeight = Owner.MinimumSize.Height;
1795                 float maxHeight = Owner.MaximumSize.Height;
1796                 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1797
1798                 // Assume that the new width and height are given from the view's suggested size by default.
1799                 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1800                 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1801
1802                 // The width and height measure specs are going to be used to set measured size.
1803                 // Mark that the measure specs are changed by default to update measure specs later.
1804                 bool widthSpecChanged = true;
1805                 bool heightSpecChanged = true;
1806
1807                 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1808                 {
1809                     newWidth = specWidth;
1810                     widthSpecChanged = false;
1811
1812                     if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1813                     {
1814                         if ((AdjustViewSize) && (aspectRatio > 0))
1815                         {
1816                             newHeight = newWidth * aspectRatio;
1817                         }
1818                     }
1819                 }
1820
1821                 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1822                 {
1823                     newHeight = specHeight;
1824                     heightSpecChanged = false;
1825
1826                     if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1827                     {
1828                         if ((AdjustViewSize) && (aspectRatio > 0))
1829                         {
1830                             newWidth = newHeight / aspectRatio;
1831                         }
1832                     }
1833                 }
1834
1835                 if (widthSpecChanged)
1836                 {
1837                     widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1838                 }
1839
1840                 if (heightSpecChanged)
1841                 {
1842                     heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1843                 }
1844
1845                 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1846                 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1847
1848                 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1849                                       ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));
1850             }
1851         }
1852     }
1853 }