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