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