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