private OrientedSize FinalMeasureItems(OrientedSize availableOriented, double spacing, bool skipHiddenSpacing) { var children = Panel.Elements; var childrenCount = children.Count; var orientation = Panel.Orientation; var desiredOriented = new OrientedSize(orientation); for (var index = 0; index < childrenCount; index++) { var child = children[index]; var flexItem = FlexElements[index]; var childFinalDirect = flexItem.ActualLength; var childDesiredOriented = child.DesiredSize.AsOriented(orientation); if (flexItem.ActualLength.IsLessThan(childDesiredOriented.Direct) == false) { childDesiredOriented.Direct = flexItem.ActualLength; desiredOriented = desiredOriented.StackSize(childDesiredOriented); continue; } childDesiredOriented = MeasureChild(child, OrientedSize.Create(orientation, childFinalDirect, availableOriented.Indirect)); flexItem = flexItem.WithUIElement(child, orientation); childDesiredOriented.Direct = flexItem.ActualLength; desiredOriented = desiredOriented.StackSize(childDesiredOriented); FlexElements[index] = flexItem; } desiredOriented.Direct = Math.Max(0, desiredOriented.Direct + CalcSpacingDelta(GetVisibleCount(Panel, skipHiddenSpacing), spacing)); return(desiredOriented); }
private OrientedSize ProcessSpacingAndOverflow(double spacing, OrientedSize desiredOriented, OrientedSize availableOriented, out bool isHiddenChanged) { var childrenCount = Panel.Elements.Count; var orientation = Panel.Orientation; var target = availableOriented.Direct; isHiddenChanged = false; // Current length is greater than available and we have no possibility to stretch down -> mark elements as hidden var current = 0.0; var visible = 0.0; var hasHiddenChildren = false; var visibleChildrenCount = 0; if (desiredOriented.Direct.IsGreaterThan(availableOriented.Direct)) { var stretchOverflow = FlexElementCollection.Mount(FlexElements.Capacity); try { // Process Pinned Flexible for (var index = 0; index < childrenCount; index++) { var flexElement = FlexElements[index]; if (CanPinStretch(flexElement) == false) { continue; } flexElement.StretchDirection = FlexStretchDirection.Shrink; stretchOverflow.Add(flexElement); Panel.SetIsHidden(Panel.Elements[index], false); } // Process Pinned for (var index = 0; index < childrenCount; index++) { var child = Panel.Elements[index]; if (child.Visibility == Visibility.Collapsed) { continue; } var flexElement = FlexElements[index]; if (CanPin(flexElement) == false) { continue; } current += flexElement.ActualLength; current += spacing; visible = current; Panel.SetIsHidden(Panel.Elements[index], false); } // Process Hide for (var index = 0; index < childrenCount; index++) { var child = Panel.Elements[index]; if (child.Visibility == Visibility.Collapsed) { continue; } visibleChildrenCount++; var flexElement = FlexElements[index]; if (CanPin(flexElement)) { continue; } current += flexElement.ActualLength; if (CanHide(flexElement) == false) { isHiddenChanged |= Panel.GetIsHidden(child); Panel.SetIsHidden(child, false); current += spacing; visible = current; continue; } var isOverflowed = current.IsGreaterThan(target, XamlConstants.LayoutComparisonPrecision); current += spacing; if (isOverflowed == false) { visible = current; } isHiddenChanged |= Panel.GetIsHidden(child) != isOverflowed; hasHiddenChildren |= isOverflowed; Panel.SetIsHidden(child, isOverflowed); } if (visibleChildrenCount > 0) { visible = visible - spacing; } Panel.HasHiddenChildren = hasHiddenChildren; // Stretch Pinned if (visible.IsGreaterThan(availableOriented.Direct) && stretchOverflow.Count > 0) { var currentPinStretch = stretchOverflow.Actual; var pinStretchTarget = (currentPinStretch - (visible - availableOriented.Direct)).Clamp(0, availableOriented.Direct); var pinStretchDesired = stretchOverflow.Stretch(FlexStretch.Fill, pinStretchTarget, FlexDistributor.Equalizer); if (pinStretchDesired < currentPinStretch) { var pinStretchIndex = 0; for (var index = 0; index < childrenCount; index++) { var flexElement = FlexElements[index]; if (CanPinStretch(flexElement)) { FlexElements[index] = stretchOverflow[pinStretchIndex++].WithStretchDirection(FlexStretchDirection.Shrink).WithMaxLength(flexElement.ActualLength); } else { FlexElements[index] = FlexElements[index].WithStretchDirection(FlexStretchDirection.Shrink).WithShrinkPriority(short.MaxValue); } } FinalMeasureItems(availableOriented, spacing, true); return(OrientedSize.Create(orientation, availableOriented.Direct, desiredOriented.Indirect)); } } } finally { FlexElementCollection.Release(stretchOverflow); } return(OrientedSize.Create(orientation, visible.Clamp(0, availableOriented.Direct), desiredOriented.Indirect)); } for (var index = 0; index < childrenCount; index++) { var flexElement = FlexElements[index]; var child = Panel.Elements[index]; if (child.Visibility == Visibility.Collapsed) { continue; } visibleChildrenCount++; current += flexElement.ActualLength; current += spacing; Panel.SetIsHidden(Panel.Elements[index], false); } Panel.HasHiddenChildren = false; visible = Math.Max(0, current); if (visibleChildrenCount > 0) { visible = visible - spacing; } return(OrientedSize.Create(orientation, visible.Clamp(0, availableOriented.Direct), desiredOriented.Indirect)); }