2016-09-11 17:55:19 +02:00
package components
2016-09-24 20:18:09 +02:00
import (
"strings"
"github.com/gizak/termui"
)
type Chat struct {
List * termui . List
}
func CreateChat ( inputHeight int ) * Chat {
chat := & Chat {
List : termui . NewList ( ) ,
}
chat . List . Height = termui . TermHeight ( ) - inputHeight
chat . List . Overflow = "wrap"
chat . LoadMessages ( )
return chat
}
// Buffer implements interface termui.Bufferer
func ( c * Chat ) Buffer ( ) termui . Buffer {
// Build cells, after every item put a newline
cells := termui . DefaultTxBuilder . Build (
strings . Join ( c . List . Items , "\n" ) ,
c . List . ItemFgColor , c . List . ItemBgColor ,
)
2016-09-25 12:54:24 +02:00
// We will create an array of Line structs, this allows us
// to more easily render the items in a list. We will range
// over the cells we've created and create a Line within
// the bounds of the Chat pane
2016-09-24 20:18:09 +02:00
type Line struct {
cells [ ] termui . Cell
}
lines := [ ] Line { }
line := Line { }
x := 0
for _ , cell := range cells {
if cell . Ch == '\n' {
lines = append ( lines , line )
line = Line { }
x = 0
continue
}
if x + cell . Width ( ) > c . List . InnerBounds ( ) . Dx ( ) {
lines = append ( lines , line )
line = Line { }
x = 0
}
line . cells = append ( line . cells , cell )
x ++
}
2016-09-25 12:54:24 +02:00
lines = append ( lines , line )
2016-09-24 20:18:09 +02:00
2016-09-25 12:54:24 +02:00
// We will print lines bottom up, it will loop over the lines
// backwards and for every line it'll set the cell in that line
2016-09-24 20:18:09 +02:00
buf := c . List . Buffer ( )
linesHeight := len ( lines )
2016-09-25 12:54:24 +02:00
paneMinY := c . List . InnerBounds ( ) . Min . Y
paneMaxY := c . List . InnerBounds ( ) . Max . Y
2016-09-24 20:18:09 +02:00
2016-09-25 12:54:24 +02:00
currentY := paneMaxY - 1
2016-09-24 20:18:09 +02:00
for i := linesHeight - 1 ; i >= 0 ; i -- {
2016-09-25 12:54:24 +02:00
if currentY < paneMinY {
2016-09-24 20:18:09 +02:00
break
}
x := c . List . InnerBounds ( ) . Min . X
for _ , cell := range lines [ i ] . cells {
buf . Set ( x , currentY , cell )
x += cell . Width ( )
}
2016-09-25 12:54:24 +02:00
// When we're not at the end of the pane, fill it up
// with empty characters
for x < c . List . InnerBounds ( ) . Max . X {
buf . Set ( x , currentY , termui . Cell { Ch : ' ' } )
x ++
}
currentY --
}
// If the space above currentY is empty we need to fill
// it up with blank lines, otherwise the List object will
// render the items top down, and the result will mix.
for currentY >= paneMinY {
x := c . List . InnerBounds ( ) . Min . X
for x < c . List . InnerBounds ( ) . Max . X {
buf . Set ( x , currentY , termui . Cell { Ch : ' ' } )
x ++
}
2016-09-24 20:18:09 +02:00
currentY --
}
return buf
}
// GetHeight implements interface termui.GridBufferer
func ( c * Chat ) GetHeight ( ) int {
return c . List . Block . GetHeight ( )
}
// SetWidth implements interface termui.GridBufferer
func ( c * Chat ) SetWidth ( w int ) {
c . List . SetWidth ( w )
}
// SetX implements interface termui.GridBufferer
func ( c * Chat ) SetX ( x int ) {
c . List . SetX ( x )
}
// SetY implements interface termui.GridBufferer
func ( c * Chat ) SetY ( y int ) {
c . List . SetY ( y )
}
func ( c * Chat ) LoadMessages ( ) {
messages := [ ] string {
"[jp] hello world" ,
"[erroneousboat] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar" ,
}
for _ , message := range messages {
c . AddMessages ( message )
}
}
func ( c * Chat ) AddMessages ( message string ) {
c . List . Items = append ( c . List . Items , message )
}
func ( c * Chat ) ScrollUp ( ) {
}
func ( c * Chat ) ScrollDown ( ) { }