Render scroll position and indicate if at end/beginning of history. Fixes #9

This commit is contained in:
Tulir Asokan 2018-03-23 17:26:06 +02:00
parent 03e9a0d5ac
commit 7dc773c990

View File

@ -19,6 +19,7 @@ package widget
import ( import (
"encoding/gob" "encoding/gob"
"fmt" "fmt"
"math"
"os" "os"
"time" "time"
@ -37,7 +38,6 @@ type MessageView struct {
DateFormat string DateFormat string
TimestampFormat string TimestampFormat string
TimestampWidth int TimestampWidth int
Separator rune
LoadingMessages bool LoadingMessages bool
widestSender int widestSender int
@ -59,7 +59,6 @@ func NewMessageView() *MessageView {
DateFormat: "January _2, 2006", DateFormat: "January _2, 2006",
TimestampFormat: "15:04:05", TimestampFormat: "15:04:05",
TimestampWidth: 8, TimestampWidth: 8,
Separator: '|',
ScrollOffset: 0, ScrollOffset: 0,
messages: make([]*types.Message, 0), messages: make([]*types.Message, 0),
@ -307,12 +306,9 @@ func (view *MessageView) Draw(screen tcell.Screen) {
return return
} }
usernameOffsetX := view.TimestampWidth + TimestampSenderGap usernameX := x + view.TimestampWidth + TimestampSenderGap
messageOffsetX := usernameOffsetX + view.widestSender + SenderMessageGap messageX := usernameX + view.widestSender + SenderMessageGap
separatorX := x + usernameOffsetX + view.widestSender + SenderSeparatorGap separatorX := usernameX + view.widestSender + SenderSeparatorGap
for separatorY := y; separatorY < y+height; separatorY++ {
screen.SetContent(separatorX, separatorY, view.Separator, nil, tcell.StyleDefault)
}
indexOffset := len(view.textBuffer) - view.ScrollOffset - height indexOffset := len(view.textBuffer) - view.ScrollOffset - height
if indexOffset <= -PaddingAtTop { if indexOffset <= -PaddingAtTop {
@ -320,7 +316,7 @@ func (view *MessageView) Draw(screen tcell.Screen) {
if view.LoadingMessages { if view.LoadingMessages {
message = "Loading more messages..." message = "Loading more messages..."
} }
view.writeLine(screen, message, x+messageOffsetX, y, tcell.ColorGreen) view.writeLine(screen, message, messageX, y, tcell.ColorGreen)
} }
if len(view.textBuffer) != len(view.metaBuffer) { if len(view.textBuffer) != len(view.metaBuffer) {
@ -328,7 +324,15 @@ func (view *MessageView) Draw(screen tcell.Screen) {
return return
} }
totalHeight := float64(len(view.textBuffer))
// ceil(height / (totalHeight / height))
scrollBarHeight := int(math.Ceil(float64(height) / (totalHeight / float64(height))))
// height - ceil(scrollOffset) / totalHeight * height
scrollBarPos := height - int(math.Ceil(float64(view.ScrollOffset) / totalHeight * float64(height)))
var prevMeta types.MessageMeta var prevMeta types.MessageMeta
firstLine := true
for line := 0; line < height; line++ { for line := 0; line < height; line++ {
index := indexOffset + line index := indexOffset + line
if index < 0 { if index < 0 {
@ -336,6 +340,23 @@ func (view *MessageView) Draw(screen tcell.Screen) {
} else if index >= len(view.textBuffer) { } else if index >= len(view.textBuffer) {
break break
} }
borderChar := '│'
borderStyle := tcell.StyleDefault
if firstLine && view.ScrollOffset+height >= len(view.textBuffer) {
// At top of loaded message history
borderChar = '┬'
} else if line == height-1 && view.ScrollOffset == 0 {
// At bottom of message history
borderChar = '┴'
} else if line >= scrollBarPos && line < scrollBarPos + scrollBarHeight {
// Scroll bar
borderChar = '║'
borderStyle = borderStyle.Foreground(tcell.ColorGreen)
}
firstLine = false
screen.SetContent(separatorX, y+line, borderChar, nil, borderStyle)
text, meta := view.textBuffer[index], view.metaBuffer[index] text, meta := view.textBuffer[index], view.metaBuffer[index]
if meta != prevMeta { if meta != prevMeta {
if len(meta.GetTimestamp()) > 0 { if len(meta.GetTimestamp()) > 0 {
@ -344,11 +365,11 @@ func (view *MessageView) Draw(screen tcell.Screen) {
if prevMeta == nil || meta.GetSender() != prevMeta.GetSender() { if prevMeta == nil || meta.GetSender() != prevMeta.GetSender() {
view.writeLineRight( view.writeLineRight(
screen, meta.GetSender(), screen, meta.GetSender(),
x+usernameOffsetX, y+line, usernameX, y+line,
view.widestSender, meta.GetSenderColor()) view.widestSender, meta.GetSenderColor())
} }
prevMeta = meta prevMeta = meta
} }
view.writeLine(screen, text, x+messageOffsetX, y+line, meta.GetTextColor()) view.writeLine(screen, text, messageX, y+line, meta.GetTextColor())
} }
} }