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 static internal new void Preload()
37 // Do not call View.Preload(), since we already call it
40 // Do nothing. Just call for load static values.
41 var temporalCachedImagePropertyKeyList = cachedImagePropertyKeyList;
42 var temporalCachedNUIImageViewPropertyKeyList = cachedNUIImageViewPropertyKeyList;
45 private EventHandler<ResourceReadyEventArgs> _resourceReadyEventHandler;
46 private ResourceReadyEventCallbackType _resourceReadyEventCallback;
47 private EventHandler<ResourceLoadedEventArgs> _resourceLoadedEventHandler;
48 private _resourceLoadedCallbackType _resourceLoadedCallback;
51 /// Convert non-null string that some keyword change as application specific directory.
53 /// <param name="value">Inputed and replaced after this function finished</param>
54 /// <returns>Replaced url</returns>
55 private static string ConvertResourceUrl(ref string value)
58 if (value.StartsWith("*Resource*"))
60 string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
61 value = value.Replace("*Resource*", resource);
66 // Collection of image-sensitive properties.
67 private static readonly List<int> cachedImagePropertyKeyList = new List<int> {
69 ImageVisualProperty.URL,
70 ImageVisualProperty.AlphaMaskURL,
71 ImageVisualProperty.CropToMask,
72 Visual.Property.VisualFittingMode,
73 ImageVisualProperty.DesiredWidth,
74 ImageVisualProperty.DesiredHeight,
75 ImageVisualProperty.ReleasePolicy,
76 ImageVisualProperty.WrapModeU,
77 ImageVisualProperty.WrapModeV,
78 ImageVisualProperty.SynchronousLoading,
79 Visual.Property.MixColor,
80 Visual.Property.Opacity,
81 Visual.Property.PremultipliedAlpha,
82 ImageVisualProperty.OrientationCorrection,
83 ImageVisualProperty.FastTrackUploading,
84 NpatchImageVisualProperty.Border,
85 NpatchImageVisualProperty.BorderOnly,
88 // Collection of image-sensitive properties, and need to update C# side cache value.
89 private static readonly List<int> cachedNUIImageViewPropertyKeyList = new List<int> {
90 ImageVisualProperty.URL,
91 ImageVisualProperty.DesiredWidth,
92 ImageVisualProperty.DesiredHeight,
93 ImageVisualProperty.FastTrackUploading,
95 internal PropertyMap cachedImagePropertyMap;
96 internal bool imagePropertyUpdatedFlag = false;
98 private bool imagePropertyUpdateProcessAttachedFlag = false;
99 private Rectangle _border;
101 // Development Guide : Please make ensure that these 4 values are matched with current image.
102 private string _resourceUrl = "";
103 private int _desired_width = -1;
104 private int _desired_height = -1;
105 private bool _fastTrackUploading = false;
107 private TriggerableSelector<string> resourceUrlSelector;
108 private TriggerableSelector<Rectangle> borderSelector;
110 private RelativeVector4 internalPixelArea;
113 /// Creates an initialized ImageView.
115 /// <since_tizen> 3 </since_tizen>
116 public ImageView() : this(Interop.ImageView.New(), true)
118 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
121 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
122 [EditorBrowsable(EditorBrowsableState.Never)]
123 public ImageView(ViewStyle viewStyle) : this(Interop.ImageView.New(), true, viewStyle)
128 /// Creates an initialized ImageView with setting the status of shown or hidden.
130 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
131 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
132 [EditorBrowsable(EditorBrowsableState.Never)]
133 public ImageView(bool shown) : this(Interop.ImageView.New(), true)
135 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
140 /// Creates an initialized ImageView from a URL to an image resource.<br />
141 /// If the string is empty, ImageView will not display anything.<br />
143 /// <param name="url">The URL of the image resource to display.</param>
144 /// <since_tizen> 3 </since_tizen>
145 public ImageView(string url) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
149 // Update cached property. Note that we should not re-create new visual.
150 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
152 UpdateImage(ImageVisualProperty.URL, urlValue, false);
154 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
159 /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden.
161 /// <param name="url">The URL of the image resource to display.</param>
162 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
163 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
164 [EditorBrowsable(EditorBrowsableState.Never)]
165 public ImageView(string url, bool shown) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
169 // Update cached property. Note that we should not re-create new visual.
170 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
172 UpdateImage(ImageVisualProperty.URL, urlValue, false);
174 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
178 internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size)), true)
181 _desired_width = size?.GetWidth() ?? -1;
182 _desired_height = size?.GetHeight() ?? -1;
184 // Update cached property. Note that we should not re-create new visual.
185 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
187 UpdateImage(ImageVisualProperty.URL, urlValue, false);
189 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
191 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
193 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
195 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
197 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
205 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
213 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
221 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
222 private delegate void ResourceReadyEventCallbackType(IntPtr data);
223 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
224 private delegate void _resourceLoadedCallbackType(IntPtr view);
227 /// An event for ResourceReady signal which can be used to subscribe or unsubscribe the event handler.<br />
228 /// This signal is emitted after all resources required by a control are loaded and ready.<br />
229 /// Most resources are only loaded when the control is placed on the stage.<br />
231 /// <since_tizen> 3 </since_tizen>
232 public event EventHandler<ResourceReadyEventArgs> ResourceReady
236 if (_resourceReadyEventHandler == null)
238 _resourceReadyEventCallback = OnResourceReady;
239 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
240 resourceReadySignal?.Connect(_resourceReadyEventCallback);
241 resourceReadySignal?.Dispose();
244 _resourceReadyEventHandler += value;
249 _resourceReadyEventHandler -= value;
251 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
252 if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
254 resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
256 resourceReadySignal?.Dispose();
260 internal event EventHandler<ResourceLoadedEventArgs> ResourceLoaded
264 if (_resourceLoadedEventHandler == null)
266 _resourceLoadedCallback = OnResourceLoaded;
267 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
268 resourceReadySignal?.Connect(_resourceLoadedCallback);
269 resourceReadySignal?.Dispose();
272 _resourceLoadedEventHandler += value;
276 _resourceLoadedEventHandler -= value;
277 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
278 if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
280 resourceReadySignal?.Disconnect(_resourceLoadedCallback);
282 resourceReadySignal?.Dispose();
287 /// Enumeration for LoadingStatus of image.
289 /// <since_tizen> 5 </since_tizen>
290 public enum LoadingStatusType
293 /// Loading preparing status.
295 /// <since_tizen> 5 </since_tizen>
298 /// Loading ready status.
300 /// <since_tizen> 5 </since_tizen>
303 /// Loading failed status.
305 /// <since_tizen> 5 </since_tizen>
310 /// Enumeration for MaskingMode of image.
312 [EditorBrowsable(EditorBrowsableState.Never)]
313 public enum MaskingModeType
316 /// Applies alpha masking on rendering time.
318 [EditorBrowsable(EditorBrowsableState.Never)]
321 /// Applies alpha masking on loading time.
323 [EditorBrowsable(EditorBrowsableState.Never)]
328 /// ImageView ResourceUrl, type string.
329 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
330 /// When it is set as null, it gives empty string ("") to be read.
332 /// <since_tizen> 3 </since_tizen>
333 public string ResourceUrl
337 return (string)GetValue(ResourceUrlProperty);
341 SetValue(ResourceUrlProperty, value);
342 NotifyPropertyChanged();
347 /// This will be deprecated, Use Image instead. <br />
348 /// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
350 /// <since_tizen> 3 </since_tizen>
351 [Obsolete("Do not use this, that will be deprecated. Use Image property instead.")]
352 [EditorBrowsable(EditorBrowsableState.Never)]
353 public PropertyMap ImageMap
357 return GetValue(ImageMapProperty) as PropertyMap;
361 SetValue(ImageMapProperty, value);
362 NotifyPropertyChanged();
365 private PropertyMap InternalImageMap
371 // Sync as current properties
374 // Get current properties force.
375 PropertyMap returnValue = new PropertyMap();
376 PropertyValue image = GetProperty(ImageView.Property.IMAGE);
377 image?.Get(returnValue);
380 // Update cached property map
381 if (returnValue != null)
383 MergeCachedImageVisualProperty(returnValue);
396 SetImageByPropertyMap(value);
398 NotifyPropertyChanged();
404 /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
407 /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
408 /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
409 /// you can also use <see cref="Visual.Property"/>. <br />
410 /// See <see cref="Visual.Property"/> for a detailed description. <br />
413 /// The following example demonstrates how to use the Image property.
415 /// PropertyMap map = new PropertyMap();
416 /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
417 /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
418 /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
419 /// imageview.Image = map;
422 /// <since_tizen> 4 </since_tizen>
423 public PropertyMap Image
429 return (PropertyMap)GetValue(ImageProperty);
440 SetValue(ImageProperty, value);
441 NotifyPropertyChanged();
447 /// ImageView PreMultipliedAlpha, type Boolean.<br />
448 /// Image must be initialized.<br />
450 /// <since_tizen> 3 </since_tizen>
451 public bool PreMultipliedAlpha
455 return (bool)GetValue(PreMultipliedAlphaProperty);
459 SetValue(PreMultipliedAlphaProperty, value);
460 NotifyPropertyChanged();
465 /// ImageView PixelArea, type Vector4 (Animatable property).<br />
466 /// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].<br />
469 /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
471 /// <since_tizen> 3 </since_tizen>
472 public RelativeVector4 PixelArea
476 return (RelativeVector4)GetValue(PixelAreaProperty);
480 SetValue(PixelAreaProperty, value);
481 NotifyPropertyChanged();
486 /// The border of the image in the order: left, right, bottom, top.<br />
487 /// If set, ImageMap will be ignored.<br />
488 /// For N-Patch images only.<br />
492 /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
494 /// <since_tizen> 3 </since_tizen>
495 public Rectangle Border
499 Rectangle temp = (Rectangle)GetValue(BorderProperty);
506 return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
511 SetValue(BorderProperty, value);
512 NotifyPropertyChanged();
517 /// Gets or sets whether to draw the borders only (if true).<br />
518 /// If not specified, the default is false.<br />
519 /// For N-Patch images only.<br />
522 /// <since_tizen> 3 </since_tizen>
523 public bool BorderOnly
527 return (bool)GetValue(BorderOnlyProperty);
531 SetValue(BorderOnlyProperty, value);
532 NotifyPropertyChanged();
537 /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
539 /// <since_tizen> 3 </since_tizen>
540 [Obsolete("This has been deprecated since API9 and will be removed in API11. Use SynchronousLoading instead.")]
541 public bool SynchronosLoading
545 return SynchronousLoading;
549 SynchronousLoading = value;
554 /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
557 /// Changing this property make this ImageView load image synchronously at the next loading
558 /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
559 /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
561 /// <since_tizen> 9 </since_tizen>
562 public bool SynchronousLoading
566 return (bool)GetValue(SynchronousLoadingProperty);
570 SetValue(SynchronousLoadingProperty, value);
571 NotifyPropertyChanged();
576 /// Gets or sets whether to automatically correct the orientation of an image.<br />
578 /// <since_tizen> 5 </since_tizen>
579 public bool OrientationCorrection
583 return (bool)GetValue(OrientationCorrectionProperty);
587 SetValue(OrientationCorrectionProperty, value);
588 NotifyPropertyChanged();
593 /// Gets or sets whether to apply mask on GPU or not.<br />
595 [EditorBrowsable(EditorBrowsableState.Never)]
596 public MaskingModeType MaskingMode
600 return (MaskingModeType)GetValue(MaskingModeProperty);
604 SetValue(MaskingModeProperty, value);
605 NotifyPropertyChanged();
609 private MaskingModeType InternalMaskingMode
613 int ret = (int)MaskingModeType.MaskingOnLoading;
615 PropertyValue maskingMode = GetCachedImageVisualProperty(ImageVisualProperty.MaskingMode);
616 maskingMode?.Get(out ret);
617 maskingMode?.Dispose();
619 return (MaskingModeType)ret;
623 MaskingModeType ret = value;
624 PropertyValue setValue = new PropertyValue((int)ret);
625 UpdateImage(ImageVisualProperty.MaskingMode, setValue);
631 /// Gets or sets whether to apply fast track uploading or not.<br />
634 /// If we use fast track uploading feature, It can upload texture without event-thead dependency. But also,<br />
635 /// - Texture size is invalid until ResourceReady signal comes.<br />
636 /// - Texture cannot be cached (We always try to load new image).<br />
637 /// - Seamless visual change didn't supported.<br />
638 /// - Alpha masking didn't supported. If you try, It will load as normal case.<br />
639 /// - Synchronous loading didn't supported. If you try, It will load as normal case.<br />
640 /// - Reload action didn't supported. If you try, It will load as normal case.<br />
641 /// - Atlas loading didn't supported. If you try, It will load as normal case.<br />
642 /// - Custom shader didn't supported. If you try, It will load as normal case.
644 [EditorBrowsable(EditorBrowsableState.Never)]
645 public bool FastTrackUploading
649 return (bool)GetValue(FastTrackUploadingProperty);
653 SetValue(FastTrackUploadingProperty, value);
654 NotifyPropertyChanged();
658 private bool InternalFastTrackUploading
662 PropertyValue fastTrackUploading = GetCachedImageVisualProperty(ImageVisualProperty.FastTrackUploading);
663 fastTrackUploading?.Get(out _fastTrackUploading);
664 fastTrackUploading?.Dispose();
666 return _fastTrackUploading;
670 if (_fastTrackUploading != value)
672 _fastTrackUploading = value;
674 PropertyValue setValue = new PropertyValue(_fastTrackUploading);
675 UpdateImage(ImageVisualProperty.FastTrackUploading, setValue);
678 if (_fastTrackUploading && !string.IsNullOrEmpty(_resourceUrl))
680 // Special case. If user set FastTrackUploading mean, user want to upload image As-Soon-As-Possible.
681 // Create ImageVisual synchronously.
689 /// Gets the loading state of the visual resource.
691 /// <since_tizen> 5 </since_tizen>
692 public ImageView.LoadingStatusType LoadingStatus
696 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
701 /// Downcasts a handle to imageView handle.
703 /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
704 /// Do not use this, that will be deprecated. Use as keyword instead.
705 /// <since_tizen> 3 </since_tizen>
706 [Obsolete("Do not use this, that will be deprecated. Use as keyword instead. " +
708 "BaseHandle handle = new ImageView(imagePath); " +
709 "ImageView image = handle as ImageView")]
710 [EditorBrowsable(EditorBrowsableState.Never)]
711 public static ImageView DownCast(BaseHandle handle)
715 throw new ArgumentNullException(nameof(handle));
717 ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
718 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
723 /// Sets this ImageView from the given URL.<br />
724 /// If the URL is empty, ImageView will not display anything.<br />
726 /// <param name="url">The URL to the image resource to display.</param>
727 /// <exception cref="ArgumentNullException"> Thrown when url is null. </exception>
728 /// <since_tizen> 3 </since_tizen>
729 public void SetImage(string url)
733 throw new ArgumentNullException(nameof(url));
736 if (url.Contains(".json"))
738 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
742 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url));
743 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
746 // Update cached property. Note that we should not re-create new visual.
747 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
749 UpdateImage(ImageVisualProperty.URL, urlValue, false);
751 imagePropertyUpdatedFlag = false;
755 /// Queries if all resources required by a control are loaded and ready.<br />
756 /// Most resources are only loaded when the control is placed on the stage.<br />
757 /// True if the resources are loaded and ready, false otherwise.<br />
759 /// <since_tizen> 3 </since_tizen>
760 public new bool IsResourceReady()
762 bool ret = Interop.View.IsResourceReady(SwigCPtr);
763 if (NDalicPINVOKE.SWIGPendingException.Pending)
764 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
769 /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
771 /// <since_tizen> 5 </since_tizen>
774 // Sync as current properties
778 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionReload);
782 /// Plays the animated GIF. This is also the default playback mode.
784 /// <since_tizen> 5 </since_tizen>
787 // Sync as current properties
791 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPlay);
795 /// Pauses the animated GIF.
797 /// <since_tizen> 5 </since_tizen>
800 // Sync as current properties
804 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPause);
808 /// Stops the animated GIF.
810 /// <since_tizen> 5 </since_tizen>
813 // Sync as current properties
818 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionStop);
822 /// Gets or sets the URL of the alpha mask.<br />
825 /// <since_tizen> 6</since_tizen>
826 [EditorBrowsable(EditorBrowsableState.Never)]
827 public string AlphaMaskURL
831 return GetValue(AlphaMaskURLProperty) as string;
835 SetValue(AlphaMaskURLProperty, value);
836 NotifyPropertyChanged();
840 private string InternalAlphaMaskURL
846 PropertyValue maskUrl = GetCachedImageVisualProperty(ImageVisualProperty.AlphaMaskURL);
847 maskUrl?.Get(out ret);
854 PropertyValue setValue = new PropertyValue(value ?? "");
855 UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
856 // When we never set CropToMask property before, we should set default value as true.
857 using (PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask))
859 if (cropToMask == null)
861 using PropertyValue setCropValue = new PropertyValue(true);
862 UpdateImage(ImageVisualProperty.CropToMask, setCropValue);
871 /// Whether to crop image to mask or scale mask to fit image.
873 /// <since_tizen> 6 </since_tizen>
874 public bool CropToMask
878 return (bool)GetValue(CropToMaskProperty);
882 SetValue(CropToMaskProperty, value);
883 NotifyPropertyChanged();
886 private bool InternalCropToMask
892 PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask);
893 cropToMask?.Get(out ret);
894 cropToMask?.Dispose();
900 PropertyValue setValue = new PropertyValue(value);
901 UpdateImage(ImageVisualProperty.CropToMask, setValue);
907 /// Actions property value for Reload image.
909 internal static readonly int ActionReload = Interop.ImageView.ImageVisualActionReloadGet();
912 /// Actions property value to Play animated images.
914 internal static readonly int ActionPlay = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
917 /// Actions property value to Pause animated images.
919 internal static readonly int ActionPause = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
922 /// Actions property value to Stop animated images.
924 internal static readonly int ActionStop = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
926 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
930 case FittingModeType.ShrinkToFit:
931 return VisualFittingModeType.FitKeepAspectRatio;
932 case FittingModeType.ScaleToFill:
933 return VisualFittingModeType.OverFitKeepAspectRatio;
934 case FittingModeType.Center:
935 return VisualFittingModeType.Center;
936 case FittingModeType.Fill:
937 return VisualFittingModeType.Fill;
938 case FittingModeType.FitHeight:
939 return VisualFittingModeType.FitHeight;
940 case FittingModeType.FitWidth:
941 return VisualFittingModeType.FitWidth;
943 return VisualFittingModeType.Fill;
947 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
951 case VisualFittingModeType.FitKeepAspectRatio:
952 return FittingModeType.ShrinkToFit;
953 case VisualFittingModeType.OverFitKeepAspectRatio:
954 return FittingModeType.ScaleToFill;
955 case VisualFittingModeType.Center:
956 return FittingModeType.Center;
957 case VisualFittingModeType.Fill:
958 return FittingModeType.Fill;
959 case VisualFittingModeType.FitHeight:
960 return FittingModeType.FitHeight;
961 case VisualFittingModeType.FitWidth:
962 return FittingModeType.FitWidth;
964 return FittingModeType.ShrinkToFit;
968 internal override LayoutItem CreateDefaultLayout()
970 return new ImageLayout();
974 /// Gets or sets fitting options used when resizing images to fit.<br />
975 /// If not supplied, the default is FittingModeType.Fill.<br />
976 /// For normal quad images only.<br />
979 /// <since_tizen> 6 </since_tizen>
980 [EditorBrowsable(EditorBrowsableState.Never)]
981 public FittingModeType FittingMode
985 return (FittingModeType)GetValue(FittingModeProperty);
989 SetValue(FittingModeProperty, value);
990 NotifyPropertyChanged();
994 private FittingModeType InternalFittingMode
998 int ret = (int)VisualFittingModeType.Fill;
1000 PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
1001 fittingMode?.Get(out ret);
1002 fittingMode?.Dispose();
1004 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
1008 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
1009 PropertyValue setValue = new PropertyValue((int)ret);
1010 UpdateImage(Visual.Property.VisualFittingMode, setValue);
1011 setValue?.Dispose();
1016 /// Gets or sets the desired image width.<br />
1017 /// If not specified, the actual image width is used.<br />
1018 /// For normal quad images only.<br />
1021 /// <since_tizen> 6 </since_tizen>
1022 [EditorBrowsable(EditorBrowsableState.Never)]
1023 public int DesiredWidth
1027 return (int)GetValue(DesiredWidthProperty);
1031 SetValue(DesiredWidthProperty, value);
1032 NotifyPropertyChanged();
1035 private int InternalDesiredWidth
1039 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1040 if (_desired_width != -1 && _desired_height != -1)
1044 PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
1045 desirewidth?.Get(out _desired_width);
1046 desirewidth?.Dispose();
1048 return _desired_width;
1052 if (_desired_width != value)
1054 _desired_width = value;
1055 PropertyValue setValue = new PropertyValue(value);
1056 UpdateImage(ImageVisualProperty.DesiredWidth, setValue, false);
1057 setValue?.Dispose();
1063 /// Gets or sets the desired image height.<br />
1064 /// If not specified, the actual image height is used.<br />
1065 /// For normal quad images only.<br />
1068 /// <since_tizen> 6 </since_tizen>
1069 [EditorBrowsable(EditorBrowsableState.Never)]
1070 public int DesiredHeight
1074 return (int)GetValue(DesiredHeightProperty);
1078 SetValue(DesiredHeightProperty, value);
1079 NotifyPropertyChanged();
1082 private int InternalDesiredHeight
1086 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1087 if (_desired_width != -1 && _desired_height != -1)
1091 PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
1092 desireheight?.Get(out _desired_height);
1093 desireheight?.Dispose();
1095 return _desired_height;
1099 if (_desired_height != value)
1101 _desired_height = value;
1102 PropertyValue setValue = new PropertyValue(value);
1103 UpdateImage(ImageVisualProperty.DesiredHeight, setValue, false);
1104 setValue?.Dispose();
1110 /// Gets or sets ReleasePolicy for image.<br />
1111 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
1113 [EditorBrowsable(EditorBrowsableState.Never)]
1114 public ReleasePolicyType ReleasePolicy
1118 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
1122 SetValue(ReleasePolicyProperty, value);
1123 NotifyPropertyChanged();
1127 private ReleasePolicyType InternalReleasePolicy
1131 int ret = (int)ReleasePolicyType.Detached;
1133 PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
1134 releasePoli?.Get(out ret);
1135 releasePoli?.Dispose();
1137 return (ReleasePolicyType)ret;
1141 PropertyValue setValue = new PropertyValue((int)value);
1142 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
1143 setValue?.Dispose();
1148 /// Gets or sets the wrap mode for the u coordinate.<br />
1149 /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
1150 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1151 /// For normal quad images only.<br />
1154 /// <since_tizen> 6 </since_tizen>
1155 [EditorBrowsable(EditorBrowsableState.Never)]
1156 public WrapModeType WrapModeU
1160 return (WrapModeType)GetValue(WrapModeUProperty);
1164 SetValue(WrapModeUProperty, value);
1165 NotifyPropertyChanged();
1169 private WrapModeType InternalWrapModeU
1173 int ret = (int)WrapModeType.Default;
1175 PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
1176 wrapModeU?.Get(out ret);
1177 wrapModeU?.Dispose();
1179 return (WrapModeType)ret;
1183 PropertyValue setValue = new PropertyValue((int)value);
1184 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
1185 setValue?.Dispose();
1190 /// Gets or sets the wrap mode for the v coordinate.<br />
1191 /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
1192 /// The first two elements indicate the top-left position of the area, and the last two elements are the areas of the width and the height respectively.<br />
1193 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1194 /// For normal quad images only.
1197 /// <since_tizen> 6 </since_tizen>
1198 [EditorBrowsable(EditorBrowsableState.Never)]
1199 public WrapModeType WrapModeV
1203 return (WrapModeType)GetValue(WrapModeVProperty);
1207 SetValue(WrapModeVProperty, value);
1208 NotifyPropertyChanged();
1212 private WrapModeType InternalWrapModeV
1216 int ret = (int)WrapModeType.Default;
1218 PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
1219 wrapModeV?.Get(out ret);
1220 wrapModeV?.Dispose();
1222 return (WrapModeType)ret;
1226 PropertyValue setValue = new PropertyValue((int)value);
1227 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1228 setValue?.Dispose();
1233 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1236 /// This is false by default.
1237 /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1238 /// to preserve the aspect ratio of the image resource.
1239 /// AdjustViewSize works only if ImageView is added to a View having Layout.
1240 /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1241 /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1243 /// <since_tizen> 9 </since_tizen>
1244 public bool AdjustViewSize
1248 return (bool)GetValue(AdjustViewSizeProperty);
1252 SetValue(AdjustViewSizeProperty, value);
1253 NotifyPropertyChanged();
1256 private bool adjustViewSize = false;
1259 /// ImageView PlaceHolderUrl, type string.
1260 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
1261 /// When it is set as null, it gives empty string ("") to be read.
1263 /// <since_tizen> 11 </since_tizen>
1264 [EditorBrowsable(EditorBrowsableState.Never)]
1265 public string PlaceHolderUrl
1269 return (string)GetValue(PlaceHolderUrlProperty);
1273 SetValue(PlaceHolderUrlProperty, value);
1274 NotifyPropertyChanged();
1279 /// Gets or sets whether the image use TransitionEffect or not<br />
1281 /// <since_tizen> 11 </since_tizen>
1282 [EditorBrowsable(EditorBrowsableState.Never)]
1283 public bool TransitionEffect
1287 return (bool)GetValue(TransitionEffectProperty);
1291 SetValue(TransitionEffectProperty, value);
1292 NotifyPropertyChanged();
1297 /// The mixed color value for the image.
1301 /// The property cascade chaining set is not recommended.
1305 /// This way is recommended for setting the property
1307 /// var imageView = new ImageView();
1308 /// imageView.ImageColor = new Color(0.5f, 0.1f, 0.0f, 1.0f);
1310 /// This way to set the property is prohibited
1312 /// imageView.ImageColor.R = 0.5f; //This does not guarantee a proper operation
1315 [EditorBrowsable(EditorBrowsableState.Never)]
1316 public Color ImageColor
1320 return (Color)GetValue(ImageColorProperty);
1324 SetValue(ImageColorProperty, value);
1325 NotifyPropertyChanged();
1329 internal Selector<string> ResourceUrlSelector
1331 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1334 resourceUrlSelector?.Reset(this);
1335 if (value == null) return;
1337 if (value.HasAll()) SetResourceUrl(value.All);
1338 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1343 /// Get attributes, it is abstract function and must be override.
1345 [EditorBrowsable(EditorBrowsableState.Never)]
1346 protected override ViewStyle CreateViewStyle()
1348 return new ImageViewStyle();
1351 internal void SetImage(string url, Uint16Pair size)
1353 if (url.Contains(".json"))
1355 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1359 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
1360 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1363 _desired_width = size?.GetWidth() ?? -1;
1364 _desired_height = size?.GetHeight() ?? -1;
1366 // Update cached property. Note that we should not re-create new visual.
1367 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
1369 UpdateImage(ImageVisualProperty.URL, urlValue, false);
1371 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
1373 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
1375 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
1377 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
1379 imagePropertyUpdatedFlag = false;
1382 internal ViewResourceReadySignal ResourceReadySignal(View view)
1384 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1385 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1389 internal override void ApplyCornerRadius()
1391 base.ApplyCornerRadius();
1393 if (backgroundExtraData == null) return;
1395 // Update corner radius properties to image by ActionUpdateProperty
1396 if (backgroundExtraDataUpdatedFlag.HasFlag(BackgroundExtraDataUpdatedFlag.ContentsCornerRadius))
1398 if (backgroundExtraData.CornerRadius != null)
1400 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1402 Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1406 internal override void ApplyBorderline()
1408 base.ApplyBorderline();
1410 if (backgroundExtraData == null) return;
1412 if (backgroundExtraDataUpdatedFlag.HasFlag(BackgroundExtraDataUpdatedFlag.ContentsBorderline))
1414 // Update borderline properties to image by ActionUpdateProperty
1415 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
1416 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
1417 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
1421 internal ResourceLoadingStatusType GetResourceStatus()
1423 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1427 /// you can override it to clean-up your own resources.
1429 /// <param name="type">DisposeTypes</param>
1430 /// <since_tizen> 3 </since_tizen>
1431 protected override void Dispose(DisposeTypes type)
1438 internalPixelArea?.Dispose();
1440 if (type == DisposeTypes.Explicit)
1443 //Release your own managed resources here.
1444 //You should release all of your own disposable objects here.
1447 borderSelector?.Reset(this);
1448 resourceUrlSelector?.Reset(this);
1449 imagePropertyUpdatedFlag = false;
1450 if (imagePropertyUpdateProcessAttachedFlag)
1452 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1453 imagePropertyUpdateProcessAttachedFlag = false;
1455 cachedImagePropertyMap?.Dispose();
1456 cachedImagePropertyMap = null;
1462 /// This will not be public opened.
1463 [EditorBrowsable(EditorBrowsableState.Never)]
1464 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1466 Interop.ImageView.DeleteImageView(swigCPtr);
1469 // Callback for View ResourceReady signal
1470 private void OnResourceReady(IntPtr data)
1472 if (!CheckResourceReady())
1477 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1478 if (data != IntPtr.Zero)
1480 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1483 if (_resourceReadyEventHandler != null)
1485 _resourceReadyEventHandler(this, e);
1489 private void SetResourceUrl(string value)
1491 if (_resourceUrl != ConvertResourceUrl(ref value))
1493 if (string.IsNullOrEmpty(value))
1495 // Special case. If we set ResourceUrl as empty, Unregist visual.
1500 _resourceUrl = value;
1501 using (PropertyValue setValue = new PropertyValue(value))
1503 UpdateImage(ImageVisualProperty.URL, setValue);
1505 // Special case. If we set GeneratedUrl, or FastTrackUploading, Create ImageVisual synchronously.
1506 if (value.StartsWith("dali://") || value.StartsWith("enbuf://") || _fastTrackUploading)
1514 private void SetBorder(Rectangle value)
1520 if (_border != value)
1522 _border = new Rectangle(value);
1523 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1528 /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1530 private void RemoveImage()
1532 // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1533 // Unregist and detach process only if previous resourceUrl was not empty
1534 if (!string.IsNullOrEmpty(_resourceUrl))
1536 PropertyValue emptyValue = new PropertyValue();
1538 // Remove current registed Image.
1539 SetProperty(ImageView.Property.IMAGE, emptyValue);
1541 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1542 imagePropertyUpdatedFlag = false;
1543 if (imagePropertyUpdateProcessAttachedFlag)
1545 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1546 imagePropertyUpdateProcessAttachedFlag = false;
1548 // Update resourceUrl as empty value
1550 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1554 internal void SetImageByPropertyMap(PropertyMap map)
1556 // Image properties are changed hardly. We should ignore lazy UpdateImage
1557 imagePropertyUpdatedFlag = false;
1558 cachedImagePropertyMap?.Dispose();
1559 cachedImagePropertyMap = null;
1560 MergeCachedImageVisualProperty(map);
1562 // Update _resourceUrl, _desired_width, _desired_height, _fastTrackUploading here.
1563 // Those values are C# side cached value.
1564 _desired_width = _desired_height = -1;
1565 _fastTrackUploading = false;
1570 foreach (int key in cachedNUIImageViewPropertyKeyList)
1572 using PropertyValue propertyValue = map.Find(key);
1573 if (propertyValue != null)
1575 if (key == ImageVisualProperty.URL)
1577 propertyValue.Get(out _resourceUrl);
1579 else if (key == ImageVisualProperty.DesiredWidth)
1581 propertyValue.Get(out _desired_width);
1583 else if (key == ImageVisualProperty.DesiredHeight)
1585 propertyValue.Get(out _desired_height);
1587 else if (key == ImageVisualProperty.FastTrackUploading)
1589 propertyValue.Get(out _fastTrackUploading);
1594 SetProperty(ImageView.Property.IMAGE, new Tizen.NUI.PropertyValue(map));
1602 /// Lazy call to UpdateImage.
1603 /// Collect Properties need to be update, and set properties that starts the Processing.
1605 /// If you want to update cachedImagePropertyMap, but don't want to request new visual creation, make requiredVisualCreation value as false.
1606 /// (Example : if we change SynchronousLoading property from 'true' to 'false', or if we call this function during UpdateImage)
1608 [EditorBrowsable(EditorBrowsableState.Never)]
1609 protected virtual void UpdateImage(int key, PropertyValue value, bool requiredVisualCreation = true)
1611 // Update image property map value as inputed value.
1616 // Throw exception if ImageView is disposed.
1617 throw new global::System.InvalidOperationException("[NUI][ImageVIew] Someone try to change disposed ImageView's property.\n");
1620 if (cachedImagePropertyMap == null)
1622 cachedImagePropertyMap = new PropertyMap();
1625 // To optimization, we don't check URL duplicate case. We already checked before.
1626 if (key != ImageVisualProperty.URL)
1628 using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1630 if (oldValue != null && oldValue.EqualTo(value))
1632 // Ignore UpdateImage query when we try to update equality value.
1637 imagePropertyUpdatedFlag = true;
1638 cachedImagePropertyMap[key] = value;
1640 // Lazy update only if visual creation required, and _resourceUrl is not empty, and ProcessAttachedFlag is false.
1641 if (requiredVisualCreation && !string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1643 imagePropertyUpdateProcessAttachedFlag = true;
1644 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1645 // Call process hardly.
1646 ProcessorController.Instance.Awake();
1652 /// Callback function to Lazy UpdateImage.
1654 private void UpdateImage(object source, EventArgs e)
1656 // Note : To allow event attachment during UpdateImage, let we make flag as false before call UpdateImage().
1657 imagePropertyUpdateProcessAttachedFlag = false;
1662 /// Update image-relative properties synchronously.
1663 /// After call this API, All image properties updated.
1666 /// Current version ImageView property update asynchronously.
1667 /// If you want to guarantee that ImageView property setuped,
1668 /// Please call this ImageView.UpdateImage() API.
1670 [EditorBrowsable(EditorBrowsableState.Never)]
1671 protected virtual void UpdateImage()
1673 if (!imagePropertyUpdatedFlag) return;
1675 imagePropertyUpdatedFlag = false;
1677 if (cachedImagePropertyMap == null)
1679 cachedImagePropertyMap = new PropertyMap();
1682 // Checkup the cached visual type is AnimatedImage.
1683 // It is trick to know that this code is running on AnimatedImageView.UpdateImage() with resourceURLs or not.
1684 int visualType = (int)Visual.Type.Invalid;
1685 if (!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage)))
1687 // If ResourceUrl is not setuped, don't set property. fast return.
1688 if (string.IsNullOrEmpty(_resourceUrl))
1692 if (_border == null)
1694 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1695 cachedImagePropertyMap[Visual.Property.Type] = image;
1700 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1701 cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1703 PropertyValue border = new PropertyValue(_border);
1704 cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1709 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1711 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1712 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1714 cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1715 cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1719 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1721 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1722 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1723 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1725 cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1726 cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1727 cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1731 // We already applied background extra data now.
1732 backgroundExtraDataUpdatedFlag &= ~BackgroundExtraDataUpdatedFlag.ContentsCornerRadius;
1733 backgroundExtraDataUpdatedFlag &= ~BackgroundExtraDataUpdatedFlag.ContentsBorderline;
1735 // Do Fitting Buffer when desired dimension is set
1736 // TODO : Couldn't we do this job in dali-engine side.
1737 if (_desired_width != -1 && _desired_height != -1)
1739 if (!string.IsNullOrEmpty(_resourceUrl))
1741 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1742 if (imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0)
1744 int adjustedDesiredWidth, adjustedDesiredHeight;
1745 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1746 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1747 if (aspectOfImageSize > aspectOfDesiredSize)
1749 adjustedDesiredWidth = _desired_width;
1750 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1754 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1755 adjustedDesiredHeight = _desired_height;
1758 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1759 cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1760 returnWidth?.Dispose();
1761 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1762 cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1763 returnHeight?.Dispose();
1764 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1765 cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1766 scaleToFit?.Dispose();
1768 imageSize?.Dispose();
1776 /// Merge our collected properties, and set IMAGE property internally.
1778 private void UpdateImageMap()
1780 // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1781 using (PropertyMap imageMap = new PropertyMap())
1783 using (PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1785 returnValue?.Get(imageMap);
1787 if (cachedImagePropertyMap != null)
1789 imageMap?.Merge(cachedImagePropertyMap);
1791 using (PropertyValue setValue = new PropertyValue(imageMap))
1793 SetProperty(ImageView.Property.IMAGE, setValue);
1796 // Update cached image property.
1797 MergeCachedImageVisualProperty(imageMap);
1802 /// Get image visual property by key.
1803 /// If we found value in local Cached result, return that.
1804 /// Else, get synced native map and return that.
1805 /// If there is no matched value, return null.
1807 [EditorBrowsable(EditorBrowsableState.Never)]
1808 protected virtual PropertyValue GetImageVisualProperty(int key)
1810 PropertyValue ret = GetCachedImageVisualProperty(key);
1813 // If we cannot find result form cached map, Get value from native engine.
1814 ret = Image?.Find(key);
1820 /// Get image visual property from NUI cached image map by key.
1821 /// If there is no matched value, return null.
1823 [EditorBrowsable(EditorBrowsableState.Never)]
1824 protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1826 return cachedImagePropertyMap?.Find(key);
1830 /// Update NUI cached image visual property map by inputed property map.
1833 /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1835 [EditorBrowsable(EditorBrowsableState.Never)]
1836 protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1838 if (map == null) return;
1839 if (cachedImagePropertyMap == null)
1841 cachedImagePropertyMap = new PropertyMap();
1843 foreach (var key in cachedImagePropertyKeyList)
1845 PropertyValue value = map.Find(key);
1848 // Update-or-Insert new value
1849 cachedImagePropertyMap[key] = value;
1855 /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1856 /// So before get base.GetNaturalSize(), we should synchronous image properties
1858 internal override Vector3 GetNaturalSize()
1860 // Sync as current properties
1862 return base.GetNaturalSize();
1865 [EditorBrowsable(EditorBrowsableState.Never)]
1866 protected override bool CheckResourceReady()
1868 // If we have some properties to be updated, this signal is old thing.
1869 // We need to ignore current signal, and wait next.
1870 return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1873 private void OnResourceLoaded(IntPtr view)
1875 if (!CheckResourceReady())
1879 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1880 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1882 if (_resourceLoadedEventHandler != null)
1884 _resourceLoadedEventHandler(this, e);
1889 /// Event arguments of resource ready.
1891 /// <since_tizen> 3 </since_tizen>
1892 public class ResourceReadyEventArgs : EventArgs
1897 /// The view whose resource is ready.
1899 /// <since_tizen> 3 </since_tizen>
1913 internal class ResourceLoadedEventArgs : EventArgs
1915 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1916 public ResourceLoadingStatusType Status
1929 internal new class Property
1931 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1932 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1933 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1934 internal static readonly int PlaceHolderUrl = Interop.ImageView.PlaceHolderImageGet();
1935 internal static readonly int TransitionEffect = Interop.ImageView.TransitionEffectGet();
1937 internal static void Preload()
1939 // Do nothing. Just call for load static values.
1943 private enum ImageType
1946 /// For Normal Image.
1951 /// For normal image, with synchronous loading and orientation correction property
1956 /// For nine-patch image
1961 private void OnBorderChanged(int x, int y, int width, int height)
1963 Border = new Rectangle(x, y, width, height);
1965 private void OnPixelAreaChanged(float x, float y, float z, float w)
1967 PixelArea = new RelativeVector4(x, y, z, w);
1970 private class ImageLayout : LayoutItem
1973 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1974 /// If this is set to be true, then the width or height, which is not set by user explicitly, can be adjusted to preserve the aspect ratio of the image resource.
1976 [EditorBrowsable(EditorBrowsableState.Never)]
1977 public bool AdjustViewSize
1981 return (Owner as ImageView)?.AdjustViewSize ?? false;
1985 if (Owner is ImageView imageView)
1987 imageView.AdjustViewSize = value;
1993 [EditorBrowsable(EditorBrowsableState.Never)]
1994 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1996 // To not change the view size by DALi
1997 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1998 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
2000 float specWidth = widthMeasureSpec.Size.AsDecimal();
2001 float specHeight = heightMeasureSpec.Size.AsDecimal();
2002 float naturalWidth = Owner.NaturalSize.Width;
2003 float naturalHeight = Owner.NaturalSize.Height;
2004 float minWidth = Owner.MinimumSize.Width;
2005 float maxWidth = Owner.MaximumSize.Width;
2006 float minHeight = Owner.MinimumSize.Height;
2007 float maxHeight = Owner.MaximumSize.Height;
2008 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
2010 // Assume that the new width and height are given from the view's suggested size by default.
2011 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
2012 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
2014 // The width and height measure specs are going to be used to set measured size.
2015 // Mark that the measure specs are changed by default to update measure specs later.
2016 bool widthSpecChanged = true;
2017 bool heightSpecChanged = true;
2019 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
2021 newWidth = specWidth;
2022 widthSpecChanged = false;
2024 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
2026 if ((AdjustViewSize) && (aspectRatio > 0))
2028 newHeight = newWidth * aspectRatio;
2033 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
2035 newHeight = specHeight;
2036 heightSpecChanged = false;
2038 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
2040 if ((AdjustViewSize) && (aspectRatio > 0))
2042 newWidth = newHeight / aspectRatio;
2047 if (widthSpecChanged)
2049 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
2052 if (heightSpecChanged)
2054 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
2057 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
2058 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
2060 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
2061 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));