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)
1501 // Note : To allow event attachment during UpdateImage, let we make flag as false before call UpdateImage().
1502 imagePropertyUpdateProcessAttachedFlag = false;
1507 /// Update image-relative properties synchronously.
1508 /// After call this API, All image properties updated.
1511 /// Current version ImageView property update asynchronously.
1512 /// If you want to guarantee that ImageView property setuped,
1513 /// Please call this ImageView.UpdateImage() API.
1515 [EditorBrowsable(EditorBrowsableState.Never)]
1516 protected virtual void UpdateImage()
1518 if (!imagePropertyUpdatedFlag) return;
1520 imagePropertyUpdatedFlag = false;
1522 if (cachedImagePropertyMap == null)
1524 cachedImagePropertyMap = new PropertyMap();
1527 // Checkup the cached visual type is AnimatedImage.
1528 // It is trick to know that this code is running on AnimatedImageView.UpdateImage() / LottieAnimationView.UpdateImage() or not.
1529 int visualType = (int)Visual.Type.Invalid;
1530 if (!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage || visualType == (int)Visual.Type.AnimatedVectorImage)))
1532 // If ResourceUrl is not setuped, don't set property. fast return.
1533 if (string.IsNullOrEmpty(_resourceUrl))
1537 if (_border == null)
1539 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1540 cachedImagePropertyMap[Visual.Property.Type] = image;
1545 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1546 cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1548 PropertyValue border = new PropertyValue(_border);
1549 cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1554 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1556 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1557 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1559 cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1560 cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1564 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1566 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1567 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1568 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1570 cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1571 cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1572 cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1576 // Do Fitting Buffer when desired dimension is set
1577 if (_desired_width != -1 && _desired_height != -1)
1579 if (_resourceUrl != null)
1581 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1582 if (imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0)
1584 int adjustedDesiredWidth, adjustedDesiredHeight;
1585 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1586 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1587 if (aspectOfImageSize > aspectOfDesiredSize)
1589 adjustedDesiredWidth = _desired_width;
1590 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1594 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1595 adjustedDesiredHeight = _desired_height;
1598 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1599 cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1600 returnWidth?.Dispose();
1601 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1602 cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1603 returnHeight?.Dispose();
1604 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1605 cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1606 scaleToFit?.Dispose();
1610 Tizen.Log.Fatal("NUI", "[ERROR] Can't use DesiredSize when ImageLoading is failed.");
1612 imageSize?.Dispose();
1620 /// Merge our collected properties, and set IMAGE property internally.
1622 private void UpdateImageMap()
1624 // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1625 using (PropertyMap imageMap = new PropertyMap())
1627 using (PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1629 returnValue?.Get(imageMap);
1631 if (cachedImagePropertyMap != null)
1633 imageMap?.Merge(cachedImagePropertyMap);
1635 using (PropertyValue setValue = new PropertyValue(imageMap))
1637 SetProperty(ImageView.Property.IMAGE, setValue);
1640 // Update cached image property.
1641 MergeCachedImageVisualProperty(imageMap);
1646 /// Get image visual property by key.
1647 /// If we found value in local Cached result, return that.
1648 /// Else, get synced native map and return that.
1649 /// If there is no matched value, return null.
1651 [EditorBrowsable(EditorBrowsableState.Never)]
1652 protected virtual PropertyValue GetImageVisualProperty(int key)
1654 PropertyValue ret = GetCachedImageVisualProperty(key);
1657 // If we cannot find result form cached map, Get value from native engine.
1658 ret = Image?.Find(key);
1664 /// Get image visual property from NUI cached image map by key.
1665 /// If there is no matched value, return null.
1667 [EditorBrowsable(EditorBrowsableState.Never)]
1668 protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1670 return cachedImagePropertyMap?.Find(key);
1674 /// Update NUI cached image visual property map by inputed property map.
1677 /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1679 [EditorBrowsable(EditorBrowsableState.Never)]
1680 protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1682 if (map == null) return;
1683 if (cachedImagePropertyMap == null)
1685 cachedImagePropertyMap = new PropertyMap();
1687 foreach (var key in cachedImagePropertyKeyList)
1689 PropertyValue value = map.Find(key);
1692 // Update-or-Insert new value
1693 cachedImagePropertyMap[key] = value;
1699 /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1700 /// So before get base.GetNaturalSize(), we should synchronous image properties
1702 internal override Vector3 GetNaturalSize()
1704 // Sync as current properties
1706 return base.GetNaturalSize();
1709 [EditorBrowsable(EditorBrowsableState.Never)]
1710 protected override bool CheckResourceReady()
1712 // If we have some properties to be updated, this signal is old thing.
1713 // We need to ignore current signal, and wait next.
1714 return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1717 private void OnResourceLoaded(IntPtr view)
1719 if (!CheckResourceReady())
1723 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1724 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1726 if (_resourceLoadedEventHandler != null)
1728 _resourceLoadedEventHandler(this, e);
1733 /// Event arguments of resource ready.
1735 /// <since_tizen> 3 </since_tizen>
1736 public class ResourceReadyEventArgs : EventArgs
1741 /// The view whose resource is ready.
1743 /// <since_tizen> 3 </since_tizen>
1757 internal class ResourceLoadedEventArgs : EventArgs
1759 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1760 public ResourceLoadingStatusType Status
1773 internal new class Property
1775 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1776 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1777 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1778 internal static readonly int PlaceHolderUrl = Interop.ImageView.PlaceHolderImageGet();
1779 internal static readonly int TransitionEffect = Interop.ImageView.TransitionEffectGet();
1782 private enum ImageType
1785 /// For Normal Image.
1790 /// For normal image, with synchronous loading and orientation correction property
1795 /// For nine-patch image
1800 private void OnBorderChanged(int x, int y, int width, int height)
1802 Border = new Rectangle(x, y, width, height);
1804 private void OnPixelAreaChanged(float x, float y, float z, float w)
1806 PixelArea = new RelativeVector4(x, y, z, w);
1809 private class ImageLayout : LayoutItem
1812 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1813 /// 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.
1815 [EditorBrowsable(EditorBrowsableState.Never)]
1816 public bool AdjustViewSize
1820 return (Owner as ImageView)?.AdjustViewSize ?? false;
1824 if (Owner is ImageView imageView)
1826 imageView.AdjustViewSize = value;
1832 [EditorBrowsable(EditorBrowsableState.Never)]
1833 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1835 // To not change the view size by DALi
1836 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1837 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1839 float specWidth = widthMeasureSpec.Size.AsDecimal();
1840 float specHeight = heightMeasureSpec.Size.AsDecimal();
1841 float naturalWidth = Owner.NaturalSize.Width;
1842 float naturalHeight = Owner.NaturalSize.Height;
1843 float minWidth = Owner.MinimumSize.Width;
1844 float maxWidth = Owner.MaximumSize.Width;
1845 float minHeight = Owner.MinimumSize.Height;
1846 float maxHeight = Owner.MaximumSize.Height;
1847 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1849 // Assume that the new width and height are given from the view's suggested size by default.
1850 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1851 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1853 // The width and height measure specs are going to be used to set measured size.
1854 // Mark that the measure specs are changed by default to update measure specs later.
1855 bool widthSpecChanged = true;
1856 bool heightSpecChanged = true;
1858 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1860 newWidth = specWidth;
1861 widthSpecChanged = false;
1863 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1865 if ((AdjustViewSize) && (aspectRatio > 0))
1867 newHeight = newWidth * aspectRatio;
1872 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1874 newHeight = specHeight;
1875 heightSpecChanged = false;
1877 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1879 if ((AdjustViewSize) && (aspectRatio > 0))
1881 newWidth = newHeight / aspectRatio;
1886 if (widthSpecChanged)
1888 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1891 if (heightSpecChanged)
1893 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1896 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1897 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1899 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1900 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));