]> git.0d.be Git - barnard.git/blob - uiterm/textview.go
945081e8b3bb4086fd520da779614c9e46882105
[barnard.git] / uiterm / textview.go
1 package uiterm
2
3 import (
4         "strings"
5
6         "github.com/nsf/termbox-go"
7 )
8
9 type Textview struct {
10         Lines       []string
11         CurrentLine int
12         Fg          Attribute
13         Bg          Attribute
14
15         parsedLines []string
16
17         ui             *Ui
18         x0, y0, x1, y1 int
19 }
20
21 func (t *Textview) uiInitialize(ui *Ui) {
22         t.ui = ui
23 }
24
25 func (t *Textview) uiSetActive(active bool) {
26 }
27
28 func (t *Textview) uiSetBounds(x0, y0, x1, y1 int) {
29         t.x0 = x0
30         t.y0 = y0
31         t.x1 = x1
32         t.y1 = y1
33         t.updateParsedLines()
34         t.uiDraw()
35 }
36
37 func (t *Textview) ScrollUp() {
38         if newLine := t.CurrentLine + 1; newLine < len(t.parsedLines) {
39                 t.CurrentLine = newLine
40         }
41         t.uiDraw()
42 }
43
44 func (t *Textview) ScrollDown() {
45         if newLine := t.CurrentLine - 1; newLine >= 0 {
46                 t.CurrentLine = newLine
47         }
48         t.uiDraw()
49 }
50
51 func (t *Textview) ScrollTop() {
52         if newLine := len(t.parsedLines) - 1; newLine > 0 {
53                 t.CurrentLine = newLine
54         } else {
55                 t.CurrentLine = 0
56         }
57         t.uiDraw()
58 }
59
60 func (t *Textview) ScrollBottom() {
61         t.CurrentLine = 0
62         t.uiDraw()
63 }
64
65 func (t *Textview) updateParsedLines() {
66         width := t.x1 - t.x0 - 3
67
68         if t.Lines == nil || width <= 0 {
69                 t.parsedLines = nil
70                 return
71         }
72
73         parsed := make([]string, 0, len(t.Lines))
74         for _, line := range t.Lines {
75                 current := ""
76                 chars := 0
77                 reader := strings.NewReader(line)
78                 for {
79                         if chars >= width {
80                                 parsed = append(parsed, current)
81                                 chars = 0
82                                 current = ""
83                         }
84                         if reader.Len() <= 0 {
85                                 if chars > 0 {
86                                         parsed = append(parsed, current)
87                                 }
88                                 break
89                         }
90                         if ch, _, err := reader.ReadRune(); err == nil {
91                                 current = current + string(ch)
92                                 chars++
93                         }
94                 }
95         }
96         t.parsedLines = parsed
97 }
98
99 func (t *Textview) AddLine(line string) {
100         t.Lines = append(t.Lines, line)
101         t.updateParsedLines()
102         t.uiDraw()
103 }
104
105 func (t *Textview) Clear() {
106         t.Lines = nil
107         t.CurrentLine = 0
108         t.parsedLines = nil
109         t.uiDraw()
110 }
111
112 func (t *Textview) uiDraw() {
113         t.ui.beginDraw()
114         defer t.ui.endDraw()
115
116         var reader *strings.Reader
117         line := len(t.parsedLines) - 1 - t.CurrentLine
118         if line < 0 {
119                 line = 0
120         }
121         totalLines := len(t.parsedLines)
122         if totalLines == 0 {
123                 totalLines = 1
124         }
125         currentScrollLine := t.y1 - 1 - int((float32(t.CurrentLine)/float32(totalLines))*float32(t.y1-t.y0))
126         for y := t.y1 - 1; y >= t.y0; y-- {
127                 if t.parsedLines != nil && line >= 0 {
128                         reader = strings.NewReader(t.parsedLines[line])
129                 } else {
130                         reader = nil
131                 }
132                 for x := t.x0; x < t.x1; x++ {
133                         var chr rune = ' '
134                         if x == t.x1-1 { // scrollbar
135                                 if y == currentScrollLine {
136                                         chr = '█'
137                                 } else {
138                                         chr = '░'
139                                 }
140                         } else if x < t.x1-3 {
141                                 if reader != nil {
142                                         if ch, _, err := reader.ReadRune(); err == nil {
143                                                 chr = ch
144                                         }
145                                 }
146                         }
147                         termbox.SetCell(x, y, chr, termbox.Attribute(t.Fg), termbox.Attribute(t.Bg))
148                 }
149                 line--
150         }
151 }
152
153 func (t *Textview) uiKeyEvent(mod Modifier, key Key) {
154 }
155
156 func (t *Textview) uiCharacterEvent(chr rune) {
157 }