1 package tview
2
3 import (
4 "github.com/gdamore/tcell/v2"
5 )
6
7
8 const (
9 FlexRow = 0
10 FlexColumn = 1
11 FlexRowCSS = 1
12 FlexColumnCSS = 0
13 )
14
15
16 type flexItem struct {
17 Item Primitive
18 FixedSize int
19 Proportion int
20 Focus bool
21 }
22
23
24
25
26
27
28
29 type Flex struct {
30 *Box
31
32
33 items []*flexItem
34
35
36 direction int
37
38
39
40 fullScreen bool
41 }
42
43
44
45
46
47
48
49
50
51
52
53 func NewFlex() *Flex {
54 f := &Flex{
55 direction: FlexColumn,
56 }
57 f.Box = NewBox()
58 f.Box.dontClear = true
59 return f
60 }
61
62
63
64
65
66 func (f *Flex) SetDirection(direction int) *Flex {
67 f.direction = direction
68 return f
69 }
70
71
72
73 func (f *Flex) SetFullScreen(fullScreen bool) *Flex {
74 f.fullScreen = fullScreen
75 return f
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 func (f *Flex) AddItem(item Primitive, fixedSize, proportion int, focus bool) *Flex {
93 f.items = append(f.items, &flexItem{Item: item, FixedSize: fixedSize, Proportion: proportion, Focus: focus})
94 return f
95 }
96
97
98
99 func (f *Flex) RemoveItem(p Primitive) *Flex {
100 for index := len(f.items) - 1; index >= 0; index-- {
101 if f.items[index].Item == p {
102 f.items = append(f.items[:index], f.items[index+1:]...)
103 }
104 }
105 return f
106 }
107
108
109 func (f *Flex) GetItemCount() int {
110 return len(f.items)
111 }
112
113
114
115
116
117 func (f *Flex) GetItem(index int) Primitive {
118 return f.items[index].Item
119 }
120
121
122 func (f *Flex) Clear() *Flex {
123 f.items = nil
124 return f
125 }
126
127
128
129
130 func (f *Flex) ResizeItem(p Primitive, fixedSize, proportion int) *Flex {
131 for _, item := range f.items {
132 if item.Item == p {
133 item.FixedSize = fixedSize
134 item.Proportion = proportion
135 }
136 }
137 return f
138 }
139
140
141 func (f *Flex) Draw(screen tcell.Screen) {
142 f.Box.DrawForSubclass(screen, f)
143
144
145
146
147 if f.fullScreen {
148 width, height := screen.Size()
149 f.SetRect(0, 0, width, height)
150 }
151
152
153 x, y, width, height := f.GetInnerRect()
154 var proportionSum int
155 distSize := width
156 if f.direction == FlexRow {
157 distSize = height
158 }
159 for _, item := range f.items {
160 if item.FixedSize > 0 {
161 distSize -= item.FixedSize
162 } else {
163 proportionSum += item.Proportion
164 }
165 }
166
167
168 pos := x
169 if f.direction == FlexRow {
170 pos = y
171 }
172 for _, item := range f.items {
173 size := item.FixedSize
174 if size <= 0 {
175 if proportionSum > 0 {
176 size = distSize * item.Proportion / proportionSum
177 distSize -= size
178 proportionSum -= item.Proportion
179 } else {
180 size = 0
181 }
182 }
183 if item.Item != nil {
184 if f.direction == FlexColumn {
185 item.Item.SetRect(pos, y, size, height)
186 } else {
187 item.Item.SetRect(x, pos, width, size)
188 }
189 }
190 pos += size
191
192 if item.Item != nil {
193 if item.Item.HasFocus() {
194 defer item.Item.Draw(screen)
195 } else {
196 item.Item.Draw(screen)
197 }
198 }
199 }
200 }
201
202
203 func (f *Flex) Focus(delegate func(p Primitive)) {
204 for _, item := range f.items {
205 if item.Item != nil && item.Focus {
206 delegate(item.Item)
207 return
208 }
209 }
210 f.Box.Focus(delegate)
211 }
212
213
214 func (f *Flex) HasFocus() bool {
215 for _, item := range f.items {
216 if item.Item != nil && item.Item.HasFocus() {
217 return true
218 }
219 }
220 return f.Box.HasFocus()
221 }
222
223
224 func (f *Flex) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
225 return f.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
226 if !f.InRect(event.Position()) {
227 return false, nil
228 }
229
230
231 for _, item := range f.items {
232 if item.Item == nil {
233 continue
234 }
235 consumed, capture = item.Item.MouseHandler()(action, event, setFocus)
236 if consumed {
237 return
238 }
239 }
240
241 return
242 })
243 }
244
245
246 func (f *Flex) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
247 return f.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
248 for _, item := range f.items {
249 if item.Item != nil && item.Item.HasFocus() {
250 if handler := item.Item.InputHandler(); handler != nil {
251 handler(event, setFocus)
252 return
253 }
254 }
255 }
256 })
257 }
258
View as plain text