/// <summary> /// Prepares the grid's rows or columns for measurement. /// </summary> /// <param name="definitions">The collection of row or column definitions to prepare for measurement.</param> /// <param name="infiniteDimension">A value indicating whether the constraint for this dimension is infinite.</param> private void PrepareForMeasure(IDefinitionBaseCollection definitions, Boolean infiniteDimension) { for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; var dim = 0.0; var dimMin = def.MinDimension; var dimMax = Math.Max(dimMin, def.MaxDimension); switch (def.Dimension.GridUnitType) { case GridUnitType.Auto: def.AssumedUnitType = GridUnitType.Auto; dim = Double.PositiveInfinity; break; case GridUnitType.Pixel: def.AssumedUnitType = GridUnitType.Pixel; dim = def.Dimension.Value; dimMin = Math.Max(dimMin, Math.Min(dim, dimMax)); break; case GridUnitType.Star: def.AssumedUnitType = infiniteDimension ? GridUnitType.Auto : GridUnitType.Star; dim = Double.PositiveInfinity; break; } def.ResetContentDimension(dimMin); def.MeasuredDimension = Math.Max(dimMin, Math.Min(dim, dimMax)); } }
/// <summary> /// Retrieves a buffer containing all of the row/column definitions in the specified span. /// </summary> /// <param name="definitions">The collection of definitions from which to retrieve the span.</param> /// <param name="index">The index of the first definition in the span.</param> /// <param name="span">The number of definitions in the span.</param> /// <param name="auto">A value indicating whether to include auto-sized definitions.</param> /// <param name="nonauto">A value indicating whether to include non-auto-sized definitions.</param> /// <returns>A buffer containing the specified span of row/column definitions.</returns> private List <DefinitionBase> EnumerateDefinitionsInSpan(IDefinitionBaseCollection definitions, Int32 index, Int32 span, Boolean auto = true, Boolean nonauto = true) { spanEnumerationBuffer.Clear(); for (int i = 0; i < span; i++) { var def = definitions[index + i]; switch (def.AssumedUnitType) { case GridUnitType.Auto: if (auto) { spanEnumerationBuffer.Add(def); } break; case GridUnitType.Pixel: case GridUnitType.Star: if (nonauto) { spanEnumerationBuffer.Add(def); } break; } } return(spanEnumerationBuffer); }
/// <summary> /// Resolves the size of the grid's star-sized rows or columns. /// </summary> /// <param name="definitions">The collection of rows or columns to resolve.</param> /// <param name="availableDimension">The amount of space which is available to the grid.</param> private void ResolveStars(IDefinitionBaseCollection definitions, Double availableDimension) { if ((definitions == RowDefinitions && starRowCount == 0) || (definitions == ColumnDefinitions && starColumnCount == 0)) { return; } availableDimension -= CalculateUsedDimension(definitions); var sumOfStarFactors = 0.0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType != GridUnitType.Star) { continue; } sumOfStarFactors += def.Dimension.Value; } var starFactorUnit = (sumOfStarFactors == 0) ? 0 : availableDimension / sumOfStarFactors; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType != GridUnitType.Star) { continue; } def.MeasuredDimension = Math.Max(0, starFactorUnit * def.Dimension.Value); } }
/// <summary> /// Performs layout rounding on the specified definition collection. /// </summary> /// <param name="definitions">The definition collection on which to perform layout rounding.</param> private void RoundDimensions(IDefinitionBaseCollection definitions) { if (definitions.Count == 0) { return; } var errorContent = 0.0; var error = 0.0; for (int i = 0; i < definitions.Count - 1; i++) { var oldValueContent = definitions[i].MeasuredContentDimension; var oldValue = definitions[i].MeasuredDimension; if (!Double.IsInfinity(oldValueContent)) { definitions[i].MeasuredContentDimension = PerformLayoutRounding(oldValueContent); errorContent += (definitions[i].MeasuredContentDimension - oldValueContent); } if (!Double.IsInfinity(oldValue)) { definitions[i].MeasuredDimension = PerformLayoutRounding(oldValue); error += (definitions[i].MeasuredDimension - oldValue); } } definitions[definitions.Count - 1].MeasuredContentDimension += errorContent; definitions[definitions.Count - 1].MeasuredDimension += error; }
/// <summary> /// Prepares the grid's rows or columns for arrangement. /// </summary> /// <param name="definitions">The collection of row or column definitions to prepare for measurement.</param> private void PrepareForArrange(IDefinitionBaseCollection definitions) { for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; def.AssumedUnitType = def.Dimension.GridUnitType; } }
/// <summary> /// Measures the total dimension of the specified row or column span. /// </summary> /// <param name="definitions">The collection of row or column definitions for which to calculate a total dimension.</param> /// <param name="index">The index of the first row or column in the span.</param> /// <param name="span">The number of rows or columns in the span.</param> /// <returns>The total dimension of the specified row or column span.</returns> private Double CalculateSpanDimension(IDefinitionBaseCollection definitions, Int32 index, Int32 span) { var size = 0.0; for (int i = 0; i < span; i++) { size += definitions[index + i].ActualDimension; } return(size); }
/// <summary> /// Retrieves a buffer containing all of the specified definitions, sorted by their minimum arranged size. /// </summary> private List <DefinitionBase> EnumerateDefinitionsByMinArrangedSize(IDefinitionBaseCollection definitions) { spanEnumerationBuffer.Clear(); for (int i = 0; i < definitions.Count; i++) { spanEnumerationBuffer.Add(definitions[i]); } spanEnumerationBuffer.Sort(cmpByMinArrangedSize); return(spanEnumerationBuffer); }
/// <summary> /// Finalizes the dimension of the grid's rows or columns during the arrange phase. /// </summary> /// <param name="dimension">The collection of row or column definitions to finalize.</param> /// <param name="definitions">The grid's final arranged dimension.</param> private void FinalizeDimension(IDefinitionBaseCollection definitions, Double dimension) { FinalizeStars(definitions, dimension); var position = 0.0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; def.Position = position; position += def.ActualDimension; } }
/// <summary> /// Retrieves a buffer containing all of the specified definitions, sorted by their minimum arranged size. /// </summary> private List <DefinitionBase> EnumerateDefinitionsByMinArrangedSize(IDefinitionBaseCollection definitions) { spanEnumerationBuffer.Clear(); for (int i = 0; i < definitions.Count; i++) { spanEnumerationBuffer.Add(definitions[i]); } spanEnumerationBuffer.Sort((def1, def2) => { var def1Min = Math.Max(def1.MinDimension, def1.MeasuredContentDimension); var def2Min = Math.Max(def2.MinDimension, def2.MeasuredContentDimension); return(def2Min.CompareTo(def1Min)); }); return(spanEnumerationBuffer); }
/// <summary> /// Gets the number of definitions in the specified collection with a unit /// type of <see cref="GridUnitType.Star"/>. /// </summary> private Int32 CountStars(IDefinitionBaseCollection definitions) { var count = 0; if (definitions != null) { for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType == GridUnitType.Star) { count++; } } } return(count); }
/// <summary> /// Measures the total amount of space which is occupied by non-star rows or columns in the specified collection. /// </summary> /// <param name="definitions">The collection of row or column definitions for which to calculate a used dimension.</param> /// <returns>The total amount of space which is occupied by non-star columns in <paramref name="definitions"/>.</returns> private Double CalculateUsedDimension(IDefinitionBaseCollection definitions) { var dimension = 0.0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; switch (def.AssumedUnitType) { case GridUnitType.Auto: case GridUnitType.Pixel: dimension += def.ActualDimension; break; } } return(dimension); }
/// <summary> /// Finalizes the dimensions of the grid's star rows or columns. /// </summary> /// <param name="dimension">The collection of row or column definitions to finalize.</param> /// <param name="definitions">The grid's final arranged dimension.</param> private void FinalizeStars(IDefinitionBaseCollection definitions, Double dimension) { var undistributed = dimension - CalculateUsedDimension(definitions); var starCombinedWeight = 0.0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType == GridUnitType.Star) { starCombinedWeight += def.Dimension.Value; } } if (starCombinedWeight <= 0) { return; } var starCountVisited = 0.0; var buffer = EnumerateDefinitionsByMinArrangedSize(definitions); for (int i = 0; i < buffer.Count; i++) { var def = buffer[i]; if (def.AssumedUnitType != GridUnitType.Star) { continue; } var defShare = def.Dimension.Value * (undistributed / (starCombinedWeight - starCountVisited)); var defMinSize = Math.Max(def.MinDimension, def.MeasuredContentDimension); var defDimension = Math.Max(defMinSize, Math.Max(0, Math.Min(defShare, def.MaxDimension))); def.MeasuredDimension = Math.Min(undistributed, defDimension); undistributed -= defDimension; starCountVisited += def.Dimension.Value; } buffer.Clear(); }
/// <summary> /// Finalizes the dimensions of the grid's star rows or columns. /// </summary> /// <param name="dimension">The collection of row or column definitions to finalize.</param> /// <param name="definitions">The grid's final arranged dimension.</param> private void FinalizeStars(IDefinitionBaseCollection definitions, Double dimension) { var undistributed = dimension - CalculateUsedDimension(definitions); var starCombinedWeight = 0.0; var starCount = 0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType == GridUnitType.Star) { starCount++; starCombinedWeight += def.Dimension.Value; } } if (starCount == 0 || starCombinedWeight == 0) { return; } var starCountVisited = 0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType != GridUnitType.Star) { continue; } var defShare = undistributed / (starCount - starCountVisited); var defDimension = Math.Max(0, Math.Min(defShare, def.MaxDimension)); def.MeasuredDimension = defDimension; undistributed -= defDimension; starCountVisited++; } }
/// <summary> /// Finalizes the dimensions of the grid's star rows or columns. /// </summary> /// <param name="dimension">The collection of row or column definitions to finalize.</param> /// <param name="definitions">The grid's final arranged dimension.</param> private void FinalizeStars(IDefinitionBaseCollection definitions, Double dimension) { var undistributed = dimension - CalculateUsedDimension(definitions); var starCombinedWeight = 0.0; var starCount = 0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType == GridUnitType.Star) { starCount++; starCombinedWeight += def.Dimension.Value; } } if (starCount == 0 || starCombinedWeight == 0) return; var starCountVisited = 0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType != GridUnitType.Star) continue; var defShare = undistributed / (starCount - starCountVisited); var defDimension = Math.Max(0, Math.Min(defShare, def.MaxDimension)); def.MeasuredDimension = defDimension; undistributed -= defDimension; starCountVisited++; } }
/// <summary> /// Retrieves a buffer containing all of the row/column definitions in the specified span. /// </summary> /// <param name="definitions">The collection of definitions from which to retrieve the span.</param> /// <param name="index">The index of the first definition in the span.</param> /// <param name="span">The number of definitions in the span.</param> /// <param name="auto">A value indicating whether to include auto-sized definitions.</param> /// <param name="nonauto">A value indicating whether to include non-auto-sized definitions.</param> /// <returns>A buffer containing the specified span of row/column definitions.</returns> private List<DefinitionBase> EnumerateDefinitionsInSpan(IDefinitionBaseCollection definitions, Int32 index, Int32 span, Boolean auto = true, Boolean nonauto = true) { spanEnumerationBuffer.Clear(); for (int i = 0; i < span; i++) { var def = definitions[index + i]; switch (def.AssumedUnitType) { case GridUnitType.Auto: if (auto) { spanEnumerationBuffer.Add(def); } break; case GridUnitType.Pixel: case GridUnitType.Star: if (nonauto) { spanEnumerationBuffer.Add(def); } break; } } return spanEnumerationBuffer; }
/// <summary> /// Retrieves a buffer containing all of the non-auto-sized row/column definitions in the specified span. /// The buffer is sorted in ascending order of <see cref="DefinitionBase.MaxDimension"/>. /// </summary> /// <param name="definitions">The collection of definitions from which to retrieve the span.</param> /// <param name="index">The index of the first definition in the span.</param> /// <param name="span">The number of definitions in the span.</param> /// <returns>A buffer containing the specified span of row/column definitions.</returns> private List<DefinitionBase> EnumerateNonAutoDefinitionsInSpanByMaxDimension(IDefinitionBaseCollection definitions, Int32 index, Int32 span) { var buffer = EnumerateDefinitionsInSpan(definitions, index, span, auto: false); buffer.Sort((def1, def2) => { return def1.MaxDimension.CompareTo(def2.MaxDimension); }); return buffer; }
/// <summary> /// Gets the number of definitions in the specified collection with a unit /// type of <see cref="GridUnitType.Star"/>. /// </summary> private Int32 CountStars(IDefinitionBaseCollection definitions) { var count = 0; if (definitions != null) { for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType == GridUnitType.Star) count++; } } return count; }
/// <summary> /// Distributes the specified dimension amongst all of the cells in the specified row or column span. /// </summary> /// <param name="definitions">The collection of row or column definitions amongst which to distribute the specified dimension.</param> /// <param name="index">The index of the first row or column in the span.</param> /// <param name="span">The number of rows or columns in the span.</param> /// <param name="dimension">The amount of space to distribute between the rows or columns in the span.</param> private void DistributeSpanDimension(IDefinitionBaseCollection definitions, Int32 index, Int32 span, Double dimension) { if (dimension == 0.0) return; var spanContentDimension = 0.0; var spanDesiredDimension = 0.0; var spanMaximumDimension = 0.0; for (int i = 0; i < span; i++) { var def = definitions[index + i]; spanContentDimension += def.MeasuredContentDimension; spanDesiredDimension += def.PreferredDesiredDimension; spanMaximumDimension += Math.Max(def.MaxDimension, spanContentDimension); } /* When the dimension to distribute is less than the current content * size of the span, we don't need to do anything. */ if (dimension <= spanContentDimension) return; /* Dimension to distribute is less than the desired dimension of the span. * Ignore auto defs, distribute equally into content sizes of other defs in order * of lowest DesiredDimension to highest. */ if (dimension <= spanDesiredDimension) { var undistributed = dimension; for (int i = 0; i < span; i++) { var def = definitions[index + i]; if (def.AssumedUnitType == GridUnitType.Auto) undistributed -= def.MeasuredContentDimension; } var defsInSpan = EnumerateNonAutoDefinitionsInSpanByDesiredDimension(definitions, index, span); for (int i = 0; i < defsInSpan.Count; i++) { var def = defsInSpan[i]; var defDistribution = undistributed / (defsInSpan.Count - i); var defContentSize = Math.Min(defDistribution, def.PreferredDesiredDimension); def.ExpandContentDimension(defContentSize); undistributed -= defContentSize; } defsInSpan.Clear(); return; } /* Dimension to distribute is less than the maximum dimension of the span. * Distribute into non-auto defs first, in order of lowest MaxSize to highest, * then distribute any remaining space into auto defs. */ if (dimension <= spanMaximumDimension) { var undistributed = dimension - spanDesiredDimension; var defsInSpan = EnumerateNonAutoDefinitionsInSpanByMaxDimension(definitions, index, span); var autoInSpan = span - defsInSpan.Count; // Non-auto defs for (int i = 0; i < defsInSpan.Count; i++) { var def = defsInSpan[i]; var defDesiredSize = def.PreferredDesiredDimension; var defDistribution = defDesiredSize + undistributed / (span - autoInSpan - i); var defContentSize = Math.Min(defDistribution, def.MaxDimension); def.ExpandContentDimension(defContentSize); var delta = def.MeasuredContentDimension - defDesiredSize; undistributed -= delta; } // Auto defs defsInSpan = EnumerateAutoDefinitionsInSpanByContentDimension(definitions, index, span); for (int i = 0; i < defsInSpan.Count; i++) { var def = defsInSpan[i]; var defDesiredSize = def.PreferredDesiredDimension; var defDistribution = defDesiredSize + undistributed / (autoInSpan - i); var defContentSize = Math.Min(defDistribution, def.MaxDimension); def.ExpandContentDimension(defContentSize); var delta = def.MeasuredContentDimension - defDesiredSize; undistributed -= delta; } return; } /* Dimension to distribute is greater than the max size of the span. * Distribute equally into all spans. */ for (int i = 0; i < span; i++) { definitions[index + i].ExpandContentDimension(dimension / span); } }
/// <summary> /// Measures the total dimension of the specified row or column span. /// </summary> /// <param name="definitions">The collection of row or column definitions for which to calculate a total dimension.</param> /// <param name="index">The index of the first row or column in the span.</param> /// <param name="span">The number of rows or columns in the span.</param> /// <returns>The total dimension of the specified row or column span.</returns> private Double CalculateSpanDimension(IDefinitionBaseCollection definitions, Int32 index, Int32 span) { var size = 0.0; for (int i = 0; i < span; i++) { size += definitions[index + i].ActualDimension; } return size; }
/// <summary> /// Retrieves a buffer containing all of the auto-sized row/column definitions in the specified span. /// The buffer is sorted in ascending order of <see cref="DefinitionBase.MeasuredContentDimension"/>. /// </summary> /// <param name="definitions">The collection of definitions from which to retrieve the span.</param> /// <param name="index">The index of the first definition in the span.</param> /// <param name="span">The number of definitions in the span.</param> /// <returns>A buffer containing the specified span of row/column definitions.</returns> private List <DefinitionBase> EnumerateAutoDefinitionsInSpanByContentDimension(IDefinitionBaseCollection definitions, Int32 index, Int32 span) { var buffer = EnumerateDefinitionsInSpan(definitions, index, span, nonauto: false); buffer.Sort((def1, def2) => { return(def1.MeasuredContentDimension.CompareTo(def2.MeasuredContentDimension)); }); return(buffer); }
/// <summary> /// Resolves the size of the grid's star-sized rows or columns. /// </summary> /// <param name="definitions">The collection of rows or columns to resolve.</param> /// <param name="availableDimension">The amount of space which is available to the grid.</param> private void ResolveStars(IDefinitionBaseCollection definitions, Double availableDimension) { if ((definitions == RowDefinitions && starRowCount == 0) || (definitions == ColumnDefinitions && starColumnCount == 0)) { return; } availableDimension -= CalculateUsedDimension(definitions); var sumOfStarFactors = 0.0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType != GridUnitType.Star) continue; sumOfStarFactors += def.Dimension.Value; } var starFactorUnit = (sumOfStarFactors == 0) ? 0 : availableDimension / sumOfStarFactors; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; if (def.AssumedUnitType != GridUnitType.Star) continue; def.MeasuredDimension = Math.Max(0, starFactorUnit * def.Dimension.Value); } }
/// <summary> /// Performs layout rounding on the specified definition collection. /// </summary> /// <param name="definitions">The definition collection on which to perform layout rounding.</param> private void RoundDimensions(IDefinitionBaseCollection definitions) { if (definitions.Count == 0) return; var errorContent = 0.0; var error = 0.0; for (int i = 0; i < definitions.Count - 1; i++) { var oldValueContent = definitions[i].MeasuredContentDimension; var oldValue = definitions[i].MeasuredDimension; definitions[i].MeasuredContentDimension = PerformLayoutRounding(oldValueContent); definitions[i].MeasuredDimension = PerformLayoutRounding(oldValue); errorContent += (definitions[i].MeasuredContentDimension - oldValueContent); error += (definitions[i].MeasuredDimension - oldValue); } definitions[definitions.Count - 1].MeasuredContentDimension += errorContent; definitions[definitions.Count - 1].MeasuredDimension += error; }
/// <summary> /// Retrieves a buffer containing all of the auto-sized row/column definitions in the specified span. /// The buffer is sorted in ascending order of <see cref="DefinitionBase.MeasuredContentDimension"/>. /// </summary> /// <param name="definitions">The collection of definitions from which to retrieve the span.</param> /// <param name="index">The index of the first definition in the span.</param> /// <param name="span">The number of definitions in the span.</param> /// <returns>A buffer containing the specified span of row/column definitions.</returns> private List <DefinitionBase> EnumerateAutoDefinitionsInSpanByContentDimension(IDefinitionBaseCollection definitions, Int32 index, Int32 span) { var buffer = EnumerateDefinitionsInSpan(definitions, index, span, nonauto: false); buffer.Sort(cmpByMeasuredContentDimension); return(buffer); }
/// <summary> /// Retrieves a buffer containing all of the non-auto-sized row/column definitions in the specified span. /// The buffer is sorted in ascending order of <see cref="DefinitionBase.PreferredDesiredDimension"/>. /// </summary> /// <param name="definitions">The collection of definitions from which to retrieve the span.</param> /// <param name="index">The index of the first definition in the span.</param> /// <param name="span">The number of definitions in the span.</param> /// <returns>A buffer containing the specified span of row/column definitions.</returns> private List <DefinitionBase> EnumerateNonAutoDefinitionsInSpanByDesiredDimension(IDefinitionBaseCollection definitions, Int32 index, Int32 span) { var buffer = EnumerateDefinitionsInSpan(definitions, index, span, auto: false); buffer.Sort((def1, def2) => { return(def1.PreferredDesiredDimension.CompareTo(def2.PreferredDesiredDimension)); }); return(buffer); }
/// <summary> /// Retrieves a buffer containing all of the non-auto-sized row/column definitions in the specified span. /// The buffer is sorted in ascending order of <see cref="DefinitionBase.MaxDimension"/>. /// </summary> /// <param name="definitions">The collection of definitions from which to retrieve the span.</param> /// <param name="index">The index of the first definition in the span.</param> /// <param name="span">The number of definitions in the span.</param> /// <returns>A buffer containing the specified span of row/column definitions.</returns> private List <DefinitionBase> EnumerateNonAutoDefinitionsInSpanByMaxDimension(IDefinitionBaseCollection definitions, Int32 index, Int32 span) { var buffer = EnumerateDefinitionsInSpan(definitions, index, span, auto: false); buffer.Sort(cmpByMaxDimension); return(buffer); }
/// <summary> /// Measures the total amount of space which is occupied by non-star rows or columns in the specified collection. /// </summary> /// <param name="definitions">The collection of row or column definitions for which to calculate a used dimension.</param> /// <returns>The total amount of space which is occupied by non-star columns in <paramref name="definitions"/>.</returns> private Double CalculateUsedDimension(IDefinitionBaseCollection definitions) { var dimension = 0.0; for (int i = 0; i < definitions.Count; i++) { var def = definitions[i]; switch (def.AssumedUnitType) { case GridUnitType.Auto: case GridUnitType.Pixel: dimension += def.ActualDimension; break; } } return dimension; }
/// <summary> /// Distributes the specified dimension amongst all of the cells in the specified row or column span. /// </summary> /// <param name="definitions">The collection of row or column definitions amongst which to distribute the specified dimension.</param> /// <param name="index">The index of the first row or column in the span.</param> /// <param name="span">The number of rows or columns in the span.</param> /// <param name="dimension">The amount of space to distribute between the rows or columns in the span.</param> private void DistributeSpanDimension(IDefinitionBaseCollection definitions, Int32 index, Int32 span, Double dimension) { if (dimension == 0.0) { return; } var spanContentDimension = 0.0; var spanDesiredDimension = 0.0; var spanMaximumDimension = 0.0; for (int i = 0; i < span; i++) { var def = definitions[index + i]; spanContentDimension += def.MeasuredContentDimension; spanDesiredDimension += def.PreferredDesiredDimension; spanMaximumDimension += Math.Max(def.MaxDimension, spanContentDimension); } /* When the dimension to distribute is less than the current content * size of the span, we don't need to do anything. */ if (dimension <= spanContentDimension) { return; } /* Dimension to distribute is less than the desired dimension of the span. * Ignore auto defs, distribute equally into content sizes of other defs in order * of lowest DesiredDimension to highest. */ if (dimension <= spanDesiredDimension) { var undistributed = dimension; for (int i = 0; i < span; i++) { var def = definitions[index + i]; if (def.AssumedUnitType == GridUnitType.Auto) { undistributed -= def.MeasuredContentDimension; } } var defsInSpan = EnumerateNonAutoDefinitionsInSpanByDesiredDimension(definitions, index, span); for (int i = 0; i < defsInSpan.Count; i++) { var def = defsInSpan[i]; var defDistribution = undistributed / (defsInSpan.Count - i); var defContentSize = Math.Min(defDistribution, def.PreferredDesiredDimension); def.ExpandContentDimension(defContentSize); undistributed -= defContentSize; } defsInSpan.Clear(); return; } /* Dimension to distribute is less than the maximum dimension of the span. * Distribute into non-auto defs first, in order of lowest MaxSize to highest, * then distribute any remaining space into auto defs. */ if (dimension <= spanMaximumDimension) { var undistributed = dimension - spanDesiredDimension; var defsInSpan = EnumerateNonAutoDefinitionsInSpanByMaxDimension(definitions, index, span); var autoInSpan = span - defsInSpan.Count; // Non-auto defs for (int i = 0; i < defsInSpan.Count; i++) { var def = defsInSpan[i]; var defDesiredSize = def.PreferredDesiredDimension; var defDistribution = defDesiredSize + undistributed / (span - autoInSpan - i); var defContentSize = Math.Min(defDistribution, def.MaxDimension); def.ExpandContentDimension(defContentSize); var delta = def.MeasuredContentDimension - defDesiredSize; undistributed -= delta; } // Auto defs defsInSpan = EnumerateAutoDefinitionsInSpanByContentDimension(definitions, index, span); for (int i = 0; i < defsInSpan.Count; i++) { var def = defsInSpan[i]; var defDesiredSize = def.PreferredDesiredDimension; var defDistribution = defDesiredSize + undistributed / (autoInSpan - i); var defContentSize = Math.Min(defDistribution, def.MaxDimension); def.ExpandContentDimension(defContentSize); var delta = def.MeasuredContentDimension - defDesiredSize; undistributed -= delta; } return; } /* Dimension to distribute is greater than the max size of the span. * Distribute equally into all spans. */ for (int i = 0; i < span; i++) { definitions[index + i].ExpandContentDimension(dimension / span); } }