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); }
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); }
protected override Size MeasureOverrideCore(Size availableSize) { var orientedSize = new OrientedSize(Orientation.Horizontal); var measureItemSize = new Size(double.PositiveInfinity, availableSize.Height); _groups.Clear(); if (IsFullMeasurePass == false) { foreach (var child in Children.Cast <RibbonItem>()) { child.ActualItemStyle = RibbonItemStyle.Large; child.Measure(measureItemSize); var childDesiredSize = child.DesiredSize; orientedSize = orientedSize.StackSize(childDesiredSize); } } else { _groups.AddRange(Group.GetGroups()); orientedSize = _groups.Aggregate(orientedSize, (current, group) => current.StackSize(MeasureControlGroup(group, measureItemSize, Group.IsFinalMeasure))); } return(orientedSize.Size); }
//public static OrientedSize ArrangeStackLine(this Panel panel, Orientation orientation, Range<int> line, double lineOffset, double itemOffset, double? fixedLineSize, double? fixedItemSize) //{ // return ArrangeStackLine(panel.Children.Cast<UIElement>().Skip(line.Minimum).Take(line.Maximum - line.Minimum), orientation, lineOffset, itemOffset, fixedLineSize, fixedItemSize); //} public static OrientedSize ArrangeStackLine(IEnumerable <UIElement> elements, Orientation orientation, double lineOffset, double itemOffset, double?fixedLineSize, double?fixedItemSize) { var isHorizontal = orientation.IsHorizontal(); var orientedSize = new OrientedSize(orientation); foreach (var element in elements) { var elementSize = element.DesiredSize.AsOriented(orientation); var itemSize = fixedItemSize ?? elementSize.Direct; var lineSize = fixedLineSize ?? elementSize.Indirect; var bounds = isHorizontal ? new Rect(itemOffset, lineOffset, itemSize, lineSize) : new Rect(lineOffset, itemOffset, lineSize, itemSize); //bounds = bounds.LayoutRoundToEven(); element.Arrange(bounds); itemOffset += itemSize; //itemOffset = itemOffset.LayoutRoundMidPointFromZero(orientation); orientedSize = orientedSize.StackSize(elementSize); } return(orientedSize); }
//public static OrientedSize MeasureStackLine(this Panel panel, Orientation orientation, Range<int> line, double lineOffset, double itemOffset, double? fixedLineSize, double? fixedItemSize) //{ // return MeasureStackLine(panel.Children.Cast<UIElement>().Skip(line.Minimum).Take(line.Length()), orientation, null, null, fixedLineSize, fixedItemSize); //} public static OrientedSize MeasureStackLine(IEnumerable <UIElement> elements, OrientedSize availableSize, OrientedSize minimumSize, double?fixedLineSize, double?fixedItemSize) { var orientation = availableSize.Orientation; var orientedSize = new OrientedSize(orientation); foreach (var element in elements) { var currentConstraint = new OrientedSize(orientation) { Direct = (availableSize.Direct - orientedSize.Direct).Clamp(minimumSize.Direct, double.PositiveInfinity), Indirect = availableSize.Indirect.Clamp(minimumSize.Indirect, double.PositiveInfinity) }; var measureSize = new OrientedSize(orientation) { Direct = Math.Min(currentConstraint.Direct, fixedItemSize ?? double.PositiveInfinity), Indirect = Math.Min(currentConstraint.Indirect, fixedLineSize ?? double.PositiveInfinity) }; element.Measure(measureSize.Size); var desired = element.DesiredSize.AsOriented(orientation); orientedSize = orientedSize.StackSize(desired); } return(orientedSize); }
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)); }
protected override Size MeasureOverrideCore(Size availableSize) { Children.Add(_phantomGroup); _phantomGroup.BeginMeasurePass(); _phantomGroup.Invalidate(); _phantomGroup.Measure(new Size(0, double.PositiveInfinity)); _phantomGroup.EndMeasurePass(); var largeItemDesiredSize = _phantomGroup.DesiredSize; Children.Remove(_phantomGroup); if (Children.Count == 0) { return(new Size(0, largeItemDesiredSize.Height)); } var reductionOrder = ActualGroupSizeReductionOrder.ToList(); OddMeasure = false; try { foreach (var ribbonGroup in Groups) { ribbonGroup.BeginMeasurePass(); } var nextReduceGroupIndex = 0; OrientedSize finalSize; var reductionLevel = 0; do { finalSize = new OrientedSize(Orientation.Horizontal); var measureItemSize = new Size(double.PositiveInfinity, largeItemDesiredSize.Height); if (OddMeasure) { measureItemSize.Height += 1; } foreach (var ribbonGroup in Groups) { ribbonGroup.InvalidateInt(this); finalSize = finalSize.StackSize(ribbonGroup.MeasureInt(measureItemSize, false)); } OddMeasure = !OddMeasure; if (finalSize.Direct.IsLessThanOrClose(availableSize.Width, XamlConstants.LayoutComparisonPrecision)) { return(GetFinalSize(availableSize, new Size(finalSize.Width, largeItemDesiredSize.Height))); } foreach (var ribbonGroup in ActualGroupSizeReductionOrder) { var shrink = ribbonGroup.Shrink(finalSize.Direct - availableSize.Width); if (shrink.IsZero(XamlConstants.LayoutComparisonPrecision)) { continue; } finalSize.Direct -= shrink; if (finalSize.Direct.IsLessThanOrClose(availableSize.Width, XamlConstants.LayoutComparisonPrecision)) { return(GetFinalSize(availableSize, new Size(finalSize.Width, largeItemDesiredSize.Height))); } } reductionLevel++; } while (ReduceNextGroup(reductionOrder, ref nextReduceGroupIndex)); return(GetFinalSize(availableSize, new Size(finalSize.Width, largeItemDesiredSize.Height))); } finally { for (var i = 0; i < (OddMeasure ? 2 : 1); i++) { var measureItemSize = new Size(double.PositiveInfinity, largeItemDesiredSize.Height); if (OddMeasure) { measureItemSize.Height += 1; } OddMeasure = !OddMeasure; foreach (var ribbonGroup in Groups) { ribbonGroup.InvalidateInt(this); ribbonGroup.MeasureInt(measureItemSize, true); } } foreach (var ribbonGroup in Groups) { ribbonGroup.EndMeasurePass(); } } }
public static OrientedSize StackSize(this OrientedSize self, Size itemSize) { return(self.StackSize(itemSize.AsOriented(self.Orientation))); }