]> git.0d.be Git - barnard.git/blob - uiterm/textview.go
f9cd0a98f784886cb6b48ced0a6e47680a5a6c11
[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 }
35
36 func (t *Textview) ScrollUp() {
37         if newLine := t.CurrentLine + 1; newLine < len(t.parsedLines) {
38                 t.CurrentLine = newLine
39         }
40 }
41
42 func (t *Textview) ScrollDown() {
43         if newLine := t.CurrentLine - 1; newLine >= 0 {
44                 t.CurrentLine = newLine
45         }
46 }
47
48 func (t *Textview) ScrollTop() {
49         if newLine := len(t.parsedLines) - 1; newLine > 0 {
50                 t.CurrentLine = newLine
51         } else {
52                 t.CurrentLine = 0
53         }
54 }
55
56 func (t *Textview) ScrollBottom() {
57         t.CurrentLine = 0
58 }
59
60 func (t *Textview) updateParsedLines() {
61         width := t.x1 - t.x0 - 3
62
63         if t.Lines == nil || width <= 0 {
64                 t.parsedLines = nil
65                 return
66         }
67
68         parsed := make([]string, 0, len(t.Lines))
69         for _, line := range t.Lines {
70                 current := ""
71                 chars := 0
72                 reader := strings.NewReader(line)
73                 for {
74                         if chars >= width {
75                                 parsed = append(parsed, current)
76                                 chars = 0
77                                 current = ""
78                         }
79                         if reader.Len() <= 0 {
80                                 if chars > 0 {
81                                         parsed = append(parsed, current)
82                                 }
83                                 break
84                         }
85                         if ch, _, err := reader.ReadRune(); err == nil {
86                                 current = current + string(ch)
87                                 chars++
88                         }
89                 }
90         }
91         t.parsedLines = parsed
92 }
93
94 func (t *Textview) AddLine(line string) {
95         t.Lines = append(t.Lines, line)
96         t.updateParsedLines()
97 }
98
99 func (t *Textview) Clear() {
100         t.Lines = nil
101         t.CurrentLine = 0
102         t.parsedLines = nil
103 }
104
105 func (t *Textview) uiDraw() {
106         t.ui.beginDraw()
107         defer t.ui.endDraw()
108
109         var reader *strings.Reader
110         line := len(t.parsedLines) - 1 - t.CurrentLine
111         if line < 0 {
112                 line = 0
113         }
114         totalLines := len(t.parsedLines)
115         if totalLines == 0 {
116                 totalLines = 1
117         }
118         currentScrollLine := t.y1 - 1 - int((float32(t.CurrentLine)/float32(totalLines))*float32(t.y1-t.y0))
119         for y := t.y1 - 1; y >= t.y0; y-- {
120                 if t.parsedLines != nil && line >= 0 {
121                         reader = strings.NewReader(t.parsedLines[line])
122                 } else {
123                         reader = nil
124                 }
125                 for x := t.x0; x < t.x1; x++ {
126                         var chr rune = ' '
127                         if x == t.x1-1 { // scrollbar
128                                 if y == currentScrollLine {
129                                         chr = '█'
130                                 } else {
131                                         chr = '░'
132                                 }
133                         } else if x < t.x1-3 {
134                                 if reader != nil {
135                                         if ch, _, err := reader.ReadRune(); err == nil {
136                                                 chr = ch
137                                         }
138                                 }
139                         }
140                         termbox.SetCell(x, y, chr, termbox.Attribute(t.Fg), termbox.Attribute(t.Bg))
141                 }
142                 line--
143         }
144 }
145
146 func (t *Textview) uiKeyEvent(mod Modifier, key Key) {
147 }
148
149 func (t *Textview) uiCharacterEvent(chr rune) {
150 }