1 package tview
2
3 import (
4 "github.com/gdamore/tcell/v2"
5 )
6
7
8 type frameText struct {
9 Text string
10 Header bool
11 Align int
12 Color tcell.Color
13 }
14
15
16
17
18
19 type Frame struct {
20 *Box
21
22
23 primitive Primitive
24
25
26 text []*frameText
27
28
29 top, bottom, header, footer, left, right int
30
31
32 setFocus func(p Primitive)
33 }
34
35
36
37
38 func NewFrame(primitive Primitive) *Frame {
39 box := NewBox()
40
41 f := &Frame{
42 Box: box,
43 primitive: primitive,
44 top: 1,
45 bottom: 1,
46 header: 1,
47 footer: 1,
48 left: 1,
49 right: 1,
50 }
51
52 return f
53 }
54
55
56
57 func (f *Frame) SetPrimitive(p Primitive) *Frame {
58 var hasFocus bool
59 if f.primitive != nil {
60 hasFocus = f.primitive.HasFocus()
61 }
62 f.primitive = p
63 if hasFocus && f.setFocus != nil {
64 f.setFocus(p)
65 }
66 return f
67 }
68
69
70 func (f *Frame) GetPrimitive() Primitive {
71 return f.primitive
72 }
73
74
75
76
77
78
79
80 func (f *Frame) AddText(text string, header bool, align int, color tcell.Color) *Frame {
81 f.text = append(f.text, &frameText{
82 Text: text,
83 Header: header,
84 Align: align,
85 Color: color,
86 })
87 return f
88 }
89
90
91 func (f *Frame) Clear() *Frame {
92 f.text = nil
93 return f
94 }
95
96
97
98
99 func (f *Frame) SetBorders(top, bottom, header, footer, left, right int) *Frame {
100 f.top, f.bottom, f.header, f.footer, f.left, f.right = top, bottom, header, footer, left, right
101 return f
102 }
103
104
105 func (f *Frame) Draw(screen tcell.Screen) {
106 f.Box.DrawForSubclass(screen, f)
107
108
109 x, top, width, height := f.GetInnerRect()
110 bottom := top + height - 1
111 x += f.left
112 top += f.top
113 bottom -= f.bottom
114 width -= f.left + f.right
115 if width <= 0 || top >= bottom {
116 return
117 }
118
119
120 var rows [6]int
121 topMax := top
122 bottomMin := bottom
123 for _, text := range f.text {
124
125 var y int
126 if text.Header {
127 y = top + rows[text.Align]
128 rows[text.Align]++
129 if y >= bottomMin {
130 continue
131 }
132 if y+1 > topMax {
133 topMax = y + 1
134 }
135 } else {
136 y = bottom - rows[3+text.Align]
137 rows[3+text.Align]++
138 if y <= topMax {
139 continue
140 }
141 if y-1 < bottomMin {
142 bottomMin = y - 1
143 }
144 }
145
146
147 Print(screen, text.Text, x, y, width, text.Align, text.Color)
148 }
149
150
151 if f.primitive != nil {
152 if topMax > top {
153 top = topMax + f.header
154 }
155 if bottomMin < bottom {
156 bottom = bottomMin - f.footer
157 }
158 if top > bottom {
159 return
160 }
161 f.primitive.SetRect(x, top, width, bottom+1-top)
162
163
164 f.primitive.Draw(screen)
165 }
166 }
167
168
169 func (f *Frame) Focus(delegate func(p Primitive)) {
170 f.setFocus = delegate
171 if f.primitive != nil {
172 delegate(f.primitive)
173 } else {
174 f.Box.Focus(delegate)
175 }
176 }
177
178
179 func (f *Frame) HasFocus() bool {
180 if f.primitive == nil {
181 return f.Box.HasFocus()
182 }
183 return f.primitive.HasFocus()
184 }
185
186
187 func (f *Frame) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
188 return f.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
189 if !f.InRect(event.Position()) {
190 return false, nil
191 }
192
193
194 if f.primitive != nil {
195 consumed, capture = f.primitive.MouseHandler()(action, event, setFocus)
196 if consumed {
197 return true, capture
198 }
199 }
200
201
202 if action == MouseLeftDown {
203 setFocus(f)
204 consumed = true
205 }
206
207 return
208 })
209 }
210
211
212 func (f *Frame) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
213 return f.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p Primitive)) {
214 if f.primitive == nil {
215 return
216 }
217 if handler := f.primitive.InputHandler(); handler != nil {
218 handler(event, setFocus)
219 return
220 }
221 })
222 }
223
View as plain text