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