ArinDash/widgets/segmentDisplay.go
2025-12-22 18:49:05 +01:00

113 lines
2.4 KiB
Go

package widgets
import (
"ArinDash/util"
"context"
"image"
"time"
"github.com/mum4k/termdash/cell"
"github.com/mum4k/termdash/terminal/terminalapi"
"github.com/mum4k/termdash/widgetapi"
"github.com/mum4k/termdash/widgets/segmentdisplay"
)
type RollingSegmentDisplayOptions struct {
UpdateText <-chan string
}
func RollingSegmentDisplay(options RollingSegmentDisplayOptions) RollingSegmentDisplayOptions {
widgetOptions["RollingSegmentDisplayOptions"] = createRollingSegmentDisplay
return RollingSegmentDisplayOptions{
UpdateText: options.UpdateText,
}
}
func createRollingSegmentDisplay(ctx context.Context, t terminalapi.Terminal, opt interface{}) widgetapi.Widget {
options, ok := opt.(RollingSegmentDisplayOptions)
if !ok {
panic("invalid options type")
}
segmentDisplayWidget := util.PanicOnErrorWithResult(segmentdisplay.New())
colors := []cell.Color{
cell.ColorNumber(33),
cell.ColorRed,
cell.ColorYellow,
cell.ColorNumber(33),
cell.ColorGreen,
cell.ColorRed,
cell.ColorGreen,
cell.ColorRed,
}
textVal := "ArinDash"
step := 0
go util.Periodic(ctx, util.RedrawInterval, func() error {
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
capacity := 0
termSize := t.Size()
for {
select {
case <-ticker.C:
if capacity == 0 {
capacity = segmentDisplayWidget.Capacity()
}
if t.Size().Eq(image.Point{}) || !t.Size().Eq(termSize) {
termSize = t.Size()
capacity = segmentDisplayWidget.Capacity()
}
state := TextState(textVal, capacity, step)
var chunks []*segmentdisplay.TextChunk
for i := 0; i < capacity; i++ {
if i >= len(state) {
break
}
color := colors[i%len(colors)]
chunks = append(chunks, segmentdisplay.NewChunk(
string(state[i]),
segmentdisplay.WriteCellOpts(cell.FgColor(color)),
))
}
if len(chunks) == 0 {
continue
}
if err := segmentDisplayWidget.Write(chunks); err != nil {
panic(err)
}
step++
case t := <-options.UpdateText:
textVal = t
segmentDisplayWidget.Reset()
step = 0
case <-ctx.Done():
return nil
}
}
})
return segmentDisplayWidget
}
func TextState(text string, capacity, step int) []rune {
if capacity == 0 {
return nil
}
var state []rune
for i := 0; i < capacity; i++ {
state = append(state, ' ')
}
state = append(state, []rune(text)...)
step = step % len(state)
return append(state[step:], state[:step]...)
}