1
1
package tview
2
2
3
3
import (
4
+ "sync"
5
+
4
6
"github.com/gdamore/tcell/v2"
5
7
)
6
8
@@ -17,6 +19,9 @@ const (
17
19
18
20
// TreeNode represents one node in a tree view.
19
21
type TreeNode struct {
22
+ // Mutex to prevent race conditions.
23
+ mu sync.RWMutex
24
+
20
25
// The reference object.
21
26
reference interface {}
22
27
@@ -73,6 +78,9 @@ func NewTreeNode(text string) *TreeNode {
73
78
// The callback returns whether traversal should continue with the traversed
74
79
// node's child nodes (true) or not recurse any deeper (false).
75
80
func (n * TreeNode ) Walk (callback func (node , parent * TreeNode ) bool ) * TreeNode {
81
+ n .mu .Lock ()
82
+ defer n .mu .Unlock ()
83
+
76
84
n .parent = nil
77
85
nodes := []* TreeNode {n }
78
86
for len (nodes ) > 0 {
@@ -98,46 +106,70 @@ func (n *TreeNode) Walk(callback func(node, parent *TreeNode) bool) *TreeNode {
98
106
// will allow you to establish a mapping between the TreeView hierarchy and your
99
107
// internal tree structure.
100
108
func (n * TreeNode ) SetReference (reference interface {}) * TreeNode {
109
+ n .mu .Lock ()
110
+ defer n .mu .Unlock ()
111
+
101
112
n .reference = reference
102
113
return n
103
114
}
104
115
105
116
// GetReference returns this node's reference object.
106
117
func (n * TreeNode ) GetReference () interface {} {
118
+ n .mu .RLock ()
119
+ defer n .mu .RUnlock ()
120
+
107
121
return n .reference
108
122
}
109
123
110
124
// SetChildren sets this node's child nodes.
111
125
func (n * TreeNode ) SetChildren (childNodes []* TreeNode ) * TreeNode {
126
+ n .mu .Lock ()
127
+ defer n .mu .Unlock ()
128
+
112
129
n .children = childNodes
113
130
return n
114
131
}
115
132
116
133
// GetText returns this node's text.
117
134
func (n * TreeNode ) GetText () string {
135
+ n .mu .RLock ()
136
+ defer n .mu .RUnlock ()
137
+
118
138
return n .text
119
139
}
120
140
121
141
// GetChildren returns this node's children.
122
142
func (n * TreeNode ) GetChildren () []* TreeNode {
143
+ n .mu .RLock ()
144
+ defer n .mu .RUnlock ()
145
+
123
146
return n .children
124
147
}
125
148
126
149
// ClearChildren removes all child nodes from this node.
127
150
func (n * TreeNode ) ClearChildren () * TreeNode {
151
+ n .mu .Lock ()
152
+ defer n .mu .Unlock ()
153
+
128
154
n .children = nil
129
155
return n
130
156
}
131
157
132
158
// AddChild adds a new child node to this node.
133
159
func (n * TreeNode ) AddChild (node * TreeNode ) * TreeNode {
160
+ n .mu .Lock ()
161
+ defer n .mu .Unlock ()
162
+
134
163
n .children = append (n .children , node )
135
164
return n
136
165
}
137
166
138
167
// RemoveChild removes a child node from this node. If the child node cannot be
139
168
// found, nothing happens.
140
169
func (n * TreeNode ) RemoveChild (node * TreeNode ) * TreeNode {
170
+ n .mu .Lock ()
171
+ defer n .mu .Unlock ()
172
+
141
173
for index , child := range n .children {
142
174
if child == node {
143
175
n .children = append (n .children [:index ], n .children [index + 1 :]... )
@@ -150,39 +182,54 @@ func (n *TreeNode) RemoveChild(node *TreeNode) *TreeNode {
150
182
// SetSelectable sets a flag indicating whether this node can be selected by
151
183
// the user.
152
184
func (n * TreeNode ) SetSelectable (selectable bool ) * TreeNode {
185
+ n .mu .Lock ()
186
+ defer n .mu .Unlock ()
187
+
153
188
n .selectable = selectable
154
189
return n
155
190
}
156
191
157
192
// SetSelectedFunc sets a function which is called when the user selects this
158
193
// node by hitting Enter when it is selected.
159
194
func (n * TreeNode ) SetSelectedFunc (handler func ()) * TreeNode {
195
+ n .mu .Lock ()
196
+ defer n .mu .Unlock ()
197
+
160
198
n .selected = handler
161
199
return n
162
200
}
163
201
164
202
// SetExpanded sets whether or not this node's child nodes should be displayed.
165
203
func (n * TreeNode ) SetExpanded (expanded bool ) * TreeNode {
204
+ n .mu .Lock ()
205
+ defer n .mu .Unlock ()
206
+
166
207
n .expanded = expanded
167
208
return n
168
209
}
169
210
170
211
// Expand makes the child nodes of this node appear.
171
212
func (n * TreeNode ) Expand () * TreeNode {
213
+ n .mu .Lock ()
214
+ defer n .mu .Unlock ()
215
+
172
216
n .expanded = true
173
217
return n
174
218
}
175
219
176
220
// Collapse makes the child nodes of this node disappear.
177
221
func (n * TreeNode ) Collapse () * TreeNode {
222
+ n .mu .Lock ()
223
+ defer n .mu .Unlock ()
224
+
178
225
n .expanded = false
179
226
return n
180
227
}
181
228
182
229
// ExpandAll expands this node and all descendent nodes.
183
230
func (n * TreeNode ) ExpandAll () * TreeNode {
184
231
n .Walk (func (node , parent * TreeNode ) bool {
185
- node .expanded = true
232
+ node .Expand ()
186
233
return true
187
234
})
188
235
return n
@@ -191,25 +238,34 @@ func (n *TreeNode) ExpandAll() *TreeNode {
191
238
// CollapseAll collapses this node and all descendent nodes.
192
239
func (n * TreeNode ) CollapseAll () * TreeNode {
193
240
n .Walk (func (node , parent * TreeNode ) bool {
194
- node .expanded = false
241
+ node .Collapse ()
195
242
return true
196
243
})
197
244
return n
198
245
}
199
246
200
247
// IsExpanded returns whether the child nodes of this node are visible.
201
248
func (n * TreeNode ) IsExpanded () bool {
249
+ n .mu .Lock ()
250
+ defer n .mu .Unlock ()
251
+
202
252
return n .expanded
203
253
}
204
254
205
255
// SetText sets the node's text which is displayed.
206
256
func (n * TreeNode ) SetText (text string ) * TreeNode {
257
+ n .mu .Lock ()
258
+ defer n .mu .Unlock ()
259
+
207
260
n .text = text
208
261
return n
209
262
}
210
263
211
264
// GetColor returns the node's text color.
212
265
func (n * TreeNode ) GetColor () tcell.Color {
266
+ n .mu .RLock ()
267
+ defer n .mu .RUnlock ()
268
+
213
269
color , _ , _ := n .textStyle .Decompose ()
214
270
return color
215
271
}
@@ -218,38 +274,56 @@ func (n *TreeNode) GetColor() tcell.Color {
218
274
// sets the background color of the selected text style. For more control over
219
275
// styles, use [TreeNode.SetTextStyle] and [TreeNode.SetSelectedTextStyle].
220
276
func (n * TreeNode ) SetColor (color tcell.Color ) * TreeNode {
277
+ n .mu .Lock ()
278
+ defer n .mu .Unlock ()
279
+
221
280
n .textStyle = n .textStyle .Foreground (color )
222
281
n .selectedTextStyle = n .selectedTextStyle .Background (color )
223
282
return n
224
283
}
225
284
226
285
// SetTextStyle sets the text style for this node.
227
286
func (n * TreeNode ) SetTextStyle (style tcell.Style ) * TreeNode {
287
+ n .mu .Lock ()
288
+ defer n .mu .Unlock ()
289
+
228
290
n .textStyle = style
229
291
return n
230
292
}
231
293
232
294
// GetTextStyle returns the text style for this node.
233
295
func (n * TreeNode ) GetTextStyle () tcell.Style {
296
+ n .mu .RLock ()
297
+ defer n .mu .RUnlock ()
298
+
234
299
return n .textStyle
235
300
}
236
301
237
302
// SetSelectedTextStyle sets the text style for this node when it is selected.
238
303
func (n * TreeNode ) SetSelectedTextStyle (style tcell.Style ) * TreeNode {
304
+ n .mu .Lock ()
305
+ defer n .mu .Unlock ()
306
+
239
307
n .selectedTextStyle = style
240
308
return n
241
309
}
242
310
243
311
// GetSelectedTextStyle returns the text style for this node when it is
244
312
// selected.
245
313
func (n * TreeNode ) GetSelectedTextStyle () tcell.Style {
314
+ n .mu .RLock ()
315
+ defer n .mu .RUnlock ()
316
+
246
317
return n .selectedTextStyle
247
318
}
248
319
249
320
// SetIndent sets an additional indentation for this node's text. A value of 0
250
321
// keeps the text as far left as possible with a minimum of line graphics. Any
251
322
// value greater than that moves the text to the right.
252
323
func (n * TreeNode ) SetIndent (indent int ) * TreeNode {
324
+ n .mu .Lock ()
325
+ defer n .mu .Unlock ()
326
+
253
327
n .indent = indent
254
328
return n
255
329
}
@@ -259,6 +333,9 @@ func (n *TreeNode) SetIndent(indent int) *TreeNode {
259
333
// guaranteed to be up to date immediately after the tree that contains this
260
334
// node is drawn.
261
335
func (n * TreeNode ) GetLevel () int {
336
+ n .mu .RLock ()
337
+ defer n .mu .RUnlock ()
338
+
262
339
return n .level
263
340
}
264
341
@@ -736,6 +813,7 @@ func (t *TreeView) Draw(screen tcell.Screen) {
736
813
continue
737
814
}
738
815
816
+ node .mu .RLock ()
739
817
// Draw the graphics.
740
818
if t .graphics {
741
819
// Draw ancestor branches.
@@ -790,6 +868,7 @@ func (t *TreeView) Draw(screen tcell.Screen) {
790
868
printWithStyle (screen , node .text , x + node .textX + prefixWidth , posY , 0 , width - node .textX - prefixWidth , AlignLeft , style , false )
791
869
}
792
870
}
871
+ defer node .mu .RUnlock ()
793
872
794
873
// Advance.
795
874
posY ++
0 commit comments