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.Runtime.InteropServices;
19 using System.ComponentModel;
20 using Tizen.NUI.Binding;
22 namespace Tizen.NUI.BaseComponents
26 /// ImageView is a class for displaying an image resource.<br />
27 /// An instance of ImageView can be created using a URL or an image instance.<br />
29 /// <since_tizen> 3 </since_tizen>
30 public partial class ImageView : View
32 static ImageView() { }
34 private EventHandler<ResourceReadyEventArgs> _resourceReadyEventHandler;
35 private ResourceReadyEventCallbackType _resourceReadyEventCallback;
36 private EventHandler<ResourceLoadedEventArgs> _resourceLoadedEventHandler;
37 private _resourceLoadedCallbackType _resourceLoadedCallback;
39 // Collection of image-sensitive properties.
40 private bool _imagePropertyUpdatedFlag = false;
41 private bool _imagePropertyUpdateProcessAttachedFlag = false;
42 private PropertyMap _imagePropertyMap;
43 private Rectangle _border;
44 private string _resourceUrl = "";
45 private int _desired_width = -1;
46 private int _desired_height = -1;
47 private TriggerableSelector<string> resourceUrlSelector;
48 private TriggerableSelector<Rectangle> borderSelector;
51 /// Creates an initialized ImageView.
53 /// <since_tizen> 3 </since_tizen>
54 public ImageView() : this(Interop.ImageView.New(), true)
56 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
59 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
60 [EditorBrowsable(EditorBrowsableState.Never)]
61 public ImageView(ViewStyle viewStyle) : this(Interop.ImageView.New(), true, viewStyle)
66 /// Creates an initialized ImageView with setting the status of shown or hidden.
68 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
69 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
70 [EditorBrowsable(EditorBrowsableState.Never)]
71 public ImageView(bool shown) : this(Interop.ImageView.New(), true)
73 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
78 /// Creates an initialized ImageView from a URL to an image resource.<br />
79 /// If the string is empty, ImageView will not display anything.<br />
81 /// <param name="url">The URL of the image resource to display.</param>
82 /// <since_tizen> 3 </since_tizen>
83 public ImageView(string url) : this(Interop.ImageView.New(url), true)
86 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
91 /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden.
93 /// <param name="url">The URL of the image resource to display.</param>
94 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
95 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
96 [EditorBrowsable(EditorBrowsableState.Never)]
97 public ImageView(string url, bool shown) : this(Interop.ImageView.New(url), true)
100 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
104 internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(url, Uint16Pair.getCPtr(size)), true)
107 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
115 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
123 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
131 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
132 private delegate void ResourceReadyEventCallbackType(IntPtr data);
133 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
134 private delegate void _resourceLoadedCallbackType(IntPtr view);
137 /// An event for ResourceReady signal which can be used to subscribe or unsubscribe the event handler.<br />
138 /// This signal is emitted after all resources required by a control are loaded and ready.<br />
139 /// Most resources are only loaded when the control is placed on the stage.<br />
141 /// <since_tizen> 3 </since_tizen>
142 public event EventHandler<ResourceReadyEventArgs> ResourceReady
146 if (_resourceReadyEventHandler == null)
148 _resourceReadyEventCallback = OnResourceReady;
149 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
150 resourceReadySignal?.Connect(_resourceReadyEventCallback);
151 resourceReadySignal?.Dispose();
154 _resourceReadyEventHandler += value;
159 _resourceReadyEventHandler -= value;
161 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
162 if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
164 resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
166 resourceReadySignal?.Dispose();
170 internal event EventHandler<ResourceLoadedEventArgs> ResourceLoaded
174 if (_resourceLoadedEventHandler == null)
176 _resourceLoadedCallback = OnResourceLoaded;
177 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
178 resourceReadySignal?.Connect(_resourceLoadedCallback);
179 resourceReadySignal?.Dispose();
182 _resourceLoadedEventHandler += value;
186 _resourceLoadedEventHandler -= value;
187 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
188 if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
190 resourceReadySignal?.Disconnect(_resourceLoadedCallback);
192 resourceReadySignal?.Dispose();
197 /// Enumeration for LoadingStatus of image.
199 /// <since_tizen> 5 </since_tizen>
200 public enum LoadingStatusType
203 /// Loading preparing status.
205 /// <since_tizen> 5 </since_tizen>
208 /// Loading ready status.
210 /// <since_tizen> 5 </since_tizen>
213 /// Loading failed status.
215 /// <since_tizen> 5 </since_tizen>
220 /// ImageView ResourceUrl, type string.
221 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
222 /// When it is set as null, it gives empty string ("") to be read.
224 /// <since_tizen> 3 </since_tizen>
225 public string ResourceUrl
229 return (string)GetValue(ResourceUrlProperty);
233 SetValue(ResourceUrlProperty, value);
234 NotifyPropertyChanged();
239 /// This will be deprecated, please use Image instead. <br />
240 /// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
242 /// <since_tizen> 3 </since_tizen>
243 [Obsolete("Please do not use! This will be deprecated! Please use Image property instead!")]
244 [EditorBrowsable(EditorBrowsableState.Never)]
245 public PropertyMap ImageMap
249 return GetValue(ImageMapProperty) as PropertyMap;
253 SetValue(ImageMapProperty, value);
254 NotifyPropertyChanged();
257 private PropertyMap InternalImageMap
263 // Sync as current properties.
266 return _imagePropertyMap == null ? new PropertyMap() : new PropertyMap(_imagePropertyMap);
277 PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
278 SetProperty(ImageView.Property.IMAGE, setValue);
279 // Image properties are changed hardly. We should ignore lazy UpdateImage
280 _imagePropertyUpdatedFlag = false;
281 _imagePropertyMap?.Dispose();
282 _imagePropertyMap = null;
285 _imagePropertyMap = new PropertyMap(value);
287 NotifyPropertyChanged();
294 /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
297 /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
298 /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
299 /// you can also use <see cref="Visual.Property"/>. <br />
300 /// See <see cref="Visual.Property"/> for a detailed description. <br />
303 /// The following example demonstrates how to use the Image property.
305 /// PropertyMap map = new PropertyMap();
306 /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
307 /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
308 /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
309 /// imageview.Image = map;
312 /// <since_tizen> 4 </since_tizen>
313 public PropertyMap Image
319 return (PropertyMap)GetValue(ImageProperty);
330 SetValue(ImageProperty, value);
331 NotifyPropertyChanged();
337 /// ImageView PreMultipliedAlpha, type Boolean.<br />
338 /// Image must be initialized.<br />
340 /// <since_tizen> 3 </since_tizen>
341 public bool PreMultipliedAlpha
345 return (bool)GetValue(PreMultipliedAlphaProperty);
349 SetValue(PreMultipliedAlphaProperty, value);
350 NotifyPropertyChanged();
355 /// ImageView PixelArea, type Vector4 (Animatable property).<br />
356 /// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].<br />
359 /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
361 /// <since_tizen> 3 </since_tizen>
362 public RelativeVector4 PixelArea
366 RelativeVector4 temp = (RelativeVector4)GetValue(PixelAreaProperty);
367 return new RelativeVector4(OnPixelAreaChanged, temp.X, temp.Y, temp.Z, temp.W);
371 SetValue(PixelAreaProperty, value);
372 NotifyPropertyChanged();
377 /// The border of the image in the order: left, right, bottom, top.<br />
378 /// If set, ImageMap will be ignored.<br />
379 /// For N-Patch images only.<br />
383 /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
385 /// <since_tizen> 3 </since_tizen>
386 public Rectangle Border
390 Rectangle temp = (Rectangle)GetValue(BorderProperty);
397 return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
402 SetValue(BorderProperty, value);
403 NotifyPropertyChanged();
408 /// Gets or sets whether to draw the borders only (if true).<br />
409 /// If not specified, the default is false.<br />
410 /// For N-Patch images only.<br />
413 /// <since_tizen> 3 </since_tizen>
414 public bool BorderOnly
418 return (bool)GetValue(BorderOnlyProperty);
422 SetValue(BorderOnlyProperty, value);
423 NotifyPropertyChanged();
428 /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
430 /// <since_tizen> 3 </since_tizen>
431 [Obsolete("Deprecated since API level 9 and will be removed in API level 11. Please use SynchronousLoading instead!")]
432 public bool SynchronosLoading
436 return SynchronousLoading;
440 SynchronousLoading = value;
445 /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
448 /// Changing this property make this ImageView load image synchronously at the next loading
449 /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
450 /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
452 /// <since_tizen> 9 </since_tizen>
453 public bool SynchronousLoading
457 return (bool)GetValue(SynchronousLoadingProperty);
461 SetValue(SynchronousLoadingProperty, value);
462 NotifyPropertyChanged();
467 /// Gets or sets whether to automatically correct the orientation of an image.<br />
469 /// <since_tizen> 5 </since_tizen>
470 public bool OrientationCorrection
474 return (bool)GetValue(OrientationCorrectionProperty);
478 SetValue(OrientationCorrectionProperty, value);
479 NotifyPropertyChanged();
484 /// Gets the loading state of the visual resource.
486 /// <since_tizen> 5 </since_tizen>
487 public ImageView.LoadingStatusType LoadingStatus
491 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
496 /// Downcasts a handle to imageView handle.
498 /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
499 /// Please do not use! this will be deprecated!
500 /// Instead please use as keyword.
501 /// <since_tizen> 3 </since_tizen>
502 [Obsolete("Please do not use! This will be deprecated! Please use as keyword instead! " +
504 "BaseHandle handle = new ImageView(imagePath); " +
505 "ImageView image = handle as ImageView")]
506 [EditorBrowsable(EditorBrowsableState.Never)]
507 public static ImageView DownCast(BaseHandle handle)
511 throw new ArgumentNullException(nameof(handle));
513 ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
514 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
519 /// Sets this ImageView from the given URL.<br />
520 /// If the URL is empty, ImageView will not display anything.<br />
522 /// <param name="url">The URL to the image resource to display.</param>
523 /// <exception cref="ArgumentNullException"> Thrown when url is null. </exception>
524 /// <since_tizen> 3 </since_tizen>
525 public void SetImage(string url)
529 throw new ArgumentNullException(nameof(url));
532 if (url.Contains(".json"))
534 Tizen.Log.Fatal("NUI", "[ERROR] Please DO NOT set lottie file in ImageView! This is temporary checking, will be removed soon!");
538 Interop.ImageView.SetImage(SwigCPtr, url);
539 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
545 /// Queries if all resources required by a control are loaded and ready.<br />
546 /// Most resources are only loaded when the control is placed on the stage.<br />
547 /// True if the resources are loaded and ready, false otherwise.<br />
549 /// <since_tizen> 3 </since_tizen>
550 public new bool IsResourceReady()
552 bool ret = Interop.View.IsResourceReady(SwigCPtr);
553 if (NDalicPINVOKE.SWIGPendingException.Pending)
554 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
559 /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
561 /// <since_tizen> 5 </since_tizen>
564 PropertyValue attributes = new PropertyValue(0);
565 this.DoAction(ImageView.Property.IMAGE, ActionReload, attributes);
566 attributes?.Dispose();
570 /// Plays the animated GIF. This is also the default playback mode.
572 /// <since_tizen> 5 </since_tizen>
575 PropertyValue attributes = new PropertyValue(0);
576 this.DoAction(ImageView.Property.IMAGE, ActionPlay, attributes);
577 attributes?.Dispose();
581 /// Pauses the animated GIF.
583 /// <since_tizen> 5 </since_tizen>
586 PropertyValue attributes = new PropertyValue(0);
587 this.DoAction(ImageView.Property.IMAGE, ActionPause, attributes);
588 attributes?.Dispose();
592 /// Stops the animated GIF.
594 /// <since_tizen> 5 </since_tizen>
597 PropertyValue attributes = new PropertyValue(0);
598 this.DoAction(ImageView.Property.IMAGE, ActionStop, attributes);
599 attributes?.Dispose();
603 /// Gets or sets the URL of the alpha mask.<br />
606 /// <since_tizen> 6</since_tizen>
607 [EditorBrowsable(EditorBrowsableState.Never)]
608 public string AlphaMaskURL
612 return GetValue(AlphaMaskURLProperty) as string;
616 SetValue(AlphaMaskURLProperty, value);
617 NotifyPropertyChanged();
620 private string InternalAlphaMaskURL
626 PropertyValue maskUrl = _imagePropertyMap?.Find(ImageVisualProperty.AlphaMaskURL);
627 maskUrl?.Get(out ret);
634 PropertyValue setValue = new PropertyValue(value ?? "");
635 UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
642 /// Whether to crop image to mask or scale mask to fit image.
644 /// <since_tizen> 6 </since_tizen>
645 public bool CropToMask
649 return (bool)GetValue(CropToMaskProperty);
653 SetValue(CropToMaskProperty, value);
654 NotifyPropertyChanged();
657 private bool InternalCropToMask
663 PropertyValue cropToMask = _imagePropertyMap?.Find(ImageVisualProperty.CropToMask);
664 cropToMask?.Get(out ret);
665 cropToMask?.Dispose();
671 PropertyValue setValue = new PropertyValue(value);
672 UpdateImage(ImageVisualProperty.CropToMask, setValue);
678 /// Actions property value for Reload image.
680 private int ActionReload { get; set; } = Interop.ImageView.ImageVisualActionReloadGet();
683 /// Actions property value to Play animated images.
684 /// This property can be redefined by child class if it use different value.
686 [EditorBrowsable(EditorBrowsableState.Never)]
687 protected int ActionPlay { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
690 /// Actions property value to Pause animated images.
691 /// This property can be redefined by child class if it use different value.
693 [EditorBrowsable(EditorBrowsableState.Never)]
694 protected int ActionPause { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
697 /// Actions property value to Stop animated images.
698 /// This property can be redefined by child class if it use different value.
700 [EditorBrowsable(EditorBrowsableState.Never)]
701 protected int ActionStop { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
703 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
707 case FittingModeType.ShrinkToFit:
708 return VisualFittingModeType.FitKeepAspectRatio;
709 case FittingModeType.ScaleToFill:
710 return VisualFittingModeType.OverFitKeepAspectRatio;
711 case FittingModeType.Center:
712 return VisualFittingModeType.Center;
713 case FittingModeType.Fill:
714 return VisualFittingModeType.Fill;
715 case FittingModeType.FitHeight:
716 return VisualFittingModeType.FitHeight;
717 case FittingModeType.FitWidth:
718 return VisualFittingModeType.FitWidth;
720 return VisualFittingModeType.Fill;
724 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
728 case VisualFittingModeType.FitKeepAspectRatio:
729 return FittingModeType.ShrinkToFit;
730 case VisualFittingModeType.OverFitKeepAspectRatio:
731 return FittingModeType.ScaleToFill;
732 case VisualFittingModeType.Center:
733 return FittingModeType.Center;
734 case VisualFittingModeType.Fill:
735 return FittingModeType.Fill;
736 case VisualFittingModeType.FitHeight:
737 return FittingModeType.FitHeight;
738 case VisualFittingModeType.FitWidth:
739 return FittingModeType.FitWidth;
741 return FittingModeType.ShrinkToFit;
745 internal override LayoutItem CreateDefaultLayout()
747 return new ImageLayout();
751 /// Gets or sets fitting options used when resizing images to fit.<br />
752 /// If not supplied, the default is FittingModeType.Fill.<br />
753 /// For normal quad images only.<br />
756 /// <since_tizen> 6 </since_tizen>
757 [EditorBrowsable(EditorBrowsableState.Never)]
758 public FittingModeType FittingMode
762 return (FittingModeType)GetValue(FittingModeProperty);
766 SetValue(FittingModeProperty, value);
767 NotifyPropertyChanged();
771 private FittingModeType InternalFittingMode
775 int ret = (int)VisualFittingModeType.Fill;
776 PropertyValue fittingMode = _imagePropertyMap?.Find(Visual.Property.VisualFittingMode);
777 fittingMode?.Get(out ret);
778 fittingMode?.Dispose();
780 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
784 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
785 PropertyValue setValue = new PropertyValue((int)ret);
786 UpdateImage(Visual.Property.VisualFittingMode, setValue);
794 /// Gets or sets the desired image width.<br />
795 /// If not specified, the actual image width is used.<br />
796 /// For normal quad images only.<br />
799 /// <since_tizen> 6 </since_tizen>
800 [EditorBrowsable(EditorBrowsableState.Never)]
801 public int DesiredWidth
805 return (int)GetValue(DesiredWidthProperty);
809 SetValue(DesiredWidthProperty, value);
810 NotifyPropertyChanged();
813 private int InternalDesiredWidth
817 // Sync as current properties only if both _desired_width and _desired_height are setuped.
818 if(_desired_width != -1 && _desired_height != -1)
822 PropertyValue desirewidth = _imagePropertyMap?.Find(ImageVisualProperty.DesiredWidth);
823 desirewidth?.Get(out _desired_width);
824 desirewidth?.Dispose();
825 return _desired_width;
829 if (_desired_width != value)
831 _desired_width = value;
832 PropertyValue setValue = new PropertyValue(value);
833 UpdateImage(ImageVisualProperty.DesiredWidth, setValue);
840 /// Gets or sets the desired image height.<br />
841 /// If not specified, the actual image height is used.<br />
842 /// For normal quad images only.<br />
845 /// <since_tizen> 6 </since_tizen>
846 [EditorBrowsable(EditorBrowsableState.Never)]
847 public int DesiredHeight
851 return (int)GetValue(DesiredHeightProperty);
855 SetValue(DesiredHeightProperty, value);
856 NotifyPropertyChanged();
859 private int InternalDesiredHeight
863 // Sync as current properties only if both _desired_width and _desired_height are setuped.
864 if(_desired_width != -1 && _desired_height != -1)
868 PropertyValue desireheight = _imagePropertyMap?.Find(ImageVisualProperty.DesiredHeight);
869 desireheight?.Get(out _desired_height);
870 desireheight?.Dispose();
872 return _desired_height;
876 if (_desired_height != value)
878 _desired_height = value;
879 PropertyValue setValue = new PropertyValue(value);
880 UpdateImage(ImageVisualProperty.DesiredHeight, setValue);
887 /// Gets or sets ReleasePolicy for image.<br />
888 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
890 [EditorBrowsable(EditorBrowsableState.Never)]
891 public ReleasePolicyType ReleasePolicy
895 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
899 SetValue(ReleasePolicyProperty, value);
900 NotifyPropertyChanged();
903 private ReleasePolicyType InternalReleasePolicy
907 int ret = (int)ReleasePolicyType.Detached;
909 PropertyValue releasePoli = _imagePropertyMap?.Find(ImageVisualProperty.ReleasePolicy);
910 releasePoli?.Get(out ret);
911 releasePoli?.Dispose();
913 return (ReleasePolicyType)ret;
917 PropertyValue setValue = new PropertyValue((int)value);
918 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
924 /// Gets or sets the wrap mode for the u coordinate.<br />
925 /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
926 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
927 /// For normal quad images only.<br />
930 /// <since_tizen> 6 </since_tizen>
931 [EditorBrowsable(EditorBrowsableState.Never)]
932 public WrapModeType WrapModeU
936 return (WrapModeType)GetValue(WrapModeUProperty);
940 SetValue(WrapModeUProperty, value);
941 NotifyPropertyChanged();
944 private WrapModeType InternalWrapModeU
948 int ret = (int)WrapModeType.Default;
950 PropertyValue wrapModeU = _imagePropertyMap?.Find(ImageVisualProperty.WrapModeU);
951 wrapModeU?.Get(out ret);
952 wrapModeU?.Dispose();
954 return (WrapModeType)ret;
958 PropertyValue setValue = new PropertyValue((int)value);
959 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
965 /// Gets or sets the wrap mode for the v coordinate.<br />
966 /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
967 /// 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 />
968 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
969 /// For normal quad images only.
972 /// <since_tizen> 6 </since_tizen>
973 [EditorBrowsable(EditorBrowsableState.Never)]
974 public WrapModeType WrapModeV
978 return (WrapModeType)GetValue(WrapModeVProperty);
982 SetValue(WrapModeVProperty, value);
983 NotifyPropertyChanged();
986 private WrapModeType InternalWrapModeV
990 int ret = (int)WrapModeType.Default;
992 PropertyValue wrapModeV = _imagePropertyMap?.Find(ImageVisualProperty.WrapModeV);
993 wrapModeV?.Get(out ret);
994 wrapModeV?.Dispose();
996 return (WrapModeType)ret;
1000 PropertyValue setValue = new PropertyValue((int)value);
1001 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1002 setValue?.Dispose();
1007 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1010 /// This is false by default.
1011 /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1012 /// to preserve the aspect ratio of the image resource.
1013 /// AdjustViewSize works only if ImageView is added to a View having Layout.
1014 /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1015 /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1017 /// <since_tizen> 9 </since_tizen>
1018 public bool AdjustViewSize
1022 return (bool)GetValue(AdjustViewSizeProperty);
1026 SetValue(AdjustViewSizeProperty, value);
1027 NotifyPropertyChanged();
1030 private bool adjustViewSize = false;
1032 internal Selector<string> ResourceUrlSelector
1034 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1037 resourceUrlSelector?.Reset(this);
1038 if (value == null) return;
1040 if (value.HasAll()) SetResourceUrl(value.All);
1041 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1046 /// Get attributes, it is abstract function and must be override.
1048 [EditorBrowsable(EditorBrowsableState.Never)]
1049 protected override ViewStyle CreateViewStyle()
1051 return new ImageViewStyle();
1054 internal void SetImage(string url, Uint16Pair size)
1056 if (url.Contains(".json"))
1058 Tizen.Log.Fatal("NUI", "[ERROR] Please DO NOT set lottie file in ImageView! This is temporary checking, will be removed soon!");
1062 Interop.ImageView.SetImage(SwigCPtr, url, Uint16Pair.getCPtr(size));
1063 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1068 internal ViewResourceReadySignal ResourceReadySignal(View view)
1070 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1071 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1075 internal override void ApplyCornerRadius()
1077 base.ApplyCornerRadius();
1079 UpdateImage(0, null);
1082 internal override void ApplyBorderline()
1084 base.ApplyBorderline();
1086 // Apply borderline to IMAGE.
1087 if (backgroundExtraData != null)
1089 var borderlineColor = backgroundExtraData.BorderlineColor == null ? new PropertyValue(Color.Black) : new PropertyValue(backgroundExtraData.BorderlineColor);
1091 // Apply to the image visual
1092 PropertyMap imageMap = new PropertyMap();
1093 PropertyValue imageValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE);
1094 if (imageValue.Get(imageMap) && !imageMap.Empty())
1096 imageMap[Visual.Property.BorderlineWidth] = new PropertyValue(backgroundExtraData.BorderlineWidth);
1097 imageMap[Visual.Property.BorderlineColor] = borderlineColor;
1098 imageMap[Visual.Property.BorderlineOffset] = new PropertyValue(backgroundExtraData.BorderlineOffset);
1099 var temp = new PropertyValue(imageMap);
1100 Tizen.NUI.Object.SetProperty(SwigCPtr, ImageView.Property.IMAGE, temp);
1104 imageValue.Dispose();
1105 borderlineColor.Dispose();
1108 UpdateImage(0, null);
1111 internal ResourceLoadingStatusType GetResourceStatus()
1113 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1117 /// you can override it to clean-up your own resources.
1119 /// <param name="type">DisposeTypes</param>
1120 /// <since_tizen> 3 </since_tizen>
1121 protected override void Dispose(DisposeTypes type)
1128 if (type == DisposeTypes.Explicit)
1131 //Release your own managed resources here.
1132 //You should release all of your own disposable objects here.
1135 borderSelector?.Reset(this);
1136 resourceUrlSelector?.Reset(this);
1137 _imagePropertyUpdatedFlag = false;
1138 if (_imagePropertyUpdateProcessAttachedFlag)
1140 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1141 _imagePropertyUpdateProcessAttachedFlag = false;
1143 _imagePropertyMap?.Dispose();
1144 _imagePropertyMap = null;
1150 /// This will not be public opened.
1151 [EditorBrowsable(EditorBrowsableState.Never)]
1152 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1154 Interop.ImageView.DeleteImageView(swigCPtr);
1157 // Callback for View ResourceReady signal
1158 private void OnResourceReady(IntPtr data)
1160 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1163 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1166 if (_resourceReadyEventHandler != null)
1168 _resourceReadyEventHandler(this, e);
1172 private void SetResourceUrl(string value)
1174 value = (value == null ? "" : value);
1175 if (value.StartsWith("*Resource*"))
1177 string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
1178 value = value.Replace("*Resource*", resource);
1180 if(_resourceUrl != value)
1182 _resourceUrl = value;
1183 UpdateImage(ImageVisualProperty.URL, new PropertyValue(value));
1187 private void SetBorder(Rectangle value)
1193 if(_border != value)
1195 _border = new Rectangle(value);
1196 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1201 /// Lazy call to UpdateImage.
1202 /// Collect Properties need to be update, and set properties that starts the Processing.
1204 private void UpdateImage(int key, PropertyValue value)
1206 // If we set ResourceUrl as empty, Unregist visual.
1207 if (key == ImageVisualProperty.URL && string.IsNullOrEmpty(_resourceUrl))
1209 // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1210 // Unregist and dettach Process only if previous resourceUrl was not empty
1211 string currentResourceUrl = "";
1212 PropertyValue currentResourceUrlValue = _imagePropertyMap?.Find(ImageVisualProperty.URL);
1213 if((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1215 PropertyValue resourceUrl = new PropertyValue(_resourceUrl);
1216 PropertyMap imageMap = new PropertyMap();
1217 imageMap.Insert(ImageVisualProperty.URL, resourceUrl);
1218 PropertyValue setValue = new PropertyValue(imageMap);
1219 SetProperty(ImageView.Property.IMAGE, setValue);
1221 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1222 _imagePropertyUpdatedFlag = false;
1223 if(_imagePropertyUpdateProcessAttachedFlag)
1225 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1226 _imagePropertyUpdateProcessAttachedFlag = false;
1228 // Update resourceUrl as null
1229 _imagePropertyMap[ImageVisualProperty.URL] = resourceUrl;
1231 resourceUrl?.Dispose();
1232 setValue?.Dispose();
1233 imageMap?.Dispose();
1238 // Update image property map value as inputed value.
1241 if (_imagePropertyMap == null)
1243 _imagePropertyMap = new PropertyMap();
1245 _imagePropertyUpdatedFlag = true;
1246 _imagePropertyMap[key] = value;
1248 // Lazy update only if _resourceUrl is not empty and ProcessAttachedFlag is false.
1249 if (!string.IsNullOrEmpty(_resourceUrl) && !_imagePropertyUpdateProcessAttachedFlag)
1251 _imagePropertyUpdateProcessAttachedFlag = true;
1252 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1253 // Call process hardly.
1254 ProcessorController.Instance.Awake();
1260 /// Callback function to Lazy UpdateImage.
1261 /// Or, We can call UpdateImage() function directly if we need.
1263 private void UpdateImage(object source, EventArgs e)
1266 _imagePropertyUpdateProcessAttachedFlag = false;
1269 private void UpdateImage()
1271 if(!_imagePropertyUpdatedFlag) return;
1273 _imagePropertyUpdatedFlag = false;
1275 if(_imagePropertyMap == null)
1277 _imagePropertyMap = new PropertyMap();
1280 if (_border == null)
1282 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1283 _imagePropertyMap[Visual.Property.Type] = image;
1288 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1289 _imagePropertyMap[Visual.Property.Type] = nPatch;
1291 PropertyValue border = new PropertyValue(_border);
1292 _imagePropertyMap[NpatchImageVisualProperty.Border] = border;
1296 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1298 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1299 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1301 _imagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1302 _imagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1306 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1308 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1309 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1310 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1312 _imagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1313 _imagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1314 _imagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1318 // Do Fitting Buffer when desired dimension is set
1319 if (_desired_width != -1 && _desired_height != -1)
1321 if (_resourceUrl != null)
1323 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1324 if( imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0 )
1326 int adjustedDesiredWidth, adjustedDesiredHeight;
1327 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1328 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1329 if (aspectOfImageSize > aspectOfDesiredSize)
1331 adjustedDesiredWidth = _desired_width;
1332 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1336 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1337 adjustedDesiredHeight = _desired_height;
1340 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1341 _imagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1342 returnWidth?.Dispose();
1343 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1344 _imagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1345 returnHeight?.Dispose();
1346 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1347 _imagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1348 scaleToFit?.Dispose();
1352 Tizen.Log.Fatal("NUI", "[ERROR] Can't use DesiredSize when ImageLoading is failed.");
1354 imageSize?.Dispose();
1360 private void UpdateImageMap()
1362 PropertyMap imageMap = new PropertyMap();
1364 PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE);
1365 image?.Get(imageMap);
1366 imageMap.Merge(_imagePropertyMap);
1367 PropertyValue setValue = new PropertyValue(imageMap);
1368 SetProperty(ImageView.Property.IMAGE, setValue);
1370 // Sync local PropertyMap
1371 // TODO: Do we need to use GetProperty(SwigCPtr, ImageView.Property.IMAGE); here?
1372 _imagePropertyMap.Dispose();
1373 _imagePropertyMap = new PropertyMap(imageMap);
1375 imageMap?.Dispose();
1377 setValue?.Dispose();
1380 private void OnResourceLoaded(IntPtr view)
1382 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1383 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1385 if (_resourceLoadedEventHandler != null)
1387 _resourceLoadedEventHandler(this, e);
1392 /// Event arguments of resource ready.
1394 /// <since_tizen> 3 </since_tizen>
1395 public class ResourceReadyEventArgs : EventArgs
1400 /// The view whose resource is ready.
1402 /// <since_tizen> 3 </since_tizen>
1416 internal class ResourceLoadedEventArgs : EventArgs
1418 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1419 public ResourceLoadingStatusType Status
1432 internal new class Property
1434 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1435 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1436 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1439 private enum ImageType
1442 /// For Normal Image.
1447 /// For normal image, with synchronous loading and orientation correction property
1452 /// For nine-patch image
1457 private void OnBorderChanged(int x, int y, int width, int height)
1459 Border = new Rectangle(x, y, width, height);
1461 private void OnPixelAreaChanged(float x, float y, float z, float w)
1463 PixelArea = new RelativeVector4(x, y, z, w);
1466 private class ImageLayout : LayoutItem
1469 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1470 /// 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.
1472 [EditorBrowsable(EditorBrowsableState.Never)]
1473 public bool AdjustViewSize
1477 return (Owner as ImageView)?.AdjustViewSize ?? false;
1481 if (Owner is ImageView imageView)
1483 imageView.AdjustViewSize = value;
1489 [EditorBrowsable(EditorBrowsableState.Never)]
1490 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1492 // To not change the view size by DALi
1493 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1494 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1496 float specWidth = widthMeasureSpec.Size.AsDecimal();
1497 float specHeight = heightMeasureSpec.Size.AsDecimal();
1498 float naturalWidth = Owner.NaturalSize.Width;
1499 float naturalHeight = Owner.NaturalSize.Height;
1500 float minWidth = Owner.MinimumSize.Width;
1501 float maxWidth = Owner.MaximumSize.Width;
1502 float minHeight = Owner.MinimumSize.Height;
1503 float maxHeight = Owner.MaximumSize.Height;
1504 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1506 // Assume that the new width and height are given from the view's suggested size by default.
1507 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1508 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1510 // The width and height measure specs are going to be used to set measured size.
1511 // Mark that the measure specs are changed by default to update measure specs later.
1512 bool widthSpecChanged = true;
1513 bool heightSpecChanged = true;
1515 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1517 newWidth = specWidth;
1518 widthSpecChanged = false;
1520 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1522 if ((AdjustViewSize) && (aspectRatio > 0))
1524 newHeight = newWidth * aspectRatio;
1529 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1531 newHeight = specHeight;
1532 heightSpecChanged = false;
1534 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1536 if ((AdjustViewSize) && (aspectRatio > 0))
1538 newWidth = newHeight / aspectRatio;
1543 if (widthSpecChanged)
1545 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1548 if (heightSpecChanged)
1550 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1553 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1554 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1556 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1557 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));