2 * Copyright(c) 2019 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
20 using System.ComponentModel;
21 using Tizen.NUI.Binding;
23 namespace Tizen.NUI.BaseComponents
27 /// ImageView is a class for displaying an image resource.<br />
28 /// An instance of ImageView can be created using a URL or an image instance.<br />
30 /// <since_tizen> 3 </since_tizen>
31 public partial class ImageView : View
33 static ImageView() { }
35 private EventHandler<ResourceReadyEventArgs> _resourceReadyEventHandler;
36 private ResourceReadyEventCallbackType _resourceReadyEventCallback;
37 private EventHandler<ResourceLoadedEventArgs> _resourceLoadedEventHandler;
38 private _resourceLoadedCallbackType _resourceLoadedCallback;
41 /// Convert non-null string that some keyword change as application specific directory.
43 /// <param name="value">Inputed and replaced after this function finished</param>
44 /// <returns>Replaced url</returns>
45 private static string ConvertResourceUrl(ref string value)
48 if (value.StartsWith("*Resource*"))
50 string resource = Tizen.Applications.Application.Current.DirectoryInfo.Resource;
51 value = value.Replace("*Resource*", resource);
56 // Collection of image-sensitive properties.
57 private static readonly List<int> cachedImagePropertyKeyList = new List<int> {
59 ImageVisualProperty.URL,
60 ImageVisualProperty.AlphaMaskURL,
61 ImageVisualProperty.CropToMask,
62 Visual.Property.VisualFittingMode,
63 ImageVisualProperty.DesiredWidth,
64 ImageVisualProperty.DesiredHeight,
65 ImageVisualProperty.ReleasePolicy,
66 ImageVisualProperty.WrapModeU,
67 ImageVisualProperty.WrapModeV,
68 ImageVisualProperty.SynchronousLoading,
69 Visual.Property.PremultipliedAlpha,
70 ImageVisualProperty.OrientationCorrection,
71 NpatchImageVisualProperty.Border,
72 NpatchImageVisualProperty.BorderOnly,
74 internal PropertyMap cachedImagePropertyMap;
75 internal bool imagePropertyUpdatedFlag = false;
77 private bool imagePropertyUpdateProcessAttachedFlag = false;
78 private Rectangle _border;
79 private string _resourceUrl = "";
80 private int _desired_width = -1;
81 private int _desired_height = -1;
82 private TriggerableSelector<string> resourceUrlSelector;
83 private TriggerableSelector<Rectangle> borderSelector;
85 private RelativeVector4 internalPixelArea;
88 /// Creates an initialized ImageView.
90 /// <since_tizen> 3 </since_tizen>
91 public ImageView() : this(Interop.ImageView.New(), true)
93 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
96 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
97 [EditorBrowsable(EditorBrowsableState.Never)]
98 public ImageView(ViewStyle viewStyle) : this(Interop.ImageView.New(), true, viewStyle)
103 /// Creates an initialized ImageView with setting the status of shown or hidden.
105 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
106 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
107 [EditorBrowsable(EditorBrowsableState.Never)]
108 public ImageView(bool shown) : this(Interop.ImageView.New(), true)
110 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
115 /// Creates an initialized ImageView from a URL to an image resource.<br />
116 /// If the string is empty, ImageView will not display anything.<br />
118 /// <param name="url">The URL of the image resource to display.</param>
119 /// <since_tizen> 3 </since_tizen>
120 public ImageView(string url) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
123 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
128 /// Creates an initialized ImageView from a URL to an image resource with setting shown or hidden.
130 /// <param name="url">The URL of the image resource to display.</param>
131 /// <param name="shown">false : Not displayed (hidden), true : displayed (shown)</param>
132 /// This will be public opened in next release of tizen after ACR done. Before ACR, it is used as HiddenAPI (InhouseAPI).
133 [EditorBrowsable(EditorBrowsableState.Never)]
134 public ImageView(string url, bool shown) : this(Interop.ImageView.New(ConvertResourceUrl(ref url)), true)
137 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
141 internal ImageView(string url, Uint16Pair size, bool shown = true) : this(Interop.ImageView.New(ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size)), true)
144 _desired_width = size?.GetWidth() ?? -1;
145 _desired_height = size?.GetHeight() ?? -1;
146 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
154 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, ViewStyle viewStyle, bool shown = true) : base(cPtr, cMemoryOwn, viewStyle)
162 internal ImageView(global::System.IntPtr cPtr, bool cMemoryOwn, bool shown = true) : base(cPtr, cMemoryOwn, null)
170 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
171 private delegate void ResourceReadyEventCallbackType(IntPtr data);
172 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
173 private delegate void _resourceLoadedCallbackType(IntPtr view);
176 /// An event for ResourceReady signal which can be used to subscribe or unsubscribe the event handler.<br />
177 /// This signal is emitted after all resources required by a control are loaded and ready.<br />
178 /// Most resources are only loaded when the control is placed on the stage.<br />
180 /// <since_tizen> 3 </since_tizen>
181 public event EventHandler<ResourceReadyEventArgs> ResourceReady
185 if (_resourceReadyEventHandler == null)
187 _resourceReadyEventCallback = OnResourceReady;
188 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
189 resourceReadySignal?.Connect(_resourceReadyEventCallback);
190 resourceReadySignal?.Dispose();
193 _resourceReadyEventHandler += value;
198 _resourceReadyEventHandler -= value;
200 ViewResourceReadySignal resourceReadySignal = ResourceReadySignal(this);
201 if (_resourceReadyEventHandler == null && resourceReadySignal?.Empty() == false)
203 resourceReadySignal?.Disconnect(_resourceReadyEventCallback);
205 resourceReadySignal?.Dispose();
209 internal event EventHandler<ResourceLoadedEventArgs> ResourceLoaded
213 if (_resourceLoadedEventHandler == null)
215 _resourceLoadedCallback = OnResourceLoaded;
216 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
217 resourceReadySignal?.Connect(_resourceLoadedCallback);
218 resourceReadySignal?.Dispose();
221 _resourceLoadedEventHandler += value;
225 _resourceLoadedEventHandler -= value;
226 ViewResourceReadySignal resourceReadySignal = this.ResourceReadySignal(this);
227 if (_resourceLoadedEventHandler == null && resourceReadySignal?.Empty() == false)
229 resourceReadySignal?.Disconnect(_resourceLoadedCallback);
231 resourceReadySignal?.Dispose();
236 /// Enumeration for LoadingStatus of image.
238 /// <since_tizen> 5 </since_tizen>
239 public enum LoadingStatusType
242 /// Loading preparing status.
244 /// <since_tizen> 5 </since_tizen>
247 /// Loading ready status.
249 /// <since_tizen> 5 </since_tizen>
252 /// Loading failed status.
254 /// <since_tizen> 5 </since_tizen>
259 /// Enumeration for MaskingMode of image.
261 [EditorBrowsable(EditorBrowsableState.Never)]
262 public enum MaskingModeType
265 /// Applies alpha masking on rendering time.
267 [EditorBrowsable(EditorBrowsableState.Never)]
270 /// Applies alpha masking on loading time.
272 [EditorBrowsable(EditorBrowsableState.Never)]
277 /// ImageView ResourceUrl, type string.
278 /// This is one of mandatory property. Even if not set or null set, it sets empty string ("") internally.
279 /// When it is set as null, it gives empty string ("") to be read.
281 /// <since_tizen> 3 </since_tizen>
282 public string ResourceUrl
286 return (string)GetValue(ResourceUrlProperty);
290 SetValue(ResourceUrlProperty, value);
291 NotifyPropertyChanged();
296 /// This will be deprecated, Use Image instead. <br />
297 /// ImageView ImageMap, type PropertyMap: string if it is a URL, map otherwise.
299 /// <since_tizen> 3 </since_tizen>
300 [Obsolete("Do not use this, that will be deprecated. Use Image property instead.")]
301 [EditorBrowsable(EditorBrowsableState.Never)]
302 public PropertyMap ImageMap
306 return GetValue(ImageMapProperty) as PropertyMap;
310 SetValue(ImageMapProperty, value);
311 NotifyPropertyChanged();
314 private PropertyMap InternalImageMap
320 // Sync as current properties
323 // Get current properties force.
324 PropertyMap returnValue = new PropertyMap();
325 PropertyValue image = GetProperty(ImageView.Property.IMAGE);
326 image?.Get(returnValue);
329 // Update cached property map
330 if(returnValue != null)
332 MergeCachedImageVisualProperty(returnValue);
345 PropertyValue setValue = new Tizen.NUI.PropertyValue(value);
346 SetProperty(ImageView.Property.IMAGE, setValue);
348 // Image properties are changed hardly. We should ignore lazy UpdateImage
349 imagePropertyUpdatedFlag = false;
350 cachedImagePropertyMap?.Dispose();
351 cachedImagePropertyMap = null;
352 MergeCachedImageVisualProperty(value);
354 NotifyPropertyChanged();
361 /// ImageView Image, type PropertyMap: string if it is a URL, map otherwise.
364 /// This PropertyMap use a <see cref="ImageVisualProperty"/>. <br />
365 /// See <see cref="ImageVisualProperty"/> for a detailed description. <br />
366 /// you can also use <see cref="Visual.Property"/>. <br />
367 /// See <see cref="Visual.Property"/> for a detailed description. <br />
370 /// The following example demonstrates how to use the Image property.
372 /// PropertyMap map = new PropertyMap();
373 /// map.Insert(Visual.Property.Type, new PropertyValue((int)Visual.Type.Image));
374 /// map.Insert(ImageVisualProperty.AlphaMaskURL, new PropertyValue(url));
375 /// map.Insert(ImageVisualProperty.FittingMode, new PropertyValue((int)FittingModeType.ScaleToFill);
376 /// imageview.Image = map;
379 /// <since_tizen> 4 </since_tizen>
380 public PropertyMap Image
386 return (PropertyMap)GetValue(ImageProperty);
397 SetValue(ImageProperty, value);
398 NotifyPropertyChanged();
404 /// ImageView PreMultipliedAlpha, type Boolean.<br />
405 /// Image must be initialized.<br />
407 /// <since_tizen> 3 </since_tizen>
408 public bool PreMultipliedAlpha
412 return (bool)GetValue(PreMultipliedAlphaProperty);
416 SetValue(PreMultipliedAlphaProperty, value);
417 NotifyPropertyChanged();
422 /// ImageView PixelArea, type Vector4 (Animatable property).<br />
423 /// Pixel area is a relative value with the whole image area as [0.0, 0.0, 1.0, 1.0].<br />
426 /// The property cascade chaining set is possible. For example, this (imageView.PixelArea.X = 0.1f;) is possible.
428 /// <since_tizen> 3 </since_tizen>
429 public RelativeVector4 PixelArea
433 return (RelativeVector4)GetValue(PixelAreaProperty);
437 SetValue(PixelAreaProperty, value);
438 NotifyPropertyChanged();
443 /// The border of the image in the order: left, right, bottom, top.<br />
444 /// If set, ImageMap will be ignored.<br />
445 /// For N-Patch images only.<br />
449 /// The property cascade chaining set is possible. For example, this (imageView.Border.X = 1;) is possible.
451 /// <since_tizen> 3 </since_tizen>
452 public Rectangle Border
456 Rectangle temp = (Rectangle)GetValue(BorderProperty);
463 return new Rectangle(OnBorderChanged, temp.X, temp.Y, temp.Width, temp.Height);
468 SetValue(BorderProperty, value);
469 NotifyPropertyChanged();
474 /// Gets or sets whether to draw the borders only (if true).<br />
475 /// If not specified, the default is false.<br />
476 /// For N-Patch images only.<br />
479 /// <since_tizen> 3 </since_tizen>
480 public bool BorderOnly
484 return (bool)GetValue(BorderOnlyProperty);
488 SetValue(BorderOnlyProperty, value);
489 NotifyPropertyChanged();
494 /// Gets or sets whether to synchronous loading the resourceurl of image.<br />
496 /// <since_tizen> 3 </since_tizen>
497 [Obsolete("This has been deprecated since API9 and will be removed in API11. Use SynchronousLoading instead.")]
498 public bool SynchronosLoading
502 return SynchronousLoading;
506 SynchronousLoading = value;
511 /// Gets or sets whether the image of the ResourceUrl property will be loaded synchronously.<br />
514 /// Changing this property make this ImageView load image synchronously at the next loading
515 /// by following operation: <see cref="Reload"/>, <see cref="SetImage(string)"/>,
516 /// and by some properties those cause reloading: <see cref="ResourceUrl"/>, <see cref="PreMultipliedAlpha"/> and etc.
518 /// <since_tizen> 9 </since_tizen>
519 public bool SynchronousLoading
523 return (bool)GetValue(SynchronousLoadingProperty);
527 SetValue(SynchronousLoadingProperty, value);
528 NotifyPropertyChanged();
533 /// Gets or sets whether to automatically correct the orientation of an image.<br />
535 /// <since_tizen> 5 </since_tizen>
536 public bool OrientationCorrection
540 return (bool)GetValue(OrientationCorrectionProperty);
544 SetValue(OrientationCorrectionProperty, value);
545 NotifyPropertyChanged();
550 /// Gets or sets whether to apply mask on GPU or not.<br />
552 [EditorBrowsable(EditorBrowsableState.Never)]
553 public MaskingModeType MaskingMode
557 return (MaskingModeType)GetValue(MaskingModeProperty);
561 SetValue(MaskingModeProperty, value);
562 NotifyPropertyChanged();
566 private MaskingModeType InternalMaskingMode
570 int ret = (int)MaskingModeType.MaskingOnLoading;
572 PropertyValue maskingMode = GetCachedImageVisualProperty(ImageVisualProperty.MaskingMode);
573 maskingMode?.Get(out ret);
574 maskingMode?.Dispose();
576 return (MaskingModeType)ret;
580 MaskingModeType ret = value;
581 PropertyValue setValue = new PropertyValue((int)ret);
582 UpdateImage(ImageVisualProperty.MaskingMode, setValue);
588 /// Gets the loading state of the visual resource.
590 /// <since_tizen> 5 </since_tizen>
591 public ImageView.LoadingStatusType LoadingStatus
595 return (ImageView.LoadingStatusType)Interop.View.GetVisualResourceStatus(SwigCPtr, (int)Property.IMAGE);
600 /// Downcasts a handle to imageView handle.
602 /// <exception cref="ArgumentNullException"> Thrown when handle is null. </exception>
603 /// Do not use this, that will be deprecated. Use as keyword instead.
604 /// <since_tizen> 3 </since_tizen>
605 [Obsolete("Do not use this, that will be deprecated. Use as keyword instead. " +
607 "BaseHandle handle = new ImageView(imagePath); " +
608 "ImageView image = handle as ImageView")]
609 [EditorBrowsable(EditorBrowsableState.Never)]
610 public static ImageView DownCast(BaseHandle handle)
614 throw new ArgumentNullException(nameof(handle));
616 ImageView ret = Registry.GetManagedBaseHandleFromNativePtr(handle) as ImageView;
617 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
622 /// Sets this ImageView from the given URL.<br />
623 /// If the URL is empty, ImageView will not display anything.<br />
625 /// <param name="url">The URL to the image resource to display.</param>
626 /// <exception cref="ArgumentNullException"> Thrown when url is null. </exception>
627 /// <since_tizen> 3 </since_tizen>
628 public void SetImage(string url)
632 throw new ArgumentNullException(nameof(url));
635 if (url.Contains(".json"))
637 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
641 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url));
642 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
648 /// Queries if all resources required by a control are loaded and ready.<br />
649 /// Most resources are only loaded when the control is placed on the stage.<br />
650 /// True if the resources are loaded and ready, false otherwise.<br />
652 /// <since_tizen> 3 </since_tizen>
653 public new bool IsResourceReady()
655 bool ret = Interop.View.IsResourceReady(SwigCPtr);
656 if (NDalicPINVOKE.SWIGPendingException.Pending)
657 throw NDalicPINVOKE.SWIGPendingException.Retrieve();
662 /// Forcefully reloads the image. All the visuals using this image will reload to the latest image.
664 /// <since_tizen> 5 </since_tizen>
667 // Sync as current properties
671 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionReload);
675 /// Plays the animated GIF. This is also the default playback mode.
677 /// <since_tizen> 5 </since_tizen>
680 // Sync as current properties
684 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPlay);
688 /// Pauses the animated GIF.
690 /// <since_tizen> 5 </since_tizen>
693 // Sync as current properties
697 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionPause);
701 /// Stops the animated GIF.
703 /// <since_tizen> 5 </since_tizen>
706 // Sync as current properties
711 Interop.View.DoActionWithEmptyAttributes(this.SwigCPtr, ImageView.Property.IMAGE, ActionStop);
715 /// Gets or sets the URL of the alpha mask.<br />
718 /// <since_tizen> 6</since_tizen>
719 [EditorBrowsable(EditorBrowsableState.Never)]
720 public string AlphaMaskURL
724 return GetValue(AlphaMaskURLProperty) as string;
728 SetValue(AlphaMaskURLProperty, value);
729 NotifyPropertyChanged();
733 private string InternalAlphaMaskURL
739 PropertyValue maskUrl = GetCachedImageVisualProperty(ImageVisualProperty.AlphaMaskURL);
740 maskUrl?.Get(out ret);
747 PropertyValue setValue = new PropertyValue(value ?? "");
748 UpdateImage(ImageVisualProperty.AlphaMaskURL, setValue);
749 // When we never set CropToMask property before, we should set default value as true.
750 using(PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask))
752 if(cropToMask == null)
754 using PropertyValue setCropValue = new PropertyValue(true);
755 UpdateImage(ImageVisualProperty.CropToMask, setCropValue);
764 /// Whether to crop image to mask or scale mask to fit image.
766 /// <since_tizen> 6 </since_tizen>
767 public bool CropToMask
771 return (bool)GetValue(CropToMaskProperty);
775 SetValue(CropToMaskProperty, value);
776 NotifyPropertyChanged();
779 private bool InternalCropToMask
785 PropertyValue cropToMask = GetCachedImageVisualProperty(ImageVisualProperty.CropToMask);
786 cropToMask?.Get(out ret);
787 cropToMask?.Dispose();
793 PropertyValue setValue = new PropertyValue(value);
794 UpdateImage(ImageVisualProperty.CropToMask, setValue);
800 /// Actions property value for Reload image.
802 private int ActionReload { get; set; } = Interop.ImageView.ImageVisualActionReloadGet();
805 /// Actions property value to Play animated images.
806 /// This property can be redefined by child class if it use different value.
808 [EditorBrowsable(EditorBrowsableState.Never)]
809 protected int ActionPlay { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPlayGet();
812 /// Actions property value to Pause animated images.
813 /// This property can be redefined by child class if it use different value.
815 [EditorBrowsable(EditorBrowsableState.Never)]
816 protected int ActionPause { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionPauseGet();
819 /// Actions property value to Stop animated images.
820 /// This property can be redefined by child class if it use different value.
822 [EditorBrowsable(EditorBrowsableState.Never)]
823 protected int ActionStop { get; set; } = Interop.AnimatedImageView.AnimatedImageVisualActionStopGet();
825 internal VisualFittingModeType ConvertFittingModetoVisualFittingMode(FittingModeType value)
829 case FittingModeType.ShrinkToFit:
830 return VisualFittingModeType.FitKeepAspectRatio;
831 case FittingModeType.ScaleToFill:
832 return VisualFittingModeType.OverFitKeepAspectRatio;
833 case FittingModeType.Center:
834 return VisualFittingModeType.Center;
835 case FittingModeType.Fill:
836 return VisualFittingModeType.Fill;
837 case FittingModeType.FitHeight:
838 return VisualFittingModeType.FitHeight;
839 case FittingModeType.FitWidth:
840 return VisualFittingModeType.FitWidth;
842 return VisualFittingModeType.Fill;
846 internal FittingModeType ConvertVisualFittingModetoFittingMode(VisualFittingModeType value)
850 case VisualFittingModeType.FitKeepAspectRatio:
851 return FittingModeType.ShrinkToFit;
852 case VisualFittingModeType.OverFitKeepAspectRatio:
853 return FittingModeType.ScaleToFill;
854 case VisualFittingModeType.Center:
855 return FittingModeType.Center;
856 case VisualFittingModeType.Fill:
857 return FittingModeType.Fill;
858 case VisualFittingModeType.FitHeight:
859 return FittingModeType.FitHeight;
860 case VisualFittingModeType.FitWidth:
861 return FittingModeType.FitWidth;
863 return FittingModeType.ShrinkToFit;
867 internal override LayoutItem CreateDefaultLayout()
869 return new ImageLayout();
873 /// Gets or sets fitting options used when resizing images to fit.<br />
874 /// If not supplied, the default is FittingModeType.Fill.<br />
875 /// For normal quad images only.<br />
878 /// <since_tizen> 6 </since_tizen>
879 [EditorBrowsable(EditorBrowsableState.Never)]
880 public FittingModeType FittingMode
884 return (FittingModeType)GetValue(FittingModeProperty);
888 SetValue(FittingModeProperty, value);
889 NotifyPropertyChanged();
893 private FittingModeType InternalFittingMode
897 int ret = (int)VisualFittingModeType.Fill;
899 PropertyValue fittingMode = GetCachedImageVisualProperty(Visual.Property.VisualFittingMode);
900 fittingMode?.Get(out ret);
901 fittingMode?.Dispose();
903 return ConvertVisualFittingModetoFittingMode((VisualFittingModeType)ret);
907 VisualFittingModeType ret = ConvertFittingModetoVisualFittingMode(value);
908 PropertyValue setValue = new PropertyValue((int)ret);
909 UpdateImage(Visual.Property.VisualFittingMode, setValue);
915 /// Gets or sets the desired image width.<br />
916 /// If not specified, the actual image width is used.<br />
917 /// For normal quad images only.<br />
920 /// <since_tizen> 6 </since_tizen>
921 [EditorBrowsable(EditorBrowsableState.Never)]
922 public int DesiredWidth
926 return (int)GetValue(DesiredWidthProperty);
930 SetValue(DesiredWidthProperty, value);
931 NotifyPropertyChanged();
934 private int InternalDesiredWidth
938 // Sync as current properties only if both _desired_width and _desired_height are setuped.
939 if(_desired_width != -1 && _desired_height != -1)
943 PropertyValue desirewidth = GetCachedImageVisualProperty(ImageVisualProperty.DesiredWidth);
944 desirewidth?.Get(out _desired_width);
945 desirewidth?.Dispose();
947 return _desired_width;
951 if (_desired_width != value)
953 _desired_width = value;
954 PropertyValue setValue = new PropertyValue(value);
955 UpdateImage(ImageVisualProperty.DesiredWidth, setValue);
962 /// Gets or sets the desired image height.<br />
963 /// If not specified, the actual image height is used.<br />
964 /// For normal quad images only.<br />
967 /// <since_tizen> 6 </since_tizen>
968 [EditorBrowsable(EditorBrowsableState.Never)]
969 public int DesiredHeight
973 return (int)GetValue(DesiredHeightProperty);
977 SetValue(DesiredHeightProperty, value);
978 NotifyPropertyChanged();
981 private int InternalDesiredHeight
985 // Sync as current properties only if both _desired_width and _desired_height are setuped.
986 if(_desired_width != -1 && _desired_height != -1)
990 PropertyValue desireheight = GetCachedImageVisualProperty(ImageVisualProperty.DesiredHeight);
991 desireheight?.Get(out _desired_height);
992 desireheight?.Dispose();
994 return _desired_height;
998 if (_desired_height != value)
1000 _desired_height = value;
1001 PropertyValue setValue = new PropertyValue(value);
1002 UpdateImage(ImageVisualProperty.DesiredHeight, setValue);
1003 setValue?.Dispose();
1009 /// Gets or sets ReleasePolicy for image.<br />
1010 /// If not supplied, the default is ReleasePolicyType.Detached.<br />
1012 [EditorBrowsable(EditorBrowsableState.Never)]
1013 public ReleasePolicyType ReleasePolicy
1017 return (ReleasePolicyType)GetValue(ReleasePolicyProperty);
1021 SetValue(ReleasePolicyProperty, value);
1022 NotifyPropertyChanged();
1026 private ReleasePolicyType InternalReleasePolicy
1030 int ret = (int)ReleasePolicyType.Detached;
1032 PropertyValue releasePoli = GetCachedImageVisualProperty(ImageVisualProperty.ReleasePolicy);
1033 releasePoli?.Get(out ret);
1034 releasePoli?.Dispose();
1036 return (ReleasePolicyType)ret;
1040 PropertyValue setValue = new PropertyValue((int)value);
1041 UpdateImage(ImageVisualProperty.ReleasePolicy, setValue);
1042 setValue?.Dispose();
1047 /// Gets or sets the wrap mode for the u coordinate.<br />
1048 /// It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.<br />
1049 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1050 /// For normal quad images only.<br />
1053 /// <since_tizen> 6 </since_tizen>
1054 [EditorBrowsable(EditorBrowsableState.Never)]
1055 public WrapModeType WrapModeU
1059 return (WrapModeType)GetValue(WrapModeUProperty);
1063 SetValue(WrapModeUProperty, value);
1064 NotifyPropertyChanged();
1068 private WrapModeType InternalWrapModeU
1072 int ret = (int)WrapModeType.Default;
1074 PropertyValue wrapModeU = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeU);
1075 wrapModeU?.Get(out ret);
1076 wrapModeU?.Dispose();
1078 return (WrapModeType)ret;
1082 PropertyValue setValue = new PropertyValue((int)value);
1083 UpdateImage(ImageVisualProperty.WrapModeU, setValue);
1084 setValue?.Dispose();
1089 /// Gets or sets the wrap mode for the v coordinate.<br />
1090 /// It decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.<br />
1091 /// 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 />
1092 /// If not specified, the default is WrapModeType.Default(CLAMP).<br />
1093 /// For normal quad images only.
1096 /// <since_tizen> 6 </since_tizen>
1097 [EditorBrowsable(EditorBrowsableState.Never)]
1098 public WrapModeType WrapModeV
1102 return (WrapModeType)GetValue(WrapModeVProperty);
1106 SetValue(WrapModeVProperty, value);
1107 NotifyPropertyChanged();
1111 private WrapModeType InternalWrapModeV
1115 int ret = (int)WrapModeType.Default;
1117 PropertyValue wrapModeV = GetCachedImageVisualProperty(ImageVisualProperty.WrapModeV);
1118 wrapModeV?.Get(out ret);
1119 wrapModeV?.Dispose();
1121 return (WrapModeType)ret;
1125 PropertyValue setValue = new PropertyValue((int)value);
1126 UpdateImage(ImageVisualProperty.WrapModeV, setValue);
1127 setValue?.Dispose();
1132 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1135 /// This is false by default.
1136 /// If this is set to be true, then the width or height value, which is not set by user explicitly, can be changed automatically
1137 /// to preserve the aspect ratio of the image resource.
1138 /// AdjustViewSize works only if ImageView is added to a View having Layout.
1139 /// e.g. If the image resource size is (100, 100), then the ImageView requests size (100, 100) to its parent layout by default.
1140 /// If the ImageView's HeightSpecification is 50 and AdjustViewSize is true, then the ImageView requests size (50, 50) instead of (100, 50).
1142 /// <since_tizen> 9 </since_tizen>
1143 public bool AdjustViewSize
1147 return (bool)GetValue(AdjustViewSizeProperty);
1151 SetValue(AdjustViewSizeProperty, value);
1152 NotifyPropertyChanged();
1155 private bool adjustViewSize = false;
1157 internal Selector<string> ResourceUrlSelector
1159 get => GetSelector<string>(resourceUrlSelector, ImageView.ResourceUrlProperty);
1162 resourceUrlSelector?.Reset(this);
1163 if (value == null) return;
1165 if (value.HasAll()) SetResourceUrl(value.All);
1166 else resourceUrlSelector = new TriggerableSelector<string>(this, value, SetResourceUrl, true);
1171 /// Get attributes, it is abstract function and must be override.
1173 [EditorBrowsable(EditorBrowsableState.Never)]
1174 protected override ViewStyle CreateViewStyle()
1176 return new ImageViewStyle();
1179 internal void SetImage(string url, Uint16Pair size)
1181 if (url.Contains(".json"))
1183 Tizen.Log.Fatal("NUI", "[ERROR] Do not set lottie file in ImageView! This is temporary checking, will be removed soon!");
1187 Interop.ImageView.SetImage(SwigCPtr, ConvertResourceUrl(ref url), Uint16Pair.getCPtr(size));
1188 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1191 _desired_width = size?.GetWidth() ?? -1;
1192 _desired_height = size?.GetHeight() ?? -1;
1195 internal ViewResourceReadySignal ResourceReadySignal(View view)
1197 ViewResourceReadySignal ret = new ViewResourceReadySignal(Interop.View.ResourceReadySignal(View.getCPtr(view)), false);
1198 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
1202 internal override void ApplyCornerRadius()
1204 base.ApplyCornerRadius();
1206 if (backgroundExtraData == null) return;
1209 // Update corner radius properties to image by ActionUpdateProperty
1210 if (backgroundExtraData.CornerRadius != null)
1212 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadius, Vector4.getCPtr(backgroundExtraData.CornerRadius));
1214 Interop.View.InternalUpdateVisualPropertyInt(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.CornerRadiusPolicy, (int)backgroundExtraData.CornerRadiusPolicy);
1217 internal override void ApplyBorderline()
1219 base.ApplyBorderline();
1221 if (backgroundExtraData == null) return;
1224 // Update borderline properties to image by ActionUpdateProperty
1225 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineWidth, backgroundExtraData.BorderlineWidth);
1226 Interop.View.InternalUpdateVisualPropertyVector4(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineColor, Vector4.getCPtr(backgroundExtraData.BorderlineColor ?? Color.Black));
1227 Interop.View.InternalUpdateVisualPropertyFloat(this.SwigCPtr, ImageView.Property.IMAGE, Visual.Property.BorderlineOffset, backgroundExtraData.BorderlineOffset);
1230 internal ResourceLoadingStatusType GetResourceStatus()
1232 return (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1236 /// you can override it to clean-up your own resources.
1238 /// <param name="type">DisposeTypes</param>
1239 /// <since_tizen> 3 </since_tizen>
1240 protected override void Dispose(DisposeTypes type)
1247 internalPixelArea?.Dispose();
1249 if (type == DisposeTypes.Explicit)
1252 //Release your own managed resources here.
1253 //You should release all of your own disposable objects here.
1256 borderSelector?.Reset(this);
1257 resourceUrlSelector?.Reset(this);
1258 imagePropertyUpdatedFlag = false;
1259 if (imagePropertyUpdateProcessAttachedFlag)
1261 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1262 imagePropertyUpdateProcessAttachedFlag = false;
1264 cachedImagePropertyMap?.Dispose();
1265 cachedImagePropertyMap = null;
1271 /// This will not be public opened.
1272 [EditorBrowsable(EditorBrowsableState.Never)]
1273 protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
1275 Interop.ImageView.DeleteImageView(swigCPtr);
1278 // Callback for View ResourceReady signal
1279 private void OnResourceReady(IntPtr data)
1281 if(!CheckResourceReady())
1286 ResourceReadyEventArgs e = new ResourceReadyEventArgs();
1289 e.View = Registry.GetManagedBaseHandleFromNativePtr(data) as View;
1292 if (_resourceReadyEventHandler != null)
1294 _resourceReadyEventHandler(this, e);
1298 private void SetResourceUrl(string value)
1300 if(_resourceUrl != ConvertResourceUrl(ref value))
1302 _resourceUrl = value;
1303 if(string.IsNullOrEmpty(_resourceUrl))
1305 // Special case. If we set ResourceUrl as empty, Unregist visual.
1310 using(PropertyValue setValue = new PropertyValue(value))
1312 UpdateImage(ImageVisualProperty.URL, setValue);
1314 // Special case. If we set GeneratedUrl, Create ImageVisual synchronously.
1315 if(value.StartsWith("dali://") || value.StartsWith("enbuf://"))
1323 private void SetBorder(Rectangle value)
1329 if(_border != value)
1331 _border = new Rectangle(value);
1332 UpdateImage(NpatchImageVisualProperty.Border, new PropertyValue(_border));
1337 /// Unregist image visual directly. After this operation, we cannot get any properties from Image property.
1339 private void RemoveImage()
1341 // If previous resourceUrl was already empty, we don't need to do anything. just ignore.
1342 // Unregist and detach process only if previous resourceUrl was not empty
1343 string currentResourceUrl = "";
1344 PropertyValue currentResourceUrlValue = GetCachedImageVisualProperty(ImageVisualProperty.URL);
1345 if((currentResourceUrlValue?.Get(out currentResourceUrl) ?? false) && !string.IsNullOrEmpty(currentResourceUrl))
1347 PropertyValue emptyValue = new PropertyValue();
1349 // Remove current registed Image.
1350 SetProperty(ImageView.Property.IMAGE, emptyValue);
1352 // Image visual is not exist anymore. We should ignore lazy UpdateImage
1353 imagePropertyUpdatedFlag = false;
1354 if(imagePropertyUpdateProcessAttachedFlag)
1356 ProcessorController.Instance.ProcessorOnceEvent -= UpdateImage;
1357 imagePropertyUpdateProcessAttachedFlag = false;
1359 // Update resourceUrl as empty value
1360 cachedImagePropertyMap[ImageVisualProperty.URL] = emptyValue;
1362 emptyValue?.Dispose();
1364 currentResourceUrlValue?.Dispose();
1368 /// Lazy call to UpdateImage.
1369 /// Collect Properties need to be update, and set properties that starts the Processing.
1371 [EditorBrowsable(EditorBrowsableState.Never)]
1372 protected virtual void UpdateImage(int key, PropertyValue value)
1374 // Update image property map value as inputed value.
1377 if (cachedImagePropertyMap == null)
1379 cachedImagePropertyMap = new PropertyMap();
1382 // To optimization, we don't check URL duplicate case. We already checked before.
1383 if (key != ImageVisualProperty.URL)
1385 using (PropertyValue oldValue = GetCachedImageVisualProperty(key))
1387 if (oldValue != null && oldValue.EqualTo(value))
1389 // Ignore UpdateImage query when we try to update equality value.
1394 imagePropertyUpdatedFlag = true;
1395 cachedImagePropertyMap[key] = value;
1397 // Lazy update only if _resourceUrl is not empty and ProcessAttachedFlag is false.
1398 if (!string.IsNullOrEmpty(_resourceUrl) && !imagePropertyUpdateProcessAttachedFlag)
1400 imagePropertyUpdateProcessAttachedFlag = true;
1401 ProcessorController.Instance.ProcessorOnceEvent += UpdateImage;
1402 // Call process hardly.
1403 ProcessorController.Instance.Awake();
1409 /// Callback function to Lazy UpdateImage.
1411 private void UpdateImage(object source, EventArgs e)
1414 imagePropertyUpdateProcessAttachedFlag = false;
1418 /// Update image-relative properties synchronously.
1419 /// After call this API, All image properties updated.
1422 /// Current version ImageView property update asynchronously.
1423 /// If you want to guarantee that ImageView property setuped,
1424 /// Please call this ImageView.UpdateImage() API.
1426 [EditorBrowsable(EditorBrowsableState.Never)]
1427 protected virtual void UpdateImage()
1429 if(!imagePropertyUpdatedFlag) return;
1431 imagePropertyUpdatedFlag = false;
1433 if(cachedImagePropertyMap == null)
1435 cachedImagePropertyMap = new PropertyMap();
1438 // Checkup the cached visual type is AnimatedImage.
1439 // It is trick to know that this code is running on AnimatedImageView.UpdateImage() / LottieAnimationView.UpdateImage() or not.
1440 int visualType = (int)Visual.Type.Invalid;
1441 if(!((GetCachedImageVisualProperty(Visual.Property.Type)?.Get(out visualType) ?? false) && (visualType == (int)Visual.Type.AnimatedImage || visualType == (int)Visual.Type.AnimatedVectorImage)))
1443 // If ResourceUrl is not setuped, don't set property. fast return.
1444 if(string.IsNullOrEmpty(_resourceUrl))
1448 if (_border == null)
1450 PropertyValue image = new PropertyValue((int)Visual.Type.Image);
1451 cachedImagePropertyMap[Visual.Property.Type] = image;
1456 PropertyValue nPatch = new PropertyValue((int)Visual.Type.NPatch);
1457 cachedImagePropertyMap[Visual.Property.Type] = nPatch;
1459 PropertyValue border = new PropertyValue(_border);
1460 cachedImagePropertyMap[NpatchImageVisualProperty.Border] = border;
1465 if (backgroundExtraData != null && backgroundExtraData.CornerRadius != null)
1467 using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
1468 using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
1470 cachedImagePropertyMap[Visual.Property.CornerRadius] = cornerRadius;
1471 cachedImagePropertyMap[Visual.Property.CornerRadiusPolicy] = new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy));
1475 if (backgroundExtraData != null && backgroundExtraData.BorderlineWidth > 0.0f)
1477 using (var borderlineWidth = new PropertyValue(backgroundExtraData.BorderlineWidth))
1478 using (var borderlineColor = new PropertyValue(backgroundExtraData.BorderlineColor))
1479 using (var borderlineOffset = new PropertyValue(backgroundExtraData.BorderlineOffset))
1481 cachedImagePropertyMap[Visual.Property.BorderlineWidth] = borderlineWidth;
1482 cachedImagePropertyMap[Visual.Property.BorderlineColor] = borderlineColor;
1483 cachedImagePropertyMap[Visual.Property.BorderlineOffset] = borderlineOffset;
1487 // Do Fitting Buffer when desired dimension is set
1488 if (_desired_width != -1 && _desired_height != -1)
1490 if (_resourceUrl != null)
1492 Size2D imageSize = ImageLoader.GetOriginalImageSize(_resourceUrl, true);
1493 if( imageSize.Height > 0 && imageSize.Width > 0 && _desired_width > 0 && _desired_height > 0 )
1495 int adjustedDesiredWidth, adjustedDesiredHeight;
1496 float aspectOfDesiredSize = (float)_desired_height / (float)_desired_width;
1497 float aspectOfImageSize = (float)imageSize.Height / (float)imageSize.Width;
1498 if (aspectOfImageSize > aspectOfDesiredSize)
1500 adjustedDesiredWidth = _desired_width;
1501 adjustedDesiredHeight = imageSize.Height * _desired_width / imageSize.Width;
1505 adjustedDesiredWidth = imageSize.Width * _desired_height / imageSize.Height;
1506 adjustedDesiredHeight = _desired_height;
1509 PropertyValue returnWidth = new PropertyValue(adjustedDesiredWidth);
1510 cachedImagePropertyMap[ImageVisualProperty.DesiredWidth] = returnWidth;
1511 returnWidth?.Dispose();
1512 PropertyValue returnHeight = new PropertyValue(adjustedDesiredHeight);
1513 cachedImagePropertyMap[ImageVisualProperty.DesiredHeight] = returnHeight;
1514 returnHeight?.Dispose();
1515 PropertyValue scaleToFit = new PropertyValue((int)FittingModeType.ScaleToFill);
1516 cachedImagePropertyMap[ImageVisualProperty.FittingMode] = scaleToFit;
1517 scaleToFit?.Dispose();
1521 Tizen.Log.Fatal("NUI", "[ERROR] Can't use DesiredSize when ImageLoading is failed.");
1523 imageSize?.Dispose();
1531 /// Merge our collected properties, and set IMAGE property internally.
1533 private void UpdateImageMap()
1535 // Note : We can't use ImageView.Image property here. Because That property call UpdateImage internally.
1536 using(PropertyMap imageMap = new PropertyMap())
1538 using(PropertyValue returnValue = Tizen.NUI.Object.GetProperty(SwigCPtr, ImageView.Property.IMAGE))
1540 returnValue?.Get(imageMap);
1542 if(cachedImagePropertyMap != null)
1544 imageMap?.Merge(cachedImagePropertyMap);
1546 using(PropertyValue setValue = new PropertyValue(imageMap))
1548 SetProperty(ImageView.Property.IMAGE, setValue);
1551 // Update cached image property.
1552 MergeCachedImageVisualProperty(imageMap);
1557 /// Get image visual property by key.
1558 /// If we found value in local Cached result, return that.
1559 /// Else, get synced native map and return that.
1560 /// If there is no matched value, return null.
1562 [EditorBrowsable(EditorBrowsableState.Never)]
1563 protected virtual PropertyValue GetImageVisualProperty(int key)
1565 PropertyValue ret = GetCachedImageVisualProperty(key);
1568 // If we cannot find result form cached map, Get value from native engine.
1569 ret = Image?.Find(key);
1575 /// Get image visual property from NUI cached image map by key.
1576 /// If there is no matched value, return null.
1578 [EditorBrowsable(EditorBrowsableState.Never)]
1579 protected virtual PropertyValue GetCachedImageVisualProperty(int key)
1581 return cachedImagePropertyMap?.Find(key);
1585 /// Update NUI cached image visual property map by inputed property map.
1588 /// For performance issue, we will collect only "cachedImagePropertyKeyList" hold.
1590 [EditorBrowsable(EditorBrowsableState.Never)]
1591 protected virtual void MergeCachedImageVisualProperty(PropertyMap map)
1593 if(map == null) return;
1594 if(cachedImagePropertyMap == null)
1596 cachedImagePropertyMap = new PropertyMap();
1598 foreach(var key in cachedImagePropertyKeyList)
1600 PropertyValue value = map.Find(key);
1603 // Update-or-Insert new value
1604 cachedImagePropertyMap[key] = value;
1610 /// GetNaturalSize() should be guaranteed that ResourceUrl property setuped.
1611 /// So before get base.GetNaturalSize(), we should synchronous image properties
1613 internal override Vector3 GetNaturalSize()
1615 // Sync as current properties
1617 return base.GetNaturalSize();
1620 [EditorBrowsable(EditorBrowsableState.Never)]
1621 protected override bool CheckResourceReady()
1623 // If we have some properties to be updated, this signal is old thing.
1624 // We need to ignore current signal, and wait next.
1625 return !(imagePropertyUpdateProcessAttachedFlag && imagePropertyUpdatedFlag);
1628 private void OnResourceLoaded(IntPtr view)
1630 if(!CheckResourceReady())
1634 ResourceLoadedEventArgs e = new ResourceLoadedEventArgs();
1635 e.Status = (ResourceLoadingStatusType)Interop.View.GetVisualResourceStatus(this.SwigCPtr, Property.IMAGE);
1637 if (_resourceLoadedEventHandler != null)
1639 _resourceLoadedEventHandler(this, e);
1644 /// Event arguments of resource ready.
1646 /// <since_tizen> 3 </since_tizen>
1647 public class ResourceReadyEventArgs : EventArgs
1652 /// The view whose resource is ready.
1654 /// <since_tizen> 3 </since_tizen>
1668 internal class ResourceLoadedEventArgs : EventArgs
1670 private ResourceLoadingStatusType status = ResourceLoadingStatusType.Invalid;
1671 public ResourceLoadingStatusType Status
1684 internal new class Property
1686 internal static readonly int IMAGE = Interop.ImageView.ImageGet();
1687 internal static readonly int PreMultipliedAlpha = Interop.ImageView.PreMultipliedAlphaGet();
1688 internal static readonly int PixelArea = Interop.ImageView.PixelAreaGet();
1691 private enum ImageType
1694 /// For Normal Image.
1699 /// For normal image, with synchronous loading and orientation correction property
1704 /// For nine-patch image
1709 private void OnBorderChanged(int x, int y, int width, int height)
1711 Border = new Rectangle(x, y, width, height);
1713 private void OnPixelAreaChanged(float x, float y, float z, float w)
1715 PixelArea = new RelativeVector4(x, y, z, w);
1718 private class ImageLayout : LayoutItem
1721 /// Gets or sets the mode to adjust view size to preserve the aspect ratio of the image resource.
1722 /// 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.
1724 [EditorBrowsable(EditorBrowsableState.Never)]
1725 public bool AdjustViewSize
1729 return (Owner as ImageView)?.AdjustViewSize ?? false;
1733 if (Owner is ImageView imageView)
1735 imageView.AdjustViewSize = value;
1741 [EditorBrowsable(EditorBrowsableState.Never)]
1742 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
1744 // To not change the view size by DALi
1745 Owner.WidthResizePolicy = ResizePolicyType.Fixed;
1746 Owner.HeightResizePolicy = ResizePolicyType.Fixed;
1748 float specWidth = widthMeasureSpec.Size.AsDecimal();
1749 float specHeight = heightMeasureSpec.Size.AsDecimal();
1750 float naturalWidth = Owner.NaturalSize.Width;
1751 float naturalHeight = Owner.NaturalSize.Height;
1752 float minWidth = Owner.MinimumSize.Width;
1753 float maxWidth = Owner.MaximumSize.Width;
1754 float minHeight = Owner.MinimumSize.Height;
1755 float maxHeight = Owner.MaximumSize.Height;
1756 float aspectRatio = (naturalWidth > 0) ? (naturalHeight / naturalWidth) : 0;
1758 // Assume that the new width and height are given from the view's suggested size by default.
1759 float newWidth = Math.Min(Math.Max(naturalWidth, minWidth), (maxWidth < 0 ? Int32.MaxValue : maxWidth));
1760 float newHeight = Math.Min(Math.Max(naturalHeight, minHeight), (maxHeight < 0 ? Int32.MaxValue : maxHeight));
1762 // The width and height measure specs are going to be used to set measured size.
1763 // Mark that the measure specs are changed by default to update measure specs later.
1764 bool widthSpecChanged = true;
1765 bool heightSpecChanged = true;
1767 if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1769 newWidth = specWidth;
1770 widthSpecChanged = false;
1772 if (heightMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1774 if ((AdjustViewSize) && (aspectRatio > 0))
1776 newHeight = newWidth * aspectRatio;
1781 if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly)
1783 newHeight = specHeight;
1784 heightSpecChanged = false;
1786 if (widthMeasureSpec.Mode != MeasureSpecification.ModeType.Exactly)
1788 if ((AdjustViewSize) && (aspectRatio > 0))
1790 newWidth = newHeight / aspectRatio;
1795 if (widthSpecChanged)
1797 widthMeasureSpec = new MeasureSpecification(new LayoutLength(newWidth), MeasureSpecification.ModeType.Exactly);
1800 if (heightSpecChanged)
1802 heightMeasureSpec = new MeasureSpecification(new LayoutLength(newHeight), MeasureSpecification.ModeType.Exactly);
1805 MeasuredSize.StateType childWidthState = MeasuredSize.StateType.MeasuredSizeOK;
1806 MeasuredSize.StateType childHeightState = MeasuredSize.StateType.MeasuredSizeOK;
1808 SetMeasuredDimensions(ResolveSizeAndState(new LayoutLength(newWidth), widthMeasureSpec, childWidthState),
1809 ResolveSizeAndState(new LayoutLength(newHeight), heightMeasureSpec, childHeightState));