private/Controls/Set-UiRowAlignment.ps1

function Set-UiRowAlignment {
    <#
    .SYNOPSIS
        Lines the rest of a row up with the labeled boxes in it after every resize.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [System.Windows.Controls.Panel]$Panel
    )

    # Only grids and horizontal panels put controls side by side
    $horizontal = [System.Windows.Controls.Orientation]::Horizontal
    $holdsRows  = $Panel -is [System.Windows.Controls.Grid] -or
        ($Panel -is [System.Windows.Controls.StackPanel] -and $Panel.Orientation -eq $horizontal) -or
        ($Panel -is [System.Windows.Controls.WrapPanel] -and $Panel.Orientation -eq $horizontal)
    if (!$holdsRows -or $Panel.Resources.Contains('__PsUiRowAlignment')) { return }

    # Button bars wait for something labeled to attach them on load
    $hasLabeled = $false
    foreach ($child in $Panel.Children) {
        $tag   = if ($child -is [System.Windows.FrameworkElement]) { $child.Tag } else { $null }
        $isRow = $child -is [System.Windows.Controls.Panel] -and $child -isnot [System.Windows.Controls.Grid] -and
            $child.Resources.Contains('__PsUiRowAlignment')
        if ($isRow -or ($tag -is [hashtable] -and $tag.FormControl -and $tag.Control)) {
            $hasLabeled = $true
            break
        }
    }
    if (!$hasLabeled) { return }
    $Panel.Resources['__PsUiRowAlignment'] = $true

    # Responsive windows only line up their content panel when something on it asks
    if ($Panel -isnot [System.Windows.Controls.Grid]) {
        $alignRows    = ${function:Set-UiRowAlignment}
        $hook         = @{}
        $hook.Handler = [System.Windows.RoutedEventHandler]{
            param($sender, $loadedArgs)
            trap { Write-Debug "Set-UiRowAlignment parent hook: $_"; continue }
            $sender.Remove_Loaded($hook.Handler)
            if ($sender.Parent -is [System.Windows.Controls.Panel]) { & $alignRows -Panel $sender.Parent }
        }.GetNewClosure()
        $Panel.Add_Loaded($hook.Handler)
    }

    $state = @{
        Panel    = $Panel
        Original = [System.Collections.Generic.Dictionary[object, object]]::new()
        Hooked   = [System.Collections.Generic.HashSet[object]]::new()
        Watched  = [System.Collections.Generic.HashSet[object]]::new()
        Shifts   = [System.Collections.Generic.Dictionary[object, object]]::new()
        Pending  = $false
    }

    # Local values of everything moved, for when its row stops mixing
    $state.Remember = {
        param($element)
        if ($state.Original.ContainsKey($element)) { return }
        $state.Original[$element] = @{
            VA     = $element.ReadLocalValue([System.Windows.FrameworkElement]::VerticalAlignmentProperty)
            Margin = $element.ReadLocalValue([System.Windows.FrameworkElement]::MarginProperty)
            Shift  = $element.ReadLocalValue([System.Windows.UIElement]::RenderTransformProperty)
            Top    = $element.Margin.Top
        }
    }.GetNewClosure()

    # The nested row's first labeled control stands in for it
    $state.Inner = {
        param($row)
        foreach ($inner in $row.Children) {
            if ($inner -isnot [System.Windows.FrameworkElement] -or $inner.Visibility -ne 'Visible') { continue }
            $tag = $inner.Tag
            if ($tag -is [hashtable] -and $tag.FormControl -and $tag.Control) { return $inner }
        }
    }

    $state.Pass = {
        param([bool]$fromResize)
        trap { Write-Debug "Set-UiRowAlignment: $_"; continue }
        $panel    = $state.Panel
        $origin   = [System.Windows.Point]::new(0, 0)
        $isGrid   = $panel -is [System.Windows.Controls.Grid]
        $vaProp   = [System.Windows.FrameworkElement]::VerticalAlignmentProperty
        $marginDp = [System.Windows.FrameworkElement]::MarginProperty
        $shiftDp  = [System.Windows.UIElement]::RenderTransformProperty
        $unset    = [System.Windows.DependencyProperty]::UnsetValue
        $keep     = [System.Collections.Generic.HashSet[object]]::new()
        $sources  = [System.Collections.Generic.Dictionary[object, object]]::new()

        # [ordered] would read int keys as positions
        $rows    = [System.Collections.Generic.Dictionary[int, object]]::new()
        $inputs  = [System.Text.StringBuilder]::new()
        $stale   = $false
        $lastKey = $null
        $line    = 0
        foreach ($child in $panel.Children) {
            if ($child -isnot [System.Windows.FrameworkElement]) { continue }

            # Collapsing a child reshapes its row, and a panel with a set height never changes size to say so
            if ($state.Watched.Add($child)) { $child.Add_IsVisibleChanged($state.OnChildSize) }
            if ($child.Visibility -ne 'Visible') { continue }
            if (!$child.IsMeasureValid -or !$child.IsArrangeValid) { $stale = $true }

            $slot = [System.Windows.Controls.Primitives.LayoutInformation]::GetLayoutSlot($child)
            $key  = if ($isGrid) { [System.Windows.Controls.Grid]::GetRow($child) }
            else { [int][Math]::Round($slot.Y) }
            if (!$rows.ContainsKey($key)) {
                $rows[$key] = [System.Collections.Generic.List[object]]::new()
            }
            $rows[$key].Add($child)

            # Line numbers, not Y, since a push moves every line under it
            if ($key -ne $lastKey) {
                $line++
                $lastKey = $key
            }

            $source = $child
            $isRow  = $child -is [System.Windows.Controls.Panel] -and $child -isnot [System.Windows.Controls.Grid] -and
                $child.Resources.Contains('__PsUiRowAlignment')
            if ($isRow) { $source = & $state.Inner $child }
            $tag     = if ($source) { $source.Tag } else { $null }
            $caption = 0
            if ($tag -is [hashtable] -and $tag.FormControl -and $tag.Control) {
                $sources[$child] = $source
                if ($tag.Label) { $caption = [int]$tag.Label.ActualHeight }
            }
            $margin  = $child.Margin
            $ownSize = [int]($child.DesiredSize.Height - $margin.Top - $margin.Bottom)
            [void]$inputs.Append($line).Append(',').Append([int]$slot.X).Append(',')
            [void]$inputs.Append($ownSize).Append(',').Append($caption).Append(';')

            # Nested rows and placed controls stay but still shift inside the row.
            if ($sources.ContainsKey($child) -and ($isRow -or $child.Resources.Contains('__PsUiPlacedByUser'))) {
                [void]$inputs.Append([int]$source.TranslatePoint($origin, $panel).Y).Append(';')
            }
        }

        # Widths another SizeChanged handler just set haven't laid out yet
        if ($fromResize -and $stale) { return }

        $seen = $inputs.ToString()
        if ($seen -eq $state.Seen) { return }
        $state.Seen = $seen

        foreach ($members in $rows.Values) {
            $labeled  = [System.Collections.Generic.List[object]]::new()
            $siblings = [System.Collections.Generic.List[object]]::new()
            foreach ($child in $members) {
                $source  = if ($sources.ContainsKey($child)) { $sources[$child] } else { $null }
                $tag     = if ($source) { $source.Tag } else { $null }
                $showing = $source -and $tag.Label -and $tag.Control -is [System.Windows.FrameworkElement]

                # The status bar collapses captions and leaves just the box
                $node = if ($showing) { $tag.Label } else { $null }
                while ($node -and ![object]::ReferenceEquals($node, $child)) {
                    if ($node.Visibility -ne 'Visible') { $showing = $false }
                    $node = $node.Parent
                }
                if (!$showing) {
                    $siblings.Add($child)
                    continue
                }

                # New-UiCredential lines up on its first text box
                $box = $tag.Control
                if ($box -is [System.Windows.Controls.Panel]) {
                    $queue = [System.Collections.Generic.Queue[object]]::new()
                    $queue.Enqueue($box)
                    $field = $null
                    while ($queue.Count -and !$field) {
                        $node = $queue.Dequeue()
                        if ($node -is [System.Windows.Controls.TextBox] -or $node -is [System.Windows.Controls.PasswordBox]) {
                            $field = $node
                        }
                        elseif ($node -is [System.Windows.Controls.Panel]) {
                            foreach ($inner in $node.Children) { $queue.Enqueue($inner) }
                        }
                        elseif ($node -is [System.Windows.Controls.Decorator] -and $node.Child) { $queue.Enqueue($node.Child) }
                    }
                    if ($field -and $field.ActualHeight -gt 0) { $box = $field }
                }

                # Not laid out yet
                if ($box.ActualHeight -le 0) { continue }

                # Box top before any push
                $pushed = 0
                if ($state.Original.ContainsKey($child)) { $pushed = $child.Margin.Top - $state.Original[$child].Top  }
                $fixed = ![object]::ReferenceEquals($source, $child) -or $child.Resources.Contains('__PsUiPlacedByUser')
                $entry = @{
                    Child   = $child
                    Source  = $source
                    X       = [System.Windows.Controls.Primitives.LayoutInformation]::GetLayoutSlot($child).X
                    Height  = $box.ActualHeight
                    Natural = $box.TranslatePoint($origin, $panel).Y - $pushed
                    Fixed   = $fixed
                    Tallest = 0
                }

                # Whatever lines up on a box pinned low or central, even one inside a nested row, stops at the row bottom
                if ($fixed -and "$($child.VerticalAlignment) $($source.VerticalAlignment)" -match 'Bottom|Center') {
                    $ownSlot      = [System.Windows.Controls.Primitives.LayoutInformation]::GetLayoutSlot($child)
                    $entry.Bottom = $ownSlot.Y + $ownSlot.Height
                }
                $labeled.Add($entry)
            }
            if (!$labeled.Count) { continue }

            # Placed boxes and nested rows never drag the row after them
            $movable = [System.Collections.Generic.List[object]]::new()
            foreach ($entry in $labeled) {
                $entry.Top = $entry.Natural
                if (!$entry.Fixed) { $movable.Add($entry) }
            }

            # Boxes more than 4px apart drop to the lowest. Radio groups sit 2px low on their own.
            $lowest  = $null
            $highest = [double]::MaxValue
            foreach ($entry in $movable) {
                if (!$lowest -or $entry.Natural -gt $lowest.Natural) { $lowest = $entry }
                $highest = [Math]::Min($highest, $entry.Natural)
            }
            if (!$lowest -or $lowest.Natural - $highest -le 4) { $movable.Clear() }
            foreach ($entry in $movable) {
                if ([object]::ReferenceEquals($entry, $lowest)) { continue }

                # Shorter boxes go on the lowest one's middle, and beside a text area the tops line up instead
                $push = $lowest.Natural - $entry.Natural
                if ($entry.Height -lt $lowest.Height -and $lowest.Height -le $entry.Height * 1.5 + 8) {
                    $push += ($lowest.Height - $entry.Height) / 2
                }
                if ($push -le 0.5) { continue }

                $child = $entry.Child
                & $state.Remember $child
                $margin    = $child.Margin
                $wantTop   = $state.Original[$child].Top + $push
                $entry.Top = $entry.Natural + $push
                [void]$keep.Add($child)
                if ([Math]::Abs($margin.Top - $wantTop) -gt 0.5) {
                    $child.Margin = [System.Windows.Thickness]::new($margin.Left, $wantTop, $margin.Right, $margin.Bottom)
                }
            }

            # Leftmost box
            $first = $labeled[0]
            foreach ($entry in $labeled) {
                if ($entry.X -lt $first.X) { $first = $entry }
            }

            # Each control sits on the nearest labeled box to its left, or on the first one when it leads the row
            $placements = [System.Collections.Generic.List[object]]::new()
            foreach ($sibling in $siblings) {
                if ($sibling.Resources.Contains('__PsUiPlacedByUser')) { continue }

                # Cards and expanders stay put, since an expander opens downward from its header
                if ($sibling -is [System.Windows.Controls.Border] -and $sibling.Child -is [System.Windows.Controls.Panel]) { continue }

                # New-UiProgress -Label's caption is already level
                if ($sibling -is [System.Windows.Controls.StackPanel] -and $sibling.Children.Count -gt 1) {
                    $bar = $sibling.Children[1]
                    if ($bar -is [System.Windows.Controls.Grid] -and $bar.Children.Count) { $bar = $bar.Children[0] }
                    
                    $captioned = $bar -is [System.Windows.Controls.ProgressBar] -and $bar.Tag -is [hashtable] -and [object]::ReferenceEquals($bar.Tag.LabelBlock, $sibling.Children[0])
                    if ($captioned) { continue }
                }

                $slot = [System.Windows.Controls.Primitives.LayoutInformation]::GetLayoutSlot($sibling)
                $ref  = $null
                
                foreach ($entry in $labeled) {
                    if ($entry.X -lt $slot.X -and (!$ref -or $entry.X -gt $ref.X)) { $ref = $entry }
                }
                if (!$ref) { $ref = $first }

                # Stretch gives a child the whole line as its ActualHeight
                $height = $sibling.ActualHeight
                if ("$($sibling.VerticalAlignment)" -eq 'Stretch' -and [double]::IsNaN($sibling.Height)) {
                    $height = $sibling.DesiredSize.Height - $sibling.Margin.Top - $sibling.Margin.Bottom
                }

                # Skips spacers and a grid or group box tall enough to set the line height itself
                if ($height -le 0.5 -or $height -gt $ref.Height * 1.5 + 8) { continue }
                $ref.Tallest = [Math]::Max($ref.Tallest, $height)
                $placements.Add(@{
                    Sibling = $sibling
                    SlotY   = $slot.Y
                    Ref     = $ref
                    Height  = $height
                })
            }

            # Never less than a 28px line or a lone small glyph floats
            foreach ($placement in $placements) {
                $ref     = $placement.Ref
                $lineH   = [Math]::Max($ref.Tallest, 28)
                $band    = $ref.Height
                $sibling = $placement.Sibling
                $margin  = $sibling.Margin
                if ($ref.Height -gt $lineH * 1.5 + 8) { $band = $lineH }
                $targetTop = $ref.Top + ($band - $placement.Height) / 2
                $marginTop = [Math]::Max(0, $targetTop - $placement.SlotY)
                $shiftY    = 0

                # RenderTransform cause a margin counts toward the row height the box follows
                if ($ref.Bottom) {
                    $ownTop    = if ($state.Original.ContainsKey($sibling)) { $state.Original[$sibling].Top } else { $margin.Top }
                    $room      = $ref.Bottom - $placement.SlotY - $placement.Height - $margin.Bottom
                    $shiftY    = [Math]::Max(0, [Math]::Min($marginTop, $room)) - $ownTop
                    $marginTop = $ownTop
                }
                [void]$keep.Add($sibling)
                if ($state.Hooked.Add($sibling)) { $sibling.Add_SizeChanged($state.OnChildSize) }

                $shift   = if ($state.Shifts.ContainsKey($sibling)) { $state.Shifts[$sibling] } else { $null }
                $shifted = if ($shift) { $shift.Y } else { 0 }
                $settled = "$($sibling.VerticalAlignment)" -eq 'Top' -and [Math]::Abs($margin.Top - $marginTop) -le 0.5 -and [Math]::Abs($shifted - $shiftY) -le 0.5

                if ($settled) { continue }
                & $state.Remember $sibling
                $sibling.VerticalAlignment = 'Top'
                $sibling.Margin = [System.Windows.Thickness]::new($margin.Left, $marginTop, $margin.Right, $margin.Bottom)
                if (!$shift -and $shiftY) {
                    $shift                   = [System.Windows.Media.TranslateTransform]::new()
                    $state.Shifts[$sibling]  = $shift
                    $sibling.RenderTransform = $shift
                }
                if ($shift) { $shift.Y = $shiftY }
            }

            # When a taller controls sets the row height, a caption that wraps moves the box without its StackPanel changing size
            foreach ($entry in $labeled) {
                if (!$state.Hooked.Add($entry.Source)) { continue }
                $entry.Source.Add_SizeChanged($state.OnChildSize)
                $entry.Source.Tag.Label.Add_SizeChanged($state.OnChildSize)
            }
        }

        # Whatever left a mixed row gets its own values back
        foreach ($moved in @($state.Original.Keys)) {
            if ($keep.Contains($moved)) { continue }
            $saved = $state.Original[$moved]
            [void]$state.Original.Remove($moved)
            if ([object]::ReferenceEquals($saved.VA, $unset)) { $moved.ClearValue($vaProp) }
            else { $moved.SetValue($vaProp, $saved.VA) }
            if ([object]::ReferenceEquals($saved.Margin, $unset)) { $moved.ClearValue($marginDp) }
            else { $moved.SetValue($marginDp, $saved.Margin) }
            if (!$state.Shifts.Remove($moved)) { continue }
            if ([object]::ReferenceEquals($saved.Shift, $unset)) { $moved.ClearValue($shiftDp) }
            else { $moved.SetValue($shiftDp, $saved.Shift) }
        }
    }.GetNewClosure()

    # Set-ResponsiveConstraints sets child widths from SizeChanged too, and those lay out after every handler has run
    $state.Deferred = {
        $state.Pending = $false
        & $state.Pass
    }.GetNewClosure()
    $state.Schedule = {
        trap { Write-Debug "Set-UiRowAlignment schedule: $_"; continue }
        if ($state.Pending) { return }
        $state.Pending = $true
        $afterLayout   = [System.Windows.Threading.DispatcherPriority]::Loaded
        [void]$state.Panel.Dispatcher.BeginInvoke($afterLayout, [Action]$state.Deferred)
    }.GetNewClosure()
    $state.OnChildSize = {
        param($sender, $changeArgs)
        & $state.Schedule
    }.GetNewClosure()

    # Straight away too for a panel without a window
    $Panel.Add_SizeChanged({
        param($sender, $sizeArgs)
        & $state.Pass $true
        & $state.Schedule
    }.GetNewClosure())

    # The panel has usually been laid out by the time a labeled control attachs it on load
    & $state.Schedule
}