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;
40 // Collection of image-sensitive properties.
41 private static readonly List<int> cachedImagePropertyKeyList = new List<int> {
43 ImageVisualProperty.URL,
44 ImageVisualProperty.AlphaMaskURL,
45 ImageVisualProperty.CropToMask,
46 Visual.Property.VisualFittingMode,
47 ImageVisualProperty.DesiredWidth,
48 ImageVisualProperty.DesiredHeight,
49 ImageVisualProperty.ReleasePolicy,
50 ImageVisualProperty.WrapModeU,
51 ImageVisualProperty.WrapModeV,
52 ImageVisualProperty.SynchronousLoading,
53 Visual.Property.PremultipliedAlpha,
54 ImageVisualProperty.OrientationCorrection,
55 NpatchImageVisualProperty.Border,
56 NpatchImageVisualProperty.BorderOnly,
58 internal PropertyMap cachedImagePropertyMap;
59 internal bool imagePropertyUpdatedFlag = false;
61 private bool imagePropertyUpdateProcessAttachedFlag = false;
62 private Rectangle _border;
63 private string _resourceUrl = "";
64 private int _desired_width = -1;
65 private int _desired_height = -1;
66 private TriggerableSelector<string> resourceUrlSelector;
67 private TriggerableSelector<Rectangle> borderSelector;
69 private RelativeVector4 internalPixelArea;
72 /// Creates an initialized ImageView.
74 /// <since_tizen> 3 </since_tizen>
75 public ImageView() : this(Interop.ImageView.New(), true)
77 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
80 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
81 [EditorBrowsable(EditorBrowsableState.Never)]
82 public ImageView(ViewStyle viewStyle) : this(Interop.ImageView.New(), true, viewStyle)
87 /// Creates an initialized ImageView with setting the status of shown or hidden.
89 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
90 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
91 [EditorBrowsable(EditorBrowsableState.Never)]
92 public ImageView(bool shown) : this(Interop.ImageView.New(), true)
94 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
99 /// Creates an initialized ImageView from a URL to an image resource.<br />
100 /// If the string is empty, ImageView will not display anything.<br />
102 /// <param name="url">The URL of the image resource to display.</param>
103 /// <since_tizen> 3 </since_tizen>
104 public ImageView(string url) : this(Interop.ImageView.New(url), true)
107 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
112 /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden.
114 /// <param name="url">The URL of the image resource to display.</param>
115 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
116 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
117 [EditorBrowsable(EditorBrowsableState.Never)]
118 public ImageView(string url, bool shown) : this(Interop.ImageView.New(url), true)
121 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
125 internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(url, Uint16Pair.getCPtr(size)), true)
128 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
136 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
144 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
152 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
153 private delegate void ResourceReadyEventCallbackType(IntPtr data);
154 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
155 private delegate void _resourceLoadedCallbackType(IntPtr view);
158 /// An event for ResourceReady signal which can be used to subscribe or unsubscribe the event handler.<br />
159 /// This signal is emitted after all resources required by a control are loaded and ready.<br />
160 /// Most resources are only loaded when the control is placed on the stage.<br />
162 /// <since_tizen> 3 </since_tizen>
163 public event EventHandler<ResourceReadyEventArgs> ResourceReady
167 if (_resourceReadyEventHandler == null)
169 _resourceReadyEventCallback = OnResourceReady;
170 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
171 resourceReadySignal?.Connect(_resourceReadyEventCallback);
172 resourceReadySignal?.Dispose();
175 _resourceReadyEventHandler += value;
180 _resourceReadyEventHandler -= value;
182 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
183 if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
185 resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
187 resourceReadySignal?.Dispose();
191 internal event EventHandler<ResourceLoadedEventArgs> ResourceLoaded
195 if (_resourceLoadedEventHandler == null)
197 _resourceLoadedCallback = OnResourceLoaded;
198 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
199 resourceReadySignal?.Connect(_resourceLoadedCallback);
200 resourceReadySignal?.Dispose();
203 _resourceLoadedEventHandler += value;
207 _resourceLoadedEventHandler -= value;
208 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
209 if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
211 resourceReadySignal?.Disconnect(_resourceLoadedCallback);
213 resourceReadySignal?.Dispose();
218 /// Enumeration for LoadingStatus of image.
220 /// <since_tizen> 5 </since_tizen>
221 public enum LoadingStatusType
224 /// Loading preparing status.
226 /// <since_tizen> 5 </since_tizen>
229 /// Loading ready status.
231 /// <since_tizen> 5 </since_tizen>
234 /// Loading failed status.
236 /// <since_tizen> 5 </since_tizen>
241 /// Enumeration for MaskingMode of image.
243 [EditorBrowsable(EditorBrowsableState.Never)]
244 public enum MaskingModeType
247 /// Applies alpha masking on rendering time.
249 [EditorBrowsable(EditorBrowsableState.Never)]
252 /// Applies alpha masking on loading time.
254 [EditorBrowsable(EditorBrowsableState.Never)]
259 /// ImageView ResourceUrl, type string.
260 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
261 /// When it is set as null, it gives empty string ("") to be read.
263 /// <since_tizen> 3 </since_tizen>
264 public string ResourceUrl
268 return (string)GetValue(ResourceUrlProperty);
272 SetValue(ResourceUrlProperty, value);
273 NotifyPropertyChanged();
278 /// This will be deprecated, Use Image instead. <br />
279 /// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
281 /// <since_tizen> 3 </since_tizen>
282 [Obsolete("Do not use this, that will be deprecated. Use Image property instead.")]
283 [EditorBrowsable(EditorBrowsableState.Never)]
284 public PropertyMap ImageMap
288 return GetValue(ImageMapProperty) as PropertyMap;
292 SetValue(ImageMapProperty, value);
293 NotifyPropertyChanged();
296 private PropertyMap InternalImageMap
302 // Sync as current properties
305 // Get current properties force.
306 PropertyMap returnValue = new PropertyMap();
307 PropertyValue image = GetProperty(ImageView.Property.IMAGE);
308 image?.Get(returnValue);
311 // Update cached property map
312 if(returnValue != null)
314 MergeCachedImageVisualProperty(returnValue);
327 PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
328 SetProperty(ImageView.Property.IMAGE, setValue);
330 // Image properties are changed hardly. We should ignore lazy UpdateImage
331 imagePropertyUpdatedFlag = false;
332 cachedImagePropertyMap?.Dispose();
333 cachedImagePropertyMap = null;
334 MergeCachedImageVisualProperty(value);
336 NotifyPropertyChanged();
343 /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
346 /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
347 /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
348 /// you can also use <see cref="Visual.Property"/>. <br />
349 /// See <see cref="Visual.Property"/> for a detailed description. <br />
352 /// The following example demonstrates how to use the Image property.
354 /// PropertyMap map = new PropertyMap();
355 /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
356 /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
357 /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
358 /// imageview.Image = map;
361 /// <since_tizen> 4 </since_tizen>
362 public PropertyMap Image
368 return (PropertyMap)GetValue(ImageProperty);
379 SetValue(ImageProperty, value);
380 NotifyPropertyChanged();
386 /// ImageView PreMultipliedAlpha, type Boolean.<br />
387 /// Image must be initialized.<br />
389 /// <since_tizen> 3 </since_tizen>
390 public bool PreMultipliedAlpha
394 return (bool)GetValue(PreMultipliedAlphaProperty);
398 SetValue(PreMultipliedAlphaProperty, value);
399 NotifyPropertyChanged();
404 /// ImageView PixelArea, type Vector4 (Animatable property).<br />
405 /// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].<br />
408 /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
410 /// <since_tizen> 3 </since_tizen>
411 public RelativeVector4 PixelArea
415 return (RelativeVector4)GetValue(PixelAreaProperty);
419 SetValue(PixelAreaProperty, value);
420 NotifyPropertyChanged();
425 /// The border of the image in the order: left, right, bottom, top.<br />
426 /// If set, ImageMap will be ignored.<br />
427 /// For N-Patch images only.<br />
431 /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
433 /// <since_tizen> 3 </since_tizen>
434 public Rectangle Border
438 Rectangle temp = (Rectangle)GetValue(BorderProperty);
445 return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
450 SetValue(BorderProperty, value);
451 NotifyPropertyChanged();
456 /// Gets or sets whether to draw the borders only (if true).<br />
457 /// If not specified, the default is false.<br />
458 /// For N-Patch images only.<br />
461 /// <since_tizen> 3 </since_tizen>
462 public bool BorderOnly
466 return (bool)GetValue(BorderOnlyProperty);
470 SetValue(BorderOnlyProperty, value);
471 NotifyPropertyChanged();
476 /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
478 /// <since_tizen> 3 </since_tizen>
479 [Obsolete("This has been deprecated since API9 and will be removed in API11. Use SynchronousLoading instead.")]
480 public bool SynchronosLoading
484 return SynchronousLoading;
488 SynchronousLoading = value;
493 /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
496 /// Changing this property make this ImageView load image synchronously at the next loading
497 /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
498 /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
500 /// <since_tizen> 9 </since_tizen>
501 public bool SynchronousLoading
505 return (bool)GetValue(SynchronousLoadingProperty);
509 SetValue(SynchronousLoadingProperty, value);
510 NotifyPropertyChanged();
515 /// Gets or sets whether to automatically correct the orientation of an image.<br />
517 /// <since_tizen> 5 </since_tizen>
518 public bool OrientationCorrection
522 return (bool)GetValue(OrientationCorrectionProperty);
526 SetValue(OrientationCorrectionProperty, value);
527 NotifyPropertyChanged();
532 /// Gets or sets whether to apply mask on GPU or not.<br />
534 [EditorBrowsable(EditorBrowsableState.Never)]
535 public MaskingModeType MaskingMode
539 return (MaskingModeType)GetValue(MaskingModeProperty);
543 SetValue(MaskingModeProperty, value);
544 NotifyPropertyChanged();
548 private MaskingModeType InternalMaskingMode
552 int ret = (int)MaskingModeType.MaskingOnLoading;
554 PropertyValue maskingMode = GetCachedImageVisualProperty(ImageVisualProperty.MaskingMode);
555 maskingMode?.Get(out ret);
556 maskingMode?.Dispose();
558 return (MaskingModeType)ret;
562 MaskingModeType ret = value;
563 PropertyValue setValue = new PropertyValue((int)ret);
564 UpdateImage(ImageVisualProperty.MaskingMode, setValue);
570 /// Gets the loading state of the visual resource.
572 /// <since_tizen> 5 </since_tizen>
573 public ImageView.LoadingStatusType LoadingStatus
577 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
582 /// Downcasts a handle to imageView handle.
584 /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
585 /// Do not use this, that will be deprecated. Use as keyword instead.
586 /// <since_tizen> 3 </since_tizen>
587 [Obsolete("Do not use this, that will be deprecated. Use as keyword instead. " +
589 "BaseHandle handle = new ImageView(imagePath); " +
590 "ImageView image = handle as ImageView")]
591 [EditorBrowsable(EditorBrowsableState.Never)]
592 public static ImageView DownCast(BaseHandle handle)
596 throw new ArgumentNullException(nameof(handle));
598 ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
599 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
604 /// Sets this ImageView from the given URL.<br />
605 /// If the URL is empty, ImageView will not display anything.<br />
607 /// <param name="url">The URL to the image resource to display.</param>
608 /// <exception cref="ArgumentNullException"> Thrown when url is null. </exception>
609 /// <since_tizen> 3 </since_tizen>
610 public void SetImage(string url)
614 throw new ArgumentNullException(nameof(url));
617 if (url.Contains(".json"))
619 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
623 Interop.ImageView.SetImage(SwigCPtr, url);
624 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
630 /// Queries if all resources required by a control are loaded and ready.<br />
631 /// Most resources are only loaded when the control is placed on the stage.<br />
632 /// True if the resources are loaded and ready, false otherwise.<br />
634 /// <since_tizen> 3 </since_tizen>
635 public new bool IsResourceReady()
637 bool ret = Interop.View.IsResourceReady(SwigCPtr);
638 if (NDalicPINVOKE.SWIGPendingException.Pending)
639 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
644 /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
646 /// <since_tizen> 5 </since_tizen>
649 // Sync as current properties
653 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionReload);
657 /// Plays the animated GIF. This is also the default playback mode.
659 /// <since_tizen> 5 </since_tizen>
662 // Sync as current properties
666 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPlay);
670 /// Pauses the animated GIF.
672 /// <since_tizen> 5 </since_tizen>
675 // Sync as current properties
679 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPause);
683 /// Stops the animated GIF.
685 /// <since_tizen> 5 </since_tizen>
688 // Sync as current properties
693 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionStop);
697 /// Gets or sets the URL of the alpha mask.<br />
700 /// <since_tizen> 6</since_tizen>
701 [EditorBrowsable(EditorBrowsableState.Never)]
702 public string AlphaMaskURL
706 return GetValue(AlphaMaskURLProperty) as string;
710 SetValue(AlphaMaskURLProperty, value);
711 NotifyPropertyChanged();
715 private string InternalAlphaMaskURL
721 PropertyValue maskUrl = GetCachedImageVisualProperty(ImageVisualProperty.AlphaMaskURL);
722 maskUrl?.Get(out ret);
729 PropertyValue setValue = new PropertyValue(value ?? "");
730 UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
731 // When we never set CropToMask property before, we should set default value as true.
732 using(PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask))
734 if(cropToMask == null)
736 using PropertyValue setCropValue = new PropertyValue(true);
737 UpdateImage(ImageVisualProperty.CropToMask, setCropValue);
746 /// Whether to crop image to mask or scale mask to fit image.
748 /// <since_tizen> 6 </since_tizen>
749 public bool CropToMask
753 return (bool)GetValue(CropToMaskProperty);
757 SetValue(CropToMaskProperty, value);
758 NotifyPropertyChanged();
761 private bool InternalCropToMask
767 PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask);
768 cropToMask?.Get(out ret);
769 cropToMask?.Dispose();
775 PropertyValue setValue = new PropertyValue(value);
776 UpdateImage(ImageVisualProperty.CropToMask, setValue);
782 /// Actions property value for Reload image.
784 private int ActionReload { get; set; } = Interop.ImageView.ImageVisualActionReloadGet();
787 /// Actions property value to Play animated images.
788 /// This property can be redefined by child class if it use different value.
790 [EditorBrowsable(EditorBrowsableState.Never)]
791 protected int ActionPlay { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
794 /// Actions property value to Pause animated images.
795 /// This property can be redefined by child class if it use different value.
797 [EditorBrowsable(EditorBrowsableState.Never)]
798 protected int ActionPause { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
801 /// Actions property value to Stop animated images.
802 /// This property can be redefined by child class if it use different value.
804 [EditorBrowsable(EditorBrowsableState.Never)]
805 protected int ActionStop { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
807 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
811 case FittingModeType.ShrinkToFit:
812 return VisualFittingModeType.FitKeepAspectRatio;
813 case FittingModeType.ScaleToFill:
814 return VisualFittingModeType.OverFitKeepAspectRatio;
815 case FittingModeType.Center:
816 return VisualFittingModeType.Center;
817 case FittingModeType.Fill:
818 return VisualFittingModeType.Fill;
819 case FittingModeType.FitHeight:
820 return VisualFittingModeType.FitHeight;
821 case FittingModeType.FitWidth:
822 return VisualFittingModeType.FitWidth;
824 return VisualFittingModeType.Fill;
828 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
832 case VisualFittingModeType.FitKeepAspectRatio:
833 return FittingModeType.ShrinkToFit;
834 case VisualFittingModeType.OverFitKeepAspectRatio:
835 return FittingModeType.ScaleToFill;
836 case VisualFittingModeType.Center:
837 return FittingModeType.Center;
838 case VisualFittingModeType.Fill:
839 return FittingModeType.Fill;
840 case VisualFittingModeType.FitHeight:
841 return FittingModeType.FitHeight;
842 case VisualFittingModeType.FitWidth:
843 return FittingModeType.FitWidth;
845 return FittingModeType.ShrinkToFit;
849 internal override LayoutItem CreateDefaultLayout()
851 return new ImageLayout();
855 /// Gets or sets fitting options used when resizing images to fit.<br />
856 /// If not supplied, the default is FittingModeType.Fill.<br />
857 /// For normal quad images only.<br />
860 /// <since_tizen> 6 </since_tizen>
861 [EditorBrowsable(EditorBrowsableState.Never)]
862 public FittingModeType FittingMode
866 return (FittingModeType)GetValue(FittingModeProperty);
870 SetValue(FittingModeProperty, value);
871 NotifyPropertyChanged();
875 private FittingModeType InternalFittingMode
879 int ret = (int)VisualFittingModeType.Fill;
881 PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
882 fittingMode?.Get(out ret);
883 fittingMode?.Dispose();
885 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
889 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
890 PropertyValue setValue = new PropertyValue((int)ret);
891 UpdateImage(Visual.Property.VisualFittingMode, setValue);
897 /// Gets or sets the desired image width.<br />
898 /// If not specified, the actual image width is used.<br />
899 /// For normal quad images only.<br />
902 /// <since_tizen> 6 </since_tizen>
903 [EditorBrowsable(EditorBrowsableState.Never)]
904 public int DesiredWidth
908 return (int)GetValue(DesiredWidthProperty);
912 SetValue(DesiredWidthProperty, value);
913 NotifyPropertyChanged();
916 private int InternalDesiredWidth
920 // Sync as current properties only if both _desired_width and _desired_height are setuped.
921 if(_desired_width != -1 && _desired_height != -1)
925 PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
926 desirewidth?.Get(out _desired_width);
927 desirewidth?.Dispose();
929 return _desired_width;
933 if (_desired_width != value)
935 _desired_width = value;
936 PropertyValue setValue = new PropertyValue(value);
937 UpdateImage(ImageVisualProperty.DesiredWidth, setValue);
944 /// Gets or sets the desired image height.<br />
945 /// If not specified, the actual image height is used.<br />
946 /// For normal quad images only.<br />
949 /// <since_tizen> 6 </since_tizen>
950 [EditorBrowsable(EditorBrowsableState.Never)]
951 public int DesiredHeight
955 return (int)GetValue(DesiredHeightProperty);
959 SetValue(DesiredHeightProperty, value);
960 NotifyPropertyChanged();
963 private int InternalDesiredHeight
967 // Sync as current properties only if both _desired_width and _desired_height are setuped.
968 if(_desired_width != -1 && _desired_height != -1)
972 PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
973 desireheight?.Get(out _desired_height);
974 desireheight?.Dispose();
976 return _desired_height;
980 if (_desired_height != value)
982 _desired_height = value;
983 PropertyValue setValue = new PropertyValue(value);
984 UpdateImage(ImageVisualProperty.DesiredHeight, setValue);
991 /// Gets or sets ReleasePolicy for image.<br />
992 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
994 [EditorBrowsable(EditorBrowsableState.Never)]
995 public ReleasePolicyType ReleasePolicy
999 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
1003 SetValue(ReleasePolicyProperty, value);
1004 NotifyPropertyChanged();
1008 private ReleasePolicyType InternalReleasePolicy
1012 int ret = (int)ReleasePolicyType.Detached;
1014 PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
1015 releasePoli?.Get(out ret);
1016 releasePoli?.Dispose();
1018 return (ReleasePolicyType)ret;
1022 PropertyValue setValue = new PropertyValue((int)value);
1023 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
1024 setValue?.Dispose();
1029 /// Gets or sets the wrap mode for the u coordinate.<br />
1030 /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
1031 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1032 /// For normal quad images only.<br />
1035 /// <since_tizen> 6 </since_tizen>
1036 [EditorBrowsable(EditorBrowsableState.Never)]
1037 public WrapModeType WrapModeU
1041 return (WrapModeType)GetValue(WrapModeUProperty);
1045 SetValue(WrapModeUProperty, value);
1046 NotifyPropertyChanged();
1050 private WrapModeType InternalWrapModeU
1054 int ret = (int)WrapModeType.Default;
1056 PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
1057 wrapModeU?.Get(out ret);
1058 wrapModeU?.Dispose();
1060 return (WrapModeType)ret;
1064 PropertyValue setValue = new PropertyValue((int)value);
1065 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
1066 setValue?.Dispose();
1071 /// Gets or sets the wrap mode for the v coordinate.<br />
1072 /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
1073 /// 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 />
1074 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1075 /// For normal quad images only.
1078 /// <since_tizen> 6 </since_tizen>
1079 [EditorBrowsable(EditorBrowsableState.Never)]
1080 public WrapModeType WrapModeV
1084 return (WrapModeType)GetValue(WrapModeVProperty);
1088 SetValue(WrapModeVProperty, value);
1089 NotifyPropertyChanged();
1093 private WrapModeType InternalWrapModeV
1097 int ret = (int)WrapModeType.Default;
1099 PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
1100 wrapModeV?.Get(out ret);
1101 wrapModeV?.Dispose();
1103 return (WrapModeType)ret;
1107 PropertyValue setValue = new PropertyValue((int)value);
1108 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1109 setValue?.Dispose();
1114 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1117 /// This is false by default.
1118 /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1119 /// to preserve the aspect ratio of the image resource.
1120 /// AdjustViewSize works only if ImageView is added to a View having Layout.
1121 /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1122 /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1124 /// <since_tizen> 9 </since_tizen>
1125 public bool AdjustViewSize
1129 return (bool)GetValue(AdjustViewSizeProperty);
1133 SetValue(AdjustViewSizeProperty, value);
1134 NotifyPropertyChanged();
1137 private bool adjustViewSize = false;
1139 internal Selector<string> ResourceUrlSelector
1141 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1144 resourceUrlSelector?.Reset(this);
1145 if (value == null) return;
1147 if (value.HasAll()) SetResourceUrl(value.All);
1148 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1153 /// Get attributes, it is abstract function and must be override.
1155 [EditorBrowsable(EditorBrowsableState.Never)]
1156 protected override ViewStyle CreateViewStyle()
1158 return new ImageViewStyle();
1161 internal void SetImage(string url, Uint16Pair size)
1163 if (url.Contains(".json"))
1165 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1169 Interop.ImageView.SetImage(SwigCPtr, url, Uint16Pair.getCPtr(size));
1170 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1175 internal ViewResourceReadySignal ResourceReadySignal(View view)
1177 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1178 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1182 internal override void ApplyCornerRadius()
1184 base.ApplyCornerRadius();
1186 if (backgroundExtraData == null) return;
1189 // Update corner radius properties to image by ActionUpdateProperty
1190 if (backgroundExtraData.CornerRadius != null)
1192 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1194 Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1197 internal override void ApplyBorderline()
1199 base.ApplyBorderline();
1201 if (backgroundExtraData == null) return;
1204 // Update borderline properties to image by ActionUpdateProperty
1205 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
1206 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
1207 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
1210 internal ResourceLoadingStatusType GetResourceStatus()
1212 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1216 /// you can override it to clean-up your own resources.
1218 /// <param name="type">DisposeTypes</param>
1219 /// <since_tizen> 3 </since_tizen>
1220 protected override void Dispose(DisposeTypes type)
1227 internalPixelArea?.Dispose();
1229 if (type == DisposeTypes.Explicit)
1232 //Release your own managed resources here.
1233 //You should release all of your own disposable objects here.
1236 borderSelector?.Reset(this);
1237 resourceUrlSelector?.Reset(this);
1238 imagePropertyUpdatedFlag = false;
1239 if (imagePropertyUpdateProcessAttachedFlag)
1241 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1242 imagePropertyUpdateProcessAttachedFlag = false;
1244 cachedImagePropertyMap?.Dispose();
1245 cachedImagePropertyMap = null;
1251 /// This will not be public opened.
1252 [EditorBrowsable(EditorBrowsableState.Never)]
1253 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1255 Interop.ImageView.DeleteImageView(swigCPtr);
1258 // Callback for View ResourceReady signal
1259 private void OnResourceReady(IntPtr data)
1261 if(!CheckResourceReady())
1266 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1269 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1272 if (_resourceReadyEventHandler != null)
1274 _resourceReadyEventHandler(this, e);
1278 private void SetResourceUrl(string value)
1280 value = (value == null ? "" : value);
1281 if (value.StartsWith("*Resource*"))
1283 string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
1284 value = value.Replace("*Resource*", resource);
1286 if(_resourceUrl != value)
1288 _resourceUrl = value;
1289 if(string.IsNullOrEmpty(_resourceUrl))
1291 // Special case. If we set ResourceUrl as empty, Unregist visual.
1296 using(PropertyValue setValue = new PropertyValue(value))
1298 UpdateImage(ImageVisualProperty.URL, setValue);
1300 // Special case. If we set GeneratedUrl, Create ImageVisual synchronously.
1301 if(value.StartsWith("dali://") || value.StartsWith("enbuf://"))
1309 private void SetBorder(Rectangle value)
1315 if(_border != value)
1317 _border = new Rectangle(value);
1318 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1323 /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1325 private void RemoveImage()
1327 // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1328 // Unregist and detach process only if previous resourceUrl was not empty
1329 string currentResourceUrl = "";
1330 PropertyValue currentResourceUrlValue = GetCachedImageVisualProperty(ImageVisualProperty.URL);
1331 if((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1333 PropertyValue emptyValue = new PropertyValue();
1335 // Remove current registed Image.
1336 SetProperty(ImageView.Property.IMAGE, emptyValue);
1338 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1339 imagePropertyUpdatedFlag = false;
1340 if(imagePropertyUpdateProcessAttachedFlag)
1342 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1343 imagePropertyUpdateProcessAttachedFlag = false;
1345 // Update resourceUrl as empty value
1346 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1348 emptyValue?.Dispose();
1350 currentResourceUrlValue?.Dispose();
1354 /// Lazy call to UpdateImage.
1355 /// Collect Properties need to be update, and set properties that starts the Processing.
1357 [EditorBrowsable(EditorBrowsableState.Never)]
1358 protected virtual void UpdateImage(int key, PropertyValue value)
1360 // Update image property map value as inputed value.
1363 if (cachedImagePropertyMap == null)
1365 cachedImagePropertyMap = new PropertyMap();
1368 // To optimization, we don't check URL duplicate case. We already checked before.
1369 if (key != ImageVisualProperty.URL)
1371 using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1373 if (oldValue != null && oldValue.EqualTo(value))
1375 // Ignore UpdateImage query when we try to update equality value.
1380 imagePropertyUpdatedFlag = true;
1381 cachedImagePropertyMap[key] = value;
1383 // Lazy update only if _resourceUrl is not empty and ProcessAttachedFlag is false.
1384 if (!string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1388 // Throw exception if ImageView is disposed.
1389 // For legacy code safety, do not throw exception. and just print log for API10 now.
1390 //throw new global::System.InvalidOperationException("[NUI][ImageVIew] Someone try to change disposed ImageView's property.\n");
1392 Tizen.Log.Error("NUI", "[NUI][ImageVIew] Someone try to change disposed ImageView's property.\n");
1396 imagePropertyUpdateProcessAttachedFlag = true;
1397 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1398 // Call process hardly.
1399 ProcessorController.Instance.Awake();
1406 /// Callback function to Lazy UpdateImage.
1408 private void UpdateImage(object source, EventArgs e)
1410 // Note : To allow event attachment during UpdateImage, let we make flag as false before call UpdateImage().
1411 imagePropertyUpdateProcessAttachedFlag = false;
1416 /// Update image-relative properties synchronously.
1417 /// After call this API, All image properties updated.
1420 /// Current version ImageView property update asynchronously.
1421 /// If you want to guarantee that ImageView property setuped,
1422 /// Please call this ImageView.UpdateImage() API.
1424 [EditorBrowsable(EditorBrowsableState.Never)]
1425 protected virtual void UpdateImage()
1427 if(!imagePropertyUpdatedFlag) return;
1429 imagePropertyUpdatedFlag = false;
1431 if(cachedImagePropertyMap == null)
1433 cachedImagePropertyMap = new PropertyMap();
1436 // Checkup the cached visual type is AnimatedImage.
1437 // It is trick to know that this code is running on AnimatedImageView.UpdateImage() or not.
1438 int visualType = -1;
1439 if(!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && visualType == (int)Visual.Type.AnimatedImage))
1441 // If ResourceUrl is not setuped, don't set property. fast return.
1442 if(string.IsNullOrEmpty(_resourceUrl))
1446 if (_border == null)
1448 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1449 cachedImagePropertyMap[Visual.Property.Type] = image;
1454 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1455 cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1457 PropertyValue border = new PropertyValue(_border);
1458 cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1463 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1465 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1466 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1468 cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1469 cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1473 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1475 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1476 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1477 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1479 cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1480 cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1481 cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1485 // Do Fitting Buffer when desired dimension is set
1486 if (_desired_width != -1 && _desired_height != -1)
1488 if (_resourceUrl != null)
1490 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1491 if( imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0 )
1493 int adjustedDesiredWidth, adjustedDesiredHeight;
1494 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1495 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1496 if (aspectOfImageSize > aspectOfDesiredSize)
1498 adjustedDesiredWidth = _desired_width;
1499 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1503 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1504 adjustedDesiredHeight = _desired_height;
1507 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1508 cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1509 returnWidth?.Dispose();
1510 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1511 cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1512 returnHeight?.Dispose();
1513 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1514 cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1515 scaleToFit?.Dispose();
1519 Tizen.Log.Fatal("NUI", "[ERROR] Can't use DesiredSize when ImageLoading is failed.");
1521 imageSize?.Dispose();
1529 /// Merge our collected properties, and set IMAGE property internally.
1531 private void UpdateImageMap()
1533 // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1534 using(PropertyMap imageMap = new PropertyMap())
1536 using(PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1538 returnValue?.Get(imageMap);
1540 if(cachedImagePropertyMap != null)
1542 imageMap?.Merge(cachedImagePropertyMap);
1544 using(PropertyValue setValue = new PropertyValue(imageMap))
1546 SetProperty(ImageView.Property.IMAGE, setValue);
1549 // Update cached image property.
1550 MergeCachedImageVisualProperty(imageMap);
1555 /// Get image visual property by key.
1556 /// If we found value in local Cached result, return that.
1557 /// Else, get synced native map and return that.
1558 /// If there is no matched value, return null.
1560 [EditorBrowsable(EditorBrowsableState.Never)]
1561 protected virtual PropertyValue GetImageVisualProperty(int key)
1563 PropertyValue ret = GetCachedImageVisualProperty(key);
1566 // If we cannot find result form cached map, Get value from native engine.
1567 ret = Image?.Find(key);
1573 /// Get image visual property from NUI cached image map by key.
1574 /// If there is no matched value, return null.
1576 [EditorBrowsable(EditorBrowsableState.Never)]
1577 protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1579 return cachedImagePropertyMap?.Find(key);
1583 /// Update NUI cached image visual property map by inputed property map.
1586 /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1588 [EditorBrowsable(EditorBrowsableState.Never)]
1589 protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1591 if(map == null) return;
1592 if(cachedImagePropertyMap == null)
1594 cachedImagePropertyMap = new PropertyMap();
1596 foreach(var key in cachedImagePropertyKeyList)
1598 PropertyValue value = map.Find(key);
1601 // Update-or-Insert new value
1602 cachedImagePropertyMap[key] = value;
1608 /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1609 /// So before get base.GetNaturalSize(), we should synchronous image properties
1611 internal override Vector3 GetNaturalSize()
1613 // Sync as current properties
1615 return base.GetNaturalSize();
1618 [EditorBrowsable(EditorBrowsableState.Never)]
1619 protected override bool CheckResourceReady()
1621 // If we have some properties to be updated, this signal is old thing.
1622 // We need to ignore current signal, and wait next.
1623 return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1626 private void OnResourceLoaded(IntPtr view)
1628 if(!CheckResourceReady())
1632 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1633 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1635 if (_resourceLoadedEventHandler != null)
1637 _resourceLoadedEventHandler(this, e);
1642 /// Event arguments of resource ready.
1644 /// <since_tizen> 3 </since_tizen>
1645 public class ResourceReadyEventArgs : EventArgs
1650 /// The view whose resource is ready.
1652 /// <since_tizen> 3 </since_tizen>
1666 internal class ResourceLoadedEventArgs : EventArgs
1668 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1669 public ResourceLoadingStatusType Status
1682 internal new class Property
1684 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1685 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1686 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1689 private enum ImageType
1692 /// For Normal Image.
1697 /// For normal image, with synchronous loading and orientation correction property
1702 /// For nine-patch image
1707 private void OnBorderChanged(int x, int y, int width, int height)
1709 Border = new Rectangle(x, y, width, height);
1711 private void OnPixelAreaChanged(float x, float y, float z, float w)
1713 PixelArea = new RelativeVector4(x, y, z, w);
1716 private class ImageLayout : LayoutItem
1719 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1720 /// 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.
1722 [EditorBrowsable(EditorBrowsableState.Never)]
1723 public bool AdjustViewSize
1727 return (Owner as ImageView)?.AdjustViewSize ?? false;
1731 if (Owner is ImageView imageView)
1733 imageView.AdjustViewSize = value;
1739 [EditorBrowsable(EditorBrowsableState.Never)]
1740 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1742 // To not change the view size by DALi
1743 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1744 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1746 float specWidth = widthMeasureSpec.Size.AsDecimal();
1747 float specHeight = heightMeasureSpec.Size.AsDecimal();
1748 float naturalWidth = Owner.NaturalSize.Width;
1749 float naturalHeight = Owner.NaturalSize.Height;
1750 float minWidth = Owner.MinimumSize.Width;
1751 float maxWidth = Owner.MaximumSize.Width;
1752 float minHeight = Owner.MinimumSize.Height;
1753 float maxHeight = Owner.MaximumSize.Height;
1754 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1756 // Assume that the new width and height are given from the view's suggested size by default.
1757 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1758 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1760 // The width and height measure specs are going to be used to set measured size.
1761 // Mark that the measure specs are changed by default to update measure specs later.
1762 bool widthSpecChanged = true;
1763 bool heightSpecChanged = true;
1765 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1767 newWidth = specWidth;
1768 widthSpecChanged = false;
1770 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1772 if ((AdjustViewSize) && (aspectRatio > 0))
1774 newHeight = newWidth * aspectRatio;
1779 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1781 newHeight = specHeight;
1782 heightSpecChanged = false;
1784 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1786 if ((AdjustViewSize) && (aspectRatio > 0))
1788 newWidth = newHeight / aspectRatio;
1793 if (widthSpecChanged)
1795 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1798 if (heightSpecChanged)
1800 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1803 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1804 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1806 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1807 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));