1 package tview
2
3 import (
4 "github.com/gdamore/tcell/v2"
5 )
6
7
8 type page struct {
9 Name string
10 Item Primitive
11 Resize bool
12 Visible bool
13 }
14
15
16
17
18
19
20 type Pages struct {
21 *Box
22
23
24 pages []*page
25
26
27
28 setFocus func(p Primitive)
29
30
31
32 changed func()
33 }
34
35
36 func NewPages() *Pages {
37 p := &Pages{
38 Box: NewBox(),
39 }
40 return p
41 }
42
43
44
45 func (p *Pages) SetChangedFunc(handler func()) *Pages {
46 p.changed = handler
47 return p
48 }
49
50
51 func (p *Pages) GetPageCount() int {
52 return len(p.pages)
53 }
54
55
56
57
58
59
60
61
62
63
64 func (p *Pages) AddPage(name string, item Primitive, resize, visible bool) *Pages {
65 hasFocus := p.HasFocus()
66 for index, pg := range p.pages {
67 if pg.Name == name {
68 p.pages = append(p.pages[:index], p.pages[index+1:]...)
69 break
70 }
71 }
72 p.pages = append(p.pages, &page{Item: item, Name: name, Resize: resize, Visible: visible})
73 if p.changed != nil {
74 p.changed()
75 }
76 if hasFocus {
77 p.Focus(p.setFocus)
78 }
79 return p
80 }
81
82
83
84 func (p *Pages) AddAndSwitchToPage(name string, item Primitive, resize bool) *Pages {
85 p.AddPage(name, item, resize, true)
86 p.SwitchToPage(name)
87 return p
88 }
89
90
91
92 func (p *Pages) RemovePage(name string) *Pages {
93 var isVisible bool
94 hasFocus := p.HasFocus()
95 for index, page := range p.pages {
96 if page.Name == name {
97 isVisible = page.Visible
98 p.pages = append(p.pages[:index], p.pages[index+1:]...)
99 if page.Visible && p.changed != nil {
100 p.changed()
101 }
102 break
103 }
104 }
105 if isVisible {
106 for index, page := range p.pages {
107 if index < len(p.pages)-1 {
108 if page.Visible {
109 break
110 }
111 } else {
112 page.Visible = true
113 }
114 }
115 }
116 if hasFocus {
117 p.Focus(p.setFocus)
118 }
119 return p
120 }
121
122
123 func (p *Pages) HasPage(name string) bool {
124 for _, page := range p.pages {
125 if page.Name == name {
126 return true
127 }
128 }
129 return false
130 }
131
132
133
134 func (p *Pages) ShowPage(name string) *Pages {
135 for _, page := range p.pages {
136 if page.Name == name {
137 page.Visible = true
138 if p.changed != nil {
139 p.changed()
140 }
141 break
142 }
143 }
144 if p.HasFocus() {
145 p.Focus(p.setFocus)
146 }
147 return p
148 }
149
150
151 func (p *Pages) HidePage(name string) *Pages {
152 for _, page := range p.pages {
153 if page.Name == name {
154 page.Visible = false
155 if p.changed != nil {
156 p.changed()
157 }
158 break
159 }
160 }
161 if p.HasFocus() {
162 p.Focus(p.setFocus)
163 }
164 return p
165 }
166
167
168
169 func (p *Pages) SwitchToPage(name string) *Pages {
170 for _, page := range p.pages {
171 if page.Name == name {
172 page.Visible = true
173 } else {
174 page.Visible = false
175 }
176 }
177 if p.changed != nil {
178 p.changed()
179 }
180 if p.HasFocus() {
181 p.Focus(p.setFocus)
182 }
183 return p
184 }
185
186
187
188
189 func (p *Pages) SendToFront(name string) *Pages {
190 for index, page := range p.pages {
191 if page.Name == name {
192 if index < len(p.pages)-1 {
193 p.pages = append(append(p.pages[:index], p.pages[index+1:]...), page)
194 }
195 if page.Visible && p.changed != nil {
196 p.changed()
197 }
198 break
199 }
200 }
201 if p.HasFocus() {
202 p.Focus(p.setFocus)
203 }
204 return p
205 }
206
207
208
209
210 func (p *Pages) SendToBack(name string) *Pages {
211 for index, pg := range p.pages {
212 if pg.Name == name {
213 if index > 0 {
214 p.pages = append(append([]*page{pg}, p.pages[:index]...), p.pages[index+1:]...)
215 }
216 if pg.Visible && p.changed != nil {
217 p.changed()
218 }
219 break
220 }
221 }
222 if p.HasFocus() {
223 p.Focus(p.setFocus)
224 }
225 return p
226 }
227
228
229
230 func (p *Pages) GetFrontPage() (name string, item Primitive) {
231 for index := len(p.pages) - 1; index >= 0; index-- {
232 if p.pages[index].Visible {
233 return p.pages[index].Name, p.pages[index].Item
234 }
235 }
236 return
237 }
238
239
240 func (p *Pages) HasFocus() bool {
241 for _, page := range p.pages {
242 if page.Item.HasFocus() {
243 return true
244 }
245 }
246 return p.Box.HasFocus()
247 }
248
249
250 func (p *Pages) Focus(delegate func(p Primitive)) {
251 if delegate == nil {
252 return
253 }
254 p.setFocus = delegate
255 var topItem Primitive
256 for _, page := range p.pages {
257 if page.Visible {
258 topItem = page.Item
259 }
260 }
261 if topItem != nil {
262 delegate(topItem)
263 } else {
264 p.Box.Focus(delegate)
265 }
266 }
267
268
269 func (p *Pages) Draw(screen tcell.Screen) {
270 p.Box.DrawForSubclass(screen, p)
271 for _, page := range p.pages {
272 if !page.Visible {
273 continue
274 }
275 if page.Resize {
276 x, y, width, height := p.GetInnerRect()
277 page.Item.SetRect(x, y, width, height)
278 }
279 page.Item.Draw(screen)
280 }
281 }
282
283
284 func (p *Pages) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
285 return p.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
286 if !p.InRect(event.Position()) {
287 return false, nil
288 }
289
290
291 for index := len(p.pages) - 1; index >= 0; index-- {
292 page := p.pages[index]
293 if page.Visible {
294 consumed, capture = page.Item.MouseHandler()(action, event, setFocus)
295 if consumed {
296 return
297 }
298 }
299 }
300
301 return
302 })
303 }
304
305
306 func (p *Pages) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
307 return p.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
308 for _, page := range p.pages {
309 if page.Item.HasFocus() {
310 if handler := page.Item.InputHandler(); handler != nil {
311 handler(event, setFocus)
312 return
313 }
314 }
315 }
316 })
317 }
318
View as plain text