Release 11.0.0.17809
[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         internal Selector<string> ResourceUrlSelector
1158         {
1159             get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1160             set
1161             {
1162                 resourceUrlSelector?.Reset(this);
1163                 if (value == null) return;
1164
1165                 if (value.HasAll()) SetResourceUrl(value.All);
1166                 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1167             }
1168         }
1169
1170         /// <summary>
1171         /// Get attributes, it is abstract function and must be override.
1172         /// </summary>
1173         [EditorBrowsable(EditorBrowsableState.Never)]
1174         protected override ViewStyle CreateViewStyle()
1175         {
1176             return new ImageViewStyle();
1177         }
1178
1179         internal void SetImage(string url, Uint16Pair size)
1180         {
1181             if (url.Contains(".json"))
1182             {
1183                 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1184                 return;
1185             }
1186
1187             Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
1188             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1189
1190             _resourceUrl = url;
1191             _desired_width = size?.GetWidth() ?? -1;
1192             _desired_height = size?.GetHeight() ?? -1;
1193         }
1194
1195         internal ViewResourceReadySignal ResourceReadySignal(View view)
1196         {
1197             ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1198             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1199             return ret;
1200         }
1201
1202         internal override void ApplyCornerRadius()
1203         {
1204             base.ApplyCornerRadius();
1205
1206             if (backgroundExtraData == null) return;
1207
1208
1209             // Update corner radius properties to image by ActionUpdateProperty
1210             if (backgroundExtraData.CornerRadius != null)
1211             {
1212                 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1213             }
1214             Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1215         }
1216
1217         internal override void ApplyBorderline()
1218         {
1219             base.ApplyBorderline();
1220
1221             if (backgroundExtraData == null) return;
1222
1223
1224             // Update borderline properties to image by ActionUpdateProperty
1225             Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
1226             Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
1227             Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
1228         }
1229
1230         internal ResourceLoadingStatusType GetResourceStatus()
1231         {
1232             return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1233         }
1234
1235         /// <summary>
1236         /// you can override it to clean-up your own resources.
1237         /// </summary>
1238         /// <param name="type">DisposeTypes</param>
1239         /// <since_tizen> 3 </since_tizen>
1240         protected override void Dispose(DisposeTypes type)
1241         {
1242             if (disposed)
1243             {
1244                 return;
1245             }
1246
1247             internalPixelArea?.Dispose();
1248
1249             if (type == DisposeTypes.Explicit)
1250             {
1251                 //Called by User
1252                 //Release your own managed resources here.
1253                 //You should release all of your own disposable objects here.
1254                 _border?.Dispose();
1255                 _border = null;
1256                 borderSelector?.Reset(this);
1257                 resourceUrlSelector?.Reset(this);
1258                 imagePropertyUpdatedFlag = false;
1259                 if (imagePropertyUpdateProcessAttachedFlag)
1260                 {
1261                     ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1262                     imagePropertyUpdateProcessAttachedFlag = false;
1263                 }
1264                 cachedImagePropertyMap?.Dispose();
1265                 cachedImagePropertyMap = null;
1266             }
1267
1268             base.Dispose(type);
1269         }
1270
1271         /// This will not be public opened.
1272         [EditorBrowsable(EditorBrowsableState.Never)]
1273         protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1274         {
1275             Interop.ImageView.DeleteImageView(swigCPtr);
1276         }
1277
1278         // Callback for View ResourceReady signal
1279         private void OnResourceReady(IntPtr data)
1280         {
1281             if(!CheckResourceReady())
1282             {
1283                 return;
1284             }
1285
1286             ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1287             if (data != null)
1288             {
1289                 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1290             }
1291
1292             if (_resourceReadyEventHandler != null)
1293             {
1294                 _resourceReadyEventHandler(this, e);
1295             }
1296         }
1297
1298         private void SetResourceUrl(string value)
1299         {
1300             if(_resourceUrl != ConvertResourceUrl(ref value))
1301             {
1302                 _resourceUrl = value;
1303                 if(string.IsNullOrEmpty(_resourceUrl))
1304                 {
1305                     // Special case. If we set ResourceUrl as empty, Unregist visual.
1306                     RemoveImage();
1307                 }
1308                 else
1309                 {
1310                     using(PropertyValue setValue = new PropertyValue(value))
1311                     {
1312                         UpdateImage(ImageVisualProperty.URL, setValue);
1313                     }
1314                     // Special case. If we set GeneratedUrl, Create ImageVisual synchronously.
1315                     if(value.StartsWith("dali://") || value.StartsWith("enbuf://"))
1316                     {
1317                         UpdateImage();
1318                     }
1319                 }
1320             }
1321         }
1322
1323         private void SetBorder(Rectangle value)
1324         {
1325             if (value == null)
1326             {
1327                 return;
1328             }
1329             if(_border != value)
1330             {
1331                 _border = new Rectangle(value);
1332                 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1333             }
1334         }
1335
1336         /// <summary>
1337         /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1338         /// </summary>
1339         private void RemoveImage()
1340         {
1341             // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1342             // Unregist and detach process only if previous resourceUrl was not empty
1343             string currentResourceUrl = "";
1344             PropertyValue currentResourceUrlValue = GetCachedImageVisualProperty(ImageVisualProperty.URL);
1345             if((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1346             {
1347                 PropertyValue emptyValue = new PropertyValue();
1348
1349                 // Remove current registed Image.
1350                 SetProperty(ImageView.Property.IMAGE, emptyValue);
1351
1352                 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1353                 imagePropertyUpdatedFlag = false;
1354                 if(imagePropertyUpdateProcessAttachedFlag)
1355                 {
1356                     ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1357                     imagePropertyUpdateProcessAttachedFlag = false;
1358                 }
1359                 // Update resourceUrl as empty value
1360                 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1361
1362                 emptyValue?.Dispose();
1363             }
1364             currentResourceUrlValue?.Dispose();
1365         }
1366
1367         /// <summary>
1368         /// Lazy call to UpdateImage.
1369         /// Collect Properties need to be update, and set properties that starts the Processing.
1370         /// </summary>
1371         [EditorBrowsable(EditorBrowsableState.Never)]
1372         protected virtual void UpdateImage(int key, PropertyValue value)
1373         {
1374             // Update image property map value as inputed value.
1375             if (key != 0)
1376             {
1377                 if (cachedImagePropertyMap == null)
1378                 {
1379                     cachedImagePropertyMap = new PropertyMap();
1380                 }
1381
1382                 // To optimization, we don't check URL duplicate case. We already checked before.
1383                 if (key != ImageVisualProperty.URL)
1384                 {
1385                     using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1386                     {
1387                         if (oldValue != null && oldValue.EqualTo(value))
1388                         {
1389                             // Ignore UpdateImage query when we try to update equality value.
1390                             return;
1391                         }
1392                     }
1393                 }
1394                 imagePropertyUpdatedFlag = true;
1395                 cachedImagePropertyMap[key] = value;
1396
1397                 // Lazy update only if _resourceUrl is not empty and ProcessAttachedFlag is false.
1398                 if (!string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1399                 {
1400                     imagePropertyUpdateProcessAttachedFlag = true;
1401                     ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1402                     // Call process hardly.
1403                     ProcessorController.Instance.Awake();
1404                 }
1405             }
1406         }
1407
1408         /// <summary>
1409         /// Callback function to Lazy UpdateImage.
1410         /// </summary>
1411         private void UpdateImage(object source, EventArgs e)
1412         {
1413             UpdateImage();
1414             imagePropertyUpdateProcessAttachedFlag = false;
1415         }
1416
1417         /// <summary>
1418         /// Update image-relative properties synchronously.
1419         /// After call this API, All image properties updated.
1420         /// </summary>
1421         /// <remarks>
1422         /// Current version ImageView property update asynchronously.
1423         /// If you want to guarantee that ImageView property setuped,
1424         /// Please call this ImageView.UpdateImage() API.
1425         /// </remarks>
1426         [EditorBrowsable(EditorBrowsableState.Never)]
1427         protected virtual void UpdateImage()
1428         {
1429             if(!imagePropertyUpdatedFlag) return;
1430
1431             imagePropertyUpdatedFlag = false;
1432
1433             if(cachedImagePropertyMap == null)
1434             {
1435                 cachedImagePropertyMap = new PropertyMap();
1436             }
1437
1438             // Checkup the cached visual type is AnimatedImage.
1439             // It is trick to know that this code is running on AnimatedImageView.UpdateImage() / LottieAnimationView.UpdateImage() or not.
1440             int visualType = (int)Visual.Type.Invalid;
1441             if(!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage || visualType == (int)Visual.Type.AnimatedVectorImage)))
1442             {
1443                 // If ResourceUrl is not setuped, don't set property. fast return.
1444                 if(string.IsNullOrEmpty(_resourceUrl))
1445                 {
1446                     return;
1447                 }
1448                 if (_border == null)
1449                 {
1450                     PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1451                     cachedImagePropertyMap[Visual.Property.Type] = image;
1452                     image?.Dispose();
1453                 }
1454                 else
1455                 {
1456                     PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1457                     cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1458                     nPatch?.Dispose();
1459                     PropertyValue border = new PropertyValue(_border);
1460                     cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1461                     border?.Dispose();
1462                 }
1463             }
1464
1465             if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1466             {
1467                 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1468                 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1469                 {
1470                     cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1471                     cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1472                 }
1473             }
1474
1475             if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1476             {
1477                 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1478                 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1479                 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1480                 {
1481                     cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1482                     cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1483                     cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1484                 }
1485             }
1486
1487             // Do Fitting Buffer when desired dimension is set
1488             if (_desired_width != -1 && _desired_height != -1)
1489             {
1490                 if (_resourceUrl != null)
1491                 {
1492                     Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1493                     if( imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0  && _desired_height > 0 )
1494                     {
1495                         int adjustedDesiredWidth, adjustedDesiredHeight;
1496                         float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1497                         float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1498                         if (aspectOfImageSize > aspectOfDesiredSize)
1499                         {
1500                             adjustedDesiredWidth = _desired_width;
1501                             adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1502                         }
1503                         else
1504                         {
1505                             adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1506                             adjustedDesiredHeight = _desired_height;
1507                         }
1508
1509                         PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1510                         cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1511                         returnWidth?.Dispose();
1512                         PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1513                         cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1514                         returnHeight?.Dispose();
1515                         PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1516                         cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1517                         scaleToFit?.Dispose();
1518                     }
1519                     else
1520                     {
1521                         Tizen.Log.Fatal("NUI", "[ERROR] Can't use DesiredSize when ImageLoading is failed.");
1522                     }
1523                     imageSize?.Dispose();
1524                 }
1525             }
1526
1527             UpdateImageMap();
1528         }
1529
1530         /// <summary>
1531         /// Merge our collected properties, and set IMAGE property internally.
1532         /// </summary>
1533         private void UpdateImageMap()
1534         {
1535             // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1536             using(PropertyMap imageMap = new PropertyMap())
1537             {
1538                 using(PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1539                 {
1540                     returnValue?.Get(imageMap);
1541                 }
1542                 if(cachedImagePropertyMap != null)
1543                 {
1544                     imageMap?.Merge(cachedImagePropertyMap);
1545                 }
1546                 using(PropertyValue setValue = new PropertyValue(imageMap))
1547                 {
1548                     SetProperty(ImageView.Property.IMAGE, setValue);
1549                 }
1550
1551                 // Update cached image property.
1552                 MergeCachedImageVisualProperty(imageMap);
1553             }
1554         }
1555
1556         /// <summary>
1557         /// Get image visual property by key.
1558         /// If we found value in local Cached result, return that.
1559         /// Else, get synced native map and return that.
1560         /// If there is no matched value, return null.
1561         /// </summary>
1562         [EditorBrowsable(EditorBrowsableState.Never)]
1563         protected virtual PropertyValue GetImageVisualProperty(int key)
1564         {
1565             PropertyValue ret = GetCachedImageVisualProperty(key);
1566             if(ret == null)
1567             {
1568                 // If we cannot find result form cached map, Get value from native engine.
1569                 ret = Image?.Find(key);
1570             }
1571             return ret;
1572         }
1573
1574         /// <summary>
1575         /// Get image visual property from NUI cached image map by key.
1576         /// If there is no matched value, return null.
1577         /// </summary>
1578         [EditorBrowsable(EditorBrowsableState.Never)]
1579         protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1580         {
1581             return cachedImagePropertyMap?.Find(key);
1582         }
1583
1584         /// <summary>
1585         /// Update NUI cached image visual property map by inputed property map.
1586         /// </summary>
1587         /// <remarks>
1588         /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1589         /// </remarks>
1590         [EditorBrowsable(EditorBrowsableState.Never)]
1591         protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1592         {
1593             if(map == null) return;
1594             if(cachedImagePropertyMap == null)
1595             {
1596                 cachedImagePropertyMap = new PropertyMap();
1597             }
1598             foreach(var key in cachedImagePropertyKeyList)
1599             {
1600                 PropertyValue value = map.Find(key);
1601                 if(value != null)
1602                 {
1603                     // Update-or-Insert new value
1604                     cachedImagePropertyMap[key] = value;
1605                 }
1606             }
1607         }
1608
1609         /// <summary>
1610         /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1611         /// So before get base.GetNaturalSize(), we should synchronous image properties
1612         /// </summary>
1613         internal override Vector3 GetNaturalSize()
1614         {
1615             // Sync as current properties
1616             UpdateImage();
1617             return base.GetNaturalSize();
1618         }
1619
1620         [EditorBrowsable(EditorBrowsableState.Never)]
1621         protected override bool CheckResourceReady()
1622         {
1623             // If we have some properties to be updated, this signal is old thing.
1624             // We need to ignore current signal, and wait next.
1625             return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1626         }
1627
1628         private void OnResourceLoaded(IntPtr view)
1629         {
1630             if(!CheckResourceReady())
1631             {
1632                 return;
1633             }
1634             ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1635             e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1636
1637             if (_resourceLoadedEventHandler != null)
1638             {
1639                 _resourceLoadedEventHandler(this, e);
1640             }
1641         }
1642
1643         /// <summary>
1644         /// Event arguments of resource ready.
1645         /// </summary>
1646         /// <since_tizen> 3 </since_tizen>
1647         public class ResourceReadyEventArgs : EventArgs
1648         {
1649             private View _view;
1650
1651             /// <summary>
1652             /// The view whose resource is ready.
1653             /// </summary>
1654             /// <since_tizen> 3 </since_tizen>
1655             public View View
1656             {
1657                 get
1658                 {
1659                     return _view;
1660                 }
1661                 set
1662                 {
1663                     _view = value;
1664                 }
1665             }
1666         }
1667
1668         internal class ResourceLoadedEventArgs : EventArgs
1669         {
1670             private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1671             public ResourceLoadingStatusType Status
1672             {
1673                 get
1674                 {
1675                     return status;
1676                 }
1677                 set
1678                 {
1679                     status = value;
1680                 }
1681             }
1682         }
1683
1684         internal new class Property
1685         {
1686             internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1687             internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1688             internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1689         }
1690
1691         private enum ImageType
1692         {
1693             /// <summary>
1694             /// For Normal Image.
1695             /// </summary>
1696             Normal = 0,
1697
1698             /// <summary>
1699             /// For normal image, with synchronous loading and orientation correction property
1700             /// </summary>
1701             Specific = 1,
1702
1703             /// <summary>
1704             /// For nine-patch image
1705             /// </summary>
1706             Npatch = 2,
1707         }
1708
1709         private void OnBorderChanged(int x, int y, int width, int height)
1710         {
1711             Border = new Rectangle(x, y, width, height);
1712         }
1713         private void OnPixelAreaChanged(float x, float y, float z, float w)
1714         {
1715             PixelArea = new RelativeVector4(x, y, z, w);
1716         }
1717
1718         private class ImageLayout : LayoutItem
1719         {
1720             /// <summary>
1721             /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1722             /// 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.
1723             /// </summary>
1724             [EditorBrowsable(EditorBrowsableState.Never)]
1725             public bool AdjustViewSize
1726             {
1727                 get
1728                 {
1729                     return (Owner as ImageView)?.AdjustViewSize ?? false;
1730                 }
1731                 set
1732                 {
1733                     if (Owner is ImageView imageView)
1734                     {
1735                         imageView.AdjustViewSize = value;
1736                     }
1737                 }
1738             }
1739
1740             /// <inheritdoc/>
1741             [EditorBrowsable(EditorBrowsableState.Never)]
1742             protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1743             {
1744                 // To not change the view size by DALi
1745                 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1746                 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1747
1748                 float specWidth = widthMeasureSpec.Size.AsDecimal();
1749                 float specHeight = heightMeasureSpec.Size.AsDecimal();
1750                 float naturalWidth = Owner.NaturalSize.Width;
1751                 float naturalHeight = Owner.NaturalSize.Height;
1752                 float minWidth = Owner.MinimumSize.Width;
1753                 float maxWidth = Owner.MaximumSize.Width;
1754                 float minHeight = Owner.MinimumSize.Height;
1755                 float maxHeight = Owner.MaximumSize.Height;
1756                 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1757
1758                 // Assume that the new width and height are given from the view's suggested size by default.
1759                 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1760                 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1761
1762                 // The width and height measure specs are going to be used to set measured size.
1763                 // Mark that the measure specs are changed by default to update measure specs later.
1764                 bool widthSpecChanged = true;
1765                 bool heightSpecChanged = true;
1766
1767                 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1768                 {
1769                     newWidth = specWidth;
1770                     widthSpecChanged = false;
1771
1772                     if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1773                     {
1774                         if ((AdjustViewSize) && (aspectRatio > 0))
1775                         {
1776                             newHeight = newWidth * aspectRatio;
1777                         }
1778                     }
1779                 }
1780
1781                 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1782                 {
1783                     newHeight = specHeight;
1784                     heightSpecChanged = false;
1785
1786                     if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1787                     {
1788                         if ((AdjustViewSize) && (aspectRatio > 0))
1789                         {
1790                             newWidth = newHeight / aspectRatio;
1791                         }
1792                     }
1793                 }
1794
1795                 if (widthSpecChanged)
1796                 {
1797                     widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1798                 }
1799
1800                 if (heightSpecChanged)
1801                 {
1802                     heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1803                 }
1804
1805                 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1806                 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1807
1808                 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1809                                       ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));
1810             }
1811         }
1812     }
1813 }