TreeControl/SRxDeferredAction.ps1

class SRxDeferredAction {

    hidden [System.Windows.Forms.Timer] $_timer
    hidden [scriptblock] $_work
    hidden [string] $_doneText
    hidden [object] $_owner
    hidden [bool] $_running

    [int] $Delay = 50

    [scriptblock] $OnStatus = $null

    [scriptblock] $OnError = $null

    SRxDeferredAction() {
        $this._running = $false
        $this._timer = [System.Windows.Forms.Timer]::new()
        $this._timer.Interval = $this.Delay
        $this._timer.Tag = $this
        $this._timer.add_tick({
            param($source, $e)
            $d = $source.Tag
            $d.tick()
        })
    }

    [void] Attach($owner) { $this._owner = $owner }

    [void] Run([string]$busyText, [string]$doneText, [scriptblock]$work) {
        try {
            if ($null -eq $work) { return }

            $this._timer.Stop()

            $this._work = $work
            $this._doneText = $doneText
            $this.setBusy($true, $busyText)

            $this._timer.Interval = $this.Delay
            $this._timer.Start()
        } catch { $this.reportError("Run - $($_.Exception.Message)") }
    }

    [void] Cancel() {
        try {
            $this._timer.Stop()
            $this._work = $null
            $this._doneText = ''
            if ($this._running) { $this.setBusy($false, $null) }
            $this._running = $false
        } catch { }
    }

    [bool] IsPending() { return $this._timer.Enabled }
    [bool] IsRunning() { return $this._running }

    hidden [void] tick() {
        $this._timer.Stop()

        $w = $this._work
        $done = $this._doneText
        $this._work = $null
        $this._doneText = ''

        if ($null -eq $w) { $this.setBusy($false, $null); return }

        $this._running = $true
        try { & $w }
        catch { $this.reportError("deferred work - $($_.Exception.Message)") }
        finally {
            $this._running = $false
            $this.setBusy($false, $done)
        }
    }

    hidden [void] setBusy([bool]$on, [string]$text) {
        try {
            if ($null -ne $this._owner) {
                if ($on) { $this._owner.Cursor = [System.Windows.Forms.Cursors]::WaitCursor }
                else     { $this._owner.Cursor = [System.Windows.Forms.Cursors]::Default }
            }
        } catch { }
        try {
            if ((-not [string]::IsNullOrEmpty($text)) -and ($null -ne $this.OnStatus)) { & $this.OnStatus $text }
        } catch { }
    }

    hidden [void] reportError([string]$message) {
        try {
            if ($null -ne $this.OnError) { & $this.OnError $message; return }
        } catch { }
        Write-Host "SRxDeferredAction - $message"
    }

    [void] Dispose() {
        try { $this.Cancel(); $this._timer.Dispose() } catch { }
    }
}