2 * Copyright(c) 2019 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using System.ComponentModel;
21 using Tizen.NUI.Binding;
23 namespace Tizen.NUI.BaseComponents
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 />
30 /// <since_tizen> 3 </since_tizen>
31 public partial class ImageView : View
33 static ImageView() { }
35 private EventHandler<ResourceReadyEventArgs> _resourceReadyEventHandler;
36 private ResourceReadyEventCallbackType _resourceReadyEventCallback;
37 private EventHandler<ResourceLoadedEventArgs> _resourceLoadedEventHandler;
38 private _resourceLoadedCallbackType _resourceLoadedCallback;
41 /// Convert non-null string that some keyword change as application specific directory.
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)
48 if (value.StartsWith("*Resource*"))
50 string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
51 value = value.Replace("*Resource*", resource);
56 // Collection of image-sensitive properties.
57 private static readonly List<int> cachedImagePropertyKeyList = new List<int> {
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,
75 internal PropertyMap cachedImagePropertyMap;
76 internal bool imagePropertyUpdatedFlag = false;
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;
87 private RelativeVector4 internalPixelArea;
90 /// Creates an initialized ImageView.
92 /// <since_tizen> 3 </since_tizen>
93 public ImageView() : this(Interop.ImageView.New(), true)
95 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
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)
105 /// Creates an initialized ImageView with setting the status of shown or hidden.
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)
112 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
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 />
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)
126 // Update cached property. Note that we should not re-create new visual.
127 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
129 UpdateImage(ImageVisualProperty.URL, urlValue, false);
131 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
136 /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden.
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)
146 // Update cached property. Note that we should not re-create new visual.
147 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
149 UpdateImage(ImageVisualProperty.URL, urlValue, false);
151 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
155 internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size)), true)
158 _desired_width = size?.GetWidth() ?? -1;
159 _desired_height = size?.GetHeight() ?? -1;
161 // Update cached property. Note that we should not re-create new visual.
162 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
164 UpdateImage(ImageVisualProperty.URL, urlValue, false);
166 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
168 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
170 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
172 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
174 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
182 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
190 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
198 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
199 private delegate void ResourceReadyEventCallbackType(IntPtr data);
200 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
201 private delegate void _resourceLoadedCallbackType(IntPtr view);
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 />
208 /// <since_tizen> 3 </since_tizen>
209 public event EventHandler<ResourceReadyEventArgs> ResourceReady
213 if (_resourceReadyEventHandler == null)
215 _resourceReadyEventCallback = OnResourceReady;
216 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
217 resourceReadySignal?.Connect(_resourceReadyEventCallback);
218 resourceReadySignal?.Dispose();
221 _resourceReadyEventHandler += value;
226 _resourceReadyEventHandler -= value;
228 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
229 if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
231 resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
233 resourceReadySignal?.Dispose();
237 internal event EventHandler<ResourceLoadedEventArgs> ResourceLoaded
241 if (_resourceLoadedEventHandler == null)
243 _resourceLoadedCallback = OnResourceLoaded;
244 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
245 resourceReadySignal?.Connect(_resourceLoadedCallback);
246 resourceReadySignal?.Dispose();
249 _resourceLoadedEventHandler += value;
253 _resourceLoadedEventHandler -= value;
254 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
255 if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
257 resourceReadySignal?.Disconnect(_resourceLoadedCallback);
259 resourceReadySignal?.Dispose();
264 /// Enumeration for LoadingStatus of image.
266 /// <since_tizen> 5 </since_tizen>
267 public enum LoadingStatusType
270 /// Loading preparing status.
272 /// <since_tizen> 5 </since_tizen>
275 /// Loading ready status.
277 /// <since_tizen> 5 </since_tizen>
280 /// Loading failed status.
282 /// <since_tizen> 5 </since_tizen>
287 /// Enumeration for MaskingMode of image.
289 [EditorBrowsable(EditorBrowsableState.Never)]
290 public enum MaskingModeType
293 /// Applies alpha masking on rendering time.
295 [EditorBrowsable(EditorBrowsableState.Never)]
298 /// Applies alpha masking on loading time.
300 [EditorBrowsable(EditorBrowsableState.Never)]
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.
309 /// <since_tizen> 3 </since_tizen>
310 public string ResourceUrl
314 return (string)GetValue(ResourceUrlProperty);
318 SetValue(ResourceUrlProperty, value);
319 NotifyPropertyChanged();
324 /// This will be deprecated, Use Image instead. <br />
325 /// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
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
334 return GetValue(ImageMapProperty) as PropertyMap;
338 SetValue(ImageMapProperty, value);
339 NotifyPropertyChanged();
342 private PropertyMap InternalImageMap
348 // Sync as current properties
351 // Get current properties force.
352 PropertyMap returnValue = new PropertyMap();
353 PropertyValue image = GetProperty(ImageView.Property.IMAGE);
354 image?.Get(returnValue);
357 // Update cached property map
358 if (returnValue != null)
360 MergeCachedImageVisualProperty(returnValue);
373 PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
374 SetProperty(ImageView.Property.IMAGE, setValue);
376 // Image properties are changed hardly. We should ignore lazy UpdateImage
377 imagePropertyUpdatedFlag = false;
378 cachedImagePropertyMap?.Dispose();
379 cachedImagePropertyMap = null;
380 MergeCachedImageVisualProperty(value);
382 NotifyPropertyChanged();
389 /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
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 />
398 /// The following example demonstrates how to use the Image property.
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;
407 /// <since_tizen> 4 </since_tizen>
408 public PropertyMap Image
414 return (PropertyMap)GetValue(ImageProperty);
425 SetValue(ImageProperty, value);
426 NotifyPropertyChanged();
432 /// ImageView PreMultipliedAlpha, type Boolean.<br />
433 /// Image must be initialized.<br />
435 /// <since_tizen> 3 </since_tizen>
436 public bool PreMultipliedAlpha
440 return (bool)GetValue(PreMultipliedAlphaProperty);
444 SetValue(PreMultipliedAlphaProperty, value);
445 NotifyPropertyChanged();
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 />
454 /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
456 /// <since_tizen> 3 </since_tizen>
457 public RelativeVector4 PixelArea
461 return (RelativeVector4)GetValue(PixelAreaProperty);
465 SetValue(PixelAreaProperty, value);
466 NotifyPropertyChanged();
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 />
477 /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
479 /// <since_tizen> 3 </since_tizen>
480 public Rectangle Border
484 Rectangle temp = (Rectangle)GetValue(BorderProperty);
491 return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
496 SetValue(BorderProperty, value);
497 NotifyPropertyChanged();
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 />
507 /// <since_tizen> 3 </since_tizen>
508 public bool BorderOnly
512 return (bool)GetValue(BorderOnlyProperty);
516 SetValue(BorderOnlyProperty, value);
517 NotifyPropertyChanged();
522 /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
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
530 return SynchronousLoading;
534 SynchronousLoading = value;
539 /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
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.
546 /// <since_tizen> 9 </since_tizen>
547 public bool SynchronousLoading
551 return (bool)GetValue(SynchronousLoadingProperty);
555 SetValue(SynchronousLoadingProperty, value);
556 NotifyPropertyChanged();
561 /// Gets or sets whether to automatically correct the orientation of an image.<br />
563 /// <since_tizen> 5 </since_tizen>
564 public bool OrientationCorrection
568 return (bool)GetValue(OrientationCorrectionProperty);
572 SetValue(OrientationCorrectionProperty, value);
573 NotifyPropertyChanged();
578 /// Gets or sets whether to apply mask on GPU or not.<br />
580 [EditorBrowsable(EditorBrowsableState.Never)]
581 public MaskingModeType MaskingMode
585 return (MaskingModeType)GetValue(MaskingModeProperty);
589 SetValue(MaskingModeProperty, value);
590 NotifyPropertyChanged();
594 private MaskingModeType InternalMaskingMode
598 int ret = (int)MaskingModeType.MaskingOnLoading;
600 PropertyValue maskingMode = GetCachedImageVisualProperty(ImageVisualProperty.MaskingMode);
601 maskingMode?.Get(out ret);
602 maskingMode?.Dispose();
604 return (MaskingModeType)ret;
608 MaskingModeType ret = value;
609 PropertyValue setValue = new PropertyValue((int)ret);
610 UpdateImage(ImageVisualProperty.MaskingMode, setValue);
616 /// Gets or sets whether to apply fast track uploading or not.<br />
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.
629 [EditorBrowsable(EditorBrowsableState.Never)]
630 public bool FastTrackUploading
634 return (bool)GetValue(FastTrackUploadingProperty);
638 SetValue(FastTrackUploadingProperty, value);
639 NotifyPropertyChanged();
643 private bool InternalFastTrackUploading
647 PropertyValue fastTrackUploading = GetCachedImageVisualProperty(ImageVisualProperty.FastTrackUploading);
648 fastTrackUploading?.Get(out _fastTrackUploading);
649 fastTrackUploading?.Dispose();
651 return _fastTrackUploading;
655 if (_fastTrackUploading != value)
657 _fastTrackUploading = value;
659 PropertyValue setValue = new PropertyValue(_fastTrackUploading);
660 UpdateImage(ImageVisualProperty.FastTrackUploading, setValue);
663 if (_fastTrackUploading && !string.IsNullOrEmpty(_resourceUrl))
665 // Special case. If user set FastTrackUploading mean, user want to upload image As-Soon-As-Possible.
666 // Create ImageVisual synchronously.
674 /// Gets the loading state of the visual resource.
676 /// <since_tizen> 5 </since_tizen>
677 public ImageView.LoadingStatusType LoadingStatus
681 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
686 /// Downcasts a handle to imageView handle.
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. " +
693 "BaseHandle handle = new ImageView(imagePath); " +
694 "ImageView image = handle as ImageView")]
695 [EditorBrowsable(EditorBrowsableState.Never)]
696 public static ImageView DownCast(BaseHandle handle)
700 throw new ArgumentNullException(nameof(handle));
702 ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
703 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
708 /// Sets this ImageView from the given URL.<br />
709 /// If the URL is empty, ImageView will not display anything.<br />
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)
718 throw new ArgumentNullException(nameof(url));
721 if (url.Contains(".json"))
723 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
727 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url));
728 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
731 // Update cached property. Note that we should not re-create new visual.
732 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
734 UpdateImage(ImageVisualProperty.URL, urlValue, false);
736 imagePropertyUpdatedFlag = false;
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 />
744 /// <since_tizen> 3 </since_tizen>
745 public new bool IsResourceReady()
747 bool ret = Interop.View.IsResourceReady(SwigCPtr);
748 if (NDalicPINVOKE.SWIGPendingException.Pending)
749 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
754 /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
756 /// <since_tizen> 5 </since_tizen>
759 // Sync as current properties
763 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionReload);
767 /// Plays the animated GIF. This is also the default playback mode.
769 /// <since_tizen> 5 </since_tizen>
772 // Sync as current properties
776 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPlay);
780 /// Pauses the animated GIF.
782 /// <since_tizen> 5 </since_tizen>
785 // Sync as current properties
789 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPause);
793 /// Stops the animated GIF.
795 /// <since_tizen> 5 </since_tizen>
798 // Sync as current properties
803 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionStop);
807 /// Gets or sets the URL of the alpha mask.<br />
810 /// <since_tizen> 6</since_tizen>
811 [EditorBrowsable(EditorBrowsableState.Never)]
812 public string AlphaMaskURL
816 return GetValue(AlphaMaskURLProperty) as string;
820 SetValue(AlphaMaskURLProperty, value);
821 NotifyPropertyChanged();
825 private string InternalAlphaMaskURL
831 PropertyValue maskUrl = GetCachedImageVisualProperty(ImageVisualProperty.AlphaMaskURL);
832 maskUrl?.Get(out ret);
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))
844 if (cropToMask == null)
846 using PropertyValue setCropValue = new PropertyValue(true);
847 UpdateImage(ImageVisualProperty.CropToMask, setCropValue);
856 /// Whether to crop image to mask or scale mask to fit image.
858 /// <since_tizen> 6 </since_tizen>
859 public bool CropToMask
863 return (bool)GetValue(CropToMaskProperty);
867 SetValue(CropToMaskProperty, value);
868 NotifyPropertyChanged();
871 private bool InternalCropToMask
877 PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask);
878 cropToMask?.Get(out ret);
879 cropToMask?.Dispose();
885 PropertyValue setValue = new PropertyValue(value);
886 UpdateImage(ImageVisualProperty.CropToMask, setValue);
892 /// Actions property value for Reload image.
894 private int ActionReload { get; set; } = Interop.ImageView.ImageVisualActionReloadGet();
897 /// Actions property value to Play animated images.
898 /// This property can be redefined by child class if it use different value.
900 [EditorBrowsable(EditorBrowsableState.Never)]
901 protected int ActionPlay { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
904 /// Actions property value to Pause animated images.
905 /// This property can be redefined by child class if it use different value.
907 [EditorBrowsable(EditorBrowsableState.Never)]
908 protected int ActionPause { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
911 /// Actions property value to Stop animated images.
912 /// This property can be redefined by child class if it use different value.
914 [EditorBrowsable(EditorBrowsableState.Never)]
915 protected int ActionStop { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
917 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
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;
934 return VisualFittingModeType.Fill;
938 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
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;
955 return FittingModeType.ShrinkToFit;
959 internal override LayoutItem CreateDefaultLayout()
961 return new ImageLayout();
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 />
970 /// <since_tizen> 6 </since_tizen>
971 [EditorBrowsable(EditorBrowsableState.Never)]
972 public FittingModeType FittingMode
976 return (FittingModeType)GetValue(FittingModeProperty);
980 SetValue(FittingModeProperty, value);
981 NotifyPropertyChanged();
985 private FittingModeType InternalFittingMode
989 int ret = (int)VisualFittingModeType.Fill;
991 PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
992 fittingMode?.Get(out ret);
993 fittingMode?.Dispose();
995 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
999 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
1000 PropertyValue setValue = new PropertyValue((int)ret);
1001 UpdateImage(Visual.Property.VisualFittingMode, setValue);
1002 setValue?.Dispose();
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 />
1012 /// <since_tizen> 6 </since_tizen>
1013 [EditorBrowsable(EditorBrowsableState.Never)]
1014 public int DesiredWidth
1018 return (int)GetValue(DesiredWidthProperty);
1022 SetValue(DesiredWidthProperty, value);
1023 NotifyPropertyChanged();
1026 private int InternalDesiredWidth
1030 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1031 if (_desired_width != -1 && _desired_height != -1)
1035 PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
1036 desirewidth?.Get(out _desired_width);
1037 desirewidth?.Dispose();
1039 return _desired_width;
1043 if (_desired_width != value)
1045 _desired_width = value;
1046 PropertyValue setValue = new PropertyValue(value);
1047 UpdateImage(ImageVisualProperty.DesiredWidth, setValue, false);
1048 setValue?.Dispose();
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 />
1059 /// <since_tizen> 6 </since_tizen>
1060 [EditorBrowsable(EditorBrowsableState.Never)]
1061 public int DesiredHeight
1065 return (int)GetValue(DesiredHeightProperty);
1069 SetValue(DesiredHeightProperty, value);
1070 NotifyPropertyChanged();
1073 private int InternalDesiredHeight
1077 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1078 if (_desired_width != -1 && _desired_height != -1)
1082 PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
1083 desireheight?.Get(out _desired_height);
1084 desireheight?.Dispose();
1086 return _desired_height;
1090 if (_desired_height != value)
1092 _desired_height = value;
1093 PropertyValue setValue = new PropertyValue(value);
1094 UpdateImage(ImageVisualProperty.DesiredHeight, setValue, false);
1095 setValue?.Dispose();
1101 /// Gets or sets ReleasePolicy for image.<br />
1102 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
1104 [EditorBrowsable(EditorBrowsableState.Never)]
1105 public ReleasePolicyType ReleasePolicy
1109 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
1113 SetValue(ReleasePolicyProperty, value);
1114 NotifyPropertyChanged();
1118 private ReleasePolicyType InternalReleasePolicy
1122 int ret = (int)ReleasePolicyType.Detached;
1124 PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
1125 releasePoli?.Get(out ret);
1126 releasePoli?.Dispose();
1128 return (ReleasePolicyType)ret;
1132 PropertyValue setValue = new PropertyValue((int)value);
1133 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
1134 setValue?.Dispose();
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 />
1145 /// <since_tizen> 6 </since_tizen>
1146 [EditorBrowsable(EditorBrowsableState.Never)]
1147 public WrapModeType WrapModeU
1151 return (WrapModeType)GetValue(WrapModeUProperty);
1155 SetValue(WrapModeUProperty, value);
1156 NotifyPropertyChanged();
1160 private WrapModeType InternalWrapModeU
1164 int ret = (int)WrapModeType.Default;
1166 PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
1167 wrapModeU?.Get(out ret);
1168 wrapModeU?.Dispose();
1170 return (WrapModeType)ret;
1174 PropertyValue setValue = new PropertyValue((int)value);
1175 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
1176 setValue?.Dispose();
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.
1188 /// <since_tizen> 6 </since_tizen>
1189 [EditorBrowsable(EditorBrowsableState.Never)]
1190 public WrapModeType WrapModeV
1194 return (WrapModeType)GetValue(WrapModeVProperty);
1198 SetValue(WrapModeVProperty, value);
1199 NotifyPropertyChanged();
1203 private WrapModeType InternalWrapModeV
1207 int ret = (int)WrapModeType.Default;
1209 PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
1210 wrapModeV?.Get(out ret);
1211 wrapModeV?.Dispose();
1213 return (WrapModeType)ret;
1217 PropertyValue setValue = new PropertyValue((int)value);
1218 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1219 setValue?.Dispose();
1224 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
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).
1234 /// <since_tizen> 9 </since_tizen>
1235 public bool AdjustViewSize
1239 return (bool)GetValue(AdjustViewSizeProperty);
1243 SetValue(AdjustViewSizeProperty, value);
1244 NotifyPropertyChanged();
1247 private bool adjustViewSize = false;
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.
1254 /// <since_tizen> 11 </since_tizen>
1255 [EditorBrowsable(EditorBrowsableState.Never)]
1256 public string PlaceHolderUrl
1260 return (string)GetValue(PlaceHolderUrlProperty);
1264 SetValue(PlaceHolderUrlProperty, value);
1265 NotifyPropertyChanged();
1270 /// Gets or sets whether the image use TransitionEffect or not<br />
1272 /// <since_tizen> 11 </since_tizen>
1273 [EditorBrowsable(EditorBrowsableState.Never)]
1274 public bool TransitionEffect
1278 return (bool)GetValue(TransitionEffectProperty);
1282 SetValue(TransitionEffectProperty, value);
1283 NotifyPropertyChanged();
1287 internal Selector<string> ResourceUrlSelector
1289 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1292 resourceUrlSelector?.Reset(this);
1293 if (value == null) return;
1295 if (value.HasAll()) SetResourceUrl(value.All);
1296 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1301 /// Get attributes, it is abstract function and must be override.
1303 [EditorBrowsable(EditorBrowsableState.Never)]
1304 protected override ViewStyle CreateViewStyle()
1306 return new ImageViewStyle();
1309 internal void SetImage(string url, Uint16Pair size)
1311 if (url.Contains(".json"))
1313 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1317 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
1318 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1321 _desired_width = size?.GetWidth() ?? -1;
1322 _desired_height = size?.GetHeight() ?? -1;
1324 // Update cached property. Note that we should not re-create new visual.
1325 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
1327 UpdateImage(ImageVisualProperty.URL, urlValue, false);
1329 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
1331 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
1333 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
1335 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
1337 imagePropertyUpdatedFlag = false;
1340 internal ViewResourceReadySignal ResourceReadySignal(View view)
1342 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1343 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1347 internal override void ApplyCornerRadius()
1349 base.ApplyCornerRadius();
1351 if (backgroundExtraData == null) return;
1354 // Update corner radius properties to image by ActionUpdateProperty
1355 if (backgroundExtraData.CornerRadius != null)
1357 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1359 Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1362 internal override void ApplyBorderline()
1364 base.ApplyBorderline();
1366 if (backgroundExtraData == null) return;
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);
1375 internal ResourceLoadingStatusType GetResourceStatus()
1377 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1381 /// you can override it to clean-up your own resources.
1383 /// <param name="type">DisposeTypes</param>
1384 /// <since_tizen> 3 </since_tizen>
1385 protected override void Dispose(DisposeTypes type)
1392 internalPixelArea?.Dispose();
1394 if (type == DisposeTypes.Explicit)
1397 //Release your own managed resources here.
1398 //You should release all of your own disposable objects here.
1401 borderSelector?.Reset(this);
1402 resourceUrlSelector?.Reset(this);
1403 imagePropertyUpdatedFlag = false;
1404 if (imagePropertyUpdateProcessAttachedFlag)
1406 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1407 imagePropertyUpdateProcessAttachedFlag = false;
1409 cachedImagePropertyMap?.Dispose();
1410 cachedImagePropertyMap = null;
1416 /// This will not be public opened.
1417 [EditorBrowsable(EditorBrowsableState.Never)]
1418 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1420 Interop.ImageView.DeleteImageView(swigCPtr);
1423 // Callback for View ResourceReady signal
1424 private void OnResourceReady(IntPtr data)
1426 if (!CheckResourceReady())
1431 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1434 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1437 if (_resourceReadyEventHandler != null)
1439 _resourceReadyEventHandler(this, e);
1443 private void SetResourceUrl(string value)
1445 if (_resourceUrl != ConvertResourceUrl(ref value))
1447 _resourceUrl = value;
1448 if (string.IsNullOrEmpty(_resourceUrl))
1450 // Special case. If we set ResourceUrl as empty, Unregist visual.
1455 using (PropertyValue setValue = new PropertyValue(value))
1457 UpdateImage(ImageVisualProperty.URL, setValue);
1459 // Special case. If we set GeneratedUrl, or FastTrackUploading, Create ImageVisual synchronously.
1460 if (value.StartsWith("dali://") || value.StartsWith("enbuf://") || _fastTrackUploading)
1468 private void SetBorder(Rectangle value)
1474 if (_border != value)
1476 _border = new Rectangle(value);
1477 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1482 /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1484 private void RemoveImage()
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))
1492 PropertyValue emptyValue = new PropertyValue();
1494 // Remove current registed Image.
1495 SetProperty(ImageView.Property.IMAGE, emptyValue);
1497 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1498 imagePropertyUpdatedFlag = false;
1499 if (imagePropertyUpdateProcessAttachedFlag)
1501 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1502 imagePropertyUpdateProcessAttachedFlag = false;
1504 // Update resourceUrl as empty value
1505 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1507 emptyValue?.Dispose();
1509 currentResourceUrlValue?.Dispose();
1513 /// Lazy call to UpdateImage.
1514 /// Collect Properties need to be update, and set properties that starts the Processing.
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)
1519 [EditorBrowsable(EditorBrowsableState.Never)]
1520 protected virtual void UpdateImage(int key, PropertyValue value, bool requiredVisualCreation = true)
1522 // Update image property map value as inputed value.
1527 // Throw exception if ImageView is disposed.
1528 throw new global::System.InvalidOperationException("[NUI][ImageVIew] Someone try to change disposed ImageView's property.\n");
1531 if (cachedImagePropertyMap == null)
1533 cachedImagePropertyMap = new PropertyMap();
1536 // To optimization, we don't check URL duplicate case. We already checked before.
1537 if (key != ImageVisualProperty.URL)
1539 using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1541 if (oldValue != null && oldValue.EqualTo(value))
1543 // Ignore UpdateImage query when we try to update equality value.
1548 imagePropertyUpdatedFlag = true;
1549 cachedImagePropertyMap[key] = value;
1551 // Lazy update only if visual creation required, and _resourceUrl is not empty, and ProcessAttachedFlag is false.
1552 if (requiredVisualCreation && !string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1554 imagePropertyUpdateProcessAttachedFlag = true;
1555 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1556 // Call process hardly.
1557 ProcessorController.Instance.Awake();
1563 /// Callback function to Lazy UpdateImage.
1565 private void UpdateImage(object source, EventArgs e)
1567 // Note : To allow event attachment during UpdateImage, let we make flag as false before call UpdateImage().
1568 imagePropertyUpdateProcessAttachedFlag = false;
1573 /// Update image-relative properties synchronously.
1574 /// After call this API, All image properties updated.
1577 /// Current version ImageView property update asynchronously.
1578 /// If you want to guarantee that ImageView property setuped,
1579 /// Please call this ImageView.UpdateImage() API.
1581 [EditorBrowsable(EditorBrowsableState.Never)]
1582 protected virtual void UpdateImage()
1584 if (!imagePropertyUpdatedFlag) return;
1586 imagePropertyUpdatedFlag = false;
1588 if (cachedImagePropertyMap == null)
1590 cachedImagePropertyMap = new PropertyMap();
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)))
1598 // If ResourceUrl is not setuped, don't set property. fast return.
1599 if (string.IsNullOrEmpty(_resourceUrl))
1603 if (_border == null)
1605 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1606 cachedImagePropertyMap[Visual.Property.Type] = image;
1611 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1612 cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1614 PropertyValue border = new PropertyValue(_border);
1615 cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1620 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1622 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1623 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1625 cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1626 cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1630 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1632 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1633 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1634 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1636 cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1637 cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1638 cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
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)
1646 if (_resourceUrl != null)
1648 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1649 if (imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0)
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)
1656 adjustedDesiredWidth = _desired_width;
1657 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1661 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1662 adjustedDesiredHeight = _desired_height;
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();
1675 imageSize?.Dispose();
1683 /// Merge our collected properties, and set IMAGE property internally.
1685 private void UpdateImageMap()
1687 // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1688 using (PropertyMap imageMap = new PropertyMap())
1690 using (PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1692 returnValue?.Get(imageMap);
1694 if (cachedImagePropertyMap != null)
1696 imageMap?.Merge(cachedImagePropertyMap);
1698 using (PropertyValue setValue = new PropertyValue(imageMap))
1700 SetProperty(ImageView.Property.IMAGE, setValue);
1703 // Update cached image property.
1704 MergeCachedImageVisualProperty(imageMap);
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.
1714 [EditorBrowsable(EditorBrowsableState.Never)]
1715 protected virtual PropertyValue GetImageVisualProperty(int key)
1717 PropertyValue ret = GetCachedImageVisualProperty(key);
1720 // If we cannot find result form cached map, Get value from native engine.
1721 ret = Image?.Find(key);
1727 /// Get image visual property from NUI cached image map by key.
1728 /// If there is no matched value, return null.
1730 [EditorBrowsable(EditorBrowsableState.Never)]
1731 protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1733 return cachedImagePropertyMap?.Find(key);
1737 /// Update NUI cached image visual property map by inputed property map.
1740 /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1742 [EditorBrowsable(EditorBrowsableState.Never)]
1743 protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1745 if (map == null) return;
1746 if (cachedImagePropertyMap == null)
1748 cachedImagePropertyMap = new PropertyMap();
1750 foreach (var key in cachedImagePropertyKeyList)
1752 PropertyValue value = map.Find(key);
1755 // Update-or-Insert new value
1756 cachedImagePropertyMap[key] = value;
1757 if (key == ImageVisualProperty.URL)
1759 // Special case. If key is Url, update _resourceUrl here.
1760 value.Get(out _resourceUrl);
1767 /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1768 /// So before get base.GetNaturalSize(), we should synchronous image properties
1770 internal override Vector3 GetNaturalSize()
1772 // Sync as current properties
1774 return base.GetNaturalSize();
1777 [EditorBrowsable(EditorBrowsableState.Never)]
1778 protected override bool CheckResourceReady()
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);
1785 private void OnResourceLoaded(IntPtr view)
1787 if (!CheckResourceReady())
1791 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1792 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1794 if (_resourceLoadedEventHandler != null)
1796 _resourceLoadedEventHandler(this, e);
1801 /// Event arguments of resource ready.
1803 /// <since_tizen> 3 </since_tizen>
1804 public class ResourceReadyEventArgs : EventArgs
1809 /// The view whose resource is ready.
1811 /// <since_tizen> 3 </since_tizen>
1825 internal class ResourceLoadedEventArgs : EventArgs
1827 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1828 public ResourceLoadingStatusType Status
1841 internal new class Property
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();
1850 private enum ImageType
1853 /// For Normal Image.
1858 /// For normal image, with synchronous loading and orientation correction property
1863 /// For nine-patch image
1868 private void OnBorderChanged(int x, int y, int width, int height)
1870 Border = new Rectangle(x, y, width, height);
1872 private void OnPixelAreaChanged(float x, float y, float z, float w)
1874 PixelArea = new RelativeVector4(x, y, z, w);
1877 private class ImageLayout : LayoutItem
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.
1883 [EditorBrowsable(EditorBrowsableState.Never)]
1884 public bool AdjustViewSize
1888 return (Owner as ImageView)?.AdjustViewSize ?? false;
1892 if (Owner is ImageView imageView)
1894 imageView.AdjustViewSize = value;
1900 [EditorBrowsable(EditorBrowsableState.Never)]
1901 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1903 // To not change the view size by DALi
1904 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1905 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
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;
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));
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;
1926 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1928 newWidth = specWidth;
1929 widthSpecChanged = false;
1931 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1933 if ((AdjustViewSize) && (aspectRatio > 0))
1935 newHeight = newWidth * aspectRatio;
1940 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1942 newHeight = specHeight;
1943 heightSpecChanged = false;
1945 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1947 if ((AdjustViewSize) && (aspectRatio > 0))
1949 newWidth = newHeight / aspectRatio;
1954 if (widthSpecChanged)
1956 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1959 if (heightSpecChanged)
1961 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1964 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1965 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1967 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1968 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));