...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package views
16
17 import (
18 "strings"
19 "sync"
20
21 "github.com/gdamore/tcell/v2"
22 )
23
24
25
26
27
28
29 type TextArea struct {
30 model *linesModel
31 once sync.Once
32 CellView
33 }
34
35 type linesModel struct {
36 runes [][]rune
37 width int
38 height int
39 x int
40 y int
41 hide bool
42 cursor bool
43 style tcell.Style
44 }
45
46 func (m *linesModel) GetCell(x, y int) (rune, tcell.Style, []rune, int) {
47 if x < 0 || y < 0 || y >= m.height || x >= len(m.runes[y]) {
48 return 0, m.style, nil, 1
49 }
50
51 return m.runes[y][x], m.style, nil, 1
52 }
53
54 func (m *linesModel) GetBounds() (int, int) {
55 return m.width, m.height
56 }
57
58 func (m *linesModel) limitCursor() {
59 if m.x > m.width-1 {
60 m.x = m.width - 1
61 }
62 if m.y > m.height-1 {
63 m.y = m.height - 1
64 }
65 if m.x < 0 {
66 m.x = 0
67 }
68 if m.y < 0 {
69 m.y = 0
70 }
71 }
72
73 func (m *linesModel) SetCursor(x, y int) {
74 m.x = x
75 m.y = y
76 m.limitCursor()
77 }
78
79 func (m *linesModel) MoveCursor(x, y int) {
80 m.x += x
81 m.y += y
82 m.limitCursor()
83 }
84
85 func (m *linesModel) GetCursor() (int, int, bool, bool) {
86 return m.x, m.y, m.cursor, !m.hide
87 }
88
89
90 func (ta *TextArea) SetLines(lines []string) {
91 ta.Init()
92 m := ta.model
93 m.width = 0
94
95
96 slice := make([][]rune, len(lines))
97 m.runes = slice
98
99 for row, line := range lines {
100 for _, ch := range line {
101 m.runes[row] = append(m.runes[row], ch)
102 }
103 if len(m.runes[row]) > m.width {
104 m.width = len(m.runes[row])
105 }
106 }
107
108 m.height = len(m.runes)
109
110 ta.CellView.SetModel(m)
111 }
112
113 func (ta *TextArea) SetStyle(style tcell.Style) {
114 ta.model.style = style
115 ta.CellView.SetStyle(style)
116 }
117
118
119 func (ta *TextArea) EnableCursor(on bool) {
120 ta.Init()
121 ta.model.cursor = on
122 }
123
124
125
126
127 func (ta *TextArea) HideCursor(on bool) {
128 ta.Init()
129 ta.model.hide = on
130 }
131
132
133
134 func (ta *TextArea) SetContent(text string) {
135 ta.Init()
136 lines := strings.Split(strings.Trim(text, "\n"), "\n")
137 ta.SetLines(lines)
138 }
139
140
141 func (ta *TextArea) Init() {
142 ta.once.Do(func() {
143 lm := &linesModel{runes: [][]rune{}, width: 0}
144 ta.model = lm
145 ta.CellView.Init()
146 ta.CellView.SetModel(lm)
147 })
148 }
149
150
151 func NewTextArea() *TextArea {
152 ta := &TextArea{}
153 ta.Init()
154 return ta
155 }
156
View as plain text