File: Layout\FlexLayout.cs
Web Access
Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls)
#nullable disable
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Layouts;
using Flex = Microsoft.Maui.Layouts.Flex;
 
namespace Microsoft.Maui.Controls
{
	/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="Type[@FullName='Microsoft.Maui.Controls.FlexLayout']/Docs/*" />
	[ContentProperty(nameof(Children))]
	public class FlexLayout : Layout, IFlexLayout
	{
		Flex.Item _root;
 
		/// <summary>Bindable property for attached property <see cref="Direction"/>.</summary>
		public static readonly BindableProperty DirectionProperty =
			BindableProperty.Create(nameof(Direction), typeof(FlexDirection), typeof(FlexLayout), FlexDirection.Row,
									propertyChanged: OnDirectionPropertyChanged);
 
		/// <summary>Bindable property for attached property <see cref="JustifyContent"/>.</summary>
		public static readonly BindableProperty JustifyContentProperty =
			BindableProperty.Create(nameof(JustifyContent), typeof(FlexJustify), typeof(FlexLayout), FlexJustify.Start,
									propertyChanged: OnJustifyContentPropertyChanged);
 
		/// <summary>Bindable property for attached property <see cref="AlignContent"/>.</summary>
		public static readonly BindableProperty AlignContentProperty =
			BindableProperty.Create(nameof(AlignContent), typeof(FlexAlignContent), typeof(FlexLayout), FlexAlignContent.Stretch,
									propertyChanged: OnAlignContentPropertyChanged);
 
		/// <summary>Bindable property for attached property <see cref="AlignItems"/>.</summary>
		public static readonly BindableProperty AlignItemsProperty =
			BindableProperty.Create(nameof(AlignItems), typeof(FlexAlignItems), typeof(FlexLayout), FlexAlignItems.Stretch,
									propertyChanged: OnAlignItemsPropertyChanged);
 
		/// <summary>Bindable property for attached property <see cref="Position"/>.</summary>
		public static readonly BindableProperty PositionProperty =
			BindableProperty.Create(nameof(Position), typeof(FlexPosition), typeof(FlexLayout), FlexPosition.Relative,
									propertyChanged: OnPositionPropertyChanged);
 
		/// <summary>Bindable property for attached property <see cref="Wrap"/>.</summary>
		public static readonly BindableProperty WrapProperty =
			BindableProperty.Create(nameof(Wrap), typeof(FlexWrap), typeof(FlexLayout), FlexWrap.NoWrap,
									propertyChanged: OnWrapPropertyChanged);
 
		/// <summary>Bindable property for attached property <c>Order</c>.</summary>
		public static readonly BindableProperty OrderProperty =
			BindableProperty.CreateAttached("Order", typeof(int), typeof(FlexLayout), default(int),
											propertyChanged: OnOrderPropertyChanged);
 
		/// <summary>Bindable property for attached property <c>Grow</c>.</summary>
		public static readonly BindableProperty GrowProperty =
			BindableProperty.CreateAttached("Grow", typeof(float), typeof(FlexLayout), default(float),
											propertyChanged: OnGrowPropertyChanged, validateValue: (bindable, value) => (float)value >= 0);
 
		/// <summary>Bindable property for attached property <c>Shrink</c>.</summary>
		public static readonly BindableProperty ShrinkProperty =
			BindableProperty.CreateAttached("Shrink", typeof(float), typeof(FlexLayout), 1f,
											propertyChanged: OnShrinkPropertyChanged, validateValue: (bindable, value) => (float)value >= 0);
 
		/// <summary>Bindable property for attached property <c>AlignSelf</c>.</summary>
		public static readonly BindableProperty AlignSelfProperty =
			BindableProperty.CreateAttached("AlignSelf", typeof(FlexAlignSelf), typeof(FlexLayout), FlexAlignSelf.Auto,
											propertyChanged: OnAlignSelfPropertyChanged);
 
		/// <summary>Bindable property for attached property <c>Basis</c>.</summary>
		public static readonly BindableProperty BasisProperty =
			BindableProperty.CreateAttached("Basis", typeof(FlexBasis), typeof(FlexLayout), FlexBasis.Auto,
											propertyChanged: OnBasisPropertyChanged);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='Direction']/Docs/*" />
		public FlexDirection Direction
		{
			get => (FlexDirection)GetValue(DirectionProperty);
			set => SetValue(DirectionProperty, value);
		}
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='JustifyContent']/Docs/*" />
		public FlexJustify JustifyContent
		{
			get => (FlexJustify)GetValue(JustifyContentProperty);
			set => SetValue(JustifyContentProperty, value);
		}
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='AlignContent']/Docs/*" />
		public FlexAlignContent AlignContent
		{
			get => (FlexAlignContent)GetValue(AlignContentProperty);
			set => SetValue(AlignContentProperty, value);
		}
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='AlignItems']/Docs/*" />
		public FlexAlignItems AlignItems
		{
			get => (FlexAlignItems)GetValue(AlignItemsProperty);
			set => SetValue(AlignItemsProperty, value);
		}
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='Position']/Docs/*" />
		public FlexPosition Position
		{
			get => (FlexPosition)GetValue(PositionProperty);
			set => SetValue(PositionProperty, value);
		}
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='Wrap']/Docs/*" />
		public FlexWrap Wrap
		{
			get => (FlexWrap)GetValue(WrapProperty);
			set => SetValue(WrapProperty, value);
		}
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='GetOrder'][1]/Docs/*" />
		public static int GetOrder(BindableObject bindable)
			=> (int)bindable.GetValue(OrderProperty);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='SetOrder'][1]/Docs/*" />
		public static void SetOrder(BindableObject bindable, int value)
			=> bindable.SetValue(OrderProperty, value);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='GetGrow'][1]/Docs/*" />
		public static float GetGrow(BindableObject bindable)
			=> (float)bindable.GetValue(GrowProperty);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='SetGrow'][1]/Docs/*" />
		public static void SetGrow(BindableObject bindable, float value)
			=> bindable.SetValue(GrowProperty, value);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='GetShrink'][1]/Docs/*" />
		public static float GetShrink(BindableObject bindable)
			=> (float)bindable.GetValue(ShrinkProperty);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='SetShrink'][1]/Docs/*" />
		public static void SetShrink(BindableObject bindable, float value)
			=> bindable.SetValue(ShrinkProperty, value);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='GetAlignSelf'][1]/Docs/*" />
		public static FlexAlignSelf GetAlignSelf(BindableObject bindable)
			=> (FlexAlignSelf)bindable.GetValue(AlignSelfProperty);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='SetAlignSelf'][1]/Docs/*" />
		public static void SetAlignSelf(BindableObject bindable, FlexAlignSelf value)
			=> bindable.SetValue(AlignSelfProperty, value);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='GetBasis'][1]/Docs/*" />
		public static FlexBasis GetBasis(BindableObject bindable)
			=> (FlexBasis)bindable.GetValue(BasisProperty);
 
		/// <include file="../../../docs/Microsoft.Maui.Controls/FlexLayout.xml" path="//Member[@MemberName='SetBasis'][1]/Docs/*" />
		public static void SetBasis(BindableObject bindable, FlexBasis value)
			=> bindable.SetValue(BasisProperty, value);
 
		static readonly BindableProperty FlexItemProperty =
			BindableProperty.CreateAttached("FlexItem", typeof(Flex.Item), typeof(FlexLayout), null);
 
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		static Flex.Item GetFlexItem(BindableObject bindable)
			=> (Flex.Item)bindable.GetValue(FlexItemProperty);
 
		static void OnOrderPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			if (!bindable.IsSet(FlexItemProperty))
				return;
			GetFlexItem(bindable).Order = (int)newValue;
			((VisualElement)bindable).InvalidateMeasureInternal(InvalidationTrigger.Undefined);
		}
 
		static void OnGrowPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			if (!bindable.IsSet(FlexItemProperty))
				return;
			GetFlexItem(bindable).Grow = (float)newValue;
			((VisualElement)bindable).InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
		}
 
		static void OnShrinkPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			if (!bindable.IsSet(FlexItemProperty))
				return;
			GetFlexItem(bindable).Shrink = (float)newValue;
			((VisualElement)bindable).InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
		}
 
		static void OnAlignSelfPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			if (!bindable.IsSet(FlexItemProperty))
				return;
			GetFlexItem(bindable).AlignSelf = (Flex.AlignSelf)(FlexAlignSelf)newValue;
			((VisualElement)bindable).InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
		}
 
		static void OnBasisPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			if (!bindable.IsSet(FlexItemProperty))
				return;
			GetFlexItem(bindable).Basis = ((FlexBasis)newValue).ToFlexBasis();
			((VisualElement)bindable).InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
		}
 
		static void OnDirectionPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var flexLayout = bindable as FlexLayout;
			if (flexLayout._root == null)
				return;
			flexLayout._root.Direction = (Flex.Direction)(FlexDirection)newValue;
			flexLayout.InvalidateMeasure();
		}
 
		static void OnJustifyContentPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var flexLayout = bindable as FlexLayout;
			if (flexLayout._root == null)
				return;
			flexLayout._root.JustifyContent = (Flex.Justify)(FlexJustify)newValue;
			flexLayout.InvalidateMeasure();
		}
 
		static void OnAlignContentPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var flexLayout = bindable as FlexLayout;
			if (flexLayout._root == null)
				return;
			flexLayout._root.AlignContent = (Flex.AlignContent)(FlexAlignContent)newValue;
			flexLayout.InvalidateMeasure();
		}
 
		static void OnAlignItemsPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var flexLayout = (FlexLayout)bindable;
			if (flexLayout._root == null)
				return;
			flexLayout._root.AlignItems = (Flex.AlignItems)(FlexAlignItems)newValue;
			flexLayout.InvalidateMeasure();
		}
 
		static void OnPositionPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var flexLayout = (FlexLayout)bindable;
			if (flexLayout._root == null)
				return;
			flexLayout._root.Position = (Flex.Position)(FlexPosition)newValue;
			flexLayout.InvalidateMeasure();
		}
 
		static void OnWrapPropertyChanged(BindableObject bindable, object oldValue, object newValue)
		{
			var flexLayout = bindable as FlexLayout;
			if (flexLayout._root == null)
				return;
			flexLayout._root.Wrap = (Flex.Wrap)(FlexWrap)newValue;
			flexLayout.InvalidateMeasure();
		}
 
		readonly Dictionary<IView, FlexInfo> _viewInfo = new();
 
		class FlexInfo
		{
			public int Order { get; set; }
			public float Grow { get; set; }
			public float Shrink { get; set; }
			public FlexAlignSelf AlignSelf { get; set; }
			public FlexBasis Basis { get; set; }
			public Flex.Item FlexItem { get; set; }
		}
 
		public int GetOrder(IView view)
		{
			return view switch
			{
				BindableObject bo => (int)bo.GetValue(OrderProperty),
				_ => _viewInfo[view].Order,
			};
		}
 
		public void SetOrder(IView view, int order)
		{
			switch (view)
			{
				case BindableObject bo:
					bo.SetValue(OrderProperty, order);
					break;
				default:
					_viewInfo[view].Order = order;
					break;
			}
		}
 
		public float GetGrow(IView view)
		{
			return view switch
			{
				BindableObject bo => (float)bo.GetValue(GrowProperty),
				_ => _viewInfo[view].Grow,
			};
		}
 
		public void SetGrow(IView view, float grow)
		{
			switch (view)
			{
				case BindableObject bo:
					bo.SetValue(GrowProperty, grow);
					break;
				default:
					_viewInfo[view].Grow = grow;
					break;
			}
		}
 
		public float GetShrink(IView view)
		{
			return view switch
			{
				BindableObject bo => (float)bo.GetValue(ShrinkProperty),
				_ => _viewInfo[view].Shrink,
			};
		}
 
		public void SetShrink(IView view, float shrink)
		{
			switch (view)
			{
				case BindableObject bo:
					bo.SetValue(ShrinkProperty, shrink);
					break;
				default:
					_viewInfo[view].Shrink = shrink;
					break;
			}
		}
 
		public FlexAlignSelf GetAlignSelf(IView view)
		{
			return view switch
			{
				BindableObject bo => (FlexAlignSelf)bo.GetValue(AlignSelfProperty),
				_ => _viewInfo[view].AlignSelf,
			};
		}
 
		public void SetAlignSelf(IView view, FlexAlignSelf alignSelf)
		{
			switch (view)
			{
				case BindableObject bo:
					bo.SetValue(AlignSelfProperty, alignSelf);
					break;
				default:
					_viewInfo[view].AlignSelf = alignSelf;
					break;
			}
		}
 
		public FlexBasis GetBasis(IView view)
		{
			return view switch
			{
				BindableObject bo => (FlexBasis)bo.GetValue(BasisProperty),
				_ => _viewInfo[view].Basis,
			};
		}
 
		public void SetBasis(IView view, FlexBasis basis)
		{
			switch (view)
			{
				case BindableObject bo:
					bo.SetValue(BasisProperty, basis);
					break;
				default:
					_viewInfo[view].Basis = basis;
					break;
			}
		}
 
		internal Flex.Item GetFlexItem(IView view)
		{
			return view switch
			{
				BindableObject bo => (Flex.Item)bo.GetValue(FlexItemProperty),
				_ => _viewInfo[view].FlexItem,
			};
		}
 
		void SetFlexItem(IView view, Flex.Item flexItem)
		{
			switch (view)
			{
				case BindableObject bo:
					bo.SetValue(FlexItemProperty, flexItem);
					break;
				default:
					_viewInfo[view].FlexItem = flexItem;
					break;
			}
		}
 
		Thickness GetMargin(IView view)
		{
			return view switch
			{
				BindableObject bo => (Thickness)bo.GetValue(MarginProperty),
				_ => view.Margin
			};
		}
 
		double GetWidth(IView view)
		{
			return view switch
			{
				BindableObject bo => (double)bo.GetValue(WidthRequestProperty),
				_ => view.Width
			};
		}
 
		double GetHeight(IView view)
		{
			return view switch
			{
				BindableObject bo => (double)bo.GetValue(HeightRequestProperty),
				_ => view.Height
			};
		}
 
		bool GetIsVisible(IView view)
		{
			return view switch
			{
				BindableObject bo => (bool)bo.GetValue(IsVisibleProperty),
				_ => view.Visibility != Visibility.Collapsed
			};
		}
 
		void InitItemProperties(IView view, Flex.Item item)
		{
			item.Order = GetOrder(view);
			item.Grow = GetGrow(view);
			item.Shrink = GetShrink(view);
			item.Basis = GetBasis(view).ToFlexBasis();
			item.AlignSelf = (Flex.AlignSelf)GetAlignSelf(view);
			var (mleft, mtop, mright, mbottom) = GetMargin(view);
			item.MarginLeft = (float)mleft;
			item.MarginTop = (float)mtop;
			item.MarginRight = (float)mright;
			item.MarginBottom = (float)mbottom;
			var width = GetWidth(view);
			item.Width = width < 0 ? float.NaN : (float)width;
			var height = GetHeight(view);
			item.Height = height < 0 ? float.NaN : (float)height;
			item.IsVisible = GetIsVisible(view);
 
			if (view is IPadding viewWithPadding)
			{
				var (pleft, ptop, pright, pbottom) = viewWithPadding.Padding;
				item.PaddingLeft = (float)pleft;
				item.PaddingTop = (float)ptop;
				item.PaddingRight = (float)pright;
				item.PaddingBottom = (float)pbottom;
			}
		}
 
		// Until we can rewrite the FlexLayout engine to handle measurement properly (without the "in measure mode" hacks)
		// we need to replace the default implementation of CrossPlatformMeasure.
		// And we need to disable the public API analyzer briefly, because it doesn't understand hiding.
#pragma warning disable RS0016 // Add public types and members to the declared API
		new public Graphics.Size CrossPlatformMeasure(double widthConstraint, double heightConstraint)
#pragma warning restore RS0016 // Add public types and members to the declared API
		{
			var layoutManager = _layoutManager ??= CreateLayoutManager();
 
			InMeasureMode = true;
			var result = layoutManager.Measure(widthConstraint, heightConstraint);
			InMeasureMode = false;
 
			return result;
		}
 
		internal bool InMeasureMode { get; set; }
 
		void AddFlexItem(int index, IView child)
		{
			if (_root == null)
				return;
 
			if (child is not BindableObject)
			{
				// If this is a pure Core IView, we need to track all the flex properties
				// locally because we don't have attached properties for them
				_viewInfo.Add(child, new FlexInfo());
			}
 
			var item = (child as FlexLayout)?._root ?? new Flex.Item();
			InitItemProperties(child, item);
			if (child is not FlexLayout)
			{
				item.SelfSizing = (Flex.Item it, ref float w, ref float h, bool inMeasureMode) =>
				{
					Size request;
 
					if (inMeasureMode)
					{
						var sizeConstraints = item.GetConstraints();
 
						sizeConstraints.Width = (inMeasureMode && sizeConstraints.Width == 0) ? double.PositiveInfinity : sizeConstraints.Width;
						sizeConstraints.Height = (inMeasureMode && sizeConstraints.Height == 0) ? double.PositiveInfinity : sizeConstraints.Height;
 
						if (child is Image)
						{
							// This is a hack to get FlexLayout to behave like it did in Forms
							// Forms always did its initial image measure unconstrained, which would return
							// the intrinsic size of the image (no scaling or aspect ratio adjustments)
 
							sizeConstraints.Width = double.PositiveInfinity;
							sizeConstraints.Height = double.PositiveInfinity;
						}
 
						request = child.Measure(sizeConstraints.Width, sizeConstraints.Height);
					}
					else
					{
						// Arrange pass, do not ever run a measure here!
						request = child.DesiredSize;
					}
					w = (float)request.Width;
					h = (float)request.Height;
				};
			}
 
			_root.InsertAt(index, item);
			SetFlexItem(child, item);
		}
 
		void RemoveFlexItem(IView child)
		{
			if (_root == null)
				return;
 
			var item = GetFlexItem(child);
			_root.Remove(item);
 
			switch (child)
			{
				case BindableObject bo:
					bo.ClearValue(FlexItemProperty);
					break;
				default:
					_viewInfo.Remove(child);
					break;
			}
		}
 
		protected override ILayoutManager CreateLayoutManager()
		{
			return new FlexLayoutManager(this);
		}
 
		public Graphics.Rect GetFlexFrame(IView view) =>
			GetFlexItem(view).GetFrame();
 
		void EnsureFlexItemPropertiesUpdated()
		{
			for (int n = 0; n < this.Count; n++)
			{
				var child = this[n];
				var flexItem = GetFlexItem(child);
 
				InitItemProperties(child, flexItem);
			}
		}
 
		public void Layout(double width, double height)
		{
			if (_root.Parent != null)   //Layout is only computed at root level
				return;
 
			var useMeasureHack = NeedsMeasureHack(width, height);
			if (useMeasureHack)
			{
				PrepareMeasureHack();
			}
 
			EnsureFlexItemPropertiesUpdated();
 
			_root.Width = !double.IsPositiveInfinity((width)) ? (float)width : 0;
			_root.Height = !double.IsPositiveInfinity((height)) ? (float)height : 0;
			_root.Layout(InMeasureMode);
 
			if (useMeasureHack)
			{
				RestoreValues();
			}
		}
 
		protected override void OnParentSet()
		{
			base.OnParentSet();
			if (Parent != null && _root == null)
				PopulateLayout();
			else if (Parent == null && _root != null)
				ClearLayout();
		}
 
		void PopulateLayout()
		{
			InitLayoutProperties(_root = new Flex.Item());
			for (var i = 0; i < Children.Count; i++)
			{
				AddFlexItem(i, Children[i]);
			}
		}
 
		void ClearLayout()
		{
			foreach (var child in Children)
				RemoveFlexItem(child);
			_root = null;
		}
 
		void InitLayoutProperties(Flex.Item item)
		{
			item.AlignContent = (Flex.AlignContent)(FlexAlignContent)GetValue(AlignContentProperty);
			item.AlignItems = (Flex.AlignItems)(FlexAlignItems)GetValue(AlignItemsProperty);
			item.Direction = (Flex.Direction)(FlexDirection)GetValue(DirectionProperty);
			item.JustifyContent = (Flex.Justify)(FlexJustify)GetValue(JustifyContentProperty);
			item.Wrap = (Flex.Wrap)(FlexWrap)GetValue(WrapProperty);
		}
 
		protected override void OnAdd(int index, IView view)
		{
			AddFlexItem(index, view);
			base.OnAdd(index, view);
		}
 
		protected override void OnInsert(int index, IView view)
		{
			AddFlexItem(index, view);
			base.OnInsert(index, view);
		}
 
		protected override void OnUpdate(int index, IView view, IView oldView)
		{
			RemoveFlexItem(oldView);
			AddFlexItem(index, view);
			base.OnUpdate(index, view, oldView);
		}
 
		protected override void OnRemove(int index, IView view)
		{
			base.OnRemove(index, view);
			RemoveFlexItem(view);
		}
 
		protected override void OnClear()
		{
			base.OnClear();
			ClearLayout();
			PopulateLayout();
		}
 
		static bool NeedsMeasureHack(double widthConstraint, double heightConstraint)
		{
			return double.IsInfinity(widthConstraint) || double.IsInfinity(heightConstraint);
		}
 
		void PrepareMeasureHack()
		{
			// FlexLayout's Shrink and Stretch features require a fixed area to measure/layout correctly;
			// when the dimensions they are working in are infinite, they don't really make sense. We can
			// get a sensible measure by temporarily setting the Shrink values of all items to 0 and the 
			// Stretch alignment values to Start. So we prepare for that here.
 
			foreach (var child in Children)
			{
				if (GetFlexItem(child) is Flex.Item item)
				{
					item.Shrink = 0;
					item.AlignSelf = Flex.AlignSelf.Start;
				}
			}
		}
 
		void RestoreValues()
		{
			// If we had to modify the Shrink and Stretch values of the FlexItems for measurement, we 
			// restore them to their original values.
 
			foreach (var child in Children)
			{
				if (GetFlexItem(child) is Flex.Item item)
				{
					item.Shrink = GetShrink(child);
					item.AlignSelf = (Flex.AlignSelf)GetAlignSelf(child);
				}
			}
		}
	}
}