diff options
Diffstat (limited to 'widgets/dirlist.go')
-rw-r--r-- | widgets/dirlist.go | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/widgets/dirlist.go b/widgets/dirlist.go new file mode 100644 index 00000000..d66ae1f5 --- /dev/null +++ b/widgets/dirlist.go @@ -0,0 +1,156 @@ +package widgets + +import ( + "log" + "sort" + + "github.com/gdamore/tcell" + + "git.sr.ht/~sircmpwn/aerc2/config" + "git.sr.ht/~sircmpwn/aerc2/lib/ui" + "git.sr.ht/~sircmpwn/aerc2/worker/types" +) + +type DirectoryList struct { + conf *config.AccountConfig + dirs []string + logger *log.Logger + onInvalidate func(d ui.Drawable) + selecting string + selected string + spinner *Spinner + worker *types.Worker +} + +func NewDirectoryList(conf *config.AccountConfig, + logger *log.Logger, worker *types.Worker) *DirectoryList { + + dirlist := &DirectoryList{ + conf: conf, + logger: logger, + spinner: NewSpinner(), + worker: worker, + } + dirlist.spinner.OnInvalidate(func(_ ui.Drawable) { + dirlist.Invalidate() + }) + dirlist.spinner.Start() + return dirlist +} + +func (dirlist *DirectoryList) UpdateList(done func(dirs []string)) { + var dirs []string + dirlist.worker.PostAction( + &types.ListDirectories{}, func(msg types.WorkerMessage) { + + switch msg := msg.(type) { + case *types.Directory: + dirs = append(dirs, msg.Name) + case *types.Done: + sort.Strings(dirs) + dirlist.dirs = dirs + dirlist.spinner.Stop() + dirlist.Invalidate() + if done != nil { + done(dirs) + } + } + }) +} + +func (dirlist *DirectoryList) Select(name string) { + dirlist.selecting = name + dirlist.worker.PostAction(&types.OpenDirectory{Directory: name}, + func(msg types.WorkerMessage) { + switch msg.(type) { + case *types.Error: + dirlist.selecting = "" + default: + dirlist.selected = dirlist.selecting + } + dirlist.Invalidate() + }) + dirlist.Invalidate() +} + +func (dirlist *DirectoryList) Selected() string { + return dirlist.selected +} + +func (dirlist *DirectoryList) OnInvalidate(onInvalidate func(d ui.Drawable)) { + dirlist.onInvalidate = onInvalidate +} + +func (dirlist *DirectoryList) Invalidate() { + if dirlist.onInvalidate != nil { + dirlist.onInvalidate(dirlist) + } +} + +func (dirlist *DirectoryList) Draw(ctx *ui.Context) { + ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault) + + if dirlist.spinner.IsRunning() { + dirlist.spinner.Draw(ctx) + return + } + + row := 0 + for _, name := range dirlist.dirs { + if row >= ctx.Height() { + break + } + if len(dirlist.conf.Folders) > 1 && name != dirlist.selected { + idx := sort.SearchStrings(dirlist.conf.Folders, name) + if idx == len(dirlist.conf.Folders) || + dirlist.conf.Folders[idx] != name { + continue + } + } + style := tcell.StyleDefault + if name == dirlist.selected { + style = style.Background(tcell.ColorWhite). + Foreground(tcell.ColorBlack) + } + ctx.Fill(0, row, ctx.Width(), 1, ' ', style) + ctx.Printf(0, row, style, "%s", name) + row++ + } +} + +func (dirlist *DirectoryList) nextPrev(delta int) { + for i, dir := range dirlist.dirs { + if dir == dirlist.selected { + var j int + ndirs := len(dirlist.dirs) + for j = i + delta; j != i; j += delta { + if j < 0 { + j = ndirs - 1 + } + if j >= ndirs { + j = 0 + } + name := dirlist.dirs[j] + if len(dirlist.conf.Folders) > 1 && name != dirlist.selected { + idx := sort.SearchStrings(dirlist.conf.Folders, name) + if idx == len(dirlist.conf.Folders) || + dirlist.conf.Folders[idx] != name { + + continue + } + } + break + } + dirlist.Select(dirlist.dirs[j]) + break + } + } +} + +func (dirlist *DirectoryList) Next() { + dirlist.nextPrev(1) +} + +func (dirlist *DirectoryList) Prev() { + dirlist.nextPrev(-1) +} |