Make termbox event loop async
This commit is contained in:
parent
db1b2cd53f
commit
77a0f68758
5 changed files with 126 additions and 18 deletions
|
@ -14,6 +14,11 @@ func main() {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_ui, err := ui.Initialize(conf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer _ui.Close()
|
||||
var workers []worker.Worker
|
||||
for _, account := range conf.Accounts {
|
||||
work, err := worker.NewWorker(account.Source)
|
||||
|
@ -23,12 +28,8 @@ func main() {
|
|||
go work.Run()
|
||||
work.PostAction(types.Configure{Config: account})
|
||||
workers = append(workers, work)
|
||||
_ui.AddTab(ui.NewAccountTab(&account, &work))
|
||||
}
|
||||
_ui, err := ui.Initialize(conf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer _ui.Close()
|
||||
for !_ui.Exit {
|
||||
activity := false
|
||||
for _, worker := range workers {
|
||||
|
|
41
ui/account.go
Normal file
41
ui/account.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
tb "github.com/nsf/termbox-go"
|
||||
|
||||
"git.sr.ht/~sircmpwn/aerc2/config"
|
||||
"git.sr.ht/~sircmpwn/aerc2/worker"
|
||||
)
|
||||
|
||||
type AccountTab struct {
|
||||
Config *config.AccountConfig
|
||||
Worker *worker.Worker
|
||||
Parent *UIState
|
||||
}
|
||||
|
||||
func NewAccountTab(conf *config.AccountConfig, work *worker.Worker) *AccountTab {
|
||||
return &AccountTab{
|
||||
Config: conf,
|
||||
Worker: work,
|
||||
}
|
||||
}
|
||||
|
||||
func (acc *AccountTab) Name() string {
|
||||
return acc.Config.Name
|
||||
}
|
||||
|
||||
func (acc *AccountTab) Invalid() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (acc *AccountTab) SetParent(parent *UIState) {
|
||||
acc.Parent = parent
|
||||
}
|
||||
|
||||
func (acc *AccountTab) Render(at Geometry) {
|
||||
cell := tb.Cell{
|
||||
Fg: tb.ColorDefault,
|
||||
Bg: tb.ColorDefault,
|
||||
}
|
||||
TPrintf(&at, cell, "%s", acc.Name())
|
||||
}
|
21
ui/helpers.go
Normal file
21
ui/helpers.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
tb "github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
func TPrintf(geo *Geometry, ref tb.Cell, format string, a ...interface{}) {
|
||||
str := fmt.Sprintf(format, a...)
|
||||
_geo := *geo
|
||||
for _, ch := range str {
|
||||
tb.SetCell(geo.Col, geo.Row, ch, ref.Fg, ref.Bg)
|
||||
geo.Col++
|
||||
if geo.Col == _geo.Col+geo.Width {
|
||||
// TODO: Abort when out of room?
|
||||
geo.Col = _geo.Col
|
||||
geo.Row++
|
||||
}
|
||||
}
|
||||
}
|
53
ui/render.go
53
ui/render.go
|
@ -8,15 +8,21 @@ import (
|
|||
|
||||
func Initialize(conf *config.AercConfig) (*UIState, error) {
|
||||
state := UIState{
|
||||
Config: conf,
|
||||
InvalidPanes: InvalidateAll,
|
||||
Tabs: make([]AercTab, len(conf.Accounts)),
|
||||
|
||||
tbEvents: make(chan tb.Event, 10),
|
||||
}
|
||||
// TODO: Initialize each tab to a mailbox tab
|
||||
if err := tb.Init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tb.SetInputMode(tb.InputEsc | tb.InputMouse)
|
||||
tb.SetOutputMode(tb.Output256)
|
||||
go (func() {
|
||||
for !state.Exit {
|
||||
state.tbEvents <- tb.PollEvent()
|
||||
}
|
||||
})()
|
||||
return &state, nil
|
||||
}
|
||||
|
||||
|
@ -24,21 +30,50 @@ func (state *UIState) Close() {
|
|||
tb.Close()
|
||||
}
|
||||
|
||||
func (state *UIState) AddTab(tab AercTab) {
|
||||
state.Tabs = append(state.Tabs, tab)
|
||||
}
|
||||
|
||||
func (state *UIState) Invalidate(what uint) {
|
||||
state.InvalidPanes |= what
|
||||
}
|
||||
|
||||
func (state *UIState) calcGeometries() {
|
||||
width, height := tb.Size()
|
||||
// TODO: more
|
||||
state.Panes.TabView = Geometry{
|
||||
Row: 0,
|
||||
Col: 0,
|
||||
Width: width,
|
||||
Height: height,
|
||||
}
|
||||
}
|
||||
|
||||
func (state *UIState) Tick() bool {
|
||||
switch e := tb.PollEvent(); e.Type {
|
||||
case tb.EventKey:
|
||||
if e.Key == tb.KeyEsc {
|
||||
state.Exit = true
|
||||
select {
|
||||
case event := <-state.tbEvents:
|
||||
switch event.Type {
|
||||
case tb.EventKey:
|
||||
if event.Key == tb.KeyEsc {
|
||||
state.Exit = true
|
||||
}
|
||||
case tb.EventResize:
|
||||
state.Invalidate(InvalidateAll)
|
||||
}
|
||||
case tb.EventResize:
|
||||
state.Invalidate(InvalidateAll)
|
||||
default:
|
||||
// no-op
|
||||
break
|
||||
}
|
||||
if state.InvalidPanes != 0 {
|
||||
// TODO: re-render
|
||||
if state.InvalidPanes&InvalidateAll == InvalidateAll {
|
||||
tb.Clear(tb.ColorDefault, tb.ColorDefault)
|
||||
state.calcGeometries()
|
||||
}
|
||||
if state.InvalidPanes&InvalidateTabs != 0 {
|
||||
tab := state.Tabs[state.SelectedTab]
|
||||
tab.Render(state.Panes.TabView)
|
||||
}
|
||||
tb.Flush()
|
||||
state.InvalidPanes = 0
|
||||
}
|
||||
return true
|
||||
|
|
18
ui/types.go
18
ui/types.go
|
@ -1,5 +1,11 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
tb "github.com/nsf/termbox-go"
|
||||
|
||||
"git.sr.ht/~sircmpwn/aerc2/config"
|
||||
)
|
||||
|
||||
const (
|
||||
Valid = 0
|
||||
InvalidateTabs = 1 << iota
|
||||
|
@ -12,19 +18,21 @@ const (
|
|||
)
|
||||
|
||||
type Geometry struct {
|
||||
row int
|
||||
col int
|
||||
width int
|
||||
height int
|
||||
Row int
|
||||
Col int
|
||||
Width int
|
||||
Height int
|
||||
}
|
||||
|
||||
type AercTab interface {
|
||||
Name() string
|
||||
Invalid() bool
|
||||
Render(at Geometry)
|
||||
SetParent(parent *UIState)
|
||||
}
|
||||
|
||||
type UIState struct {
|
||||
Config *config.AercConfig
|
||||
Exit bool
|
||||
InvalidPanes uint
|
||||
|
||||
|
@ -44,4 +52,6 @@ type UIState struct {
|
|||
Index int
|
||||
Scroll int
|
||||
}
|
||||
|
||||
tbEvents chan tb.Event
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue