2017-11-25 18:30:50 +00:00
|
|
|
package widgets
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2017-11-28 13:40:43 +00:00
|
|
|
|
|
|
|
ui "github.com/gizak/termui"
|
2017-11-25 18:30:50 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type TextView struct {
|
|
|
|
ui.Block
|
2017-11-28 13:40:43 +00:00
|
|
|
inputStream <-chan string
|
2017-11-25 18:30:50 +00:00
|
|
|
render chan bool
|
|
|
|
Text []string // all the text
|
|
|
|
TextOut []string // text to be displayed
|
|
|
|
TextFgColor ui.Attribute
|
|
|
|
TextBgColor ui.Attribute
|
|
|
|
padding Padding
|
|
|
|
}
|
|
|
|
|
2017-11-28 13:40:43 +00:00
|
|
|
func NewTextView(lines <-chan string) *TextView {
|
2017-11-25 18:30:50 +00:00
|
|
|
i := &TextView{
|
|
|
|
Block: *ui.NewBlock(),
|
|
|
|
inputStream: lines,
|
|
|
|
render: make(chan bool),
|
|
|
|
Text: []string{},
|
|
|
|
TextOut: []string{},
|
|
|
|
TextFgColor: ui.ThemeAttr("menu.text.fg"),
|
|
|
|
TextBgColor: ui.ThemeAttr("menu.text.bg"),
|
|
|
|
padding: Padding{4, 2},
|
|
|
|
}
|
|
|
|
|
|
|
|
i.BorderFg = ui.ThemeAttr("menu.border.fg")
|
|
|
|
i.BorderLabelFg = ui.ThemeAttr("menu.label.fg")
|
|
|
|
|
2017-11-28 13:55:29 +00:00
|
|
|
i.Resize()
|
2017-11-25 18:30:50 +00:00
|
|
|
|
|
|
|
i.readInputLoop()
|
|
|
|
i.renderLoop()
|
|
|
|
return i
|
|
|
|
}
|
|
|
|
|
2017-11-28 13:55:29 +00:00
|
|
|
func (i *TextView) Resize() {
|
|
|
|
ui.Clear()
|
|
|
|
i.Height = ui.TermHeight()
|
|
|
|
i.Width = ui.TermWidth()
|
|
|
|
}
|
|
|
|
|
2017-11-25 18:30:50 +00:00
|
|
|
func (i *TextView) Buffer() ui.Buffer {
|
|
|
|
|
|
|
|
var cell ui.Cell
|
|
|
|
buf := i.Block.Buffer()
|
|
|
|
|
|
|
|
x := i.Block.X + i.padding[0]
|
|
|
|
y := i.Block.Y + i.padding[1]
|
|
|
|
|
2017-11-28 13:55:29 +00:00
|
|
|
maxWidth := i.Width - (i.padding[0] * 2)
|
|
|
|
|
2017-11-25 18:30:50 +00:00
|
|
|
for _, line := range i.TextOut {
|
2017-11-28 13:55:29 +00:00
|
|
|
// truncate lines longer than maxWidth
|
|
|
|
if len(line) > maxWidth {
|
|
|
|
line = fmt.Sprintf("%s...", line[:maxWidth-3])
|
|
|
|
}
|
2017-11-25 18:30:50 +00:00
|
|
|
for _, ch := range line {
|
|
|
|
cell = ui.Cell{Ch: ch, Fg: i.TextFgColor, Bg: i.TextBgColor}
|
|
|
|
buf.Set(x, y, cell)
|
|
|
|
x++
|
|
|
|
}
|
|
|
|
x = i.Block.X + i.padding[0]
|
|
|
|
y++
|
|
|
|
}
|
|
|
|
return buf
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *TextView) renderLoop() {
|
|
|
|
go func() {
|
|
|
|
for range i.render {
|
|
|
|
size := i.Height - (i.padding[1] * 2)
|
|
|
|
if size > len(i.Text) {
|
|
|
|
size = len(i.Text)
|
|
|
|
}
|
2017-11-28 13:40:43 +00:00
|
|
|
i.TextOut = i.Text[len(i.Text)-size:]
|
2017-11-25 18:30:50 +00:00
|
|
|
|
|
|
|
ui.Render(i)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *TextView) readInputLoop() {
|
|
|
|
go func() {
|
|
|
|
for line := range i.inputStream {
|
|
|
|
i.Text = append(i.Text, line)
|
|
|
|
i.render <- true
|
|
|
|
}
|
|
|
|
close(i.render)
|
|
|
|
}()
|
|
|
|
}
|