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 NpatchImageVisualProperty.Border,
72 NpatchImageVisualProperty.BorderOnly,
74 internal PropertyMap cachedImagePropertyMap;
75 internal bool imagePropertyUpdatedFlag = false;
77 private bool imagePropertyUpdateProcessAttachedFlag = false;
78 private Rectangle _border;
79 private string _resourceUrl = "";
80 private int _desired_width = -1;
81 private int _desired_height = -1;
82 private TriggerableSelector<string> resourceUrlSelector;
83 private TriggerableSelector<Rectangle> borderSelector;
85 private RelativeVector4 internalPixelArea;
88 /// Creates an initialized ImageView.
90 /// <since_tizen> 3 </since_tizen>
91 public ImageView() : this(Interop.ImageView.New(), true)
93 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
96 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
97 [EditorBrowsable(EditorBrowsableState.Never)]
98 public ImageView(ViewStyle viewStyle) : this(Interop.ImageView.New(), true, viewStyle)
103 /// Creates an initialized ImageView with setting the status of shown or hidden.
105 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
106 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
107 [EditorBrowsable(EditorBrowsableState.Never)]
108 public ImageView(bool shown) : this(Interop.ImageView.New(), true)
110 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
115 /// Creates an initialized ImageView from a URL to an image resource.<br />
116 /// If the string is empty, ImageView will not display anything.<br />
118 /// <param name="url">The URL of the image resource to display.</param>
119 /// <since_tizen> 3 </since_tizen>
120 public ImageView(string url) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
124 // Update cached property. Note that we should not re-create new visual.
125 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
127 UpdateImage(ImageVisualProperty.URL, urlValue, false);
129 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
134 /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden.
136 /// <param name="url">The URL of the image resource to display.</param>
137 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
138 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
139 [EditorBrowsable(EditorBrowsableState.Never)]
140 public ImageView(string url, bool shown) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
144 // Update cached property. Note that we should not re-create new visual.
145 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
147 UpdateImage(ImageVisualProperty.URL, urlValue, false);
149 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
153 internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size)), true)
156 _desired_width = size?.GetWidth() ?? -1;
157 _desired_height = size?.GetHeight() ?? -1;
159 // Update cached property. Note that we should not re-create new visual.
160 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
162 UpdateImage(ImageVisualProperty.URL, urlValue, false);
164 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
166 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
168 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
170 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
172 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
180 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
188 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
196 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
197 private delegate void ResourceReadyEventCallbackType(IntPtr data);
198 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
199 private delegate void _resourceLoadedCallbackType(IntPtr view);
202 /// An event for ResourceReady signal which can be used to subscribe or unsubscribe the event handler.<br />
203 /// This signal is emitted after all resources required by a control are loaded and ready.<br />
204 /// Most resources are only loaded when the control is placed on the stage.<br />
206 /// <since_tizen> 3 </since_tizen>
207 public event EventHandler<ResourceReadyEventArgs> ResourceReady
211 if (_resourceReadyEventHandler == null)
213 _resourceReadyEventCallback = OnResourceReady;
214 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
215 resourceReadySignal?.Connect(_resourceReadyEventCallback);
216 resourceReadySignal?.Dispose();
219 _resourceReadyEventHandler += value;
224 _resourceReadyEventHandler -= value;
226 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
227 if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
229 resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
231 resourceReadySignal?.Dispose();
235 internal event EventHandler<ResourceLoadedEventArgs> ResourceLoaded
239 if (_resourceLoadedEventHandler == null)
241 _resourceLoadedCallback = OnResourceLoaded;
242 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
243 resourceReadySignal?.Connect(_resourceLoadedCallback);
244 resourceReadySignal?.Dispose();
247 _resourceLoadedEventHandler += value;
251 _resourceLoadedEventHandler -= value;
252 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
253 if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
255 resourceReadySignal?.Disconnect(_resourceLoadedCallback);
257 resourceReadySignal?.Dispose();
262 /// Enumeration for LoadingStatus of image.
264 /// <since_tizen> 5 </since_tizen>
265 public enum LoadingStatusType
268 /// Loading preparing status.
270 /// <since_tizen> 5 </since_tizen>
273 /// Loading ready status.
275 /// <since_tizen> 5 </since_tizen>
278 /// Loading failed status.
280 /// <since_tizen> 5 </since_tizen>
285 /// Enumeration for MaskingMode of image.
287 [EditorBrowsable(EditorBrowsableState.Never)]
288 public enum MaskingModeType
291 /// Applies alpha masking on rendering time.
293 [EditorBrowsable(EditorBrowsableState.Never)]
296 /// Applies alpha masking on loading time.
298 [EditorBrowsable(EditorBrowsableState.Never)]
303 /// ImageView ResourceUrl, type string.
304 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
305 /// When it is set as null, it gives empty string ("") to be read.
307 /// <since_tizen> 3 </since_tizen>
308 public string ResourceUrl
312 return (string)GetValue(ResourceUrlProperty);
316 SetValue(ResourceUrlProperty, value);
317 NotifyPropertyChanged();
322 /// This will be deprecated, Use Image instead. <br />
323 /// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
325 /// <since_tizen> 3 </since_tizen>
326 [Obsolete("Do not use this, that will be deprecated. Use Image property instead.")]
327 [EditorBrowsable(EditorBrowsableState.Never)]
328 public PropertyMap ImageMap
332 return GetValue(ImageMapProperty) as PropertyMap;
336 SetValue(ImageMapProperty, value);
337 NotifyPropertyChanged();
340 private PropertyMap InternalImageMap
346 // Sync as current properties
349 // Get current properties force.
350 PropertyMap returnValue = new PropertyMap();
351 PropertyValue image = GetProperty(ImageView.Property.IMAGE);
352 image?.Get(returnValue);
355 // Update cached property map
356 if (returnValue != null)
358 MergeCachedImageVisualProperty(returnValue);
371 PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
372 SetProperty(ImageView.Property.IMAGE, setValue);
374 // Image properties are changed hardly. We should ignore lazy UpdateImage
375 imagePropertyUpdatedFlag = false;
376 cachedImagePropertyMap?.Dispose();
377 cachedImagePropertyMap = null;
378 MergeCachedImageVisualProperty(value);
380 NotifyPropertyChanged();
387 /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
390 /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
391 /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
392 /// you can also use <see cref="Visual.Property"/>. <br />
393 /// See <see cref="Visual.Property"/> for a detailed description. <br />
396 /// The following example demonstrates how to use the Image property.
398 /// PropertyMap map = new PropertyMap();
399 /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
400 /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
401 /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
402 /// imageview.Image = map;
405 /// <since_tizen> 4 </since_tizen>
406 public PropertyMap Image
412 return (PropertyMap)GetValue(ImageProperty);
423 SetValue(ImageProperty, value);
424 NotifyPropertyChanged();
430 /// ImageView PreMultipliedAlpha, type Boolean.<br />
431 /// Image must be initialized.<br />
433 /// <since_tizen> 3 </since_tizen>
434 public bool PreMultipliedAlpha
438 return (bool)GetValue(PreMultipliedAlphaProperty);
442 SetValue(PreMultipliedAlphaProperty, value);
443 NotifyPropertyChanged();
448 /// ImageView PixelArea, type Vector4 (Animatable property).<br />
449 /// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].<br />
452 /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
454 /// <since_tizen> 3 </since_tizen>
455 public RelativeVector4 PixelArea
459 return (RelativeVector4)GetValue(PixelAreaProperty);
463 SetValue(PixelAreaProperty, value);
464 NotifyPropertyChanged();
469 /// The border of the image in the order: left, right, bottom, top.<br />
470 /// If set, ImageMap will be ignored.<br />
471 /// For N-Patch images only.<br />
475 /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
477 /// <since_tizen> 3 </since_tizen>
478 public Rectangle Border
482 Rectangle temp = (Rectangle)GetValue(BorderProperty);
489 return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
494 SetValue(BorderProperty, value);
495 NotifyPropertyChanged();
500 /// Gets or sets whether to draw the borders only (if true).<br />
501 /// If not specified, the default is false.<br />
502 /// For N-Patch images only.<br />
505 /// <since_tizen> 3 </since_tizen>
506 public bool BorderOnly
510 return (bool)GetValue(BorderOnlyProperty);
514 SetValue(BorderOnlyProperty, value);
515 NotifyPropertyChanged();
520 /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
522 /// <since_tizen> 3 </since_tizen>
523 [Obsolete("This has been deprecated since API9 and will be removed in API11. Use SynchronousLoading instead.")]
524 public bool SynchronosLoading
528 return SynchronousLoading;
532 SynchronousLoading = value;
537 /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
540 /// Changing this property make this ImageView load image synchronously at the next loading
541 /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
542 /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
544 /// <since_tizen> 9 </since_tizen>
545 public bool SynchronousLoading
549 return (bool)GetValue(SynchronousLoadingProperty);
553 SetValue(SynchronousLoadingProperty, value);
554 NotifyPropertyChanged();
559 /// Gets or sets whether to automatically correct the orientation of an image.<br />
561 /// <since_tizen> 5 </since_tizen>
562 public bool OrientationCorrection
566 return (bool)GetValue(OrientationCorrectionProperty);
570 SetValue(OrientationCorrectionProperty, value);
571 NotifyPropertyChanged();
576 /// Gets or sets whether to apply mask on GPU or not.<br />
578 [EditorBrowsable(EditorBrowsableState.Never)]
579 public MaskingModeType MaskingMode
583 return (MaskingModeType)GetValue(MaskingModeProperty);
587 SetValue(MaskingModeProperty, value);
588 NotifyPropertyChanged();
592 private MaskingModeType InternalMaskingMode
596 int ret = (int)MaskingModeType.MaskingOnLoading;
598 PropertyValue maskingMode = GetCachedImageVisualProperty(ImageVisualProperty.MaskingMode);
599 maskingMode?.Get(out ret);
600 maskingMode?.Dispose();
602 return (MaskingModeType)ret;
606 MaskingModeType ret = value;
607 PropertyValue setValue = new PropertyValue((int)ret);
608 UpdateImage(ImageVisualProperty.MaskingMode, setValue);
614 /// Gets the loading state of the visual resource.
616 /// <since_tizen> 5 </since_tizen>
617 public ImageView.LoadingStatusType LoadingStatus
621 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
626 /// Downcasts a handle to imageView handle.
628 /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
629 /// Do not use this, that will be deprecated. Use as keyword instead.
630 /// <since_tizen> 3 </since_tizen>
631 [Obsolete("Do not use this, that will be deprecated. Use as keyword instead. " +
633 "BaseHandle handle = new ImageView(imagePath); " +
634 "ImageView image = handle as ImageView")]
635 [EditorBrowsable(EditorBrowsableState.Never)]
636 public static ImageView DownCast(BaseHandle handle)
640 throw new ArgumentNullException(nameof(handle));
642 ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
643 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
648 /// Sets this ImageView from the given URL.<br />
649 /// If the URL is empty, ImageView will not display anything.<br />
651 /// <param name="url">The URL to the image resource to display.</param>
652 /// <exception cref="ArgumentNullException"> Thrown when url is null. </exception>
653 /// <since_tizen> 3 </since_tizen>
654 public void SetImage(string url)
658 throw new ArgumentNullException(nameof(url));
661 if (url.Contains(".json"))
663 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
667 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url));
668 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
671 // Update cached property. Note that we should not re-create new visual.
672 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
674 UpdateImage(ImageVisualProperty.URL, urlValue, false);
676 imagePropertyUpdatedFlag = false;
680 /// Queries if all resources required by a control are loaded and ready.<br />
681 /// Most resources are only loaded when the control is placed on the stage.<br />
682 /// True if the resources are loaded and ready, false otherwise.<br />
684 /// <since_tizen> 3 </since_tizen>
685 public new bool IsResourceReady()
687 bool ret = Interop.View.IsResourceReady(SwigCPtr);
688 if (NDalicPINVOKE.SWIGPendingException.Pending)
689 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
694 /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
696 /// <since_tizen> 5 </since_tizen>
699 // Sync as current properties
703 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionReload);
707 /// Plays the animated GIF. This is also the default playback mode.
709 /// <since_tizen> 5 </since_tizen>
712 // Sync as current properties
716 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPlay);
720 /// Pauses the animated GIF.
722 /// <since_tizen> 5 </since_tizen>
725 // Sync as current properties
729 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPause);
733 /// Stops the animated GIF.
735 /// <since_tizen> 5 </since_tizen>
738 // Sync as current properties
743 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionStop);
747 /// Gets or sets the URL of the alpha mask.<br />
750 /// <since_tizen> 6</since_tizen>
751 [EditorBrowsable(EditorBrowsableState.Never)]
752 public string AlphaMaskURL
756 return GetValue(AlphaMaskURLProperty) as string;
760 SetValue(AlphaMaskURLProperty, value);
761 NotifyPropertyChanged();
765 private string InternalAlphaMaskURL
771 PropertyValue maskUrl = GetCachedImageVisualProperty(ImageVisualProperty.AlphaMaskURL);
772 maskUrl?.Get(out ret);
779 PropertyValue setValue = new PropertyValue(value ?? "");
780 UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
781 // When we never set CropToMask property before, we should set default value as true.
782 using (PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask))
784 if (cropToMask == null)
786 using PropertyValue setCropValue = new PropertyValue(true);
787 UpdateImage(ImageVisualProperty.CropToMask, setCropValue);
796 /// Whether to crop image to mask or scale mask to fit image.
798 /// <since_tizen> 6 </since_tizen>
799 public bool CropToMask
803 return (bool)GetValue(CropToMaskProperty);
807 SetValue(CropToMaskProperty, value);
808 NotifyPropertyChanged();
811 private bool InternalCropToMask
817 PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask);
818 cropToMask?.Get(out ret);
819 cropToMask?.Dispose();
825 PropertyValue setValue = new PropertyValue(value);
826 UpdateImage(ImageVisualProperty.CropToMask, setValue);
832 /// Actions property value for Reload image.
834 private int ActionReload { get; set; } = Interop.ImageView.ImageVisualActionReloadGet();
837 /// Actions property value to Play animated images.
838 /// This property can be redefined by child class if it use different value.
840 [EditorBrowsable(EditorBrowsableState.Never)]
841 protected int ActionPlay { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
844 /// Actions property value to Pause animated images.
845 /// This property can be redefined by child class if it use different value.
847 [EditorBrowsable(EditorBrowsableState.Never)]
848 protected int ActionPause { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
851 /// Actions property value to Stop animated images.
852 /// This property can be redefined by child class if it use different value.
854 [EditorBrowsable(EditorBrowsableState.Never)]
855 protected int ActionStop { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
857 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
861 case FittingModeType.ShrinkToFit:
862 return VisualFittingModeType.FitKeepAspectRatio;
863 case FittingModeType.ScaleToFill:
864 return VisualFittingModeType.OverFitKeepAspectRatio;
865 case FittingModeType.Center:
866 return VisualFittingModeType.Center;
867 case FittingModeType.Fill:
868 return VisualFittingModeType.Fill;
869 case FittingModeType.FitHeight:
870 return VisualFittingModeType.FitHeight;
871 case FittingModeType.FitWidth:
872 return VisualFittingModeType.FitWidth;
874 return VisualFittingModeType.Fill;
878 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
882 case VisualFittingModeType.FitKeepAspectRatio:
883 return FittingModeType.ShrinkToFit;
884 case VisualFittingModeType.OverFitKeepAspectRatio:
885 return FittingModeType.ScaleToFill;
886 case VisualFittingModeType.Center:
887 return FittingModeType.Center;
888 case VisualFittingModeType.Fill:
889 return FittingModeType.Fill;
890 case VisualFittingModeType.FitHeight:
891 return FittingModeType.FitHeight;
892 case VisualFittingModeType.FitWidth:
893 return FittingModeType.FitWidth;
895 return FittingModeType.ShrinkToFit;
899 internal override LayoutItem CreateDefaultLayout()
901 return new ImageLayout();
905 /// Gets or sets fitting options used when resizing images to fit.<br />
906 /// If not supplied, the default is FittingModeType.Fill.<br />
907 /// For normal quad images only.<br />
910 /// <since_tizen> 6 </since_tizen>
911 [EditorBrowsable(EditorBrowsableState.Never)]
912 public FittingModeType FittingMode
916 return (FittingModeType)GetValue(FittingModeProperty);
920 SetValue(FittingModeProperty, value);
921 NotifyPropertyChanged();
925 private FittingModeType InternalFittingMode
929 int ret = (int)VisualFittingModeType.Fill;
931 PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
932 fittingMode?.Get(out ret);
933 fittingMode?.Dispose();
935 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
939 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
940 PropertyValue setValue = new PropertyValue((int)ret);
941 UpdateImage(Visual.Property.VisualFittingMode, setValue);
947 /// Gets or sets the desired image width.<br />
948 /// If not specified, the actual image width is used.<br />
949 /// For normal quad images only.<br />
952 /// <since_tizen> 6 </since_tizen>
953 [EditorBrowsable(EditorBrowsableState.Never)]
954 public int DesiredWidth
958 return (int)GetValue(DesiredWidthProperty);
962 SetValue(DesiredWidthProperty, value);
963 NotifyPropertyChanged();
966 private int InternalDesiredWidth
970 // Sync as current properties only if both _desired_width and _desired_height are setuped.
971 if (_desired_width != -1 && _desired_height != -1)
975 PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
976 desirewidth?.Get(out _desired_width);
977 desirewidth?.Dispose();
979 return _desired_width;
983 if (_desired_width != value)
985 _desired_width = value;
986 PropertyValue setValue = new PropertyValue(value);
987 UpdateImage(ImageVisualProperty.DesiredWidth, setValue, false);
994 /// Gets or sets the desired image height.<br />
995 /// If not specified, the actual image height is used.<br />
996 /// For normal quad images only.<br />
999 /// <since_tizen> 6 </since_tizen>
1000 [EditorBrowsable(EditorBrowsableState.Never)]
1001 public int DesiredHeight
1005 return (int)GetValue(DesiredHeightProperty);
1009 SetValue(DesiredHeightProperty, value);
1010 NotifyPropertyChanged();
1013 private int InternalDesiredHeight
1017 // Sync as current properties only if both _desired_width and _desired_height are setuped.
1018 if (_desired_width != -1 && _desired_height != -1)
1022 PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
1023 desireheight?.Get(out _desired_height);
1024 desireheight?.Dispose();
1026 return _desired_height;
1030 if (_desired_height != value)
1032 _desired_height = value;
1033 PropertyValue setValue = new PropertyValue(value);
1034 UpdateImage(ImageVisualProperty.DesiredHeight, setValue, false);
1035 setValue?.Dispose();
1041 /// Gets or sets ReleasePolicy for image.<br />
1042 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
1044 [EditorBrowsable(EditorBrowsableState.Never)]
1045 public ReleasePolicyType ReleasePolicy
1049 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
1053 SetValue(ReleasePolicyProperty, value);
1054 NotifyPropertyChanged();
1058 private ReleasePolicyType InternalReleasePolicy
1062 int ret = (int)ReleasePolicyType.Detached;
1064 PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
1065 releasePoli?.Get(out ret);
1066 releasePoli?.Dispose();
1068 return (ReleasePolicyType)ret;
1072 PropertyValue setValue = new PropertyValue((int)value);
1073 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
1074 setValue?.Dispose();
1079 /// Gets or sets the wrap mode for the u coordinate.<br />
1080 /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
1081 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1082 /// For normal quad images only.<br />
1085 /// <since_tizen> 6 </since_tizen>
1086 [EditorBrowsable(EditorBrowsableState.Never)]
1087 public WrapModeType WrapModeU
1091 return (WrapModeType)GetValue(WrapModeUProperty);
1095 SetValue(WrapModeUProperty, value);
1096 NotifyPropertyChanged();
1100 private WrapModeType InternalWrapModeU
1104 int ret = (int)WrapModeType.Default;
1106 PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
1107 wrapModeU?.Get(out ret);
1108 wrapModeU?.Dispose();
1110 return (WrapModeType)ret;
1114 PropertyValue setValue = new PropertyValue((int)value);
1115 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
1116 setValue?.Dispose();
1121 /// Gets or sets the wrap mode for the v coordinate.<br />
1122 /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
1123 /// 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 />
1124 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1125 /// For normal quad images only.
1128 /// <since_tizen> 6 </since_tizen>
1129 [EditorBrowsable(EditorBrowsableState.Never)]
1130 public WrapModeType WrapModeV
1134 return (WrapModeType)GetValue(WrapModeVProperty);
1138 SetValue(WrapModeVProperty, value);
1139 NotifyPropertyChanged();
1143 private WrapModeType InternalWrapModeV
1147 int ret = (int)WrapModeType.Default;
1149 PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
1150 wrapModeV?.Get(out ret);
1151 wrapModeV?.Dispose();
1153 return (WrapModeType)ret;
1157 PropertyValue setValue = new PropertyValue((int)value);
1158 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1159 setValue?.Dispose();
1164 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1167 /// This is false by default.
1168 /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1169 /// to preserve the aspect ratio of the image resource.
1170 /// AdjustViewSize works only if ImageView is added to a View having Layout.
1171 /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1172 /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1174 /// <since_tizen> 9 </since_tizen>
1175 public bool AdjustViewSize
1179 return (bool)GetValue(AdjustViewSizeProperty);
1183 SetValue(AdjustViewSizeProperty, value);
1184 NotifyPropertyChanged();
1187 private bool adjustViewSize = false;
1190 /// ImageView PlaceHolderUrl, type string.
1191 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
1192 /// When it is set as null, it gives empty string ("") to be read.
1194 /// <since_tizen> 11 </since_tizen>
1195 [EditorBrowsable(EditorBrowsableState.Never)]
1196 public string PlaceHolderUrl
1200 return (string)GetValue(PlaceHolderUrlProperty);
1204 SetValue(PlaceHolderUrlProperty, value);
1205 NotifyPropertyChanged();
1210 /// Gets or sets whether the image use TransitionEffect or not<br />
1212 /// <since_tizen> 11 </since_tizen>
1213 [EditorBrowsable(EditorBrowsableState.Never)]
1214 public bool TransitionEffect
1218 return (bool)GetValue(TransitionEffectProperty);
1222 SetValue(TransitionEffectProperty, value);
1223 NotifyPropertyChanged();
1227 internal Selector<string> ResourceUrlSelector
1229 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1232 resourceUrlSelector?.Reset(this);
1233 if (value == null) return;
1235 if (value.HasAll()) SetResourceUrl(value.All);
1236 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1241 /// Get attributes, it is abstract function and must be override.
1243 [EditorBrowsable(EditorBrowsableState.Never)]
1244 protected override ViewStyle CreateViewStyle()
1246 return new ImageViewStyle();
1249 internal void SetImage(string url, Uint16Pair size)
1251 if (url.Contains(".json"))
1253 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1257 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
1258 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1261 _desired_width = size?.GetWidth() ?? -1;
1262 _desired_height = size?.GetHeight() ?? -1;
1264 // Update cached property. Note that we should not re-create new visual.
1265 using (PropertyValue urlValue = new PropertyValue(_resourceUrl))
1267 UpdateImage(ImageVisualProperty.URL, urlValue, false);
1269 using (PropertyValue desiredWidthValue = new PropertyValue(_desired_width))
1271 UpdateImage(ImageVisualProperty.DesiredWidth, desiredWidthValue, false);
1273 using (PropertyValue desiredHeightValue = new PropertyValue(_desired_height))
1275 UpdateImage(ImageVisualProperty.DesiredWidth, desiredHeightValue, false);
1277 imagePropertyUpdatedFlag = false;
1280 internal ViewResourceReadySignal ResourceReadySignal(View view)
1282 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1283 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1287 internal override void ApplyCornerRadius()
1289 base.ApplyCornerRadius();
1291 if (backgroundExtraData == null) return;
1294 // Update corner radius properties to image by ActionUpdateProperty
1295 if (backgroundExtraData.CornerRadius != null)
1297 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1299 Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1302 internal override void ApplyBorderline()
1304 base.ApplyBorderline();
1306 if (backgroundExtraData == null) return;
1309 // Update borderline properties to image by ActionUpdateProperty
1310 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
1311 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
1312 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
1315 internal ResourceLoadingStatusType GetResourceStatus()
1317 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1321 /// you can override it to clean-up your own resources.
1323 /// <param name="type">DisposeTypes</param>
1324 /// <since_tizen> 3 </since_tizen>
1325 protected override void Dispose(DisposeTypes type)
1332 internalPixelArea?.Dispose();
1334 if (type == DisposeTypes.Explicit)
1337 //Release your own managed resources here.
1338 //You should release all of your own disposable objects here.
1341 borderSelector?.Reset(this);
1342 resourceUrlSelector?.Reset(this);
1343 imagePropertyUpdatedFlag = false;
1344 if (imagePropertyUpdateProcessAttachedFlag)
1346 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1347 imagePropertyUpdateProcessAttachedFlag = false;
1349 cachedImagePropertyMap?.Dispose();
1350 cachedImagePropertyMap = null;
1356 /// This will not be public opened.
1357 [EditorBrowsable(EditorBrowsableState.Never)]
1358 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1360 Interop.ImageView.DeleteImageView(swigCPtr);
1363 // Callback for View ResourceReady signal
1364 private void OnResourceReady(IntPtr data)
1366 if (!CheckResourceReady())
1371 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1374 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1377 if (_resourceReadyEventHandler != null)
1379 _resourceReadyEventHandler(this, e);
1383 private void SetResourceUrl(string value)
1385 if (_resourceUrl != ConvertResourceUrl(ref value))
1387 _resourceUrl = value;
1388 if (string.IsNullOrEmpty(_resourceUrl))
1390 // Special case. If we set ResourceUrl as empty, Unregist visual.
1395 using (PropertyValue setValue = new PropertyValue(value))
1397 UpdateImage(ImageVisualProperty.URL, setValue);
1399 // Special case. If we set GeneratedUrl, Create ImageVisual synchronously.
1400 if (value.StartsWith("dali://") || value.StartsWith("enbuf://"))
1408 private void SetBorder(Rectangle value)
1414 if (_border != value)
1416 _border = new Rectangle(value);
1417 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1422 /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1424 private void RemoveImage()
1426 // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1427 // Unregist and detach process only if previous resourceUrl was not empty
1428 string currentResourceUrl = "";
1429 PropertyValue currentResourceUrlValue = GetCachedImageVisualProperty(ImageVisualProperty.URL);
1430 if ((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1432 PropertyValue emptyValue = new PropertyValue();
1434 // Remove current registed Image.
1435 SetProperty(ImageView.Property.IMAGE, emptyValue);
1437 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1438 imagePropertyUpdatedFlag = false;
1439 if (imagePropertyUpdateProcessAttachedFlag)
1441 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1442 imagePropertyUpdateProcessAttachedFlag = false;
1444 // Update resourceUrl as empty value
1445 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1447 emptyValue?.Dispose();
1449 currentResourceUrlValue?.Dispose();
1453 /// Lazy call to UpdateImage.
1454 /// Collect Properties need to be update, and set properties that starts the Processing.
1456 /// If you want to update cachedImagePropertyMap, but don't want to request new visual creation, make requiredVisualCreation value as false.
1457 /// (Example : if we change SynchronousLoading property from 'true' to 'false', or if we call this function during UpdateImage)
1459 [EditorBrowsable(EditorBrowsableState.Never)]
1460 protected virtual void UpdateImage(int key, PropertyValue value, bool requiredVisualCreation = true)
1462 // Update image property map value as inputed value.
1465 if (cachedImagePropertyMap == null)
1467 cachedImagePropertyMap = new PropertyMap();
1470 // To optimization, we don't check URL duplicate case. We already checked before.
1471 if (key != ImageVisualProperty.URL)
1473 using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1475 if (oldValue != null && oldValue.EqualTo(value))
1477 // Ignore UpdateImage query when we try to update equality value.
1482 imagePropertyUpdatedFlag = true;
1483 cachedImagePropertyMap[key] = value;
1485 // Lazy update only if visual creation required, and _resourceUrl is not empty, and ProcessAttachedFlag is false.
1486 if (requiredVisualCreation && !string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1488 imagePropertyUpdateProcessAttachedFlag = true;
1489 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1490 // Call process hardly.
1491 ProcessorController.Instance.Awake();
1497 /// Callback function to Lazy UpdateImage.
1499 private void UpdateImage(object source, EventArgs e)
1502 imagePropertyUpdateProcessAttachedFlag = false;
1506 /// Update image-relative properties synchronously.
1507 /// After call this API, All image properties updated.
1510 /// Current version ImageView property update asynchronously.
1511 /// If you want to guarantee that ImageView property setuped,
1512 /// Please call this ImageView.UpdateImage() API.
1514 [EditorBrowsable(EditorBrowsableState.Never)]
1515 protected virtual void UpdateImage()
1517 if (!imagePropertyUpdatedFlag) return;
1519 imagePropertyUpdatedFlag = false;
1521 if (cachedImagePropertyMap == null)
1523 cachedImagePropertyMap = new PropertyMap();
1526 // Checkup the cached visual type is AnimatedImage.
1527 // It is trick to know that this code is running on AnimatedImageView.UpdateImage() / LottieAnimationView.UpdateImage() or not.
1528 int visualType = (int)Visual.Type.Invalid;
1529 if (!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage || visualType == (int)Visual.Type.AnimatedVectorImage)))
1531 // If ResourceUrl is not setuped, don't set property. fast return.
1532 if (string.IsNullOrEmpty(_resourceUrl))
1536 if (_border == null)
1538 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1539 cachedImagePropertyMap[Visual.Property.Type] = image;
1544 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1545 cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1547 PropertyValue border = new PropertyValue(_border);
1548 cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1553 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1555 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1556 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1558 cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1559 cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1563 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1565 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1566 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1567 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1569 cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1570 cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1571 cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1575 // Do Fitting Buffer when desired dimension is set
1576 if (_desired_width != -1 && _desired_height != -1)
1578 if (_resourceUrl != null)
1580 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1581 if (imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0)
1583 int adjustedDesiredWidth, adjustedDesiredHeight;
1584 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1585 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1586 if (aspectOfImageSize > aspectOfDesiredSize)
1588 adjustedDesiredWidth = _desired_width;
1589 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1593 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1594 adjustedDesiredHeight = _desired_height;
1597 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1598 cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1599 returnWidth?.Dispose();
1600 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1601 cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1602 returnHeight?.Dispose();
1603 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1604 cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1605 scaleToFit?.Dispose();
1609 Tizen.Log.Fatal("NUI", "[ERROR] Can't use DesiredSize when ImageLoading is failed.");
1611 imageSize?.Dispose();
1619 /// Merge our collected properties, and set IMAGE property internally.
1621 private void UpdateImageMap()
1623 // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1624 using (PropertyMap imageMap = new PropertyMap())
1626 using (PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1628 returnValue?.Get(imageMap);
1630 if (cachedImagePropertyMap != null)
1632 imageMap?.Merge(cachedImagePropertyMap);
1634 using (PropertyValue setValue = new PropertyValue(imageMap))
1636 SetProperty(ImageView.Property.IMAGE, setValue);
1639 // Update cached image property.
1640 MergeCachedImageVisualProperty(imageMap);
1645 /// Get image visual property by key.
1646 /// If we found value in local Cached result, return that.
1647 /// Else, get synced native map and return that.
1648 /// If there is no matched value, return null.
1650 [EditorBrowsable(EditorBrowsableState.Never)]
1651 protected virtual PropertyValue GetImageVisualProperty(int key)
1653 PropertyValue ret = GetCachedImageVisualProperty(key);
1656 // If we cannot find result form cached map, Get value from native engine.
1657 ret = Image?.Find(key);
1663 /// Get image visual property from NUI cached image map by key.
1664 /// If there is no matched value, return null.
1666 [EditorBrowsable(EditorBrowsableState.Never)]
1667 protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1669 return cachedImagePropertyMap?.Find(key);
1673 /// Update NUI cached image visual property map by inputed property map.
1676 /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1678 [EditorBrowsable(EditorBrowsableState.Never)]
1679 protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1681 if (map == null) return;
1682 if (cachedImagePropertyMap == null)
1684 cachedImagePropertyMap = new PropertyMap();
1686 foreach (var key in cachedImagePropertyKeyList)
1688 PropertyValue value = map.Find(key);
1691 // Update-or-Insert new value
1692 cachedImagePropertyMap[key] = value;
1698 /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1699 /// So before get base.GetNaturalSize(), we should synchronous image properties
1701 internal override Vector3 GetNaturalSize()
1703 // Sync as current properties
1705 return base.GetNaturalSize();
1708 [EditorBrowsable(EditorBrowsableState.Never)]
1709 protected override bool CheckResourceReady()
1711 // If we have some properties to be updated, this signal is old thing.
1712 // We need to ignore current signal, and wait next.
1713 return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1716 private void OnResourceLoaded(IntPtr view)
1718 if (!CheckResourceReady())
1722 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1723 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1725 if (_resourceLoadedEventHandler != null)
1727 _resourceLoadedEventHandler(this, e);
1732 /// Event arguments of resource ready.
1734 /// <since_tizen> 3 </since_tizen>
1735 public class ResourceReadyEventArgs : EventArgs
1740 /// The view whose resource is ready.
1742 /// <since_tizen> 3 </since_tizen>
1756 internal class ResourceLoadedEventArgs : EventArgs
1758 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1759 public ResourceLoadingStatusType Status
1772 internal new class Property
1774 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1775 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1776 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1777 internal static readonly int PlaceHolderUrl = Interop.ImageView.PlaceHolderImageGet();
1778 internal static readonly int TransitionEffect = Interop.ImageView.TransitionEffectGet();
1781 private enum ImageType
1784 /// For Normal Image.
1789 /// For normal image, with synchronous loading and orientation correction property
1794 /// For nine-patch image
1799 private void OnBorderChanged(int x, int y, int width, int height)
1801 Border = new Rectangle(x, y, width, height);
1803 private void OnPixelAreaChanged(float x, float y, float z, float w)
1805 PixelArea = new RelativeVector4(x, y, z, w);
1808 private class ImageLayout : LayoutItem
1811 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1812 /// 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.
1814 [EditorBrowsable(EditorBrowsableState.Never)]
1815 public bool AdjustViewSize
1819 return (Owner as ImageView)?.AdjustViewSize ?? false;
1823 if (Owner is ImageView imageView)
1825 imageView.AdjustViewSize = value;
1831 [EditorBrowsable(EditorBrowsableState.Never)]
1832 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1834 // To not change the view size by DALi
1835 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1836 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1838 float specWidth = widthMeasureSpec.Size.AsDecimal();
1839 float specHeight = heightMeasureSpec.Size.AsDecimal();
1840 float naturalWidth = Owner.NaturalSize.Width;
1841 float naturalHeight = Owner.NaturalSize.Height;
1842 float minWidth = Owner.MinimumSize.Width;
1843 float maxWidth = Owner.MaximumSize.Width;
1844 float minHeight = Owner.MinimumSize.Height;
1845 float maxHeight = Owner.MaximumSize.Height;
1846 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1848 // Assume that the new width and height are given from the view's suggested size by default.
1849 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1850 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1852 // The width and height measure specs are going to be used to set measured size.
1853 // Mark that the measure specs are changed by default to update measure specs later.
1854 bool widthSpecChanged = true;
1855 bool heightSpecChanged = true;
1857 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1859 newWidth = specWidth;
1860 widthSpecChanged = false;
1862 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1864 if ((AdjustViewSize) && (aspectRatio > 0))
1866 newHeight = newWidth * aspectRatio;
1871 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1873 newHeight = specHeight;
1874 heightSpecChanged = false;
1876 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1878 if ((AdjustViewSize) && (aspectRatio > 0))
1880 newWidth = newHeight / aspectRatio;
1885 if (widthSpecChanged)
1887 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1890 if (heightSpecChanged)
1892 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1895 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1896 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1898 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1899 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));