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 internal static readonly int ActionReload = Interop.ImageView.ImageVisualActionReloadGet();
897 /// Actions property value to Play animated images.
899 internal static readonly int ActionPlay = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
902 /// Actions property value to Pause animated images.
904 internal static readonly int ActionPause = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
907 /// Actions property value to Stop animated images.
909 internal static readonly int ActionStop = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
911 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
915 case FittingModeType.ShrinkToFit:
916 return VisualFittingModeType.FitKeepAspectRatio;
917 case FittingModeType.ScaleToFill:
918 return VisualFittingModeType.OverFitKeepAspectRatio;
919 case FittingModeType.Center:
920 return VisualFittingModeType.Center;
921 case FittingModeType.Fill:
922 return VisualFittingModeType.Fill;
923 case FittingModeType.FitHeight:
924 return VisualFittingModeType.FitHeight;
925 case FittingModeType.FitWidth:
926 return VisualFittingModeType.FitWidth;
928 return VisualFittingModeType.Fill;
932 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
936 case VisualFittingModeType.FitKeepAspectRatio:
937 return FittingModeType.ShrinkToFit;
938 case VisualFittingModeType.OverFitKeepAspectRatio:
939 return FittingModeType.ScaleToFill;
940 case VisualFittingModeType.Center:
941 return FittingModeType.Center;
942 case VisualFittingModeType.Fill:
943 return FittingModeType.Fill;
944 case VisualFittingModeType.FitHeight:
945 return FittingModeType.FitHeight;
946 case VisualFittingModeType.FitWidth:
947 return FittingModeType.FitWidth;
949 return FittingModeType.ShrinkToFit;
953 internal override LayoutItem CreateDefaultLayout()
955 return new ImageLayout();
959 /// Gets or sets fitting options used when resizing images to fit.<br />
960 /// If not supplied, the default is FittingModeType.Fill.<br />
961 /// For normal quad images only.<br />
964 /// <since_tizen> 6 </since_tizen>
965 [EditorBrowsable(EditorBrowsableState.Never)]
966 public FittingModeType FittingMode
970 return (FittingModeType)GetValue(FittingModeProperty);
974 SetValue(FittingModeProperty, value);
975 NotifyPropertyChanged();
979 private FittingModeType InternalFittingMode
983 int ret = (int)VisualFittingModeType.Fill;
985 PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
986 fittingMode?.Get(out ret);
987 fittingMode?.Dispose();
989 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
993 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
994 PropertyValue setValue = new PropertyValue((int)ret);
995 UpdateImage(Visual.Property.VisualFittingMode, setValue);
1001 /// Gets or sets the desired image width.<br />
1002 /// If not specified, the actual image width is used.<br />
1003 /// For normal quad images only.<br />
1006 /// <since_tizen> 6 </since_tizen>
1007 [EditorBrowsable(EditorBrowsableState.Never)]
1008 public int DesiredWidth
1012 return (int)GetValue(DesiredWidthProperty);
1016 SetValue(DesiredWidthProperty, value);
1017 NotifyPropertyChanged();
1020 private int InternalDesiredWidth
1024 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1025 if (_desired_width != -1 && _desired_height != -1)
1029 PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
1030 desirewidth?.Get(out _desired_width);
1031 desirewidth?.Dispose();
1033 return _desired_width;
1037 if (_desired_width != value)
1039 _desired_width = value;
1040 PropertyValue setValue = new PropertyValue(value);
1041 UpdateImage(ImageVisualProperty.DesiredWidth, setValue, false);
1042 setValue?.Dispose();
1048 /// Gets or sets the desired image height.<br />
1049 /// If not specified, the actual image height is used.<br />
1050 /// For normal quad images only.<br />
1053 /// <since_tizen> 6 </since_tizen>
1054 [EditorBrowsable(EditorBrowsableState.Never)]
1055 public int DesiredHeight
1059 return (int)GetValue(DesiredHeightProperty);
1063 SetValue(DesiredHeightProperty, value);
1064 NotifyPropertyChanged();
1067 private int InternalDesiredHeight
1071 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1072 if (_desired_width != -1 && _desired_height != -1)
1076 PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
1077 desireheight?.Get(out _desired_height);
1078 desireheight?.Dispose();
1080 return _desired_height;
1084 if (_desired_height != value)
1086 _desired_height = value;
1087 PropertyValue setValue = new PropertyValue(value);
1088 UpdateImage(ImageVisualProperty.DesiredHeight, setValue, false);
1089 setValue?.Dispose();
1095 /// Gets or sets ReleasePolicy for image.<br />
1096 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
1098 [EditorBrowsable(EditorBrowsableState.Never)]
1099 public ReleasePolicyType ReleasePolicy
1103 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
1107 SetValue(ReleasePolicyProperty, value);
1108 NotifyPropertyChanged();
1112 private ReleasePolicyType InternalReleasePolicy
1116 int ret = (int)ReleasePolicyType.Detached;
1118 PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
1119 releasePoli?.Get(out ret);
1120 releasePoli?.Dispose();
1122 return (ReleasePolicyType)ret;
1126 PropertyValue setValue = new PropertyValue((int)value);
1127 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
1128 setValue?.Dispose();
1133 /// Gets or sets the wrap mode for the u coordinate.<br />
1134 /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
1135 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1136 /// For normal quad images only.<br />
1139 /// <since_tizen> 6 </since_tizen>
1140 [EditorBrowsable(EditorBrowsableState.Never)]
1141 public WrapModeType WrapModeU
1145 return (WrapModeType)GetValue(WrapModeUProperty);
1149 SetValue(WrapModeUProperty, value);
1150 NotifyPropertyChanged();
1154 private WrapModeType InternalWrapModeU
1158 int ret = (int)WrapModeType.Default;
1160 PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
1161 wrapModeU?.Get(out ret);
1162 wrapModeU?.Dispose();
1164 return (WrapModeType)ret;
1168 PropertyValue setValue = new PropertyValue((int)value);
1169 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
1170 setValue?.Dispose();
1175 /// Gets or sets the wrap mode for the v coordinate.<br />
1176 /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
1177 /// 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 />
1178 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1179 /// For normal quad images only.
1182 /// <since_tizen> 6 </since_tizen>
1183 [EditorBrowsable(EditorBrowsableState.Never)]
1184 public WrapModeType WrapModeV
1188 return (WrapModeType)GetValue(WrapModeVProperty);
1192 SetValue(WrapModeVProperty, value);
1193 NotifyPropertyChanged();
1197 private WrapModeType InternalWrapModeV
1201 int ret = (int)WrapModeType.Default;
1203 PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
1204 wrapModeV?.Get(out ret);
1205 wrapModeV?.Dispose();
1207 return (WrapModeType)ret;
1211 PropertyValue setValue = new PropertyValue((int)value);
1212 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1213 setValue?.Dispose();
1218 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1221 /// This is false by default.
1222 /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1223 /// to preserve the aspect ratio of the image resource.
1224 /// AdjustViewSize works only if ImageView is added to a View having Layout.
1225 /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1226 /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1228 /// <since_tizen> 9 </since_tizen>
1229 public bool AdjustViewSize
1233 return (bool)GetValue(AdjustViewSizeProperty);
1237 SetValue(AdjustViewSizeProperty, value);
1238 NotifyPropertyChanged();
1241 private bool adjustViewSize = false;
1244 /// ImageView PlaceHolderUrl, type string.
1245 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
1246 /// When it is set as null, it gives empty string ("") to be read.
1248 /// <since_tizen> 11 </since_tizen>
1249 [EditorBrowsable(EditorBrowsableState.Never)]
1250 public string PlaceHolderUrl
1254 return (string)GetValue(PlaceHolderUrlProperty);
1258 SetValue(PlaceHolderUrlProperty, value);
1259 NotifyPropertyChanged();
1264 /// Gets or sets whether the image use TransitionEffect or not<br />
1266 /// <since_tizen> 11 </since_tizen>
1267 [EditorBrowsable(EditorBrowsableState.Never)]
1268 public bool TransitionEffect
1272 return (bool)GetValue(TransitionEffectProperty);
1276 SetValue(TransitionEffectProperty, value);
1277 NotifyPropertyChanged();
1281 internal Selector<string> ResourceUrlSelector
1283 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1286 resourceUrlSelector?.Reset(this);
1287 if (value == null) return;
1289 if (value.HasAll()) SetResourceUrl(value.All);
1290 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1295 /// Get attributes, it is abstract function and must be override.
1297 [EditorBrowsable(EditorBrowsableState.Never)]
1298 protected override ViewStyle CreateViewStyle()
1300 return new ImageViewStyle();
1303 internal void SetImage(string url, Uint16Pair size)
1305 if (url.Contains(".json"))
1307 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1311 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
1312 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1315 _desired_width = size?.GetWidth() ?? -1;
1316 _desired_height = size?.GetHeight() ?? -1;
1318 // Update cached property. Note that we should not re-create new visual.
1319 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
1321 UpdateImage(ImageVisualProperty.URL, urlValue, false);
1323 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
1325 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
1327 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
1329 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
1331 imagePropertyUpdatedFlag = false;
1334 internal ViewResourceReadySignal ResourceReadySignal(View view)
1336 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1337 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1341 internal override void ApplyCornerRadius()
1343 base.ApplyCornerRadius();
1345 if (backgroundExtraData == null) return;
1348 // Update corner radius properties to image by ActionUpdateProperty
1349 if (backgroundExtraData.CornerRadius != null)
1351 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1353 Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1356 internal override void ApplyBorderline()
1358 base.ApplyBorderline();
1360 if (backgroundExtraData == null) return;
1363 // Update borderline properties to image by ActionUpdateProperty
1364 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
1365 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
1366 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
1369 internal ResourceLoadingStatusType GetResourceStatus()
1371 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1375 /// you can override it to clean-up your own resources.
1377 /// <param name="type">DisposeTypes</param>
1378 /// <since_tizen> 3 </since_tizen>
1379 protected override void Dispose(DisposeTypes type)
1386 internalPixelArea?.Dispose();
1388 if (type == DisposeTypes.Explicit)
1391 //Release your own managed resources here.
1392 //You should release all of your own disposable objects here.
1395 borderSelector?.Reset(this);
1396 resourceUrlSelector?.Reset(this);
1397 imagePropertyUpdatedFlag = false;
1398 if (imagePropertyUpdateProcessAttachedFlag)
1400 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1401 imagePropertyUpdateProcessAttachedFlag = false;
1403 cachedImagePropertyMap?.Dispose();
1404 cachedImagePropertyMap = null;
1410 /// This will not be public opened.
1411 [EditorBrowsable(EditorBrowsableState.Never)]
1412 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1414 Interop.ImageView.DeleteImageView(swigCPtr);
1417 // Callback for View ResourceReady signal
1418 private void OnResourceReady(IntPtr data)
1420 if (!CheckResourceReady())
1425 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1428 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1431 if (_resourceReadyEventHandler != null)
1433 _resourceReadyEventHandler(this, e);
1437 private void SetResourceUrl(string value)
1439 if (_resourceUrl != ConvertResourceUrl(ref value))
1441 _resourceUrl = value;
1442 if (string.IsNullOrEmpty(_resourceUrl))
1444 // Special case. If we set ResourceUrl as empty, Unregist visual.
1449 using (PropertyValue setValue = new PropertyValue(value))
1451 UpdateImage(ImageVisualProperty.URL, setValue);
1453 // Special case. If we set GeneratedUrl, or FastTrackUploading, Create ImageVisual synchronously.
1454 if (value.StartsWith("dali://") || value.StartsWith("enbuf://") || _fastTrackUploading)
1462 private void SetBorder(Rectangle value)
1468 if (_border != value)
1470 _border = new Rectangle(value);
1471 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1476 /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1478 private void RemoveImage()
1480 // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1481 // Unregist and detach process only if previous resourceUrl was not empty
1482 string currentResourceUrl = "";
1483 PropertyValue currentResourceUrlValue = GetCachedImageVisualProperty(ImageVisualProperty.URL);
1484 if ((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1486 PropertyValue emptyValue = new PropertyValue();
1488 // Remove current registed Image.
1489 SetProperty(ImageView.Property.IMAGE, emptyValue);
1491 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1492 imagePropertyUpdatedFlag = false;
1493 if (imagePropertyUpdateProcessAttachedFlag)
1495 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1496 imagePropertyUpdateProcessAttachedFlag = false;
1498 // Update resourceUrl as empty value
1499 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1501 emptyValue?.Dispose();
1503 currentResourceUrlValue?.Dispose();
1507 /// Lazy call to UpdateImage.
1508 /// Collect Properties need to be update, and set properties that starts the Processing.
1510 /// If you want to update cachedImagePropertyMap, but don't want to request new visual creation, make requiredVisualCreation value as false.
1511 /// (Example : if we change SynchronousLoading property from 'true' to 'false', or if we call this function during UpdateImage)
1513 [EditorBrowsable(EditorBrowsableState.Never)]
1514 protected virtual void UpdateImage(int key, PropertyValue value, bool requiredVisualCreation = true)
1516 // Update image property map value as inputed value.
1521 // Throw exception if ImageView is disposed.
1522 throw new global::System.InvalidOperationException("[NUI][ImageVIew] Someone try to change disposed ImageView's property.\n");
1525 if (cachedImagePropertyMap == null)
1527 cachedImagePropertyMap = new PropertyMap();
1530 // To optimization, we don't check URL duplicate case. We already checked before.
1531 if (key != ImageVisualProperty.URL)
1533 using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1535 if (oldValue != null && oldValue.EqualTo(value))
1537 // Ignore UpdateImage query when we try to update equality value.
1542 imagePropertyUpdatedFlag = true;
1543 cachedImagePropertyMap[key] = value;
1545 // Lazy update only if visual creation required, and _resourceUrl is not empty, and ProcessAttachedFlag is false.
1546 if (requiredVisualCreation && !string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1548 imagePropertyUpdateProcessAttachedFlag = true;
1549 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1550 // Call process hardly.
1551 ProcessorController.Instance.Awake();
1557 /// Callback function to Lazy UpdateImage.
1559 private void UpdateImage(object source, EventArgs e)
1561 // Note : To allow event attachment during UpdateImage, let we make flag as false before call UpdateImage().
1562 imagePropertyUpdateProcessAttachedFlag = false;
1567 /// Update image-relative properties synchronously.
1568 /// After call this API, All image properties updated.
1571 /// Current version ImageView property update asynchronously.
1572 /// If you want to guarantee that ImageView property setuped,
1573 /// Please call this ImageView.UpdateImage() API.
1575 [EditorBrowsable(EditorBrowsableState.Never)]
1576 protected virtual void UpdateImage()
1578 if (!imagePropertyUpdatedFlag) return;
1580 imagePropertyUpdatedFlag = false;
1582 if (cachedImagePropertyMap == null)
1584 cachedImagePropertyMap = new PropertyMap();
1587 // Checkup the cached visual type is AnimatedImage.
1588 // It is trick to know that this code is running on AnimatedImageView.UpdateImage() with resourceURLs or not.
1589 int visualType = (int)Visual.Type.Invalid;
1590 if (!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage)))
1592 // If ResourceUrl is not setuped, don't set property. fast return.
1593 if (string.IsNullOrEmpty(_resourceUrl))
1597 if (_border == null)
1599 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1600 cachedImagePropertyMap[Visual.Property.Type] = image;
1605 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1606 cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1608 PropertyValue border = new PropertyValue(_border);
1609 cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1614 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1616 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1617 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1619 cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1620 cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1624 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1626 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1627 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1628 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1630 cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1631 cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1632 cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1636 // Do Fitting Buffer when desired dimension is set
1637 // TODO : Couldn't we do this job in dali-engine side.
1638 if (_desired_width != -1 && _desired_height != -1)
1640 if (_resourceUrl != null)
1642 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1643 if (imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0)
1645 int adjustedDesiredWidth, adjustedDesiredHeight;
1646 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1647 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1648 if (aspectOfImageSize > aspectOfDesiredSize)
1650 adjustedDesiredWidth = _desired_width;
1651 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1655 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1656 adjustedDesiredHeight = _desired_height;
1659 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1660 cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1661 returnWidth?.Dispose();
1662 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1663 cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1664 returnHeight?.Dispose();
1665 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1666 cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1667 scaleToFit?.Dispose();
1669 imageSize?.Dispose();
1677 /// Merge our collected properties, and set IMAGE property internally.
1679 private void UpdateImageMap()
1681 // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1682 using (PropertyMap imageMap = new PropertyMap())
1684 using (PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1686 returnValue?.Get(imageMap);
1688 if (cachedImagePropertyMap != null)
1690 imageMap?.Merge(cachedImagePropertyMap);
1692 using (PropertyValue setValue = new PropertyValue(imageMap))
1694 SetProperty(ImageView.Property.IMAGE, setValue);
1697 // Update cached image property.
1698 MergeCachedImageVisualProperty(imageMap);
1703 /// Get image visual property by key.
1704 /// If we found value in local Cached result, return that.
1705 /// Else, get synced native map and return that.
1706 /// If there is no matched value, return null.
1708 [EditorBrowsable(EditorBrowsableState.Never)]
1709 protected virtual PropertyValue GetImageVisualProperty(int key)
1711 PropertyValue ret = GetCachedImageVisualProperty(key);
1714 // If we cannot find result form cached map, Get value from native engine.
1715 ret = Image?.Find(key);
1721 /// Get image visual property from NUI cached image map by key.
1722 /// If there is no matched value, return null.
1724 [EditorBrowsable(EditorBrowsableState.Never)]
1725 protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1727 return cachedImagePropertyMap?.Find(key);
1731 /// Update NUI cached image visual property map by inputed property map.
1734 /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1736 [EditorBrowsable(EditorBrowsableState.Never)]
1737 protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1739 if (map == null) return;
1740 if (cachedImagePropertyMap == null)
1742 cachedImagePropertyMap = new PropertyMap();
1744 foreach (var key in cachedImagePropertyKeyList)
1746 PropertyValue value = map.Find(key);
1749 // Update-or-Insert new value
1750 cachedImagePropertyMap[key] = value;
1751 if (key == ImageVisualProperty.URL)
1753 // Special case. If key is Url, update _resourceUrl here.
1754 value.Get(out _resourceUrl);
1761 /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1762 /// So before get base.GetNaturalSize(), we should synchronous image properties
1764 internal override Vector3 GetNaturalSize()
1766 // Sync as current properties
1768 return base.GetNaturalSize();
1771 [EditorBrowsable(EditorBrowsableState.Never)]
1772 protected override bool CheckResourceReady()
1774 // If we have some properties to be updated, this signal is old thing.
1775 // We need to ignore current signal, and wait next.
1776 return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1779 private void OnResourceLoaded(IntPtr view)
1781 if (!CheckResourceReady())
1785 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1786 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1788 if (_resourceLoadedEventHandler != null)
1790 _resourceLoadedEventHandler(this, e);
1795 /// Event arguments of resource ready.
1797 /// <since_tizen> 3 </since_tizen>
1798 public class ResourceReadyEventArgs : EventArgs
1803 /// The view whose resource is ready.
1805 /// <since_tizen> 3 </since_tizen>
1819 internal class ResourceLoadedEventArgs : EventArgs
1821 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1822 public ResourceLoadingStatusType Status
1835 internal new class Property
1837 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1838 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1839 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1840 internal static readonly int PlaceHolderUrl = Interop.ImageView.PlaceHolderImageGet();
1841 internal static readonly int TransitionEffect = Interop.ImageView.TransitionEffectGet();
1844 private enum ImageType
1847 /// For Normal Image.
1852 /// For normal image, with synchronous loading and orientation correction property
1857 /// For nine-patch image
1862 private void OnBorderChanged(int x, int y, int width, int height)
1864 Border = new Rectangle(x, y, width, height);
1866 private void OnPixelAreaChanged(float x, float y, float z, float w)
1868 PixelArea = new RelativeVector4(x, y, z, w);
1871 private class ImageLayout : LayoutItem
1874 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1875 /// 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.
1877 [EditorBrowsable(EditorBrowsableState.Never)]
1878 public bool AdjustViewSize
1882 return (Owner as ImageView)?.AdjustViewSize ?? false;
1886 if (Owner is ImageView imageView)
1888 imageView.AdjustViewSize = value;
1894 [EditorBrowsable(EditorBrowsableState.Never)]
1895 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1897 // To not change the view size by DALi
1898 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1899 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1901 float specWidth = widthMeasureSpec.Size.AsDecimal();
1902 float specHeight = heightMeasureSpec.Size.AsDecimal();
1903 float naturalWidth = Owner.NaturalSize.Width;
1904 float naturalHeight = Owner.NaturalSize.Height;
1905 float minWidth = Owner.MinimumSize.Width;
1906 float maxWidth = Owner.MaximumSize.Width;
1907 float minHeight = Owner.MinimumSize.Height;
1908 float maxHeight = Owner.MaximumSize.Height;
1909 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1911 // Assume that the new width and height are given from the view's suggested size by default.
1912 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1913 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1915 // The width and height measure specs are going to be used to set measured size.
1916 // Mark that the measure specs are changed by default to update measure specs later.
1917 bool widthSpecChanged = true;
1918 bool heightSpecChanged = true;
1920 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1922 newWidth = specWidth;
1923 widthSpecChanged = false;
1925 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1927 if ((AdjustViewSize) && (aspectRatio > 0))
1929 newHeight = newWidth * aspectRatio;
1934 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1936 newHeight = specHeight;
1937 heightSpecChanged = false;
1939 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1941 if ((AdjustViewSize) && (aspectRatio > 0))
1943 newWidth = newHeight / aspectRatio;
1948 if (widthSpecChanged)
1950 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1953 if (heightSpecChanged)
1955 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1958 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1959 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1961 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1962 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));