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