diff options
author | Robin Jarry <robin@jarry.cc> | 2023-10-10 00:36:02 +0200 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-10-11 10:21:56 +0200 |
commit | 1300b2c81bf96ca143ded90a7f6af130006a516b (patch) | |
tree | afb65be011e1c6bb454a3075313c36bb9110ac5b /lib/ui/ui.go | |
parent | 34650131379a4542538da63751a89588d2f2cc85 (diff) | |
download | aerc-1300b2c81bf96ca143ded90a7f6af130006a516b.tar.gz |
ui: export global functions
There is no need for an UI object. The Aerc.ui field is unused. And
there is a single instance of it anyway.
Move the object's public fields as global variables and change methods
to public functions.
This makes the code cleaner and removes boilerplate.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Moritz Poldrack <moritz@poldrack.dev>
Diffstat (limited to 'lib/ui/ui.go')
-rw-r--r-- | lib/ui/ui.go | 71 |
1 files changed, 28 insertions, 43 deletions
diff --git a/lib/ui/ui.go b/lib/ui/ui.go index 628946fa..d2506b48 100644 --- a/lib/ui/ui.go +++ b/lib/ui/ui.go @@ -6,16 +6,12 @@ import ( "github.com/gdamore/tcell/v2" ) -const ( - // nominal state, UI is up to date - CLEAN int32 = iota - // UI render has been queued in Redraw channel - DIRTY -) +// Use unbuffered channels (always blocking unless somebody can read +// immediately) We are merely using this as a proxy to tcell screen internal +// event channel. +var Events = make(chan tcell.Event) -// State of the UI. Any value other than 0 means the UI is in a dirty state. -// This should only be accessed via atomic operations to maintain thread safety -var uiState int32 +var Quit = make(chan struct{}) var Callbacks = make(chan func(), 50) @@ -31,28 +27,27 @@ var Redraw = make(chan bool, 1) // Invalidate marks the entire UI as invalid and request a redraw as soon as // possible. Invalidate can be called from any goroutine and will never block. func Invalidate() { - if atomic.SwapInt32(&uiState, DIRTY) != DIRTY { + if atomic.SwapUint32(&state.dirty, 1) != 1 { Redraw <- true } } -type UI struct { - Content DrawableInteractive - Quit chan struct{} - Events chan tcell.Event +var state struct { + content DrawableInteractive ctx *Context screen tcell.Screen popover *Popover + dirty uint32 // == 1 if render has been queued in Redraw channel } -func Initialize(content DrawableInteractive) (*UI, error) { +func Initialize(content DrawableInteractive) error { screen, err := tcell.NewScreen() if err != nil { - return nil, err + return err } if err = screen.Init(); err != nil { - return nil, err + return err } screen.Clear() @@ -61,16 +56,9 @@ func Initialize(content DrawableInteractive) (*UI, error) { width, height := screen.Size() - state := UI{ - Content: content, - screen: screen, - // Use unbuffered channels (always blocking unless somebody can - // read immediately) We are merely using this as a proxy to - // tcell screen internal event channel. - Events: make(chan tcell.Event), - Quit: make(chan struct{}), - } - state.ctx = NewContext(width, height, screen, state.onPopover) + state.content = content + state.screen = screen + state.ctx = NewContext(width, height, state.screen, onPopover) Invalidate() if beeper, ok := content.(DrawableInteractiveBeeper); ok { @@ -78,31 +66,28 @@ func Initialize(content DrawableInteractive) (*UI, error) { } content.Focus(true) - if root, ok := content.(RootDrawable); ok { - root.Initialize(&state) - } - go state.screen.ChannelEvents(state.Events, state.Quit) + go state.screen.ChannelEvents(Events, Quit) - return &state, nil + return nil } -func (state *UI) onPopover(p *Popover) { +func onPopover(p *Popover) { state.popover = p } -func (state *UI) Exit() { - close(state.Quit) +func Exit() { + close(Quit) } -func (state *UI) Close() { +func Close() { state.screen.Fini() } -func (state *UI) Render() { - if atomic.SwapInt32(&uiState, CLEAN) != CLEAN { +func Render() { + if atomic.SwapUint32(&state.dirty, 0) != 0 { // reset popover for the next Draw state.popover = nil - state.Content.Draw(state.ctx) + state.content.Draw(state.ctx) if state.popover != nil { // if the Draw resulted in a popover, draw it state.popover.Draw(state.ctx) @@ -111,20 +96,20 @@ func (state *UI) Render() { } } -func (state *UI) EnableMouse() { +func EnableMouse() { state.screen.EnableMouse() } -func (state *UI) HandleEvent(event tcell.Event) { +func HandleEvent(event tcell.Event) { if event, ok := event.(*tcell.EventResize); ok { state.screen.Clear() width, height := event.Size() - state.ctx = NewContext(width, height, state.screen, state.onPopover) + state.ctx = NewContext(width, height, state.screen, onPopover) Invalidate() } // if we have a popover, and it can handle the event, it does so if state.popover == nil || !state.popover.Event(event) { // otherwise, we send the event to the main content - state.Content.Event(event) + state.content.Event(event) } } |