Private/Resolve-FluenceClickedButton.ps1
|
<# Copyright (c) 2026, Dan Cunningham. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #> function Resolve-FluenceClickedButton { <# .SYNOPSIS Returns the name of the button that caused the dialog to close. .DESCRIPTION Given a dialog result hashtable and the button list, resolves which button was clicked. If a non-cancel button's flag is true in Result, returns that button's Name. If Result.TimedOut is true and -DefaultButton names a button, returns that name. If Result.Cancelled or Result.TimedOut is true and a cancel button exists in the set, returns its Name; with no cancel button the last (right-most, safe) button's Name is returned. Otherwise returns $null (window closed without a recognized action). .PARAMETER Result The raw result hashtable (or Fluence.DialogResult) from Show-FluenceDialog. .PARAMETER Buttons The array of Fluence.Button objects that were passed to Show-FluenceDialog. .PARAMETER DefaultButton The button name a timeout resolves to. When omitted, a timeout maps like a dismissal. .OUTPUTS System.String .NOTES Does not require a host application; pure logic helper for Show-FluenceMessage. #> [CmdletBinding()] [OutputType([string])] param ( [Parameter(Mandatory = $true)] [object]$Result, [Parameter(Mandatory = $true)] [object[]]$Buttons, [Parameter()] [string]$DefaultButton ) # Normalize Result to a plain hashtable so the same logic works for both # a raw [hashtable] (unit tests) and a [pscustomobject] / Fluence.DialogResult # (the runtime shape returned by ConvertTo-FluenceResult). $values = @{} if ($Result -is [System.Collections.IDictionary]) { foreach ($key in $Result.Keys) { $values[$key] = $Result[$key] } } else { foreach ($property in $Result.PSObject.Properties) { $values[$property.Name] = $property.Value } } # Check non-cancel buttons first: if any flag is true, that button was clicked. foreach ($button in $Buttons) { if (-not $button.IsCancel) { $flag = $values[$button.Name] if ($flag -eq $true) { return $button.Name } } } # A timeout resolves to the caller's chosen default when one is named. Without one it maps like # a dismissal below, so an unattended dialog still lands on the safe choice. $timedOut = ($values['TimedOut'] -eq $true) if ($timedOut -and -not [string]::IsNullOrWhiteSpace($DefaultButton)) { return $DefaultButton } # Dismissal path (title-bar X, Esc, or an unattended timeout). $isCancelled = ($values['Cancelled'] -eq $true) if ($isCancelled -or $timedOut) { $cancelButton = $Buttons | Where-Object { $_.IsCancel -eq $true } | Select-Object -First 1 if ($null -ne $cancelButton) { return $cancelButton.Name } # No explicit cancel button (for example the YesNo or OK preset): a dismissal maps to the # safe/negative choice, the last (right-most) button in the set, by the Win32 convention that # the dismissing action sits last (YesNo -> No, OK -> OK). This avoids returning $null, which # a caller guard like `if ($answer -ne 'No')` would treat as "proceed" and run a destructive # branch on a dismiss. if ($Buttons.Count -ge 1) { return $Buttons[$Buttons.Count - 1].Name } } return $null } |