private Size StarMeasurePass(Size availableSize) { Size originalDesiredSize = DesiredSize; UIElementCollection children = InternalChildren; int childCount = children.Count; int starLayoutCombinationCount = _starLayoutCombinations.Count; for (int i = 0; i < childCount; i++) { UIElement child = children[i]; if (IsStarChild(child)) { if (_childIndexToStarLayoutIndexMap.ContainsKey(i)) { int starLayoutIndex = _childIndexToStarLayoutIndexMap[i]; if (starLayoutIndex < starLayoutCombinationCount) { StarLayoutInfo starLayoutInfo = _starLayoutCombinations[starLayoutIndex]; child.Measure(new Size(starLayoutInfo.AllocatedStarWidth, availableSize.Height)); } } } } double desiredWidth = originalDesiredSize.Width; AdjustDesiredWidthForStars(children, ref desiredWidth); return(new Size(desiredWidth, originalDesiredSize.Height)); }
private void CreateStarLayoutCombination(Size constraint, double starWeight, double starMinWidth, double starMaxWidth, List <int> starChildIndices) { if (starChildIndices.Count > 0) { StarLayoutInfo starLayoutInfo = new StarLayoutInfo() { RequestedStarMinWidth = starMinWidth, RequestedStarMaxWidth = starMaxWidth, RequestedStarWeight = starWeight }; _starLayoutCombinations.Add(starLayoutInfo); UIElementCollection children = InternalChildren; int starLayoutIndex = _starLayoutCombinations.Count - 1; foreach (int starChildIndex in starChildIndices) { _childIndexToStarLayoutIndexMap[starChildIndex] = starLayoutIndex; children[starChildIndex].Measure(new Size(starLayoutInfo.RequestedStarMinWidth, constraint.Height)); } starChildIndices.Clear(); } }
/// <summary> /// Distributes the remaining space after step 1 equally among all the /// qualified member, such that they are constrained by their min/max constraints /// maintaining (but not necessarily attaining) the goal of making perstarvalue of /// all the elements as equal as possible. /// </summary> private static void DistributeRemainingSpace(List <StarLayoutInfo> starInfoList, int distributionCount, ref double remainingSpace) { Debug.Assert(distributionCount > 0 && distributionCount <= starInfoList.Count); Debug.Assert(DoubleUtil.GreaterThan(remainingSpace, 0)); double remainingStarWeight = 0; for (int i = 0; i < distributionCount; i++) { remainingStarWeight += starInfoList[i].RequestedStarWeight; } double impactPerStar = 0; for (int i = 0; i < distributionCount; i++) { StarLayoutInfo starInfo = starInfoList[i]; if (DoubleUtil.GreaterThan(remainingSpace, 0)) { double currentContribution = starInfo.RequestedStarMaxWidth - starInfo.AllocatedStarWidth; currentContribution -= (impactPerStar * starInfo.RequestedStarWeight); currentContribution /= starInfo.RequestedStarWeight; if (DoubleUtil.GreaterThan(currentContribution * remainingStarWeight, remainingSpace)) { currentContribution = remainingSpace / remainingStarWeight; } impactPerStar += currentContribution; remainingSpace -= (currentContribution * remainingStarWeight); } starInfo.AllocatedStarWidth += (impactPerStar * starInfo.RequestedStarWeight); remainingStarWeight -= starInfo.RequestedStarWeight; } }
protected override Size ArrangeOverride(Size finalSize) { UIElementCollection children = InternalChildren; int childCount = children.Count; double remainingHeightInColumn = finalSize.Height; double columnWidth = 0; double currentX = 0; double starLayoutCombinationCount = _starLayoutCombinations.Count; for (int i = 0; i < childCount; i++) { UIElement child = children[i]; Size childDesiredSize = child.DesiredSize; if (DoubleUtil.GreaterThan(childDesiredSize.Height, remainingHeightInColumn)) { currentX += columnWidth; columnWidth = childDesiredSize.Width; if (IsStarChild(child)) { if (_childIndexToStarLayoutIndexMap.ContainsKey(i)) { int starLayoutIndex = _childIndexToStarLayoutIndexMap[i]; if (starLayoutIndex < starLayoutCombinationCount) { StarLayoutInfo starLayoutInfo = _starLayoutCombinations[starLayoutIndex]; columnWidth = starLayoutInfo.AllocatedStarWidth; } } } child.Arrange(new Rect(currentX, 0, columnWidth, childDesiredSize.Height)); remainingHeightInColumn = Math.Max(0, finalSize.Height - childDesiredSize.Height); } else { double arrangeWidth = child.DesiredSize.Width; if (IsStarChild(child)) { if (_childIndexToStarLayoutIndexMap.ContainsKey(i)) { int starLayoutIndex = _childIndexToStarLayoutIndexMap[i]; if (starLayoutIndex < starLayoutCombinationCount) { if (CanChildStretch(child)) { // If the child's HorizontalAlignment is Left/Right, then // use its desired width as arrange width. StarLayoutInfo starLayoutInfo = _starLayoutCombinations[starLayoutIndex]; arrangeWidth = starLayoutInfo.AllocatedStarWidth; } } } } columnWidth = Math.Max(columnWidth, arrangeWidth); child.Arrange(new Rect(currentX, (finalSize.Height - remainingHeightInColumn), arrangeWidth, childDesiredSize.Height)); remainingHeightInColumn -= childDesiredSize.Height; } } return(finalSize); }
private static object OnCoerceAllocatedStarWidth(DependencyObject d, object baseValue) { double allocatedWidth = (double)baseValue; StarLayoutInfo layoutInfo = (StarLayoutInfo)d; if (DoubleUtil.LessThan(allocatedWidth, layoutInfo.RequestedStarMinWidth)) { return(layoutInfo.RequestedStarMinWidth); } return(baseValue); }
private static object OnCoerceRequestedStarMaxWidth(DependencyObject d, object baseValue) { double maxWidth = (double)baseValue; StarLayoutInfo starLayoutInfo = (StarLayoutInfo)d; double minWidth = starLayoutInfo.RequestedStarMinWidth; if (DoubleUtil.LessThan(maxWidth, minWidth)) { return(minWidth); } return(baseValue); }
private static double EqualizeLeftOf(List <StarLayoutInfo> starInfoList, int index, bool isChecking) { Debug.Assert(index >= 0 && index < starInfoList.Count); double spaceNeeded = 0; StarLayoutInfo baseStarInfo = starInfoList[index]; double basePerStar = baseStarInfo.AllocatedStarWidth / baseStarInfo.RequestedStarWeight; for (int i = 0; i < index; i++) { StarLayoutInfo starInfo = starInfoList[i]; double targetValue = Math.Min(basePerStar * starInfo.RequestedStarWeight, starInfo.RequestedStarMaxWidth); spaceNeeded += (targetValue - starInfo.AllocatedStarWidth); if (!isChecking) { starInfo.AllocatedStarWidth = targetValue; } } return(spaceNeeded); }
/// <summary> /// Adjust the desired width for all the star /// based children in a column based upon their /// allocated/desired width. /// </summary> private void AdjustDesiredWidthForStarColumn(UIElementCollection children, List <int> columnStarChildren, int starLayoutIndex, ref double desiredWidth) { if (columnStarChildren != null && columnStarChildren.Count > 0 && starLayoutIndex >= 0) { bool foundStretchableStar = false; double columnDesiredWidth = 0; foreach (int columnChildIndex in columnStarChildren) { UIElement child = children[columnChildIndex]; if (CanChildStretch(child)) { foundStretchableStar = true; break; } else { columnDesiredWidth = Math.Max(columnDesiredWidth, child.DesiredSize.Width); } } if (foundStretchableStar) { // if there are any non-item based star children // then desired width should be equal to that of // allocated width. StarLayoutInfo starLayoutInfo = _starLayoutCombinations[starLayoutIndex]; desiredWidth += (starLayoutInfo.AllocatedStarWidth - starLayoutInfo.RequestedStarMinWidth); } else { // if there are no non-item based star children // then desired width should be equal to that of // computed desired width. StarLayoutInfo starLayoutInfo = _starLayoutCombinations[starLayoutIndex]; desiredWidth += Math.Max((columnDesiredWidth - starLayoutInfo.RequestedStarMinWidth), 0); } columnStarChildren.Clear(); } }