Rework msglist scrolling

This changes the scrolling to be done on the draw, when the height is
updated, ensuring that the selected item is kept on screen during
resizing.

Also, this ensures that messages will fill the screen when resizing the
window, for instance, shrinking and then growing drags down more
messages if possible.

This is a transplant of the dirlist scrolling logic.
This commit is contained in:
Jeffas 2020-06-09 20:13:13 +01:00 committed by Reto Brunner
parent c6f4d7badd
commit 15b72df1da
7 changed files with 40 additions and 24 deletions

View file

@ -34,13 +34,13 @@ func (NextPrevResult) Execute(aerc *widgets.Aerc, args []string) error {
if store != nil { if store != nil {
store.PrevResult() store.PrevResult()
} }
acct.Messages().Scroll() acct.Messages().Invalidate()
} else { } else {
store := acct.Store() store := acct.Store()
if store != nil { if store != nil {
store.NextResult() store.NextResult()
} }
acct.Messages().Scroll() acct.Messages().Invalidate()
} }
return nil return nil
} }

View file

@ -65,13 +65,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().Scroll() acct.Messages().Invalidate()
} }
} else { } else {
store := acct.Store() store := acct.Store()
if store != nil { if store != nil {
store.NextPrev(n) store.NextPrev(n)
acct.Messages().Scroll() acct.Messages().Invalidate()
} }
} }
return nil return nil

View file

@ -45,7 +45,7 @@ func (SearchFilter) Execute(aerc *widgets.Aerc, args []string) error {
acct.Logger().Printf("Search results: %v", uids) acct.Logger().Printf("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().Scroll() acct.Messages().Invalidate()
} }
} }
store.Search(args, cb) store.Search(args, cb)

View file

@ -53,7 +53,7 @@ func (Archive) Execute(aerc *widgets.Aerc, args []string) error {
} }
archiveDir := acct.AccountConfig().Archive archiveDir := acct.AccountConfig().Archive
store.Next() store.Next()
acct.Messages().Scroll() acct.Messages().Invalidate()
var uidMap map[string][]uint32 var uidMap map[string][]uint32
switch args[1] { switch args[1] {

View file

@ -62,7 +62,7 @@ func (Delete) Execute(aerc *widgets.Aerc, args []string) error {
// no more messages in the list // no more messages in the list
if next == nil { if next == nil {
aerc.RemoveTab(h.msgProvider) aerc.RemoveTab(h.msgProvider)
acct.Messages().Scroll() acct.Messages().Invalidate()
return nil return nil
} }
lib.NewMessageStoreView(next, store, aerc.DecryptKeys, lib.NewMessageStoreView(next, store, aerc.DecryptKeys,
@ -76,7 +76,7 @@ func (Delete) Execute(aerc *widgets.Aerc, args []string) error {
}) })
} }
} }
acct.Messages().Scroll() acct.Messages().Invalidate()
return nil return nil
} }

View file

@ -62,7 +62,7 @@ func (Move) Execute(aerc *widgets.Aerc, args []string) error {
aerc.RemoveTab(h.msgProvider) aerc.RemoveTab(h.msgProvider)
} }
store.Next() store.Next()
acct.Messages().Scroll() acct.Messages().Invalidate()
joinedArgs := strings.Join(args[optind:], " ") joinedArgs := strings.Join(args[optind:], " ")
store.Move(uids, joinedArgs, createParents, func( store.Move(uids, joinedArgs, createParents, func(
msg types.WorkerMessage) { msg types.WorkerMessage) {

View file

@ -63,6 +63,8 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
} }
} }
ml.ensureScroll()
var ( var (
needsHeaders []uint32 needsHeaders []uint32
row int = 0 row int = 0
@ -179,12 +181,12 @@ func (ml *MessageList) MouseEvent(localX int, localY int, event tcell.Event) {
if ml.store != nil { if ml.store != nil {
ml.store.Next() ml.store.Next()
} }
ml.Scroll() ml.Invalidate()
case tcell.WheelUp: case tcell.WheelUp:
if ml.store != nil { if ml.store != nil {
ml.store.Prev() ml.store.Prev()
} }
ml.Scroll() ml.Invalidate()
} }
} }
} }
@ -225,7 +227,6 @@ func (ml *MessageList) storeUpdate(store *lib.MessageStore) {
ml.nmsgs = len(uids) ml.nmsgs = len(uids)
} }
ml.Scroll()
ml.Invalidate() ml.Invalidate()
} }
@ -266,25 +267,40 @@ func (ml *MessageList) Selected() *models.MessageInfo {
func (ml *MessageList) Select(index int) { func (ml *MessageList) Select(index int) {
store := ml.Store() store := ml.Store()
store.Select(index) store.Select(index)
ml.Scroll() ml.Invalidate()
} }
func (ml *MessageList) Scroll() { func (ml *MessageList) ensureScroll() {
store := ml.Store() store := ml.Store()
if store == nil || len(store.Uids()) == 0 { if store == nil || len(store.Uids()) == 0 {
return return
} }
if ml.Height() != 0 {
// I'm too lazy to do the math right now h := ml.Height()
for store.SelectedIndex()-ml.scroll >= ml.Height() {
ml.scroll += 1 maxScroll := len(store.Uids()) - h
if maxScroll < 0 {
maxScroll = 0
} }
for store.SelectedIndex()-ml.scroll < 0 {
ml.scroll -= 1 selectedIndex := store.SelectedIndex()
if selectedIndex >= ml.scroll && selectedIndex < ml.scroll+h {
if ml.scroll > maxScroll {
ml.scroll = maxScroll
} }
return
}
if selectedIndex >= ml.scroll+h {
ml.scroll = selectedIndex - h + 1
} else if selectedIndex < ml.scroll {
ml.scroll = selectedIndex
}
if ml.scroll > maxScroll {
ml.scroll = maxScroll
} }
ml.Invalidate()
} }
func (ml *MessageList) drawEmptyMessage(ctx *ui.Context) { func (ml *MessageList) drawEmptyMessage(ctx *ui.Context) {