1 package cview
2
3 import (
4 "sync"
5
6 "github.com/gdamore/tcell/v2"
7 )
8
9
10
11 type CheckBox struct {
12 *Box
13
14
15 checked bool
16
17
18 label []byte
19
20
21 message []byte
22
23
24
25 labelWidth int
26
27
28 labelColor tcell.Color
29
30
31 labelColorFocused tcell.Color
32
33
34 fieldBackgroundColor tcell.Color
35
36
37 fieldBackgroundColorFocused tcell.Color
38
39
40 fieldTextColor tcell.Color
41
42
43 fieldTextColorFocused tcell.Color
44
45
46
47 changed func(checked bool)
48
49
50
51
52 done func(tcell.Key)
53
54
55
56 finished func(tcell.Key)
57
58
59 checkedRune rune
60
61
62 cursorRune rune
63
64 sync.RWMutex
65 }
66
67
68 func NewCheckBox() *CheckBox {
69 return &CheckBox{
70 Box: NewBox(),
71 labelColor: Styles.SecondaryTextColor,
72 fieldBackgroundColor: Styles.MoreContrastBackgroundColor,
73 fieldBackgroundColorFocused: Styles.ContrastBackgroundColor,
74 fieldTextColor: Styles.PrimaryTextColor,
75 checkedRune: Styles.CheckBoxCheckedRune,
76 cursorRune: Styles.CheckBoxCursorRune,
77 labelColorFocused: ColorUnset,
78 fieldTextColorFocused: ColorUnset,
79 }
80 }
81
82
83 func (c *CheckBox) SetChecked(checked bool) {
84 c.Lock()
85 defer c.Unlock()
86
87 c.checked = checked
88 }
89
90
91 func (c *CheckBox) SetCheckedRune(rune rune) {
92 c.Lock()
93 defer c.Unlock()
94
95 c.checkedRune = rune
96 }
97
98
99 func (c *CheckBox) SetCursorRune(rune rune) {
100 c.Lock()
101 defer c.Unlock()
102
103 c.cursorRune = rune
104 }
105
106
107 func (c *CheckBox) IsChecked() bool {
108 c.RLock()
109 defer c.RUnlock()
110
111 return c.checked
112 }
113
114
115 func (c *CheckBox) SetLabel(label string) {
116 c.Lock()
117 defer c.Unlock()
118
119 c.label = []byte(label)
120 }
121
122
123 func (c *CheckBox) GetLabel() string {
124 c.RLock()
125 defer c.RUnlock()
126
127 return string(c.label)
128 }
129
130
131 func (c *CheckBox) SetMessage(message string) {
132 c.Lock()
133 defer c.Unlock()
134
135 c.message = []byte(message)
136 }
137
138
139 func (c *CheckBox) GetMessage() string {
140 c.RLock()
141 defer c.RUnlock()
142
143 return string(c.message)
144 }
145
146
147
148 func (c *CheckBox) SetLabelWidth(width int) {
149 c.Lock()
150 defer c.Unlock()
151
152 c.labelWidth = width
153 }
154
155
156 func (c *CheckBox) SetLabelColor(color tcell.Color) {
157 c.Lock()
158 defer c.Unlock()
159
160 c.labelColor = color
161 }
162
163
164 func (c *CheckBox) SetLabelColorFocused(color tcell.Color) {
165 c.Lock()
166 defer c.Unlock()
167
168 c.labelColorFocused = color
169 }
170
171
172 func (c *CheckBox) SetFieldBackgroundColor(color tcell.Color) {
173 c.Lock()
174 defer c.Unlock()
175
176 c.fieldBackgroundColor = color
177 }
178
179
180 func (c *CheckBox) SetFieldBackgroundColorFocused(color tcell.Color) {
181 c.Lock()
182 defer c.Unlock()
183
184 c.fieldBackgroundColorFocused = color
185 }
186
187
188 func (c *CheckBox) SetFieldTextColor(color tcell.Color) {
189 c.Lock()
190 defer c.Unlock()
191
192 c.fieldTextColor = color
193 }
194
195
196 func (c *CheckBox) SetFieldTextColorFocused(color tcell.Color) {
197 c.Lock()
198 defer c.Unlock()
199
200 c.fieldTextColorFocused = color
201 }
202
203
204 func (c *CheckBox) GetFieldHeight() int {
205 return 1
206 }
207
208
209 func (c *CheckBox) GetFieldWidth() int {
210 c.RLock()
211 defer c.RUnlock()
212
213 if len(c.message) == 0 {
214 return 1
215 }
216
217 return 2 + len(c.message)
218 }
219
220
221
222
223 func (c *CheckBox) SetChangedFunc(handler func(checked bool)) {
224 c.Lock()
225 defer c.Unlock()
226
227 c.changed = handler
228 }
229
230
231
232
233
234
235
236
237 func (c *CheckBox) SetDoneFunc(handler func(key tcell.Key)) {
238 c.Lock()
239 defer c.Unlock()
240
241 c.done = handler
242 }
243
244
245 func (c *CheckBox) SetFinishedFunc(handler func(key tcell.Key)) {
246 c.Lock()
247 defer c.Unlock()
248
249 c.finished = handler
250 }
251
252
253 func (c *CheckBox) Draw(screen tcell.Screen) {
254 if !c.GetVisible() {
255 return
256 }
257
258 c.Box.Draw(screen)
259
260 c.Lock()
261 defer c.Unlock()
262
263 hasFocus := c.GetFocusable().HasFocus()
264
265
266 labelColor := c.labelColor
267 fieldBackgroundColor := c.fieldBackgroundColor
268 fieldTextColor := c.fieldTextColor
269 if hasFocus {
270 if c.labelColorFocused != ColorUnset {
271 labelColor = c.labelColorFocused
272 }
273 if c.fieldBackgroundColorFocused != ColorUnset {
274 fieldBackgroundColor = c.fieldBackgroundColorFocused
275 }
276 if c.fieldTextColorFocused != ColorUnset {
277 fieldTextColor = c.fieldTextColorFocused
278 }
279 }
280
281
282 x, y, width, height := c.GetInnerRect()
283 rightLimit := x + width
284 if height < 1 || rightLimit <= x {
285 return
286 }
287
288
289 if c.labelWidth > 0 {
290 labelWidth := c.labelWidth
291 if labelWidth > rightLimit-x {
292 labelWidth = rightLimit - x
293 }
294 Print(screen, c.label, x, y, labelWidth, AlignLeft, labelColor)
295 x += labelWidth
296 } else {
297 _, drawnWidth := Print(screen, c.label, x, y, rightLimit-x, AlignLeft, labelColor)
298 x += drawnWidth
299 }
300
301
302 fieldStyle := tcell.StyleDefault.Background(fieldBackgroundColor).Foreground(fieldTextColor)
303
304 checkedRune := c.checkedRune
305 if !c.checked {
306 checkedRune = ' '
307 }
308 rightRune := ' '
309 if c.cursorRune != 0 && hasFocus {
310 rightRune = c.cursorRune
311 }
312 screen.SetContent(x, y, ' ', nil, fieldStyle)
313 screen.SetContent(x+1, y, checkedRune, nil, fieldStyle)
314 screen.SetContent(x+2, y, rightRune, nil, fieldStyle)
315
316 if len(c.message) > 0 {
317 Print(screen, c.message, x+4, y, len(c.message), AlignLeft, labelColor)
318 }
319 }
320
321
322 func (c *CheckBox) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
323 return c.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
324 if HitShortcut(event, Keys.Select, Keys.Select2) {
325 c.Lock()
326 c.checked = !c.checked
327 c.Unlock()
328 if c.changed != nil {
329 c.changed(c.checked)
330 }
331 } else if HitShortcut(event, Keys.Cancel, Keys.MovePreviousField, Keys.MoveNextField) {
332 if c.done != nil {
333 c.done(event.Key())
334 }
335 if c.finished != nil {
336 c.finished(event.Key())
337 }
338 }
339 })
340 }
341
342
343 func (c *CheckBox) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
344 return c.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
345 x, y := event.Position()
346 _, rectY, _, _ := c.GetInnerRect()
347 if !c.InRect(x, y) {
348 return false, nil
349 }
350
351
352 if action == MouseLeftClick && y == rectY {
353 setFocus(c)
354 c.checked = !c.checked
355 if c.changed != nil {
356 c.changed(c.checked)
357 }
358 consumed = true
359 }
360
361 return
362 })
363 }
364
View as plain text