diff options
author | Robin Jarry <robin@jarry.cc> | 2023-10-09 13:52:20 +0200 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-10-10 11:37:56 +0200 |
commit | 598e4a5803578ab3e291f232d6aad31b4efd8ea4 (patch) | |
tree | c55e16d60e2c3eea2d6de27d1bac18db5670ec77 /app/spinner.go | |
parent | 61bca76423ee87bd59084a146eca71c6bae085e1 (diff) | |
download | aerc-598e4a5803578ab3e291f232d6aad31b4efd8ea4.tar.gz |
widgets: rename package to app
This is the central point of all aerc. Having it named widgets is
confusing. Rename it to app. It will make a cleaner transition when
making the app.Aerc object available globally in the next commit.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Moritz Poldrack <moritz@poldrack.dev>
Diffstat (limited to 'app/spinner.go')
-rw-r--r-- | app/spinner.go | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/app/spinner.go b/app/spinner.go new file mode 100644 index 00000000..bcf8168a --- /dev/null +++ b/app/spinner.go @@ -0,0 +1,86 @@ +package app + +import ( + "strings" + "sync/atomic" + "time" + + "github.com/gdamore/tcell/v2" + + "git.sr.ht/~rjarry/aerc/config" + "git.sr.ht/~rjarry/aerc/lib/ui" + "git.sr.ht/~rjarry/aerc/log" +) + +type Spinner struct { + frame int64 // access via atomic + frames []string + interval time.Duration + stop chan struct{} + style tcell.Style +} + +func NewSpinner(uiConf *config.UIConfig) *Spinner { + spinner := Spinner{ + stop: make(chan struct{}), + frame: -1, + interval: uiConf.SpinnerInterval, + frames: strings.Split(uiConf.Spinner, uiConf.SpinnerDelimiter), + style: uiConf.GetStyle(config.STYLE_SPINNER), + } + return &spinner +} + +func (s *Spinner) Start() { + if s.IsRunning() { + return + } + + atomic.StoreInt64(&s.frame, 0) + + go func() { + defer log.PanicHandler() + + for { + select { + case <-s.stop: + atomic.StoreInt64(&s.frame, -1) + s.stop <- struct{}{} + return + case <-time.After(s.interval): + atomic.AddInt64(&s.frame, 1) + ui.Invalidate() + } + } + }() +} + +func (s *Spinner) Stop() { + if !s.IsRunning() { + return + } + + s.stop <- struct{}{} + <-s.stop + s.Invalidate() +} + +func (s *Spinner) IsRunning() bool { + return atomic.LoadInt64(&s.frame) != -1 +} + +func (s *Spinner) Draw(ctx *ui.Context) { + if !s.IsRunning() { + s.Start() + } + + cur := int(atomic.LoadInt64(&s.frame) % int64(len(s.frames))) + + ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', s.style) + col := ctx.Width()/2 - len(s.frames[0])/2 + 1 + ctx.Printf(col, 0, s.style, "%s", s.frames[cur]) +} + +func (s *Spinner) Invalidate() { + ui.Invalidate() +} |