Files
Win11Debloat/Scripts/GUI/Show-Bubble.ps1
2026-06-24 20:55:17 +02:00

164 lines
5.1 KiB
PowerShell

<#
.SYNOPSIS
Hides the currently displayed bubble popup.
.DESCRIPTION
Closes the bubble popup with a smooth fade-out animation (220ms). If the
-Immediate switch is used, the popup is closed instantly without animation.
This function is called automatically by Show-Bubble's timer and can also
be invoked manually to dismiss the bubble early.
.PARAMETER Immediate
If specified, the bubble popup is closed instantly without a fade-out
animation. Any pending close timer is also stopped.
.EXAMPLE
Hide-Bubble
.EXAMPLE
Hide-Bubble -Immediate
#>
function Hide-Bubble {
param (
[Parameter(Mandatory=$false)]
[switch]$Immediate
)
if ($script:BubbleTimer) {
$script:BubbleTimer.Stop()
$script:BubbleTimer = $null
}
if (-not $script:BubblePopup) { return }
if ($Immediate -or -not $script:BubblePopup.Child) {
$script:BubblePopup.IsOpen = $false
$script:BubblePopup = $null
$script:BubbleIsClosing = $false
return
}
if ($script:BubbleIsClosing) { return }
$script:BubbleIsClosing = $true
$bubblePanel = $script:BubblePopup.Child
$fadeOut = New-Object System.Windows.Media.Animation.DoubleAnimation
$fadeOut.From = [double]$bubblePanel.Opacity
$fadeOut.To = 0
$fadeOut.Duration = [System.Windows.Duration]::new([TimeSpan]::FromMilliseconds(220))
$fadeOut.Add_Completed({
if ($script:BubblePopup) {
$script:BubblePopup.IsOpen = $false
$script:BubblePopup = $null
}
$script:BubbleIsClosing = $false
})
$bubblePanel.BeginAnimation([System.Windows.UIElement]::OpacityProperty, $fadeOut)
}
<#
.SYNOPSIS
Displays a transient bubble popup hint anchored above a target control.
.DESCRIPTION
Shows a WPF popup styled as a speech bubble above the specified target
control. The bubble fades in with a animation, displays for a configurable
duration, then fades out. Any previously shown bubble is dismissed
immediately before showing the new one.
.PARAMETER TargetControl
The WPF Control above which the bubble popup will be placed. This
parameter is mandatory.
.PARAMETER Message
The text message to display inside the bubble. Defaults to
'View the selected changes here'.
.PARAMETER DurationSeconds
The number of seconds the bubble remains visible before auto-hiding.
The minimum value is 1 second. Defaults to 5 seconds.
.EXAMPLE
Show-Bubble -TargetControl $myButton
.EXAMPLE
Show-Bubble -TargetControl $myButton -Message 'Changes saved!' -DurationSeconds 3
#>
function Show-Bubble {
param (
[Parameter(Mandatory=$true)]
[System.Windows.Controls.Control]$TargetControl,
[Parameter(Mandatory=$false)]
[string]$Message = 'View the selected changes here',
[Parameter(Mandatory=$false)]
[int]$DurationSeconds = 5
)
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase | Out-Null
if (-not $TargetControl) { return }
Hide-Bubble -Immediate
$xaml = Get-Content -Path $script:BubbleHintSchema -Raw
$reader = [System.Xml.XmlReader]::Create([System.IO.StringReader]::new($xaml))
try {
$bubblePanel = [System.Windows.Markup.XamlReader]::Load($reader)
}
finally {
$reader.Close()
}
$bubbleText = $bubblePanel.FindName('BubbleText')
if ($bubbleText) {
$bubbleText.Text = $Message
}
$bubblePanel.BeginAnimation([System.Windows.UIElement]::OpacityProperty, $null)
$bubblePanel.Opacity = 0
$popup = New-Object System.Windows.Controls.Primitives.Popup
$popup.AllowsTransparency = $true
$popup.PopupAnimation = 'None'
$popup.StaysOpen = $true
$popup.PlacementTarget = $TargetControl
$popup.Placement = [System.Windows.Controls.Primitives.PlacementMode]::Top
$popup.VerticalOffset = -1
$popup.Child = $bubblePanel
$popup.Add_Opened({
param($sender, $e)
if (-not $sender) { return }
$panel = $sender.Child
$target = $sender.PlacementTarget
if (-not $panel -or -not $target) { return }
$panel.Measure([System.Windows.Size]::new([double]::PositiveInfinity, [double]::PositiveInfinity))
$bubbleWidth = $panel.DesiredSize.Width
$targetWidth = $target.ActualWidth
$sender.HorizontalOffset = ($targetWidth - $bubbleWidth) / 2
$fadeIn = New-Object System.Windows.Media.Animation.DoubleAnimation
$fadeIn.From = 0
$fadeIn.To = 1
$fadeIn.BeginTime = [TimeSpan]::FromMilliseconds(30)
$fadeIn.Duration = [System.Windows.Duration]::new([TimeSpan]::FromMilliseconds(320))
$panel.BeginAnimation([System.Windows.UIElement]::OpacityProperty, $fadeIn)
})
$script:BubbleIsClosing = $false
$script:BubblePopup = $popup
$script:BubblePopup.IsOpen = $true
$script:BubbleTimer = New-Object System.Windows.Threading.DispatcherTimer
$script:BubbleTimer.Interval = [TimeSpan]::FromSeconds([Math]::Max(1, $DurationSeconds))
$script:BubbleTimer.Add_Tick({
Hide-Bubble
})
$script:BubbleTimer.Start()
}