1 package cview
2
3 import (
4 "sync"
5
6 "github.com/gdamore/tcell/v2"
7 )
8
9
10
11
12
13
14
15 type Modal struct {
16 *Box
17
18
19 frame *Frame
20
21
22 form *Form
23
24
25 text string
26
27
28 textColor tcell.Color
29
30
31 textAlign int
32
33
34
35 done func(buttonIndex int, buttonLabel string)
36
37 sync.RWMutex
38 }
39
40
41 func NewModal() *Modal {
42 m := &Modal{
43 Box: NewBox(),
44 textColor: Styles.PrimaryTextColor,
45 textAlign: AlignCenter,
46 }
47
48 m.form = NewForm()
49 m.form.SetButtonsAlign(AlignCenter)
50 m.form.SetPadding(0, 0, 0, 0)
51 m.form.SetCancelFunc(func() {
52 if m.done != nil {
53 m.done(-1, "")
54 }
55 })
56
57 m.frame = NewFrame(m.form)
58 m.frame.SetBorder(true)
59 m.frame.SetBorders(0, 0, 1, 0, 0, 0)
60 m.frame.SetPadding(1, 1, 1, 1)
61
62 m.focus = m
63 return m
64 }
65
66
67 func (m *Modal) SetBackgroundColor(color tcell.Color) {
68 m.Lock()
69 defer m.Unlock()
70
71 m.form.SetBackgroundColor(color)
72 m.frame.SetBackgroundColor(color)
73 }
74
75
76 func (m *Modal) SetTextColor(color tcell.Color) {
77 m.Lock()
78 defer m.Unlock()
79
80 m.textColor = color
81 }
82
83
84 func (m *Modal) SetButtonBackgroundColor(color tcell.Color) {
85 m.Lock()
86 defer m.Unlock()
87
88 m.form.SetButtonBackgroundColor(color)
89 }
90
91
92 func (m *Modal) SetButtonTextColor(color tcell.Color) {
93 m.Lock()
94 defer m.Unlock()
95
96 m.form.SetButtonTextColor(color)
97 }
98
99
100
101 func (m *Modal) SetButtonsAlign(align int) {
102 m.Lock()
103 defer m.Unlock()
104
105 m.form.SetButtonsAlign(align)
106 }
107
108
109
110
111
112 func (m *Modal) SetDoneFunc(handler func(buttonIndex int, buttonLabel string)) {
113 m.Lock()
114 defer m.Unlock()
115
116 m.done = handler
117 }
118
119
120
121
122 func (m *Modal) SetText(text string) {
123 m.Lock()
124 defer m.Unlock()
125
126 m.text = text
127 }
128
129
130
131 func (m *Modal) SetTextAlign(align int) {
132 m.Lock()
133 defer m.Unlock()
134
135 m.textAlign = align
136 }
137
138
139
140 func (m *Modal) GetForm() *Form {
141 m.RLock()
142 defer m.RUnlock()
143
144 return m.form
145 }
146
147
148 func (m *Modal) GetFrame() *Frame {
149 m.RLock()
150 defer m.RUnlock()
151
152 return m.frame
153 }
154
155
156
157 func (m *Modal) AddButtons(labels []string) {
158 m.Lock()
159 defer m.Unlock()
160
161 for index, label := range labels {
162 func(i int, l string) {
163 m.form.AddButton(label, func() {
164 if m.done != nil {
165 m.done(i, l)
166 }
167 })
168 button := m.form.GetButton(m.form.GetButtonCount() - 1)
169 button.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
170 switch event.Key() {
171 case tcell.KeyDown, tcell.KeyRight:
172 return tcell.NewEventKey(tcell.KeyTab, 0, tcell.ModNone)
173 case tcell.KeyUp, tcell.KeyLeft:
174 return tcell.NewEventKey(tcell.KeyBacktab, 0, tcell.ModNone)
175 }
176 return event
177 })
178 }(index, label)
179 }
180 }
181
182
183 func (m *Modal) ClearButtons() {
184 m.Lock()
185 defer m.Unlock()
186
187 m.form.ClearButtons()
188 }
189
190
191 func (m *Modal) SetFocus(index int) {
192 m.Lock()
193 defer m.Unlock()
194
195 m.form.SetFocus(index)
196 }
197
198
199 func (m *Modal) Focus(delegate func(p Primitive)) {
200 delegate(m.form)
201 }
202
203
204 func (m *Modal) HasFocus() bool {
205 return m.GetForm().HasFocus()
206 }
207
208
209 func (m *Modal) Draw(screen tcell.Screen) {
210 if !m.GetVisible() {
211 return
212 }
213
214 formItemCount := m.form.GetFormItemCount()
215
216 m.Lock()
217 defer m.Unlock()
218
219
220 buttonsWidth := 0
221 for _, button := range m.form.buttons {
222 buttonsWidth += TaggedTextWidth(button.label) + 4 + 2
223 }
224 buttonsWidth -= 2
225 screenWidth, screenHeight := screen.Size()
226 width := screenWidth / 3
227 if width < buttonsWidth {
228 width = buttonsWidth
229 }
230
231
232
233 m.frame.Clear()
234 lines := WordWrap(m.text, width)
235 for _, line := range lines {
236 m.frame.AddText(line, true, m.textAlign, m.textColor)
237 }
238
239
240 height := len(lines) + (formItemCount * 2) + 6
241 width += 4
242 x := (screenWidth - width) / 2
243 y := (screenHeight - height) / 2
244 m.SetRect(x, y, width, height)
245
246
247 m.frame.SetRect(x, y, width, height)
248 m.frame.Draw(screen)
249 }
250
251
252 func (m *Modal) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
253 return m.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
254
255 consumed, capture = m.form.MouseHandler()(action, event, setFocus)
256 if !consumed && action == MouseLeftClick && m.InRect(event.Position()) {
257 setFocus(m)
258 consumed = true
259 }
260 return
261 })
262 }
263
View as plain text