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 // Get current properties force.
264 // TODO: Need to make some flag that we only need cached property map.
265 PropertyMap returnValue = new PropertyMap();
266 PropertyValue image = GetProperty(ImageView.Property.IMAGE);
267 image?.Get(returnValue);
280 PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
281 SetProperty(ImageView.Property.IMAGE, setValue);
282 // Image properties are changed hardly. We should ignore lazy UpdateImage
283 _imagePropertyUpdatedFlag = false;
284 _imagePropertyMap?.Dispose();
285 _imagePropertyMap = null;
288 _imagePropertyMap = new PropertyMap(value);
290 NotifyPropertyChanged();
297 /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
300 /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
301 /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
302 /// you can also use <see cref="Visual.Property"/>. <br />
303 /// See <see cref="Visual.Property"/> for a detailed description. <br />
306 /// The following example demonstrates how to use the Image property.
308 /// PropertyMap map = new PropertyMap();
309 /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
310 /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
311 /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
312 /// imageview.Image = map;
315 /// <since_tizen> 4 </since_tizen>
316 public PropertyMap Image
322 return (PropertyMap)GetValue(ImageProperty);
333 SetValue(ImageProperty, value);
334 NotifyPropertyChanged();
340 /// ImageView PreMultipliedAlpha, type Boolean.<br />
341 /// Image must be initialized.<br />
343 /// <since_tizen> 3 </since_tizen>
344 public bool PreMultipliedAlpha
348 return (bool)GetValue(PreMultipliedAlphaProperty);
352 SetValue(PreMultipliedAlphaProperty, value);
353 NotifyPropertyChanged();
358 /// ImageView PixelArea, type Vector4 (Animatable property).<br />
359 /// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].<br />
362 /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
364 /// <since_tizen> 3 </since_tizen>
365 public RelativeVector4 PixelArea
369 RelativeVector4 temp = (RelativeVector4)GetValue(PixelAreaProperty);
370 return new RelativeVector4(OnPixelAreaChanged, temp.X, temp.Y, temp.Z, temp.W);
374 SetValue(PixelAreaProperty, value);
375 NotifyPropertyChanged();
380 /// The border of the image in the order: left, right, bottom, top.<br />
381 /// If set, ImageMap will be ignored.<br />
382 /// For N-Patch images only.<br />
386 /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
388 /// <since_tizen> 3 </since_tizen>
389 public Rectangle Border
393 Rectangle temp = (Rectangle)GetValue(BorderProperty);
400 return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
405 SetValue(BorderProperty, value);
406 NotifyPropertyChanged();
411 /// Gets or sets whether to draw the borders only (if true).<br />
412 /// If not specified, the default is false.<br />
413 /// For N-Patch images only.<br />
416 /// <since_tizen> 3 </since_tizen>
417 public bool BorderOnly
421 return (bool)GetValue(BorderOnlyProperty);
425 SetValue(BorderOnlyProperty, value);
426 NotifyPropertyChanged();
431 /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
433 /// <since_tizen> 3 </since_tizen>
434 [Obsolete("Deprecated since API level 9 and will be removed in API level 11. Please use SynchronousLoading instead!")]
435 public bool SynchronosLoading
439 return SynchronousLoading;
443 SynchronousLoading = value;
448 /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
451 /// Changing this property make this ImageView load image synchronously at the next loading
452 /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
453 /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
455 /// <since_tizen> 9 </since_tizen>
456 public bool SynchronousLoading
460 return (bool)GetValue(SynchronousLoadingProperty);
464 SetValue(SynchronousLoadingProperty, value);
465 NotifyPropertyChanged();
470 /// Gets or sets whether to automatically correct the orientation of an image.<br />
472 /// <since_tizen> 5 </since_tizen>
473 public bool OrientationCorrection
477 return (bool)GetValue(OrientationCorrectionProperty);
481 SetValue(OrientationCorrectionProperty, value);
482 NotifyPropertyChanged();
487 /// Gets the loading state of the visual resource.
489 /// <since_tizen> 5 </since_tizen>
490 public ImageView.LoadingStatusType LoadingStatus
494 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
499 /// Downcasts a handle to imageView handle.
501 /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
502 /// Please do not use! this will be deprecated!
503 /// Instead please use as keyword.
504 /// <since_tizen> 3 </since_tizen>
505 [Obsolete("Please do not use! This will be deprecated! Please use as keyword instead! " +
507 "BaseHandle handle = new ImageView(imagePath); " +
508 "ImageView image = handle as ImageView")]
509 [EditorBrowsable(EditorBrowsableState.Never)]
510 public static ImageView DownCast(BaseHandle handle)
514 throw new ArgumentNullException(nameof(handle));
516 ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
517 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
522 /// Sets this ImageView from the given URL.<br />
523 /// If the URL is empty, ImageView will not display anything.<br />
525 /// <param name="url">The URL to the image resource to display.</param>
526 /// <exception cref="ArgumentNullException"> Thrown when url is null. </exception>
527 /// <since_tizen> 3 </since_tizen>
528 public void SetImage(string url)
532 throw new ArgumentNullException(nameof(url));
535 if (url.Contains(".json"))
537 Tizen.Log.Fatal("NUI", "[ERROR] Please DO NOT set lottie file in ImageView! This is temporary checking, will be removed soon!");
541 Interop.ImageView.SetImage(SwigCPtr, url);
542 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
548 /// Queries if all resources required by a control are loaded and ready.<br />
549 /// Most resources are only loaded when the control is placed on the stage.<br />
550 /// True if the resources are loaded and ready, false otherwise.<br />
552 /// <since_tizen> 3 </since_tizen>
553 public new bool IsResourceReady()
555 bool ret = Interop.View.IsResourceReady(SwigCPtr);
556 if (NDalicPINVOKE.SWIGPendingException.Pending)
557 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
562 /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
564 /// <since_tizen> 5 </since_tizen>
567 PropertyValue attributes = new PropertyValue(0);
568 this.DoAction(ImageView.Property.IMAGE, ActionReload, attributes);
569 attributes?.Dispose();
573 /// Plays the animated GIF. This is also the default playback mode.
575 /// <since_tizen> 5 </since_tizen>
578 PropertyValue attributes = new PropertyValue(0);
579 this.DoAction(ImageView.Property.IMAGE, ActionPlay, attributes);
580 attributes?.Dispose();
584 /// Pauses the animated GIF.
586 /// <since_tizen> 5 </since_tizen>
589 PropertyValue attributes = new PropertyValue(0);
590 this.DoAction(ImageView.Property.IMAGE, ActionPause, attributes);
591 attributes?.Dispose();
595 /// Stops the animated GIF.
597 /// <since_tizen> 5 </since_tizen>
600 PropertyValue attributes = new PropertyValue(0);
601 this.DoAction(ImageView.Property.IMAGE, ActionStop, attributes);
602 attributes?.Dispose();
606 /// Gets or sets the URL of the alpha mask.<br />
609 /// <since_tizen> 6</since_tizen>
610 [EditorBrowsable(EditorBrowsableState.Never)]
611 public string AlphaMaskURL
615 return GetValue(AlphaMaskURLProperty) as string;
619 SetValue(AlphaMaskURLProperty, value);
620 NotifyPropertyChanged();
624 private string InternalAlphaMaskURL
630 PropertyValue maskUrl = _imagePropertyMap?.Find(ImageVisualProperty.AlphaMaskURL);
631 maskUrl?.Get(out ret);
638 PropertyValue setValue = new PropertyValue(value ?? "");
639 UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
646 /// Whether to crop image to mask or scale mask to fit image.
648 /// <since_tizen> 6 </since_tizen>
649 public bool CropToMask
653 return (bool)GetValue(CropToMaskProperty);
657 SetValue(CropToMaskProperty, value);
658 NotifyPropertyChanged();
661 private bool InternalCropToMask
667 PropertyValue cropToMask = _imagePropertyMap?.Find(ImageVisualProperty.CropToMask);
668 cropToMask?.Get(out ret);
669 cropToMask?.Dispose();
675 PropertyValue setValue = new PropertyValue(value);
676 UpdateImage(ImageVisualProperty.CropToMask, setValue);
682 /// Actions property value for Reload image.
684 private int ActionReload { get; set; } = Interop.ImageView.ImageVisualActionReloadGet();
687 /// Actions property value to Play animated images.
688 /// This property can be redefined by child class if it use different value.
690 [EditorBrowsable(EditorBrowsableState.Never)]
691 protected int ActionPlay { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
694 /// Actions property value to Pause animated images.
695 /// This property can be redefined by child class if it use different value.
697 [EditorBrowsable(EditorBrowsableState.Never)]
698 protected int ActionPause { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
701 /// Actions property value to Stop animated images.
702 /// This property can be redefined by child class if it use different value.
704 [EditorBrowsable(EditorBrowsableState.Never)]
705 protected int ActionStop { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
707 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
711 case FittingModeType.ShrinkToFit:
712 return VisualFittingModeType.FitKeepAspectRatio;
713 case FittingModeType.ScaleToFill:
714 return VisualFittingModeType.OverFitKeepAspectRatio;
715 case FittingModeType.Center:
716 return VisualFittingModeType.Center;
717 case FittingModeType.Fill:
718 return VisualFittingModeType.Fill;
719 case FittingModeType.FitHeight:
720 return VisualFittingModeType.FitHeight;
721 case FittingModeType.FitWidth:
722 return VisualFittingModeType.FitWidth;
724 return VisualFittingModeType.Fill;
728 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
732 case VisualFittingModeType.FitKeepAspectRatio:
733 return FittingModeType.ShrinkToFit;
734 case VisualFittingModeType.OverFitKeepAspectRatio:
735 return FittingModeType.ScaleToFill;
736 case VisualFittingModeType.Center:
737 return FittingModeType.Center;
738 case VisualFittingModeType.Fill:
739 return FittingModeType.Fill;
740 case VisualFittingModeType.FitHeight:
741 return FittingModeType.FitHeight;
742 case VisualFittingModeType.FitWidth:
743 return FittingModeType.FitWidth;
745 return FittingModeType.ShrinkToFit;
749 internal override LayoutItem CreateDefaultLayout()
751 return new ImageLayout();
755 /// Gets or sets fitting options used when resizing images to fit.<br />
756 /// If not supplied, the default is FittingModeType.Fill.<br />
757 /// For normal quad images only.<br />
760 /// <since_tizen> 6 </since_tizen>
761 [EditorBrowsable(EditorBrowsableState.Never)]
762 public FittingModeType FittingMode
766 return (FittingModeType)GetValue(FittingModeProperty);
770 SetValue(FittingModeProperty, value);
771 NotifyPropertyChanged();
775 private FittingModeType InternalFittingMode
779 int ret = (int)VisualFittingModeType.Fill;
781 PropertyValue fittingMode = _imagePropertyMap?.Find(Visual.Property.VisualFittingMode);
782 fittingMode?.Get(out ret);
783 fittingMode?.Dispose();
785 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
789 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
790 PropertyValue setValue = new PropertyValue((int)ret);
791 UpdateImage(Visual.Property.VisualFittingMode, setValue);
799 /// Gets or sets the desired image width.<br />
800 /// If not specified, the actual image width is used.<br />
801 /// For normal quad images only.<br />
804 /// <since_tizen> 6 </since_tizen>
805 [EditorBrowsable(EditorBrowsableState.Never)]
806 public int DesiredWidth
810 return (int)GetValue(DesiredWidthProperty);
814 SetValue(DesiredWidthProperty, value);
815 NotifyPropertyChanged();
818 private int InternalDesiredWidth
822 // Sync as current properties only if both _desired_width and _desired_height are setuped.
823 if(_desired_width != -1 && _desired_height != -1)
827 PropertyValue desirewidth = _imagePropertyMap?.Find(ImageVisualProperty.DesiredWidth);
828 desirewidth?.Get(out _desired_width);
829 desirewidth?.Dispose();
831 return _desired_width;
835 if (_desired_width != value)
837 _desired_width = value;
838 PropertyValue setValue = new PropertyValue(value);
839 UpdateImage(ImageVisualProperty.DesiredWidth, setValue);
846 /// Gets or sets the desired image height.<br />
847 /// If not specified, the actual image height is used.<br />
848 /// For normal quad images only.<br />
851 /// <since_tizen> 6 </since_tizen>
852 [EditorBrowsable(EditorBrowsableState.Never)]
853 public int DesiredHeight
857 return (int)GetValue(DesiredHeightProperty);
861 SetValue(DesiredHeightProperty, value);
862 NotifyPropertyChanged();
865 private int InternalDesiredHeight
869 // Sync as current properties only if both _desired_width and _desired_height are setuped.
870 if(_desired_width != -1 && _desired_height != -1)
874 PropertyValue desireheight = _imagePropertyMap?.Find(ImageVisualProperty.DesiredHeight);
875 desireheight?.Get(out _desired_height);
876 desireheight?.Dispose();
878 return _desired_height;
882 if (_desired_height != value)
884 _desired_height = value;
885 PropertyValue setValue = new PropertyValue(value);
886 UpdateImage(ImageVisualProperty.DesiredHeight, setValue);
893 /// Gets or sets ReleasePolicy for image.<br />
894 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
896 [EditorBrowsable(EditorBrowsableState.Never)]
897 public ReleasePolicyType ReleasePolicy
901 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
905 SetValue(ReleasePolicyProperty, value);
906 NotifyPropertyChanged();
910 private ReleasePolicyType InternalReleasePolicy
914 int ret = (int)ReleasePolicyType.Detached;
916 PropertyValue releasePoli = _imagePropertyMap?.Find(ImageVisualProperty.ReleasePolicy);
917 releasePoli?.Get(out ret);
918 releasePoli?.Dispose();
920 return (ReleasePolicyType)ret;
924 PropertyValue setValue = new PropertyValue((int)value);
925 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
931 /// Gets or sets the wrap mode for the u coordinate.<br />
932 /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
933 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
934 /// For normal quad images only.<br />
937 /// <since_tizen> 6 </since_tizen>
938 [EditorBrowsable(EditorBrowsableState.Never)]
939 public WrapModeType WrapModeU
943 return (WrapModeType)GetValue(WrapModeUProperty);
947 SetValue(WrapModeUProperty, value);
948 NotifyPropertyChanged();
952 private WrapModeType InternalWrapModeU
956 int ret = (int)WrapModeType.Default;
958 PropertyValue wrapModeU = _imagePropertyMap?.Find(ImageVisualProperty.WrapModeU);
959 wrapModeU?.Get(out ret);
960 wrapModeU?.Dispose();
962 return (WrapModeType)ret;
966 PropertyValue setValue = new PropertyValue((int)value);
967 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
973 /// Gets or sets the wrap mode for the v coordinate.<br />
974 /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
975 /// 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 />
976 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
977 /// For normal quad images only.
980 /// <since_tizen> 6 </since_tizen>
981 [EditorBrowsable(EditorBrowsableState.Never)]
982 public WrapModeType WrapModeV
986 return (WrapModeType)GetValue(WrapModeVProperty);
990 SetValue(WrapModeVProperty, value);
991 NotifyPropertyChanged();
995 private WrapModeType InternalWrapModeV
999 int ret = (int)WrapModeType.Default;
1001 PropertyValue wrapModeV = _imagePropertyMap?.Find(ImageVisualProperty.WrapModeV);
1002 wrapModeV?.Get(out ret);
1003 wrapModeV?.Dispose();
1005 return (WrapModeType)ret;
1009 PropertyValue setValue = new PropertyValue((int)value);
1010 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1011 setValue?.Dispose();
1016 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1019 /// This is false by default.
1020 /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1021 /// to preserve the aspect ratio of the image resource.
1022 /// AdjustViewSize works only if ImageView is added to a View having Layout.
1023 /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1024 /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1026 /// <since_tizen> 9 </since_tizen>
1027 public bool AdjustViewSize
1031 return (bool)GetValue(AdjustViewSizeProperty);
1035 SetValue(AdjustViewSizeProperty, value);
1036 NotifyPropertyChanged();
1039 private bool adjustViewSize = false;
1041 internal Selector<string> ResourceUrlSelector
1043 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1046 resourceUrlSelector?.Reset(this);
1047 if (value == null) return;
1049 if (value.HasAll()) SetResourceUrl(value.All);
1050 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1055 /// Get attributes, it is abstract function and must be override.
1057 [EditorBrowsable(EditorBrowsableState.Never)]
1058 protected override ViewStyle CreateViewStyle()
1060 return new ImageViewStyle();
1063 internal void SetImage(string url, Uint16Pair size)
1065 if (url.Contains(".json"))
1067 Tizen.Log.Fatal("NUI", "[ERROR] Please DO NOT set lottie file in ImageView! This is temporary checking, will be removed soon!");
1071 Interop.ImageView.SetImage(SwigCPtr, url, Uint16Pair.getCPtr(size));
1072 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1077 internal ViewResourceReadySignal ResourceReadySignal(View view)
1079 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1080 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1084 internal override void ApplyCornerRadius()
1086 base.ApplyCornerRadius();
1088 if (backgroundExtraData == null) return;
1090 // Apply corner radius to IMAGE.
1091 var cornerRadiusValue = backgroundExtraData.CornerRadius == null ? new PropertyValue() : new PropertyValue(backgroundExtraData.CornerRadius);
1092 var cornerRadiusPolicyValue = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy);
1094 // Make current propertyMap
1095 PropertyMap currentPropertyMap = new PropertyMap();
1096 currentPropertyMap[Visual.Property.CornerRadius] = cornerRadiusValue;
1097 currentPropertyMap[Visual.Property.CornerRadiusPolicy] = cornerRadiusPolicyValue;
1098 var temp = new PropertyValue(currentPropertyMap);
1100 // Update corner radius properties to image by ActionUpdateProperty
1101 this.DoAction(ImageView.Property.IMAGE, ActionUpdateProperty, temp);
1104 currentPropertyMap.Dispose();
1105 cornerRadiusValue.Dispose();
1106 cornerRadiusPolicyValue.Dispose();
1109 internal override void ApplyBorderline()
1111 base.ApplyBorderline();
1113 if (backgroundExtraData == null) return;
1115 // Apply borderline to IMAGE.
1116 var borderlineWidthValue = new PropertyValue(backgroundExtraData.BorderlineWidth);
1117 var borderlineColorValue = backgroundExtraData.BorderlineColor == null ? new PropertyValue(Color.Black) : new PropertyValue(backgroundExtraData.BorderlineColor);
1118 var borderlineOffsetValue = new PropertyValue(backgroundExtraData.BorderlineOffset);
1120 // Make current propertyMap
1121 PropertyMap currentPropertyMap = new PropertyMap();
1122 currentPropertyMap[Visual.Property.BorderlineWidth] = borderlineWidthValue;
1123 currentPropertyMap[Visual.Property.BorderlineColor] = borderlineColorValue;
1124 currentPropertyMap[Visual.Property.BorderlineOffset] = borderlineOffsetValue;
1125 var temp = new PropertyValue(currentPropertyMap);
1127 // Update borderline properties to image by ActionUpdateProperty
1128 this.DoAction(ImageView.Property.IMAGE, ActionUpdateProperty, temp);
1131 currentPropertyMap.Dispose();
1132 borderlineWidthValue.Dispose();
1133 borderlineColorValue.Dispose();
1134 borderlineOffsetValue.Dispose();
1137 internal ResourceLoadingStatusType GetResourceStatus()
1139 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1143 /// you can override it to clean-up your own resources.
1145 /// <param name="type">DisposeTypes</param>
1146 /// <since_tizen> 3 </since_tizen>
1147 protected override void Dispose(DisposeTypes type)
1154 if (type == DisposeTypes.Explicit)
1157 //Release your own managed resources here.
1158 //You should release all of your own disposable objects here.
1161 borderSelector?.Reset(this);
1162 resourceUrlSelector?.Reset(this);
1163 _imagePropertyUpdatedFlag = false;
1164 if (_imagePropertyUpdateProcessAttachedFlag)
1166 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1167 _imagePropertyUpdateProcessAttachedFlag = false;
1169 _imagePropertyMap?.Dispose();
1170 _imagePropertyMap = null;
1176 /// This will not be public opened.
1177 [EditorBrowsable(EditorBrowsableState.Never)]
1178 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1180 Interop.ImageView.DeleteImageView(swigCPtr);
1183 // Callback for View ResourceReady signal
1184 private void OnResourceReady(IntPtr data)
1186 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1189 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1192 if (_resourceReadyEventHandler != null)
1194 _resourceReadyEventHandler(this, e);
1198 private void SetResourceUrl(string value)
1200 value = (value == null ? "" : value);
1201 if (value.StartsWith("*Resource*"))
1203 string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
1204 value = value.Replace("*Resource*", resource);
1206 if(_resourceUrl != value)
1208 _resourceUrl = value;
1209 UpdateImage(ImageVisualProperty.URL, new PropertyValue(value));
1213 private void SetBorder(Rectangle value)
1219 if(_border != value)
1221 _border = new Rectangle(value);
1222 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1227 /// Lazy call to UpdateImage.
1228 /// Collect Properties need to be update, and set properties that starts the Processing.
1230 private void UpdateImage(int key, PropertyValue value)
1232 // If we set ResourceUrl as empty, Unregist visual.
1233 if (key == ImageVisualProperty.URL && string.IsNullOrEmpty(_resourceUrl))
1235 // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1236 // Unregist and dettach Process only if previous resourceUrl was not empty
1237 string currentResourceUrl = "";
1238 PropertyValue currentResourceUrlValue = _imagePropertyMap?.Find(ImageVisualProperty.URL);
1239 if((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1241 PropertyValue emptyValue = new PropertyValue();
1243 // Remove current registed Image.
1244 SetProperty(ImageView.Property.IMAGE, emptyValue);
1246 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1247 _imagePropertyUpdatedFlag = false;
1248 if(_imagePropertyUpdateProcessAttachedFlag)
1250 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1251 _imagePropertyUpdateProcessAttachedFlag = false;
1253 // Update resourceUrl as null
1254 _imagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1256 emptyValue?.Dispose();
1261 // Update image property map value as inputed value.
1264 if (_imagePropertyMap == null)
1266 _imagePropertyMap = new PropertyMap();
1268 _imagePropertyUpdatedFlag = true;
1269 _imagePropertyMap[key] = value;
1271 // Lazy update only if _resourceUrl is not empty and ProcessAttachedFlag is false.
1272 if (!string.IsNullOrEmpty(_resourceUrl) && !_imagePropertyUpdateProcessAttachedFlag)
1274 _imagePropertyUpdateProcessAttachedFlag = true;
1275 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1276 // Call process hardly.
1277 ProcessorController.Instance.Awake();
1283 /// Callback function to Lazy UpdateImage.
1284 /// Or, We can call UpdateImage() function directly if we need.
1286 private void UpdateImage(object source, EventArgs e)
1289 _imagePropertyUpdateProcessAttachedFlag = false;
1292 private void UpdateImage()
1294 if(!_imagePropertyUpdatedFlag) return;
1296 _imagePropertyUpdatedFlag = false;
1298 if(_imagePropertyMap == null)
1300 _imagePropertyMap = new PropertyMap();
1303 if (_border == null)
1305 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1306 _imagePropertyMap[Visual.Property.Type] = image;
1311 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1312 _imagePropertyMap[Visual.Property.Type] = nPatch;
1314 PropertyValue border = new PropertyValue(_border);
1315 _imagePropertyMap[NpatchImageVisualProperty.Border] = border;
1319 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1321 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1322 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1324 _imagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1325 _imagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1329 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1331 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1332 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1333 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1335 _imagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1336 _imagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1337 _imagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1341 // Do Fitting Buffer when desired dimension is set
1342 if (_desired_width != -1 && _desired_height != -1)
1344 if (_resourceUrl != null)
1346 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1347 if( imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0 )
1349 int adjustedDesiredWidth, adjustedDesiredHeight;
1350 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1351 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1352 if (aspectOfImageSize > aspectOfDesiredSize)
1354 adjustedDesiredWidth = _desired_width;
1355 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1359 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1360 adjustedDesiredHeight = _desired_height;
1363 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1364 _imagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1365 returnWidth?.Dispose();
1366 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1367 _imagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1368 returnHeight?.Dispose();
1369 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1370 _imagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1371 scaleToFit?.Dispose();
1375 Tizen.Log.Fatal("NUI", "[ERROR] Can't use DesiredSize when ImageLoading is failed.");
1377 imageSize?.Dispose();
1383 private void UpdateImageMap()
1385 PropertyMap imageMap = new PropertyMap();
1387 PropertyValue image = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE);
1388 image?.Get(imageMap);
1389 imageMap.Merge(_imagePropertyMap);
1390 PropertyValue setValue = new PropertyValue(imageMap);
1391 SetProperty(ImageView.Property.IMAGE, setValue);
1393 // Sync local PropertyMap
1394 // TODO: Do we need to use GetProperty(SwigCPtr, ImageView.Property.IMAGE); here?
1395 _imagePropertyMap.Dispose();
1396 _imagePropertyMap = new PropertyMap(imageMap);
1398 imageMap?.Dispose();
1400 setValue?.Dispose();
1403 private void OnResourceLoaded(IntPtr view)
1405 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1406 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1408 if (_resourceLoadedEventHandler != null)
1410 _resourceLoadedEventHandler(this, e);
1415 /// Event arguments of resource ready.
1417 /// <since_tizen> 3 </since_tizen>
1418 public class ResourceReadyEventArgs : EventArgs
1423 /// The view whose resource is ready.
1425 /// <since_tizen> 3 </since_tizen>
1439 internal class ResourceLoadedEventArgs : EventArgs
1441 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1442 public ResourceLoadingStatusType Status
1455 internal new class Property
1457 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1458 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1459 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1462 private enum ImageType
1465 /// For Normal Image.
1470 /// For normal image, with synchronous loading and orientation correction property
1475 /// For nine-patch image
1480 private void OnBorderChanged(int x, int y, int width, int height)
1482 Border = new Rectangle(x, y, width, height);
1484 private void OnPixelAreaChanged(float x, float y, float z, float w)
1486 PixelArea = new RelativeVector4(x, y, z, w);
1489 private class ImageLayout : LayoutItem
1492 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1493 /// 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.
1495 [EditorBrowsable(EditorBrowsableState.Never)]
1496 public bool AdjustViewSize
1500 return (Owner as ImageView)?.AdjustViewSize ?? false;
1504 if (Owner is ImageView imageView)
1506 imageView.AdjustViewSize = value;
1512 [EditorBrowsable(EditorBrowsableState.Never)]
1513 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1515 // To not change the view size by DALi
1516 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1517 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1519 float specWidth = widthMeasureSpec.Size.AsDecimal();
1520 float specHeight = heightMeasureSpec.Size.AsDecimal();
1521 float naturalWidth = Owner.NaturalSize.Width;
1522 float naturalHeight = Owner.NaturalSize.Height;
1523 float minWidth = Owner.MinimumSize.Width;
1524 float maxWidth = Owner.MaximumSize.Width;
1525 float minHeight = Owner.MinimumSize.Height;
1526 float maxHeight = Owner.MaximumSize.Height;
1527 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1529 // Assume that the new width and height are given from the view's suggested size by default.
1530 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1531 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1533 // The width and height measure specs are going to be used to set measured size.
1534 // Mark that the measure specs are changed by default to update measure specs later.
1535 bool widthSpecChanged = true;
1536 bool heightSpecChanged = true;
1538 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1540 newWidth = specWidth;
1541 widthSpecChanged = false;
1543 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1545 if ((AdjustViewSize) && (aspectRatio > 0))
1547 newHeight = newWidth * aspectRatio;
1552 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1554 newHeight = specHeight;
1555 heightSpecChanged = false;
1557 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1559 if ((AdjustViewSize) && (aspectRatio > 0))
1561 newWidth = newHeight / aspectRatio;
1566 if (widthSpecChanged)
1568 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1571 if (heightSpecChanged)
1573 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1576 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1577 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1579 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1580 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));