invalidatable: cleanup dead code

Remove invalidatable type and all associated calls. All items can
directly invalidate the UI.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Tim Culverhouse 2022-10-07 11:00:31 -05:00 committed by Robin Jarry
parent 34014d3cee
commit ba24e92062
41 changed files with 76 additions and 303 deletions

View file

@ -10,6 +10,7 @@ import (
"github.com/emersion/go-message/mail" "github.com/emersion/go-message/mail"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
@ -64,7 +65,7 @@ func (Compose) Execute(aerc *widgets.Aerc, args []string) error {
} else { } else {
tab.Name = subject tab.Name = subject
} }
tab.Content.Invalidate() ui.Invalidate()
}) })
go func() { go func() {
defer logging.PanicHandler() defer logging.PanicHandler()

View file

@ -4,6 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
) )
@ -34,13 +35,13 @@ func (NextPrevResult) Execute(aerc *widgets.Aerc, args []string) error {
if store != nil { if store != nil {
store.PrevResult() store.PrevResult()
} }
acct.Messages().Invalidate() ui.Invalidate()
} else { } else {
store := acct.Store() store := acct.Store()
if store != nil { if store != nil {
store.NextResult() store.NextResult()
} }
acct.Messages().Invalidate() ui.Invalidate()
} }
return nil return nil
} }

View file

@ -6,6 +6,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
) )
@ -65,13 +66,13 @@ func ExecuteNextPrevMessage(args []string, acct *widgets.AccountView, pct bool,
store := acct.Store() store := acct.Store()
if store != nil { if store != nil {
store.NextPrev(-n) store.NextPrev(-n)
acct.Messages().Invalidate() ui.Invalidate()
} }
} else { } else {
store := acct.Store() store := acct.Store()
if store != nil { if store != nil {
store.NextPrev(n) store.NextPrev(n)
acct.Messages().Invalidate() ui.Invalidate()
} }
} }
return nil return nil

View file

@ -8,6 +8,7 @@ import (
"path/filepath" "path/filepath"
"git.sr.ht/~rjarry/aerc/commands" "git.sr.ht/~rjarry/aerc/commands"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
@ -110,7 +111,7 @@ func (Recover) Execute(aerc *widgets.Aerc, args []string) error {
tab := aerc.NewTab(composer, "Recovered") tab := aerc.NewTab(composer, "Recovered")
composer.OnHeaderChange("Subject", func(subject string) { composer.OnHeaderChange("Subject", func(subject string) {
tab.Name = subject tab.Name = subject
tab.Content.Invalidate() ui.Invalidate()
}) })
go func() { go func() {
defer logging.PanicHandler() defer logging.PanicHandler()

View file

@ -5,6 +5,7 @@ import (
"strings" "strings"
"git.sr.ht/~rjarry/aerc/lib/statusline" "git.sr.ht/~rjarry/aerc/lib/statusline"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
"git.sr.ht/~rjarry/aerc/worker/types" "git.sr.ht/~rjarry/aerc/worker/types"
@ -54,7 +55,7 @@ func (SearchFilter) Execute(aerc *widgets.Aerc, args []string) error {
logging.Infof("Search results: %v", uids) logging.Infof("Search results: %v", uids)
store.ApplySearch(uids) store.ApplySearch(uids)
// TODO: Remove when stores have multiple OnUpdate handlers // TODO: Remove when stores have multiple OnUpdate handlers
acct.Messages().Invalidate() ui.Invalidate()
} }
store.Search(args, cb) store.Search(args, cb)
} }

View file

@ -9,6 +9,7 @@ import (
"git.sr.ht/~rjarry/aerc/commands" "git.sr.ht/~rjarry/aerc/commands"
"git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
@ -117,7 +118,7 @@ func (Archive) Execute(aerc *widgets.Aerc, args []string) error {
if next == nil { if next == nil {
aerc.RemoveTab(h.msgProvider) aerc.RemoveTab(h.msgProvider)
acct.Messages().Select(-1) acct.Messages().Select(-1)
acct.Messages().Invalidate() ui.Invalidate()
return return
} }
lib.NewMessageStoreView(next, mv.MessageView().SeenFlagSet(), lib.NewMessageStoreView(next, mv.MessageView().SeenFlagSet(),

View file

@ -5,6 +5,7 @@ import (
"time" "time"
"git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
"git.sr.ht/~rjarry/aerc/worker/types" "git.sr.ht/~rjarry/aerc/worker/types"
@ -60,7 +61,7 @@ func (Delete) Execute(aerc *widgets.Aerc, args []string) error {
if next == nil { if next == nil {
aerc.RemoveTab(h.msgProvider) aerc.RemoveTab(h.msgProvider)
acct.Messages().Select(-1) acct.Messages().Select(-1)
acct.Messages().Invalidate() ui.Invalidate()
return return
} }
lib.NewMessageStoreView(next, mv.MessageView().SeenFlagSet(), lib.NewMessageStoreView(next, mv.MessageView().SeenFlagSet(),

View file

@ -14,6 +14,7 @@ import (
"git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib"
"git.sr.ht/~rjarry/aerc/lib/format" "git.sr.ht/~rjarry/aerc/lib/format"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
@ -117,7 +118,7 @@ func (forward) Execute(aerc *widgets.Aerc, args []string) error {
} else { } else {
tab.Name = subject tab.Name = subject
} }
tab.Content.Invalidate() ui.Invalidate()
}) })
return composer, nil return composer, nil
} }

View file

@ -8,6 +8,7 @@ import (
"git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib"
"git.sr.ht/~rjarry/aerc/lib/calendar" "git.sr.ht/~rjarry/aerc/lib/calendar"
"git.sr.ht/~rjarry/aerc/lib/format" "git.sr.ht/~rjarry/aerc/lib/format"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
@ -167,7 +168,7 @@ func (invite) Execute(aerc *widgets.Aerc, args []string) error {
} else { } else {
tab.Name = subject tab.Name = subject
} }
tab.Content.Invalidate() ui.Invalidate()
}) })
composer.OnClose(func(c *widgets.Composer) { composer.OnClose(func(c *widgets.Composer) {

View file

@ -13,6 +13,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
@ -93,7 +94,7 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
} else { } else {
tab.Name = subject tab.Name = subject
} }
tab.Content.Invalidate() ui.Invalidate()
}) })
composer.OnClose(func(composer *widgets.Composer) { composer.OnClose(func(composer *widgets.Composer) {
worker := composer.Worker() worker := composer.Worker()

View file

@ -13,6 +13,7 @@ import (
"git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib"
"git.sr.ht/~rjarry/aerc/lib/crypto" "git.sr.ht/~rjarry/aerc/lib/crypto"
"git.sr.ht/~rjarry/aerc/lib/format" "git.sr.ht/~rjarry/aerc/lib/format"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
@ -194,7 +195,7 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
} else { } else {
tab.Name = subject tab.Name = subject
} }
tab.Content.Invalidate() ui.Invalidate()
}) })
composer.OnClose(func(c *widgets.Composer) { composer.OnClose(func(c *widgets.Composer) {

View file

@ -4,6 +4,7 @@ import (
"errors" "errors"
"git.sr.ht/~rjarry/aerc/lib/statusline" "git.sr.ht/~rjarry/aerc/lib/statusline"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
) )
@ -36,6 +37,6 @@ func (ToggleThreads) Execute(aerc *widgets.Aerc, args []string) error {
} }
store.SetThreadedView(!store.ThreadedView()) store.SetThreadedView(!store.ThreadedView())
acct.SetStatus(statusline.Threading(store.ThreadedView())) acct.SetStatus(statusline.Threading(store.ThreadedView()))
acct.Messages().Invalidate() ui.Invalidate()
return nil return nil
} }

View file

@ -9,6 +9,7 @@ import (
"time" "time"
"git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/lib"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
@ -168,7 +169,7 @@ func unsubscribeMailto(aerc *widgets.Aerc, u *url.URL) error {
} else { } else {
tab.Name = subject tab.Name = subject
} }
tab.Content.Invalidate() ui.Invalidate()
}) })
composer.FocusTerminal() composer.FocusTerminal()
return nil return nil

View file

@ -5,6 +5,7 @@ import (
"github.com/riywo/loginshell" "github.com/riywo/loginshell"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/widgets" "git.sr.ht/~rjarry/aerc/widgets"
) )
@ -41,7 +42,7 @@ func TermCore(aerc *widgets.Aerc, args []string) error {
title = args[1] title = args[1]
} }
tab.Name = title tab.Name = title
tab.Content.Invalidate() ui.Invalidate()
} }
term.OnClose = func(err error) { term.OnClose = func(err error) {
aerc.RemoveTab(term) aerc.RemoveTab(term)

View file

@ -14,7 +14,6 @@ const (
) )
type Bordered struct { type Bordered struct {
Invalidatable
borders uint borders uint
content Drawable content Drawable
uiConfig *config.UIConfig uiConfig *config.UIConfig
@ -28,20 +27,15 @@ func NewBordered(
content: content, content: content,
uiConfig: uiConfig, uiConfig: uiConfig,
} }
content.OnInvalidate(b.contentInvalidated)
return b return b
} }
func (bordered *Bordered) contentInvalidated(d Drawable) {
bordered.Invalidate()
}
func (bordered *Bordered) Children() []Drawable { func (bordered *Bordered) Children() []Drawable {
return []Drawable{bordered.content} return []Drawable{bordered.content}
} }
func (bordered *Bordered) Invalidate() { func (bordered *Bordered) Invalidate() {
bordered.DoInvalidate(bordered) Invalidate()
} }
func (bordered *Bordered) Draw(ctx *Context) { func (bordered *Bordered) Draw(ctx *Context) {

View file

@ -21,10 +21,6 @@ func (f Fill) Draw(ctx *Context) {
} }
} }
func (f Fill) OnInvalidate(callback func(d Drawable)) {
// no-op
}
func (f Fill) Invalidate() { func (f Fill) Invalidate() {
// no-op // no-op
} }

View file

@ -1,21 +1,17 @@
package ui package ui
import ( import (
"fmt"
"math" "math"
"sync" "sync"
"sync/atomic"
"github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2"
) )
type Grid struct { type Grid struct {
Invalidatable
rows []GridSpec rows []GridSpec
rowLayout []gridLayout rowLayout []gridLayout
columns []GridSpec columns []GridSpec
columnLayout []gridLayout columnLayout []gridLayout
invalid bool
// Protected by mutex // Protected by mutex
cells []*GridCell cells []*GridCell
@ -51,11 +47,10 @@ type GridCell struct {
RowSpan int RowSpan int
ColSpan int ColSpan int
Content Drawable Content Drawable
invalid atomic.Value // bool
} }
func NewGrid() *Grid { func NewGrid() *Grid {
return &Grid{invalid: true} return &Grid{}
} }
// MakeGrid creates a grid with the specified number of columns and rows. Each // MakeGrid creates a grid with the specified number of columns and rows. Each
@ -95,19 +90,12 @@ func (grid *Grid) Columns(spec []GridSpec) *Grid {
} }
func (grid *Grid) Draw(ctx *Context) { func (grid *Grid) Draw(ctx *Context) {
invalid := grid.invalid grid.reflow(ctx)
if invalid {
grid.reflow(ctx)
}
grid.mutex.RLock() grid.mutex.RLock()
defer grid.mutex.RUnlock() defer grid.mutex.RUnlock()
for _, cell := range grid.cells { for _, cell := range grid.cells {
cellInvalid := cell.invalid.Load().(bool)
if !cellInvalid && !invalid {
continue
}
rows := grid.rowLayout[cell.Row : cell.Row+cell.RowSpan] rows := grid.rowLayout[cell.Row : cell.Row+cell.RowSpan]
cols := grid.columnLayout[cell.Column : cell.Column+cell.ColSpan] cols := grid.columnLayout[cell.Column : cell.Column+cell.ColSpan]
x := cols[0].Offset x := cols[0].Offset
@ -142,16 +130,11 @@ func (grid *Grid) Draw(ctx *Context) {
func (grid *Grid) MouseEvent(localX int, localY int, event tcell.Event) { func (grid *Grid) MouseEvent(localX int, localY int, event tcell.Event) {
if event, ok := event.(*tcell.EventMouse); ok { if event, ok := event.(*tcell.EventMouse); ok {
invalid := grid.invalid
grid.mutex.RLock() grid.mutex.RLock()
defer grid.mutex.RUnlock() defer grid.mutex.RUnlock()
for _, cell := range grid.cells { for _, cell := range grid.cells {
cellInvalid := cell.invalid.Load().(bool)
if !cellInvalid && !invalid {
continue
}
rows := grid.rowLayout[cell.Row : cell.Row+cell.RowSpan] rows := grid.rowLayout[cell.Row : cell.Row+cell.RowSpan]
cols := grid.columnLayout[cell.Column : cell.Column+cell.ColSpan] cols := grid.columnLayout[cell.Column : cell.Column+cell.ColSpan]
x := cols[0].Offset x := cols[0].Offset
@ -220,23 +203,10 @@ func (grid *Grid) reflow(ctx *Context) {
} }
flow(&grid.rows, &grid.rowLayout, ctx.Height()) flow(&grid.rows, &grid.rowLayout, ctx.Height())
flow(&grid.columns, &grid.columnLayout, ctx.Width()) flow(&grid.columns, &grid.columnLayout, ctx.Width())
grid.invalid = false
}
func (grid *Grid) invalidateLayout() {
grid.invalid = true
grid.DoInvalidate(grid)
} }
func (grid *Grid) Invalidate() { func (grid *Grid) Invalidate() {
grid.invalidateLayout() Invalidate()
grid.mutex.RLock()
for _, cell := range grid.cells {
if cell.Content != nil {
cell.Content.Invalidate()
}
}
grid.mutex.RUnlock()
} }
func (grid *Grid) AddChild(content Drawable) *GridCell { func (grid *Grid) AddChild(content Drawable) *GridCell {
@ -248,9 +218,7 @@ func (grid *Grid) AddChild(content Drawable) *GridCell {
grid.mutex.Lock() grid.mutex.Lock()
grid.cells = append(grid.cells, cell) grid.cells = append(grid.cells, cell)
grid.mutex.Unlock() grid.mutex.Unlock()
cell.Content.OnInvalidate(grid.cellInvalidated) grid.Invalidate()
cell.invalid.Store(true)
grid.invalidateLayout()
return cell return cell
} }
@ -263,24 +231,7 @@ func (grid *Grid) RemoveChild(content Drawable) {
} }
} }
grid.mutex.Unlock() grid.mutex.Unlock()
grid.invalidateLayout() grid.Invalidate()
}
func (grid *Grid) cellInvalidated(drawable Drawable) {
var cell *GridCell
grid.mutex.RLock()
for _, cell = range grid.cells {
if cell.Content == drawable {
break
}
cell = nil
}
grid.mutex.RUnlock()
if cell == nil {
panic(fmt.Errorf("Attempted to invalidate unknown cell"))
}
cell.invalid.Store(true)
grid.DoInvalidate(grid)
} }
func Const(i int) func() int { func Const(i int) func() int {

View file

@ -12,10 +12,7 @@ type AercMsg interface{}
type Drawable interface { type Drawable interface {
// Called when this renderable should draw itself. // Called when this renderable should draw itself.
Draw(ctx *Context) Draw(ctx *Context)
// Specifies a function to call when this cell needs to be redrawn. The // Invalidates the UI. This can be called from any goroutine.
// callback may be called in any goroutine.
OnInvalidate(callback func(d Drawable))
// Invalidates the drawable. This can be called from any goroutine.
Invalidate() Invalidate()
} }

View file

@ -1,17 +0,0 @@
package ui
import (
"sync/atomic"
)
type Invalidatable struct {
onInvalidate atomic.Value
}
func (i *Invalidatable) OnInvalidate(f func(d Drawable)) {
i.onInvalidate.Store(f)
}
func (i *Invalidatable) DoInvalidate(d Drawable) {
atomic.StoreInt32(&dirty, DIRTY)
}

View file

@ -53,11 +53,5 @@ func (p *Popover) Focus(f bool) {
} }
func (p *Popover) Invalidate() { func (p *Popover) Invalidate() {
p.content.Invalidate() Invalidate()
}
func (p *Popover) OnInvalidate(f func(Drawable)) {
p.content.OnInvalidate(func(_ Drawable) {
f(p)
})
} }

View file

@ -9,9 +9,8 @@ import (
) )
type Stack struct { type Stack struct {
children []Drawable children []Drawable
onInvalidate []func(d Drawable) uiConfig config.UIConfig
uiConfig config.UIConfig
} }
func NewStack(uiConfig config.UIConfig) *Stack { func NewStack(uiConfig config.UIConfig) *Stack {
@ -22,14 +21,8 @@ func (stack *Stack) Children() []Drawable {
return stack.children return stack.children
} }
func (stack *Stack) OnInvalidate(onInvalidate func(d Drawable)) {
stack.onInvalidate = append(stack.onInvalidate, onInvalidate)
}
func (stack *Stack) Invalidate() { func (stack *Stack) Invalidate() {
for _, fn := range stack.onInvalidate { Invalidate()
fn(stack)
}
} }
func (stack *Stack) Draw(ctx *Context) { func (stack *Stack) Draw(ctx *Context) {
@ -50,11 +43,7 @@ func (stack *Stack) MouseEvent(localX int, localY int, event tcell.Event) {
} }
func (stack *Stack) Push(d Drawable) { func (stack *Stack) Push(d Drawable) {
if len(stack.children) != 0 {
stack.Peek().OnInvalidate(nil)
}
stack.children = append(stack.children, d) stack.children = append(stack.children, d)
d.OnInvalidate(stack.invalidateFromChild)
stack.Invalidate() stack.Invalidate()
} }
@ -65,10 +54,6 @@ func (stack *Stack) Pop() Drawable {
d := stack.children[len(stack.children)-1] d := stack.children[len(stack.children)-1]
stack.children = stack.children[:len(stack.children)-1] stack.children = stack.children[:len(stack.children)-1]
stack.Invalidate() stack.Invalidate()
d.OnInvalidate(nil)
if len(stack.children) != 0 {
stack.Peek().OnInvalidate(stack.invalidateFromChild)
}
return d return d
} }
@ -78,7 +63,3 @@ func (stack *Stack) Peek() Drawable {
} }
return stack.children[len(stack.children)-1] return stack.children[len(stack.children)-1]
} }
func (stack *Stack) invalidateFromChild(d Drawable) {
stack.Invalidate()
}

View file

@ -20,9 +20,6 @@ type Tabs struct {
uiConfig *config.UIConfig uiConfig *config.UIConfig
onInvalidateStrip func(d Drawable) //nolint:structcheck // used within this file
onInvalidateContent func(d Drawable)
parent *Tabs //nolint:structcheck // used within this file parent *Tabs //nolint:structcheck // used within this file
CloseTab func(index int) CloseTab func(index int)
} }
@ -59,7 +56,6 @@ func (tabs *Tabs) Add(content Drawable, name string, uiConf *config.UIConfig) *T
} }
tabs.tabs = append(tabs.tabs, tab) tabs.tabs = append(tabs.tabs, tab)
tabs.selectPriv(len(tabs.tabs) - 1) tabs.selectPriv(len(tabs.tabs) - 1)
content.OnInvalidate(tabs.invalidateChild)
return tab return tab
} }
@ -73,18 +69,6 @@ func (tabs *Tabs) Names() []string {
return names return names
} }
func (tabs *Tabs) invalidateChild(d Drawable) {
if tabs.curIndex >= len(tabs.tabs) {
return
}
if tabs.tabs[tabs.curIndex].Content == d {
if tabs.onInvalidateContent != nil {
tabs.onInvalidateContent(tabs.TabContent)
}
}
}
func (tabs *Tabs) Remove(content Drawable) { func (tabs *Tabs) Remove(content Drawable) {
tabs.m.Lock() tabs.m.Lock()
defer tabs.m.Unlock() defer tabs.m.Unlock()
@ -133,8 +117,7 @@ func (tabs *Tabs) Replace(contentSrc Drawable, contentTarget Drawable, name stri
break break
} }
} }
tabs.TabStrip.Invalidate() Invalidate()
contentTarget.OnInvalidate(tabs.invalidateChild)
} }
func (tabs *Tabs) Get(index int) *Tab { func (tabs *Tabs) Get(index int) *Tab {
@ -172,8 +155,7 @@ func (tabs *Tabs) selectPriv(index int) bool {
tabs.pushHistory(tabs.curIndex) tabs.pushHistory(tabs.curIndex)
} }
tabs.curIndex = index tabs.curIndex = index
tabs.TabStrip.Invalidate() Invalidate()
tabs.TabContent.Invalidate()
} }
return true return true
} }
@ -246,7 +228,7 @@ func (tabs *Tabs) moveTabPriv(to int, relative bool) {
tabs.tabs[to] = tab tabs.tabs[to] = tab
tabs.curIndex = to tabs.curIndex = to
tabs.TabStrip.Invalidate() Invalidate()
} }
func (tabs *Tabs) PinTab() { func (tabs *Tabs) PinTab() {
@ -384,9 +366,7 @@ func (strip *TabStrip) Draw(ctx *Context) {
} }
func (strip *TabStrip) Invalidate() { func (strip *TabStrip) Invalidate() {
if strip.onInvalidateStrip != nil { Invalidate()
strip.onInvalidateStrip(strip)
}
} }
func (strip *TabStrip) MouseEvent(localX int, localY int, event tcell.Event) { func (strip *TabStrip) MouseEvent(localX int, localY int, event tcell.Event) {
@ -440,10 +420,6 @@ func (strip *TabStrip) MouseEvent(localX int, localY int, event tcell.Event) {
} }
} }
func (strip *TabStrip) OnInvalidate(onInvalidate func(d Drawable)) {
strip.onInvalidateStrip = onInvalidate
}
func (strip *TabStrip) clicked(mouseX int, mouseY int) (int, bool) { func (strip *TabStrip) clicked(mouseX int, mouseY int) (int, bool) {
x := 0 x := 0
for i, tab := range strip.tabs { for i, tab := range strip.tabs {
@ -490,13 +466,5 @@ func (content *TabContent) MouseEvent(localX int, localY int, event tcell.Event)
} }
func (content *TabContent) Invalidate() { func (content *TabContent) Invalidate() {
if content.onInvalidateContent != nil { Invalidate()
content.onInvalidateContent(content)
}
tab := content.tabs[content.curIndex]
tab.Content.Invalidate()
}
func (content *TabContent) OnInvalidate(onInvalidate func(d Drawable)) {
content.onInvalidateContent = onInvalidate
} }

View file

@ -12,7 +12,6 @@ const (
) )
type Text struct { type Text struct {
Invalidatable
text string text string
strategy uint strategy uint
style tcell.Style style tcell.Style
@ -51,5 +50,5 @@ func (t *Text) Draw(ctx *Context) {
} }
func (t *Text) Invalidate() { func (t *Text) Invalidate() {
t.DoInvalidate(t) Invalidate()
} }

View file

@ -17,7 +17,6 @@ import (
// TODO: scrolling // TODO: scrolling
type TextInput struct { type TextInput struct {
Invalidatable
sync.Mutex sync.Mutex
cells int cells int
ctx *Context ctx *Context
@ -90,7 +89,7 @@ func (ti *TextInput) Set(value string) *TextInput {
} }
func (ti *TextInput) Invalidate() { func (ti *TextInput) Invalidate() {
ti.DoInvalidate(ti) Invalidate()
} }
func (ti *TextInput) Draw(ctx *Context) { func (ti *TextInput) Draw(ctx *Context) {
@ -530,5 +529,3 @@ func findStem(words []string) string {
func (c *completions) Focus(_ bool) {} func (c *completions) Focus(_ bool) {}
func (c *completions) Invalidate() {} func (c *completions) Invalidate() {}
func (c *completions) OnInvalidate(_ func(Drawable)) {}

View file

@ -122,7 +122,7 @@ func (state *UI) HandleEvent(event tcell.Event) {
state.screen.Clear() state.screen.Clear()
width, height := event.Size() width, height := event.Size()
state.ctx = NewContext(width, height, state.screen, state.onPopover) state.ctx = NewContext(width, height, state.screen, state.onPopover)
state.Content.Invalidate() Invalidate()
} }
// if we have a popover, and it can handle the event, it does so // if we have a popover, and it can handle the event, it does so
if state.popover == nil || !state.popover.Event(event) { if state.popover == nil || !state.popover.Event(event) {

View file

@ -40,7 +40,6 @@ const (
) )
type AccountWizard struct { type AccountWizard struct {
ui.Invalidatable
aerc *Aerc aerc *Aerc
conf *config.AercConfig conf *config.AercConfig
step int step int
@ -224,9 +223,6 @@ func NewAccountWizard(conf *config.AercConfig, aerc *Aerc) *AccountWizard {
wizard.basics = []ui.Interactive{ wizard.basics = []ui.Interactive{
wizard.accountName, wizard.fullName, wizard.email, selector, wizard.accountName, wizard.fullName, wizard.email, selector,
} }
basics.OnInvalidate(func(_ ui.Drawable) {
wizard.Invalidate()
})
incoming := ui.NewGrid().Rows([]ui.GridSpec{ incoming := ui.NewGrid().Rows([]ui.GridSpec{
{Strategy: ui.SIZE_EXACT, Size: ui.Const(3)}, // Introduction {Strategy: ui.SIZE_EXACT, Size: ui.Const(3)}, // Introduction
@ -303,9 +299,6 @@ func NewAccountWizard(conf *config.AercConfig, aerc *Aerc) *AccountWizard {
wizard.imapUsername, wizard.imapPassword, wizard.imapServer, wizard.imapUsername, wizard.imapPassword, wizard.imapServer,
imapMode, selector, imapMode, selector,
} }
incoming.OnInvalidate(func(_ ui.Drawable) {
wizard.Invalidate()
})
outgoing := ui.NewGrid().Rows([]ui.GridSpec{ outgoing := ui.NewGrid().Rows([]ui.GridSpec{
{Strategy: ui.SIZE_EXACT, Size: ui.Const(3)}, // Introduction {Strategy: ui.SIZE_EXACT, Size: ui.Const(3)}, // Introduction
@ -399,9 +392,6 @@ func NewAccountWizard(conf *config.AercConfig, aerc *Aerc) *AccountWizard {
wizard.smtpUsername, wizard.smtpPassword, wizard.smtpServer, wizard.smtpUsername, wizard.smtpPassword, wizard.smtpServer,
smtpMode, copySent, selector, smtpMode, copySent, selector,
} }
outgoing.OnInvalidate(func(_ ui.Drawable) {
wizard.Invalidate()
})
complete := ui.NewGrid().Rows([]ui.GridSpec{ complete := ui.NewGrid().Rows([]ui.GridSpec{
{Strategy: ui.SIZE_EXACT, Size: ui.Const(7)}, // Introduction {Strategy: ui.SIZE_EXACT, Size: ui.Const(7)}, // Introduction
@ -431,9 +421,6 @@ func NewAccountWizard(conf *config.AercConfig, aerc *Aerc) *AccountWizard {
}) })
complete.AddChild(selector).At(1, 0) complete.AddChild(selector).At(1, 0)
wizard.complete = []ui.Interactive{selector} wizard.complete = []ui.Interactive{selector}
complete.OnInvalidate(func(_ ui.Drawable) {
wizard.Invalidate()
})
wizard.steps = []*ui.Grid{basics, incoming, outgoing, complete} wizard.steps = []*ui.Grid{basics, incoming, outgoing, complete}
return wizard return wizard
@ -665,7 +652,7 @@ func (wizard *AccountWizard) smtpUri() url.URL {
} }
func (wizard *AccountWizard) Invalidate() { func (wizard *AccountWizard) Invalidate() {
wizard.DoInvalidate(wizard) ui.Invalidate()
} }
func (wizard *AccountWizard) Draw(ctx *ui.Context) { func (wizard *AccountWizard) Draw(ctx *ui.Context) {

View file

@ -143,14 +143,8 @@ func (acct *AccountView) Name() string {
return acct.acct.Name return acct.acct.Name
} }
func (acct *AccountView) OnInvalidate(onInvalidate func(d ui.Drawable)) {
acct.grid.OnInvalidate(func(_ ui.Drawable) {
onInvalidate(acct)
})
}
func (acct *AccountView) Invalidate() { func (acct *AccountView) Invalidate() {
acct.grid.Invalidate() ui.Invalidate()
} }
func (acct *AccountView) Draw(ctx *ui.Context) { func (acct *AccountView) Draw(ctx *ui.Context) {

View file

@ -152,14 +152,8 @@ func (aerc *Aerc) HandleMessage(msg types.WorkerMessage) {
} }
} }
func (aerc *Aerc) OnInvalidate(onInvalidate func(d ui.Drawable)) {
aerc.grid.OnInvalidate(func(_ ui.Drawable) {
onInvalidate(aerc)
})
}
func (aerc *Aerc) Invalidate() { func (aerc *Aerc) Invalidate() {
aerc.grid.Invalidate() ui.Invalidate()
} }
func (aerc *Aerc) Focus(focus bool) { func (aerc *Aerc) Focus(focus bool) {
@ -304,7 +298,7 @@ func (aerc *Aerc) Event(event tcell.Event) bool {
Key: event.Key(), Key: event.Key(),
Rune: event.Rune(), Rune: event.Rune(),
}) })
aerc.statusline.Invalidate() ui.Invalidate()
bindings := aerc.getBindings() bindings := aerc.getBindings()
incomplete := false incomplete := false
result, strokes := bindings.GetBinding(aerc.pendingKeys) result, strokes := bindings.GetBinding(aerc.pendingKeys)
@ -724,7 +718,7 @@ func (aerc *Aerc) Mailto(addr *url.URL) error {
} else { } else {
tab.Name = subject tab.Name = subject
} }
tab.Content.Invalidate() ui.Invalidate()
}) })
return nil return nil
} }
@ -775,9 +769,6 @@ func (aerc *Aerc) CloseBackends() error {
func (aerc *Aerc) AddDialog(d ui.DrawableInteractive) { func (aerc *Aerc) AddDialog(d ui.DrawableInteractive) {
aerc.dialog = d aerc.dialog = d
aerc.dialog.OnInvalidate(func(_ ui.Drawable) {
aerc.Invalidate()
})
aerc.Invalidate() aerc.Invalidate()
} }

View file

@ -11,7 +11,6 @@ import (
) )
type AuthInfo struct { type AuthInfo struct {
ui.Invalidatable
authdetails *auth.Details authdetails *auth.Details
showInfo bool showInfo bool
uiConfig *config.UIConfig uiConfig *config.UIConfig
@ -85,5 +84,5 @@ func (a *AuthInfo) Draw(ctx *ui.Context) {
} }
func (a *AuthInfo) Invalidate() { func (a *AuthInfo) Invalidate() {
a.DoInvalidate(a) ui.Invalidate()
} }

View file

@ -127,7 +127,6 @@ func (c *Composer) SwitchAccount(newAcct *AccountView) error {
editor.loadValue() editor.loadValue()
} }
c.Invalidate() c.Invalidate()
c.aerc.Invalidate()
logging.Infof("account sucessfully switched") logging.Infof("account sucessfully switched")
return nil return nil
} }
@ -567,13 +566,7 @@ func (c *Composer) Draw(ctx *ui.Context) {
} }
func (c *Composer) Invalidate() { func (c *Composer) Invalidate() {
c.grid.Invalidate() ui.Invalidate()
}
func (c *Composer) OnInvalidate(fn func(d ui.Drawable)) {
c.grid.OnInvalidate(func(_ ui.Drawable) {
fn(c)
})
} }
func (c *Composer) Close() { func (c *Composer) Close() {
@ -1107,7 +1100,7 @@ func extractHumanHeaderValue(key string, h *mail.Header) string {
// decoding issues are ignored and return their raw values // decoding issues are ignored and return their raw values
func (he *headerEditor) loadValue() { func (he *headerEditor) loadValue() {
he.input.Set(extractHumanHeaderValue(he.name, he.header)) he.input.Set(extractHumanHeaderValue(he.name, he.header))
he.input.Invalidate() ui.Invalidate()
} }
// storeValue writes the current state back to the underlying header. // storeValue writes the current state back to the underlying header.
@ -1159,13 +1152,7 @@ func (he *headerEditor) MouseEvent(localX int, localY int, event tcell.Event) {
} }
func (he *headerEditor) Invalidate() { func (he *headerEditor) Invalidate() {
he.input.Invalidate() ui.Invalidate()
}
func (he *headerEditor) OnInvalidate(fn func(ui.Drawable)) {
he.input.OnInvalidate(func(_ ui.Drawable) {
fn(he)
})
} }
func (he *headerEditor) Focus(focused bool) { func (he *headerEditor) Focus(focused bool) {
@ -1301,13 +1288,7 @@ func newReviewMessage(composer *Composer, err error) *reviewMessage {
} }
func (rm *reviewMessage) Invalidate() { func (rm *reviewMessage) Invalidate() {
rm.grid.Invalidate() ui.Invalidate()
}
func (rm *reviewMessage) OnInvalidate(fn func(ui.Drawable)) {
rm.grid.OnInvalidate(func(_ ui.Drawable) {
fn(rm)
})
} }
func (rm *reviewMessage) Draw(ctx *ui.Context) { func (rm *reviewMessage) Draw(ctx *ui.Context) {
@ -1344,13 +1325,7 @@ func (cs *cryptoStatus) Draw(ctx *ui.Context) {
} }
func (cs *cryptoStatus) Invalidate() { func (cs *cryptoStatus) Invalidate() {
cs.status.Invalidate() ui.Invalidate()
}
func (cs *cryptoStatus) OnInvalidate(fn func(ui.Drawable)) {
cs.status.OnInvalidate(func(_ ui.Drawable) {
fn(cs)
})
} }
func (c *Composer) checkEncryptionKeys(_ string) bool { func (c *Composer) checkEncryptionKeys(_ string) bool {

View file

@ -48,7 +48,6 @@ type DirectoryLister interface {
} }
type DirectoryList struct { type DirectoryList struct {
ui.Invalidatable
sync.Mutex sync.Mutex
Scrollable Scrollable
aercConf *config.AercConfig aercConf *config.AercConfig
@ -199,7 +198,7 @@ func (dirlist *DirectoryList) Selected() string {
} }
func (dirlist *DirectoryList) Invalidate() { func (dirlist *DirectoryList) Invalidate() {
dirlist.DoInvalidate(dirlist) ui.Invalidate()
} }
func (dirlist *DirectoryList) getDirString(name string, width int, recentUnseen func() string) string { func (dirlist *DirectoryList) getDirString(name string, width int, recentUnseen func() string) string {

View file

@ -9,7 +9,6 @@ import (
) )
type ExLine struct { type ExLine struct {
ui.Invalidatable
commit func(cmd string) commit func(cmd string)
finish func() finish func()
tabcomplete func(cmd string) ([]string, string) tabcomplete func(cmd string) ([]string, string)
@ -34,9 +33,6 @@ func NewExLine(conf *config.AercConfig, cmd string, commit func(cmd string), fin
input: input, input: input,
conf: conf, conf: conf,
} }
input.OnInvalidate(func(d ui.Drawable) {
exline.Invalidate()
})
return exline return exline
} }
@ -57,14 +53,11 @@ func NewPrompt(conf *config.AercConfig, prompt string, commit func(text string),
cmdHistory: &nullHistory{input: input}, cmdHistory: &nullHistory{input: input},
input: input, input: input,
} }
input.OnInvalidate(func(d ui.Drawable) {
exline.Invalidate()
})
return exline return exline
} }
func (ex *ExLine) Invalidate() { func (ex *ExLine) Invalidate() {
ex.DoInvalidate(ex) ui.Invalidate()
} }
func (ex *ExLine) Draw(ctx *ui.Context) { func (ex *ExLine) Draw(ctx *ui.Context) {

View file

@ -10,7 +10,6 @@ import (
) )
type GetPasswd struct { type GetPasswd struct {
ui.Invalidatable
callback func(string, error) callback func(string, error)
title string title string
prompt string prompt string
@ -28,9 +27,6 @@ func NewGetPasswd(title string, prompt string, conf *config.AercConfig,
conf: conf, conf: conf,
input: ui.NewTextInput("", &conf.Ui).Password(true).Prompt("Password: "), input: ui.NewTextInput("", &conf.Ui).Password(true).Prompt("Password: "),
} }
getpasswd.input.OnInvalidate(func(_ ui.Drawable) {
getpasswd.Invalidate()
})
getpasswd.input.Focus(true) getpasswd.input.Focus(true)
return getpasswd return getpasswd
} }
@ -47,7 +43,7 @@ func (gp *GetPasswd) Draw(ctx *ui.Context) {
} }
func (gp *GetPasswd) Invalidate() { func (gp *GetPasswd) Invalidate() {
gp.DoInvalidate(gp) ui.Invalidate()
} }
func (gp *GetPasswd) Event(event tcell.Event) bool { func (gp *GetPasswd) Event(event tcell.Event) bool {

View file

@ -13,7 +13,6 @@ import (
type ListBox struct { type ListBox struct {
Scrollable Scrollable
ui.Invalidatable
title string title string
lines []string lines []string
selected string selected string
@ -186,7 +185,7 @@ func (lb *ListBox) drawScrollbar(ctx *ui.Context) {
} }
func (lb *ListBox) Invalidate() { func (lb *ListBox) Invalidate() {
lb.DoInvalidate(lb) ui.Invalidate()
} }
func (lb *ListBox) Event(event tcell.Event) bool { func (lb *ListBox) Event(event tcell.Event) bool {

View file

@ -19,7 +19,6 @@ import (
) )
type MessageList struct { type MessageList struct {
ui.Invalidatable
Scrollable Scrollable
conf *config.AercConfig conf *config.AercConfig
height int height int
@ -37,16 +36,13 @@ func NewMessageList(conf *config.AercConfig, aerc *Aerc) *MessageList {
isInitalizing: true, isInitalizing: true,
aerc: aerc, aerc: aerc,
} }
ml.spinner.OnInvalidate(func(_ ui.Drawable) {
ml.Invalidate()
})
// TODO: stop spinner, probably // TODO: stop spinner, probably
ml.spinner.Start() ml.spinner.Start()
return ml return ml
} }
func (ml *MessageList) Invalidate() { func (ml *MessageList) Invalidate() {
ml.DoInvalidate(ml) ui.Invalidate()
} }
func (ml *MessageList) Draw(ctx *ui.Context) { func (ml *MessageList) Draw(ctx *ui.Context) {

View file

@ -30,7 +30,6 @@ var ansi = regexp.MustCompile("\x1B\\[[0-?]*[ -/]*[@-~]")
var _ ProvidesMessages = (*MessageViewer)(nil) var _ ProvidesMessages = (*MessageViewer)(nil)
type MessageViewer struct { type MessageViewer struct {
ui.Invalidatable
acct *AccountView acct *AccountView
conf *config.AercConfig conf *config.AercConfig
err error err error
@ -41,7 +40,6 @@ type MessageViewer struct {
} }
type PartSwitcher struct { type PartSwitcher struct {
ui.Invalidatable
parts []*PartViewer parts []*PartViewer
selected int selected int
showHeaders bool showHeaders bool
@ -219,9 +217,6 @@ func createSwitcher(acct *AccountView, switcher *PartSwitcher,
return err return err
} }
switcher.parts = []*PartViewer{pv} switcher.parts = []*PartViewer{pv}
pv.OnInvalidate(func(_ ui.Drawable) {
switcher.Invalidate()
})
} else { } else {
switcher.parts, err = enumerateParts(acct, conf, msg, switcher.parts, err = enumerateParts(acct, conf, msg,
msg.BodyStructure(), []int{}) msg.BodyStructure(), []int{})
@ -231,9 +226,6 @@ func createSwitcher(acct *AccountView, switcher *PartSwitcher,
selectedPriority := -1 selectedPriority := -1
logging.Infof("Selecting best message from %v", conf.Viewer.Alternatives) logging.Infof("Selecting best message from %v", conf.Viewer.Alternatives)
for i, pv := range switcher.parts { for i, pv := range switcher.parts {
pv.OnInvalidate(func(_ ui.Drawable) {
switcher.Invalidate()
})
// Switch to user's preferred mimetype // Switch to user's preferred mimetype
if switcher.selected == -1 && pv.part.MIMEType != "multipart" { if switcher.selected == -1 && pv.part.MIMEType != "multipart" {
switcher.selected = i switcher.selected = i
@ -273,13 +265,7 @@ func (mv *MessageViewer) MouseEvent(localX int, localY int, event tcell.Event) {
} }
func (mv *MessageViewer) Invalidate() { func (mv *MessageViewer) Invalidate() {
mv.grid.Invalidate() ui.Invalidate()
}
func (mv *MessageViewer) OnInvalidate(fn func(d ui.Drawable)) {
mv.grid.OnInvalidate(func(_ ui.Drawable) {
fn(mv)
})
} }
func (mv *MessageViewer) Store() *lib.MessageStore { func (mv *MessageViewer) Store() *lib.MessageStore {
@ -408,7 +394,7 @@ func (mv *MessageViewer) UpdateScreen() {
} }
func (ps *PartSwitcher) Invalidate() { func (ps *PartSwitcher) Invalidate() {
ps.DoInvalidate(ps) ui.Invalidate()
} }
func (ps *PartSwitcher) Focus(focus bool) { func (ps *PartSwitcher) Focus(focus bool) {
@ -521,7 +507,6 @@ func (mv *MessageViewer) Focus(focus bool) {
} }
type PartViewer struct { type PartViewer struct {
ui.Invalidatable
conf *config.AercConfig conf *config.AercConfig
acctConfig *config.AccountConfig acctConfig *config.AccountConfig
err error err error
@ -630,9 +615,6 @@ func NewPartViewer(acct *AccountView, conf *config.AercConfig,
term.OnStart = func() { term.OnStart = func() {
pv.attemptCopy() pv.attemptCopy()
} }
term.OnInvalidate(func(_ ui.Drawable) {
pv.Invalidate()
})
} }
return pv, nil return pv, nil
@ -644,9 +626,7 @@ func (pv *PartViewer) SetSource(reader io.Reader) {
} }
func (pv *PartViewer) UpdateScreen() { func (pv *PartViewer) UpdateScreen() {
if pv.term != nil { pv.Invalidate()
pv.term.Invalidate()
}
} }
func (pv *PartViewer) attemptCopy() { func (pv *PartViewer) attemptCopy() {
@ -840,7 +820,7 @@ What would you like to do?`, pv.part.MIMEType, pv.part.MIMESubType)
} }
func (pv *PartViewer) Invalidate() { func (pv *PartViewer) Invalidate() {
pv.DoInvalidate(pv) ui.Invalidate()
} }
func (pv *PartViewer) Draw(ctx *ui.Context) { func (pv *PartViewer) Draw(ctx *ui.Context) {
@ -878,7 +858,6 @@ func (pv *PartViewer) Event(event tcell.Event) bool {
} }
type HeaderView struct { type HeaderView struct {
ui.Invalidatable
conf *config.AercConfig conf *config.AercConfig
Name string Name string
Value string Value string
@ -913,5 +892,5 @@ func (hv *HeaderView) Draw(ctx *ui.Context) {
} }
func (hv *HeaderView) Invalidate() { func (hv *HeaderView) Invalidate() {
hv.DoInvalidate(hv) ui.Invalidate()
} }

View file

@ -12,7 +12,6 @@ import (
) )
type PGPInfo struct { type PGPInfo struct {
ui.Invalidatable
details *models.MessageDetails details *models.MessageDetails
uiConfig *config.UIConfig uiConfig *config.UIConfig
} }
@ -95,5 +94,5 @@ func (p *PGPInfo) Draw(ctx *ui.Context) {
} }
func (p *PGPInfo) Invalidate() { func (p *PGPInfo) Invalidate() {
p.DoInvalidate(p) ui.Invalidate()
} }

View file

@ -11,7 +11,6 @@ import (
) )
type Selector struct { type Selector struct {
ui.Invalidatable
chooser bool chooser bool
focused bool focused bool
focus int focus int
@ -36,7 +35,7 @@ func (sel *Selector) Chooser(chooser bool) *Selector {
} }
func (sel *Selector) Invalidate() { func (sel *Selector) Invalidate() {
sel.DoInvalidate(sel) ui.Invalidate()
} }
func (sel *Selector) Draw(ctx *ui.Context) { func (sel *Selector) Draw(ctx *ui.Context) {
@ -166,7 +165,6 @@ func (sel *Selector) Event(event tcell.Event) bool {
var ErrNoOptionSelected = fmt.Errorf("no option selected") var ErrNoOptionSelected = fmt.Errorf("no option selected")
type SelectorDialog struct { type SelectorDialog struct {
ui.Invalidatable
callback func(string, error) callback func(string, error)
title string title string
prompt string prompt string
@ -184,9 +182,6 @@ func NewSelectorDialog(title string, prompt string, options []string, focus int,
uiConfig: uiConfig, uiConfig: uiConfig,
selector: NewSelector(options, focus, uiConfig).Chooser(true), selector: NewSelector(options, focus, uiConfig).Chooser(true),
} }
sd.selector.OnInvalidate(func(_ ui.Drawable) {
sd.Invalidate()
})
sd.selector.Focus(true) sd.selector.Focus(true)
return sd return sd
} }
@ -203,7 +198,7 @@ func (gp *SelectorDialog) Draw(ctx *ui.Context) {
} }
func (gp *SelectorDialog) Invalidate() { func (gp *SelectorDialog) Invalidate() {
gp.DoInvalidate(gp) ui.Invalidate()
} }
func (gp *SelectorDialog) Event(event tcell.Event) bool { func (gp *SelectorDialog) Event(event tcell.Event) bool {

View file

@ -13,7 +13,6 @@ import (
) )
type Spinner struct { type Spinner struct {
ui.Invalidatable
frame int64 // access via atomic frame int64 // access via atomic
frames []string frames []string
stop chan struct{} stop chan struct{}
@ -82,5 +81,5 @@ func (s *Spinner) Draw(ctx *ui.Context) {
} }
func (s *Spinner) Invalidate() { func (s *Spinner) Invalidate() {
s.DoInvalidate(s) ui.Invalidate()
} }

View file

@ -12,7 +12,6 @@ import (
) )
type StatusLine struct { type StatusLine struct {
ui.Invalidatable
stack []*StatusMessage stack []*StatusMessage
fallback StatusMessage fallback StatusMessage
aerc *Aerc aerc *Aerc
@ -33,7 +32,7 @@ func NewStatusLine(uiConfig config.UIConfig) *StatusLine {
} }
func (status *StatusLine) Invalidate() { func (status *StatusLine) Invalidate() {
status.DoInvalidate(status) ui.Invalidate()
} }
func (status *StatusLine) Draw(ctx *ui.Context) { func (status *StatusLine) Draw(ctx *ui.Context) {

View file

@ -13,7 +13,6 @@ import (
) )
type Terminal struct { type Terminal struct {
ui.Invalidatable
closed bool closed bool
cmd *exec.Cmd cmd *exec.Cmd
ctx *ui.Context ctx *ui.Context
@ -71,7 +70,7 @@ func (term *Terminal) Destroy() {
} }
func (term *Terminal) Invalidate() { func (term *Terminal) Invalidate() {
term.DoInvalidate(term) ui.Invalidate()
} }
func (term *Terminal) Draw(ctx *ui.Context) { func (term *Terminal) Draw(ctx *ui.Context) {