public static Size Measure(IStackPanel panel, Size availableSize) { var spacing = panel is IStackPanelAdvanced advanced ? advanced.Spacing : 0.0; var orientation = panel.Orientation; var childConstraint = availableSize.AsOriented(orientation).ChangeDirect(double.PositiveInfinity); var result = new OrientedSize(orientation); var elementsCount = panel.Elements.Count; var spacingSize = new OrientedSize().ChangeDirect(spacing); for (var index = 0; index < elementsCount; index++) { var child = panel.Elements[index]; child.Measure(childConstraint.Size); result = result.StackSize(child.DesiredSize); if (index + 1 < elementsCount) { result = result.StackSize(spacingSize); } } return(result.Size); }
public VirtualMeasureContext(VirtualUnitStackPanelLayout layout, Size availableSize) { Layout = layout; Orientation = layout.Orientation; var canScrollDirect = Orientation == Orientation.Vertical ? layout.CanVerticallyScroll : layout.CanHorizontallyScroll; var canScrollIndirect = Orientation == Orientation.Vertical ? layout.CanHorizontallyScroll : layout.CanVerticallyScroll; LeadingElements = layout.Panel.LeadingElements; TrailingElements = layout.Panel.TrailingElements; SourceCount = layout.ItemsCount + (LeadingElements?.Count ?? 0) + (TrailingElements?.Count ?? 0); OrientedResult = new OrientedSize(Orientation); OrientedLeadingSize = new OrientedSize(Orientation); OrientedTrailingSize = new OrientedSize(Orientation); OrientedAvailable = availableSize.AsOriented(Orientation); OffsetElementIndex = layout.CalcFirstVisibleIndex(layout.Offset); OrientedConstraint = new OrientedSize(Orientation) .ChangeDirect(canScrollDirect ? double.PositiveInfinity : OrientedAvailable.Direct) .ChangeIndirect(canScrollIndirect ? double.PositiveInfinity : OrientedAvailable.Indirect); LastIndex = -1; FirstIndex = -1; FirstVisibleIndex = -1; LastVisibleIndex = -1; LeadingCacheCount = 0; TrailingCacheCount = 0; }
internal static Rect FillRectIndirect(this FrameworkElement fre, Orientation orientation, Size availableSize) { if (!fre.ShouldFill(orientation)) { return(fre.DesiredSize.Rect()); } var orientedSize = fre.DesiredSize.AsOriented(orientation); orientedSize.Indirect = availableSize.AsOriented(orientation).Indirect; return(orientedSize.Size.Rect()); }
private Size MeasureCoreImpl(Size availableSize) { var flexPanel = Panel; var orientation = flexPanel.Orientation; var availableOriented = availableSize.AsOriented(orientation); var children = flexPanel.Elements; var visibility = VisibilityArrayPool.GetArray(children.Count); _measureInfinite = availableOriented.Direct.IsPositiveInfinity(); // First measure pass try { // Cache children visibility for (var index = 0; index < children.Count; index++) { visibility[index] = children[index].Visibility; } var result = MeasureImpl(availableOriented.Size, out var isOverflowedChanged); var childVisibilityChanged = false; // Check children visibility changes if (isOverflowedChanged == false) { var count = Math.Min(children.Count, visibility.Length); for (var index = 0; index < count; index++) { childVisibilityChanged = visibility[index] != children[index].Visibility; if (childVisibilityChanged) { break; } } } // Second measure pass if (isOverflowedChanged || childVisibilityChanged) { result = MeasureImpl(availableOriented.Size, out isOverflowedChanged); } return(result.AsOriented(orientation).Size); } finally { VisibilityArrayPool.ReleaseArray(visibility); } }
public static Size Arrange(IStackPanel panel, Size finalSize) { var spacing = panel is IStackPanelAdvanced advanced ? advanced.Spacing : 0.0; var orientation = panel.Orientation; var offset = new OrientedPoint(orientation); var finalOriented = finalSize.AsOriented(orientation); foreach (var child in panel.Elements) { var size = child.DesiredSize.AsOriented(orientation); size.Indirect = finalOriented.Indirect; var rect = new Rect(offset.Point, size.Size); child.Arrange(rect); offset.Direct += size.Direct + spacing; } return(finalSize); }
private Size MeasureImpl(Size availableSize, out bool overflowChanged) { overflowChanged = false; var children = Panel.Elements; var orientation = Panel.Orientation; var childrenCount = children.Count; if (childrenCount == 0) { return(XamlConstants.ZeroSize); } var useLayoutRounding = Panel.UseLayoutRounding; FlexElements.UseLayoutRounding = useLayoutRounding; if (useLayoutRounding) { availableSize = availableSize.LayoutRound(RoundingMode.MidPointFromZero); } var spacing = GetRoundSpacing(Panel.Spacing, useLayoutRounding); var availableOriented = availableSize.AsOriented(orientation); // First measure var desiredOriented = MeasureItems(availableSize, out var desiredFixed, out _); // Stretch desiredOriented.Direct = Stretch(FlexElements, spacing, availableOriented.Direct, false); // Final measure desiredOriented = FinalMeasureItems(availableOriented, spacing, false); // Overflow var visibleSize = ProcessSpacingAndOverflow(spacing, desiredOriented, availableOriented, out overflowChanged); // Return return(GetFinalMeasureSize(availableOriented.Clamp(desiredFixed, XamlConstants.InfiniteSize.AsOriented(orientation)), desiredOriented, visibleSize).Size); }
private Vector CalcBringIntoViewOffset(int index, BringIntoViewMode mode, Size viewport, Size extent, Vector offset) { if (index < 0 || index >= ItemsCount) { return(offset); } var orientation = Orientation; var orientedViewPort = viewport.AsOriented(orientation); var orientedExtent = extent.AsOriented(orientation); var orientedOffset = offset.AsOriented(orientation); var orientedViewer = new OrientedScrollView(orientation, orientedViewPort.Direct, orientedExtent.Direct, orientedOffset.Direct); orientedViewer.Offset = orientedViewer.Offset - index > 0.0 || mode == BringIntoViewMode.Top ? index : index - orientedViewer.Viewport + 1.0; orientedOffset.Direct = orientedViewer.Offset; return(orientedOffset.Vector); }
protected override Size ArrangeCore(Size finalSize) { var orientation = Orientation; var offset = new OrientedPoint(orientation); var finalOriented = finalSize.AsOriented(orientation); offset.Direct -= _preCacheDelta; foreach (UIElement child in Children) { var size = child.DesiredSize.AsOriented(orientation); size.Indirect = finalOriented.Indirect; var rect = new Rect(offset.Point, size.Size); ArrangeChild(child, rect); offset.Direct += size.Direct; } return(finalSize); }
private Size ArrangeCoreImpl(Size finalSize) { var flexPanel = Panel; var flexPanelEx = Panel as IFlexPanelEx; var allowMeasure = flexPanelEx?.AllowMeasureInArrange ?? false; var orientation = flexPanel.Orientation; var useLayoutRounding = flexPanel.UseLayoutRounding; var spacing = GetRoundSpacing(flexPanel.Spacing, useLayoutRounding); for (var index = 0; index < flexPanel.Elements.Count; index++) { FlexElements[index] = FlexElements[index].WithUIElement(flexPanel.Elements[index], orientation); } var currentFlexElements = FlexElementCollection.Mount(FlexElements.Capacity); try { FlexElements.CopyTo(currentFlexElements); while (true) { var nextArrangePass = false; var size = new OrientedSize(orientation); var spacingDelta = 0.0; var finalOriented = finalSize.AsOriented(orientation); var finalIndirect = finalOriented.Indirect; var currentPoint = new OrientedPoint(orientation); var childFinalOriented = new OrientedSize(orientation); // Stretch Stretch(currentFlexElements, spacing, finalOriented.Direct, true); for (var index = 0; index < flexPanel.Elements.Count; index++) { var child = flexPanel.Elements[index]; var flexElement = currentFlexElements[index]; if (child.Visibility == Visibility.Collapsed) { continue; } if (flexPanel.GetIsHidden(child)) { child.Arrange(XamlConstants.ZeroRect); flexElement.ActualLength = 0.0; currentFlexElements[index] = flexElement; continue; } var desiredOriented = child.DesiredSize.AsOriented(orientation); childFinalOriented.Direct = flexElement.ActualLength; childFinalOriented.Indirect = Math.Max(finalIndirect, desiredOriented.Indirect); // Arrange Child var rect = new Rect(XamlConstants.ZeroPoint, childFinalOriented.Size).Offset(currentPoint); if (useLayoutRounding) { rect = rect.LayoutRound(RoundingMode.MidPointFromZero); } if (_measureInfinite && allowMeasure && desiredOriented.Direct.IsGreaterThan(childFinalOriented.Direct)) { var remeasureOriented = desiredOriented; remeasureOriented.ChangeDirect(childFinalOriented.Direct); child.Measure(remeasureOriented.Size); } child.Arrange(rect); var arrangeSize = GetActualArrangeSize(child); if (arrangeSize.IsEmpty == false) { rect.Width = arrangeSize.Width; rect.Height = arrangeSize.Height; } var finalChildDirect = rect.Size().AsOriented(orientation).Direct; if (IsArrangeFixed(flexElement) == false && finalChildDirect.IsLessThan(childFinalOriented.Direct)) { var length = finalChildDirect; flexElement.SetLengths(length, length, length, length); currentFlexElements[index] = flexElement; nextArrangePass = true; break; } if (useLayoutRounding) { var rectSize = rect.Size().AsOriented(orientation); flexElement.ActualLength = rectSize.Direct; currentPoint.Direct = Math.Max(0, (currentPoint.Direct + rectSize.Direct + spacing).LayoutRound(orientation, RoundingMode.MidPointFromZero)); } else { var rectSize = rect.Size().AsOriented(orientation); flexElement.ActualLength = rectSize.Direct; currentPoint.Direct = Math.Max(0, currentPoint.Direct + rectSize.Direct + spacing); } currentFlexElements[index] = flexElement; spacingDelta += spacing; size = size.StackSize(childFinalOriented); } if (nextArrangePass) { continue; } if (spacingDelta.Equals(0.0) == false) { size.Direct = Math.Max(0, size.Direct + spacingDelta - spacing); } var result = finalSize; if (orientation == Orientation.Horizontal) { result.Width = flexPanel.ShouldFill(Orientation.Horizontal) ? finalSize.Width : Math.Min(finalSize.Width, size.Width); } else { result.Height = flexPanel.ShouldFill(Orientation.Vertical) ? finalSize.Height : Math.Min(finalSize.Height, size.Height); } return(result); } } finally { FlexElementCollection.Release(currentFlexElements); } }
private OrientedSize MeasureItems(Size availableSize, out OrientedSize fixedSize, out OrientedSize flexibleSize) { var stretch = Panel.Stretch; var orientation = Panel.Orientation; var children = Panel.Elements; var childrenCount = children.Count; var oriented = availableSize.AsOriented(orientation); var fixedChildConstraint = oriented.Clone.ChangeDirect(double.PositiveInfinity); var starChildConstraint = oriented.Clone.ChangeDirect(0); var fixedResult = new OrientedSize(orientation); var starValue = 0.0; FlexElements.EnsureCount(childrenCount); for (var index = 0; index < childrenCount; index++) { var flexElement = Panel.GetFlexElement(children[index]).WithOrientation(orientation); if (flexElement.IsStar) { starValue += flexElement.Length.Value; } FlexElements[index] = flexElement; } // None Stretch if (stretch == FlexStretch.None) { for (var index = 0; index < childrenCount; index++) { var flexElement = FlexElements[index]; var child = children[index]; var childConstraint = GetChildConstraint(flexElement, fixedChildConstraint, starChildConstraint); // Stack child size var size = MeasureChild(child, childConstraint); flexElement = flexElement.WithUIElement(child, orientation); size.Direct = flexElement.DesiredLength; fixedResult = fixedResult.StackSize(size); FlexElements[index] = flexElement; } fixedSize = fixedResult; flexibleSize = new OrientedSize(orientation); return(fixedResult); } // Fixed size children for (var index = 0; index < childrenCount; index++) { var flexElement = FlexElements[index]; if (flexElement.IsStar) { continue; } var child = children[index]; var childConstraint = GetChildConstraint(flexElement, fixedChildConstraint, starChildConstraint); // Stack child size var size = MeasureChild(child, childConstraint); flexElement = flexElement.WithUIElement(child, orientation); size.Direct = flexElement.DesiredLength; fixedResult = fixedResult.StackSize(size); FlexElements[index] = flexElement; } fixedSize = fixedResult; flexibleSize = new OrientedSize(orientation); starChildConstraint.ChangeDirect(FlexUtils.CalcStarValue(oriented.Direct, fixedResult.Direct, starValue)); // Star size children var flexibleResult = new OrientedSize(orientation); for (var index = 0; index < childrenCount; index++) { var flexElement = FlexElements[index]; if (flexElement.IsFixed) { continue; } var child = children[index]; var childConstraint = GetChildConstraint(flexElement, fixedChildConstraint, starChildConstraint); // Stack child size var size = MeasureChild(child, childConstraint); flexElement = flexElement.WithUIElement(child, orientation); size.Direct = flexElement.DesiredLength; flexibleResult = flexibleResult.StackSize(size); FlexElements[index] = flexElement.WithUIElement(child, orientation); } flexibleSize = flexibleResult; return(fixedResult.StackSize(flexibleResult)); }
public static OrientedSize WrapSize(this OrientedSize self, Size itemSize) { return(self.WrapSize(itemSize.AsOriented(self.Orientation))); }