mirror of
https://github.com/navidys/tvxwidgets.git
synced 2025-04-28 13:48:52 +08:00
Add spinner widget.
Signed-off-by: Andreas Krennmair <ak@synflood.at>
This commit is contained in:
parent
02e3c8f9d9
commit
f1d2fee386
@ -56,3 +56,4 @@ func main() {
|
|||||||
* percentage mode gauge
|
* percentage mode gauge
|
||||||
* utilisation mode gauge
|
* utilisation mode gauge
|
||||||
* message dialog (info and error)
|
* message dialog (info and error)
|
||||||
|
* spinner
|
||||||
|
1
demos/spinner/README.md
Normal file
1
demos/spinner/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|

|
67
demos/spinner/main.go
Normal file
67
demos/spinner/main.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/navidys/tvxwidgets"
|
||||||
|
"github.com/rivo/tview"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := tview.NewApplication()
|
||||||
|
grid := tview.NewGrid()
|
||||||
|
grid.SetBorder(true).SetTitle("Spinners")
|
||||||
|
|
||||||
|
spinners := [][]*tvxwidgets.Spinner{
|
||||||
|
{
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerDotsCircling),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerDotsUpDown),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerBounce),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerLine),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerCircleQuarters),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerSquareCorners),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerCircleHalves),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerCorners),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerArrows),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerHamburger),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerStack),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerStar),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerGrowHorizontal),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerGrowVertical),
|
||||||
|
tvxwidgets.NewSpinner().SetStyle(tvxwidgets.SpinnerBoxBounce),
|
||||||
|
tvxwidgets.NewSpinner().SetCustomStyle([]rune{'🕛', '🕐', '🕑', '🕒', '🕓', '🕔', '🕕', '🕖', '🕗', '🕘', '🕙', '🕚'}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for rowIdx, row := range spinners {
|
||||||
|
for colIdx, spinner := range row {
|
||||||
|
grid.AddItem(spinner, rowIdx, colIdx, 1, 1, 1, 1, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update := func() {
|
||||||
|
tick := time.NewTicker(100 * time.Millisecond)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-tick.C:
|
||||||
|
for _, row := range spinners {
|
||||||
|
for _, spinner := range row {
|
||||||
|
spinner.Pulse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
app.Draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go update()
|
||||||
|
|
||||||
|
if err := app.SetRoot(grid, false).EnableMouse(true).Run(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
BIN
demos/spinner/screenshot.png
Normal file
BIN
demos/spinner/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
101
spinner.go
Normal file
101
spinner.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package tvxwidgets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
|
"github.com/rivo/tview"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Spinner represents a spinner widget
|
||||||
|
type Spinner struct {
|
||||||
|
*tview.Box
|
||||||
|
|
||||||
|
counter int
|
||||||
|
currentStyle SpinnerStyle
|
||||||
|
|
||||||
|
styles map[SpinnerStyle][]rune
|
||||||
|
}
|
||||||
|
|
||||||
|
type SpinnerStyle int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SpinnerDotsCircling SpinnerStyle = iota
|
||||||
|
SpinnerDotsUpDown
|
||||||
|
SpinnerBounce
|
||||||
|
SpinnerLine
|
||||||
|
SpinnerCircleQuarters
|
||||||
|
SpinnerSquareCorners
|
||||||
|
SpinnerCircleHalves
|
||||||
|
SpinnerCorners
|
||||||
|
SpinnerArrows
|
||||||
|
SpinnerHamburger
|
||||||
|
SpinnerStack
|
||||||
|
SpinnerGrowHorizontal
|
||||||
|
SpinnerGrowVertical
|
||||||
|
SpinnerStar
|
||||||
|
SpinnerBoxBounce
|
||||||
|
spinnerCustom // non-public constant to indicate that a custom style has been set by the user.
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewSpinner returns a new spinner widget.
|
||||||
|
func NewSpinner() *Spinner {
|
||||||
|
return &Spinner{
|
||||||
|
Box: tview.NewBox(),
|
||||||
|
currentStyle: SpinnerDotsCircling,
|
||||||
|
styles: map[SpinnerStyle][]rune{
|
||||||
|
SpinnerDotsCircling: []rune(`⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏`),
|
||||||
|
SpinnerDotsUpDown: []rune(`⠋⠙⠚⠞⠖⠦⠴⠲⠳⠓`),
|
||||||
|
SpinnerBounce: []rune(`⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆`),
|
||||||
|
SpinnerLine: []rune(`|/-\`),
|
||||||
|
SpinnerCircleQuarters: []rune(`◴◷◶◵`),
|
||||||
|
SpinnerSquareCorners: []rune(`◰◳◲◱`),
|
||||||
|
SpinnerCircleHalves: []rune(`◐◓◑◒`),
|
||||||
|
SpinnerCorners: []rune(`⌜⌝⌟⌞`),
|
||||||
|
SpinnerArrows: []rune(`⇑⇗⇒⇘⇓⇙⇐⇖`),
|
||||||
|
SpinnerHamburger: []rune(`☰☱☳☷☶☴`),
|
||||||
|
SpinnerStack: []rune(`䷀䷪䷡䷊䷒䷗䷁䷖䷓䷋䷠䷫`),
|
||||||
|
SpinnerGrowHorizontal: []rune(`▉▊▋▌▍▎▏▎▍▌▋▊▉`),
|
||||||
|
SpinnerGrowVertical: []rune(`▁▃▄▅▆▇▆▅▄▃`),
|
||||||
|
SpinnerStar: []rune(`✶✸✹✺✹✷`),
|
||||||
|
SpinnerBoxBounce: []rune(`▌▀▐▄`),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw draws this primitive onto the screen.
|
||||||
|
func (s *Spinner) Draw(screen tcell.Screen) {
|
||||||
|
s.Box.DrawForSubclass(screen, s)
|
||||||
|
x, y, width, _ := s.Box.GetInnerRect()
|
||||||
|
tview.Print(screen, s.getCurrentFrame(), x, y, width, tview.AlignLeft, tcell.ColorDefault)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pulse updates the spinner to the next frame.
|
||||||
|
func (s *Spinner) Pulse() {
|
||||||
|
s.counter++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset sets the frame counter to 0.
|
||||||
|
func (s *Spinner) Reset() {
|
||||||
|
s.counter = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStyle sets the spinner style.
|
||||||
|
func (s *Spinner) SetStyle(style SpinnerStyle) *Spinner {
|
||||||
|
s.currentStyle = style
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Spinner) getCurrentFrame() string {
|
||||||
|
frames := s.styles[s.currentStyle]
|
||||||
|
if len(frames) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(frames[s.counter%len(frames)])
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCustomStyle sets a list of runes as custom frames to show as the spinner.
|
||||||
|
func (s *Spinner) SetCustomStyle(frames []rune) *Spinner {
|
||||||
|
s.styles[spinnerCustom] = frames
|
||||||
|
s.currentStyle = spinnerCustom
|
||||||
|
return s
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user