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