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