using System; using Windows.Foundation; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace OwlCore.WinUI.Controls { #if NETFX_CORE public partial class PruningStackPanel : Panel { /// /// A for the property. /// public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register( nameof(Orientation), typeof(Orientation), typeof(PruningStackPanel), new PropertyMetadata(Orientation.Horizontal, LayoutPropertyChanged)); /// /// Gets or sets the of the . /// public Orientation Orientation { get { return (Orientation)GetValue(OrientationProperty); } set { SetValue(OrientationProperty, value); } } public int HiddenItemCount { get; private set; } protected override Size MeasureOverride(Size availableSize) { double usedSpace = 0; double maxSpace = 0; foreach (var child in Children) { child.Measure(availableSize); Size childDesiredSize = child.DesiredSize; double newUsedSpace = usedSpace + (Orientation == Orientation.Horizontal ? childDesiredSize.Width : childDesiredSize.Height); double newMaxSpace = (Orientation == Orientation.Horizontal ? childDesiredSize.Height : childDesiredSize.Width); if (newMaxSpace > maxSpace) { maxSpace = Math.Min(newMaxSpace, (Orientation == Orientation.Horizontal ? availableSize.Height : availableSize.Width)); } if (newUsedSpace > (Orientation == Orientation.Horizontal ? availableSize.Width : availableSize.Height)) { break; } } return new Size() { Height = Orientation == Orientation.Horizontal ? maxSpace : usedSpace, Width = Orientation == Orientation.Horizontal ? usedSpace : maxSpace, }; } protected override Size ArrangeOverride(Size finalSize) { if (Children.Count == 0) { return new Size(0, 0); } // The used space in which-ever dimension the orientation is. double usedSpace = 0; for (var i = 0; i < Children.Count; i++) { // Determine room for new item double remainingHeight = finalSize.Height; double remainingWidth = finalSize.Width; if (Orientation == Orientation.Horizontal) { remainingWidth -= usedSpace; } else { remainingHeight -= usedSpace; } Size lastUsedSize = ArrangeChild(Children[i], new Size(remainingWidth, remainingHeight), usedSpace); // If the last item used none of the allocated space. if ((Orientation == Orientation.Horizontal ? lastUsedSize.Width : lastUsedSize.Height) == 0) { HiddenItemCount = Children.Count - i + 1; } usedSpace += Orientation == Orientation.Horizontal ? lastUsedSize.Width : lastUsedSize.Height; } return finalSize; } private static void LayoutPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is PruningStackPanel psp) { psp.InvalidateMeasure(); psp.InvalidateArrange(); } } private Size ArrangeChild(UIElement child, Size remainingSize, double constrainedOffset) { // The desired space of the child over the constrained orientation. double desiredSpace = Orientation == Orientation.Horizontal ? child.DesiredSize.Width : child.DesiredSize.Height; if (desiredSpace > (Orientation == Orientation.Horizontal ? remainingSize.Width : remainingSize.Height)) { // The child wants more space than available. return new Size(0, 0); } else { // The child can be fit in this space. Size childSize = new Size() { Height = Orientation == Orientation.Horizontal ? remainingSize.Height : desiredSpace, Width = Orientation == Orientation.Horizontal ? desiredSpace : remainingSize.Width, }; Rect renderRect = new Rect() { X = Orientation == Orientation.Horizontal ? constrainedOffset : 0, Y = Orientation == Orientation.Horizontal ? 0 : constrainedOffset, Height = childSize.Height, Width = childSize.Width, }; child.Arrange(renderRect); return childSize; } } } #endif }