aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/msglist.go
diff options
context:
space:
mode:
authorKoni Marti <koni.marti@gmail.com>2022-02-25 17:53:33 +0100
committerRobin Jarry <robin@jarry.cc>2022-03-03 21:11:05 +0100
commit515a8b56f6e9b4e6efaf6a6a29c851dadf4b4a56 (patch)
tree773eb7af099ea985087d76db41c40d36f81cc153 /widgets/msglist.go
parentbd65ce1010a78eec38ba9c70d9fc23f85cd087a1 (diff)
downloadaerc-515a8b56f6e9b4e6efaf6a6a29c851dadf4b4a56.tar.gz
scrollable: extract scrolling behavior for reuse
Extract the vertical scrolling ability into its own Scrollable struct that can be embedded and reused across any ui element that relies on scrolling. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'widgets/msglist.go')
-rw-r--r--widgets/msglist.go67
1 files changed, 15 insertions, 52 deletions
diff --git a/widgets/msglist.go b/widgets/msglist.go
index ae0d2118..f4cea709 100644
--- a/widgets/msglist.go
+++ b/widgets/msglist.go
@@ -20,10 +20,10 @@ import (
type MessageList struct {
ui.Invalidatable
+ Scrollable
conf *config.AercConfig
logger *log.Logger
height int
- scroll int
nmsgs int
spinner *Spinner
store *lib.MessageStore
@@ -70,16 +70,13 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
}
}
- ml.ensureScroll()
-
- needScrollbar := true
- percentVisible := float64(ctx.Height()) / float64(len(store.Uids()))
- if percentVisible >= 1.0 {
- needScrollbar = false
+ ml.UpdateScroller(ml.height, len(store.Uids()))
+ if store := ml.Store(); store != nil && len(store.Uids()) > 0 {
+ ml.EnsureScroll(store.SelectedIndex())
}
textWidth := ctx.Width()
- if needScrollbar {
+ if ml.NeedScrollbar() {
textWidth -= 1
}
if textWidth < 0 {
@@ -105,7 +102,7 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
return nil
}
counter--
- if counter > len(store.Uids())-1-ml.scroll {
+ if counter > len(store.Uids())-1-ml.Scroll() {
//skip messages which are higher than the viewport
return nil
}
@@ -142,7 +139,7 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
}
} else {
uids := store.Uids()
- for i := len(uids) - 1 - ml.scroll; i >= 0; i-- {
+ for i := len(uids) - 1 - ml.Scroll(); i >= 0; i-- {
uid := uids[i]
msg := store.Messages[uid]
fmtCtx := format.Ctx{
@@ -159,9 +156,9 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
}
}
- if needScrollbar {
+ if ml.NeedScrollbar() {
scrollbarCtx := ctx.Subcontext(ctx.Width()-1, 0, 1, ctx.Height())
- ml.drawScrollbar(scrollbarCtx, percentVisible)
+ ml.drawScrollbar(scrollbarCtx)
}
if len(store.Uids()) == 0 {
@@ -241,7 +238,7 @@ func (ml *MessageList) drawRow(textWidth int, ctx *ui.Context, uid uint32, row i
var style tcell.Style
// current row
- if row == ml.store.SelectedIndex()-ml.scroll {
+ if row == ml.store.SelectedIndex()-ml.Scroll() {
style = uiConfig.GetComposedStyleSelected(config.STYLE_MSGLIST_DEFAULT, msg_styles)
} else {
style = uiConfig.GetComposedStyle(config.STYLE_MSGLIST_DEFAULT, msg_styles)
@@ -265,7 +262,7 @@ func (ml *MessageList) drawRow(textWidth int, ctx *ui.Context, uid uint32, row i
return false
}
-func (ml *MessageList) drawScrollbar(ctx *ui.Context, percentVisible float64) {
+func (ml *MessageList) drawScrollbar(ctx *ui.Context) {
gutterStyle := tcell.StyleDefault
pillStyle := tcell.StyleDefault.Reverse(true)
@@ -273,9 +270,8 @@ func (ml *MessageList) drawScrollbar(ctx *ui.Context, percentVisible float64) {
ctx.Fill(0, 0, 1, ctx.Height(), ' ', gutterStyle)
// pill
- pillSize := int(math.Ceil(float64(ctx.Height()) * percentVisible))
- percentScrolled := float64(ml.scroll) / float64(len(ml.Store().Uids()))
- pillOffset := int(math.Floor(float64(ctx.Height()) * percentScrolled))
+ pillSize := int(math.Ceil(float64(ctx.Height()) * ml.PercentVisible()))
+ pillOffset := int(math.Floor(float64(ctx.Height()) * ml.PercentScrolled()))
ctx.Fill(0, pillOffset, 1, pillSize, ' ', pillStyle)
}
@@ -328,7 +324,7 @@ func (ml *MessageList) Clicked(x, y int) (int, bool) {
if store == nil || ml.nmsgs == 0 || y >= ml.nmsgs {
return 0, false
}
- return y + ml.scroll, true
+ return y + ml.Scroll(), true
}
func (ml *MessageList) Height() int {
@@ -364,7 +360,7 @@ func (ml *MessageList) storeUpdate(store *lib.MessageStore) {
func (ml *MessageList) SetStore(store *lib.MessageStore) {
if ml.Store() != store {
- ml.scroll = 0
+ ml.Scrollable = Scrollable{}
}
ml.store = store
if store != nil {
@@ -402,39 +398,6 @@ func (ml *MessageList) Select(index int) {
ml.Invalidate()
}
-func (ml *MessageList) ensureScroll() {
- store := ml.Store()
- if store == nil || len(store.Uids()) == 0 {
- return
- }
-
- h := ml.Height()
-
- maxScroll := len(store.Uids()) - h
- if maxScroll < 0 {
- maxScroll = 0
- }
-
- 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
- }
-}
-
func (ml *MessageList) drawEmptyMessage(ctx *ui.Context) {
uiConfig := ml.aerc.SelectedAccountUiConfig()
msg := uiConfig.EmptyMessage