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