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