visuals.ps1
function color { param ( $Text, $ForegroundColor = 'default', $BackgroundColor = 'default' ) # Terminal Colors $Colors = @{ "default" = @(40, 50) "black" = @(30, 0) "lightgrey" = @(33, 43) "grey" = @(37, 47) "darkgrey" = @(90, 100) "red" = @(91, 101) "darkred" = @(31, 41) "green" = @(92, 102) "darkgreen" = @(32, 42) "yellow" = @(93, 103) "white" = @(97, 107) "brightblue" = @(94, 104) "darkblue" = @(34, 44) "indigo" = @(35, 45) "cyan" = @(96, 106) "darkcyan" = @(36, 46) } if ( $ForegroundColor -notin $Colors.Keys -or $BackgroundColor -notin $Colors.Keys) { Write-Error "Invalid color choice!" -ErrorAction Stop } "$([char]27)[$($colors[$ForegroundColor][0])m$([char]27)[$($colors[$BackgroundColor][1])m$($Text)$([char]27)[0m" } function Open-Spinner { param( [string]$label = "Loading", [string]$type = "Dot" ) $Spinners = @{ "Circle" = @{ "Frames" = @("◜", "◠", "◝", "◞", "◡", "◟") "Sleep" = 50 } "Dots" = @{ "Frames" = @("⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷", "⣿") "Sleep" = 50 } "Line" = @{ "Frames" = @("▰▱▱▱▱▱▱", "▰▰▱▱▱▱▱", "▰▰▰▱▱▱▱", "▰▰▰▰▱▱▱", "▰▰▰▰▰▱▱", "▰▰▰▰▰▰▱", "▰▰▰▰▰▰▰", "▰▱▱▱▱▱▱") "Sleep" = 50 } "Square" = @{ "Frames" = @("⣾⣿", "⣽⣿", "⣻⣿", "⢿⣿", "⡿⣿", "⣟⣿", "⣯⣿", "⣷⣿","⣿⣾", "⣿⣽", "⣿⣻", "⣿⢿", "⣿⡿", "⣿⣟", "⣿⣯", "⣿⣷") "Sleep" = 50 } "Bubble" = @{ "Frames" = @("......","o.....","Oo....","oOo...",".oOo..","..oOo.","...oOo","....oO",".....o","....oO","...oOo","..oOo.",".oOo..","oOo...","Oo....","o.....","......") "Sleep" = 50 } "Arrow" = @{ "Frames" = @("≻ ", " ≻ ", " ≻ ", " ≻ ", " ≻"," ≺", " ≺ ", " ≺ ", " ≺ ", "≺ ") "Sleep" = 50 } "Pulse" = @{ "Frames" = @("◾", "◾", "◼️", "◼️", "⬛", "⬛", "◼️", "◼️") "Sleep" = 50 } } $statedata = [System.Collections.Hashtable]::Synchronized([System.Collections.Hashtable]::new()) $runspace = [runspacefactory]::CreateRunspace() $statedata.X = $host.ui.rawui.CursorPosition.X $statedata.Y = $host.ui.rawui.CursorPosition.Y $statedata.offset = ($Spinners[$type].Frames | Measure-Object -Property Length -Maximum).Maximum $ThemedFrames = @() $Spinners[$type].Frames | ForEach-Object { $ThemedFrames += gum style $_ --foreground $($Theme["brightPurple"]) } $statedata.Frames =$ThemedFrames $statedata.Sleep = $Spinners[$type].Sleep $statedata.label = $label $runspace.Open() $Runspace.SessionStateProxy.SetVariable("StateData", $StateData) $sb = { [System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [system.Console]::CursorVisible = $false $X = $StateData.X $Y = $StateData.Y $Frames = $statedata.Frames $i = 0 while ($true) { [System.Console]::setcursorposition($X, $Y) # $text = "$([char]27)[35m$([char]27)[50m$($Frames[$i])$([char]27)[0m" $text = $Frames[$i] [system.console]::write($text) [System.Console]::setcursorposition(($X + $statedata.offset) + 1, $Y) [system.console]::write($statedata.label) $i = ($i + 1) % $Frames.Length Start-Sleep -Milliseconds $Statedata.Sleep } } $session = [powershell]::create() $null = $session.AddScript($sb) $session.Runspace = $runspace $null = $session.BeginInvoke() return $Session, $runspace } function Close-Spinner { param( $Session, $Runspace ) $null = $session.Stop() $null = $runspace.dispose() [System.Console]::setcursorposition(0, $host.ui.rawui.CursorPosition.Y) # setting the cursor position (X) [system.console]::write(" ".PadLeft(($host.ui.rawui.BufferSize.Width), " ")) [System.Console]::setcursorposition(0, $host.ui.rawui.CursorPosition.Y) [System.Console]::CursorVisible = $true } class Frame { [char]$UL [char]$UR [char]$TOP [char]$LEFT [char]$RIGHT [char]$BL [char]$BR [char]$BOTTOM [char]$LEFTSPLIT [char]$RIGHTSPLIT $FrameStyles = @{ "Single" = @{ "UL" = "┌" "UR" = "┐" "TOP" = "─" "LEFT" = "│" "RIGHT" = "│" "BL" = "└" "BR" = "┘" "BOTTOM" = "─" "LEFTSPLIT" = "├" "RIGHTSPLIT" = "┤" } "Double" = @{ "UL" = "╔" "UR" = "╗" "TOP" = "═" "LEFT" = "║" "RIGHT" = "║" "BL" = "╚" "BR" = "╝" "BOTTOM" = "═" "LEFTSPLIT" = "╠" "RIGHTSPLIT" = "╣" } "Rounded" = @{ "UL" = "╭" "UR" = "╮" "TOP" = "─" "LEFT" = "│" "RIGHT" = "│" "BL" = "╰" "BR" = "╯" "BOTTOM" = "─" "LEFTSPLIT" = "├" "RIGHTSPLIT" = "┤" } } Frame ( [string]$FrameStyle ) { $this.UL = $this.FrameStyles[$FrameStyle].UL $this.UR = $this.FrameStyles[$FrameStyle].UR $this.TOP = $this.FrameStyles[$FrameStyle].TOP $this.LEFT = $this.FrameStyles[$FrameStyle].LEFT $this.RIGHT = $this.FrameStyles[$FrameStyle].RIGHT $this.BL = $this.FrameStyles[$FrameStyle].BL $this.BR = $this.FrameStyles[$FrameStyle].BR $this.BOTTOM = $this.FrameStyles[$FrameStyle].BOTTOM $this.LEFTSPLIT = $this.FrameStyles[$FrameStyle].LEFTSPLIT $this.RIGHTSPLIT = $this.FrameStyles[$FrameStyle].RIGHTSPLIT } } class window { [int]$X [int]$Y [int]$W [int]$H [Frame]$frameStyle [System.ConsoleColor]$frameColor [string]$title = "" [System.ConsoleColor]$titleColor [string]$footer = "" [int]$page = 1 [int]$nbPages = 1 window( [int]$X, [int]$y, [int]$w, [int]$h, [string]$FrameStyle = "Single", [System.ConsoleColor]$color = "White" ) { $this.X = $X $this.Y = $y $this.W = $W $this.H = $H $this.frameStyle = [Frame]::new($FrameStyle) $this.frameColor = $color } window( [int]$X, [int]$y, [int]$w, [int]$h, [string]$FrameStyle = "Single", [System.ConsoleColor]$color = "White", [string]$title = "", [System.ConsoleColor]$titlecolor = "Blue" ) { $this.X = $X $this.Y = $y $this.W = $W $this.H = $H $this.frameStyle = [Frame]::new($FrameStyle) $this.frameColor = $color $this.title = $title $this.titleColor = $titlecolor } [void] setPosition( [int]$X, [int]$Y ) { [System.Console]::SetCursorPosition($X, $Y) } [void] drawWindow() { # $esc = $([char]0x1b) [System.Console]::CursorVisible = $false $this.setPosition($this.X, $this.Y) $bloc1 = $this.frameStyle.UL, "".PadLeft($this.W - 2, $this.frameStyle.TOP), $this.frameStyle.UR -join "" $blank = $this.frameStyle.LEFT, "".PadLeft($this.W - 2, " "), $this.frameStyle.RIGHT -join "" Write-Host $bloc1 -ForegroundColor $this.frameColor -NoNewline for ($i = 1; $i -lt $this.H; $i++) { $Y2 = $this.Y + $i $X3 = $this.X $this.setPosition($X3, $Y2) Write-Host $blank -ForegroundColor $this.frameColor } $Y2 = $this.Y + $this.H $this.setPosition( $this.X, $Y2) $bloc1 = $this.frameStyle.BL, "".PadLeft($this.W - 2, $this.frameStyle.BOTTOM), $this.frameStyle.BR -join "" Write-Host $bloc1 -ForegroundColor $this.frameColor -NoNewline $this.drawTitle() $this.drawFooter() } [void] drawVersion() { $v = Get-WGPVersion -param WGP $version = $this.frameStyle.LEFTSPLIT, $v, $this.frameStyle.RIGHTSPLIT -join "" $isempty = [string]::IsNullOrEmpty($v) if ($isempty -eq $true) { $version = $this.frameStyle.LEFTSPLIT, "Debug", $this.frameStyle.RIGHTSPLIT -join "" } [System.Console]::setcursorposition($this.W - ($version.Length + 6), $this.Y ) [console]::write($version) } [void] drawTitle() { if ($this.title -ne "") { $local:X = $this.x + 2 $this.setPosition($local:X, $this.Y) Write-Host ($this.frameStyle.RIGHTSPLIT, " " -join "") -NoNewline -ForegroundColor $this.frameColor $local:X = $local:X + 2 $this.setPosition($local:X, $this.Y) Write-Host $this.title -NoNewline -ForegroundColor $this.titleColor $local:X = $local:X + $this.title.Length $this.setPosition($local:X, $this.Y) Write-Host (" ", $this.frameStyle.LEFTSPLIT -join "") -NoNewline -ForegroundColor $this.frameColor } } [void] drawFooter() { $Y2 = $this.Y + $this.H $this.setPosition( $this.X, $Y2) $bloc1 = $this.frameStyle.BL, "".PadLeft($this.W - 2, $this.frameStyle.BOTTOM), $this.frameStyle.BR -join "" Write-Host $bloc1 -ForegroundColor $this.frameColor -NoNewline if ($this.footer -ne "") { $local:x = $this.x + 2 $local:Y = $this.Y + $this.h $this.setPosition($local:X, $local:Y) $foot = $this.frameStyle.RIGHTSPLIT, " ", $this.footer, " ", $this.frameStyle.LEFTSPLIT -join "" [console]::write($foot) } } [void] drawPagination() { $sPages = ('Page {0}/{1}' -f ($this.page, $this.nbPages)) [System.Console]::setcursorposition($this.W - ($sPages.Length + 6), $this.Y + $this.H) [console]::write($sPages) } [void] clearWindow() { $local:blank = "".PadLeft($this.W, " ") for ($i = 1; $i -lt $this.H; $i++) { $this.setPosition(($this.X), ($this.Y + $i)) Write-Host $blank } } } class Grid { [int]$X [int]$Y [int]$Width [int]$Height } function makeLines { param( [column[]]$columns, [package[]]$items ) $index = 0 [string]$line = "" while ($index -lt $items.Count) { $item = $items[$index] [string]$temp = "" if ($item.IsUpdateAvailable) { $temp = [string]::Concat($temp, "↺ ") } else { $temp = [string]::Concat($temp, " ") } $columns | ForEach-Object { $fieldname = $_.FieldName $width = [int32]$_.Width $buffer = TruncateString -InputString $([string]$item."$fieldname") -MaxLength $width $temp = [string]::Concat($temp,[string]$buffer," ") } $line = [string]::Concat($line, $temp) if ($index -lt $items.Count - 1) { $line = [string]::Concat($line, "`n") } $index ++ } return $line } function makeHeader { param( [column[]]$columns ) $header = " " $columns | ForEach-Object { $w = Get-ProportionalLength -MaxLength $_.Width $header = [string]::Concat($header, $_.Label.PadRight($w," "), " ") } return gum style $([string]::Concat(" ",$header)) --foreground $($Theme["brightYellow"]) } function makeTitle { param( [string]$title, [int]$width ) $w = ($width / 2) + ($title.Length / 2) $title = $title.PadLeft($w, " ") $title = $title.PadRight($width, " ") return gum style $title --foreground $($Theme["brightPurple"]) --background $($Theme["background"]) --bold --align "center" } |