public/controls/status/Set-UiProgress.ps1
|
function Set-UiProgress { <# .SYNOPSIS Updates a progress bar's value, label, severity tint, or mode. .DESCRIPTION Updates a New-UiProgress bar while an action runs: set or increment the value, swap the label, tint by severity, or flip indeterminate mode. Safe to call from async actions. .PARAMETER Variable Name of the progress bar to update. .PARAMETER Value New value. Clamped to the bar's Min/Max. .PARAMETER Increment Add this to the current value. If combined with -Value, adds to that. .PARAMETER Label Replace the label text above the bar (only works if built with -Label). .PARAMETER Severity Re-tint the bar: Info, Success, Warning, Error. .PARAMETER Indeterminate Toggle indeterminate mode on/off. Bar template is fixed at construction, so the first toggle starts the animation cold. Pass -Indeterminate to New-UiProgress up front for cleaner motion. .EXAMPLE Set-UiProgress -Variable 'progress' -Value 50 .EXAMPLE Set-UiProgress -Variable 'files' -Increment 1 -Label "Processed $i of $total" .EXAMPLE Set-UiProgress -Variable 'job' -Severity Error -Label 'Failed' #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Variable, [double]$Value, [double]$Increment, [string]$Label, [ValidateSet('Info', 'Success', 'Warning', 'Error')] [string]$Severity, # Bool can't be null, so only PSBoundParameters.ContainsKey() says whether your script asked to toggle the mode. [bool]$Indeterminate ) $session = Get-UiSession if (!$session) { Write-Verbose "Set-UiProgress: no active session for '$Variable' - update dropped." return } $progress = $session.Variables[$Variable] if (!$progress) { Write-Verbose "Set-UiProgress: control '$Variable' not found in session - update dropped." return } # Only what was passed goes across and is keyed by parameter name $change = @{} foreach ($key in 'Value', 'Increment', 'Label', 'Severity', 'Indeterminate') { if ($PSBoundParameters.ContainsKey($key)) { $change[$key] = $PSBoundParameters[$key] } } # Only -Variable passed? Don't bother the UI thread about it. if (!$change.Count) { return } if ($change.Contains('Severity')) { $change.BrushKey = Get-SeverityBrushKey -Severity $Severity -UseAccentDefault } $labelMissed = Invoke-OnUIThread -ArgumentList $progress, $change -ScriptBlock { param($progress, $change) if ($change.Contains('Value') -or $change.Contains('Increment')) { # Read $progress.Value here on the UI thread, so -Increment in a tight loop sees the latest committed value and not whatever was current when the call queued $newValue = if ($change.Contains('Value')) { $change.Value } else { $progress.Value } if ($change.Contains('Increment')) { $newValue += $change.Increment } # Clamp so your script doesn't have to think about it if ($newValue -lt $progress.Minimum) { $newValue = $progress.Minimum } if ($newValue -gt $progress.Maximum) { $newValue = $progress.Maximum } $progress.Value = $newValue } if ($change.Contains('Severity')) { # Clear local value so the resource binding wins $progress.ClearValue([System.Windows.Controls.Control]::ForegroundProperty) $progress.SetResourceReference([System.Windows.Controls.Control]::ForegroundProperty, $change.BrushKey) } $meta = $progress.Tag if ($meta -is [hashtable]) { if ($change.Contains('Label')) { if ($meta.LabelBlock) { $meta.LabelBlock.Text = $change.Label } else { $true } } if ($change.Contains('Severity')) { $meta.Severity = $change.Severity $meta.BrushTag = $change.BrushKey } } # See .PARAMETER Indeterminate for the construction time caveat. if ($change.Contains('Indeterminate')) { $progress.IsIndeterminate = $change.Indeterminate } } if ($labelMissed) { Write-Verbose "Set-UiProgress: '$Variable' was created without -Label; skipping label update." } if ($change.Contains('Indeterminate')) { Write-Verbose "Set-UiProgress: toggled IsIndeterminate=$Indeterminate on '$Variable'." } } |