1 package main
2
3 import (
4 "strings"
5
6 "github.com/gdamore/tcell/v2"
7 "github.com/rivo/tview"
8 )
9
10 const treeAllCode = `[green]package[white] main
11
12 [green]import[white] [red]"github.com/rivo/tview"[white]
13
14 [green]func[white] [yellow]main[white]() {
15 $$$
16
17 root := tview.[yellow]NewTreeNode[white]([red]"Root"[white]).
18 [yellow]AddChild[white](tview.[yellow]NewTreeNode[white]([red]"First child"[white]).
19 [yellow]AddChild[white](tview.[yellow]NewTreeNode[white]([red]"Grandchild A"[white])).
20 [yellow]AddChild[white](tview.[yellow]NewTreeNode[white]([red]"Grandchild B"[white]))).
21 [yellow]AddChild[white](tview.[yellow]NewTreeNode[white]([red]"Second child"[white]).
22 [yellow]AddChild[white](tview.[yellow]NewTreeNode[white]([red]"Grandchild C"[white])).
23 [yellow]AddChild[white](tview.[yellow]NewTreeNode[white]([red]"Grandchild D"[white]))).
24 [yellow]AddChild[white](tview.[yellow]NewTreeNode[white]([red]"Third child"[white]))
25
26 tree.[yellow]SetRoot[white](root).
27 [yellow]SetCurrentNode[white](root)
28
29 tview.[yellow]NewApplication[white]().
30 [yellow]SetRoot[white](tree, true).
31 [yellow]Run[white]()
32 }`
33
34 const treeBasicCode = `tree := tview.[yellow]NewTreeView[white]()`
35
36 const treeTopLevelCode = `tree := tview.[yellow]NewTreeView[white]().
37 [yellow]SetTopLevel[white]([red]1[white])`
38
39 const treeAlignCode = `tree := tview.[yellow]NewTreeView[white]().
40 [yellow]SetAlign[white](true)`
41
42 const treePrefixCode = `tree := tview.[yellow]NewTreeView[white]().
43 [yellow]SetGraphics[white](false).
44 [yellow]SetTopLevel[white]([red]1[white]).
45 [yellow]SetPrefixes[white]([][green]string[white]{
46 [red]"[red[]* "[white],
47 [red]"[darkcyan[]- "[white],
48 [red]"[darkmagenta[]- "[white],
49 })`
50
51 type node struct {
52 text string
53 expand bool
54 selected func()
55 children []*node
56 }
57
58 var (
59 tree = tview.NewTreeView()
60 treeNextSlide func()
61 treeCode = tview.NewTextView().SetWrap(false).SetDynamicColors(true)
62 )
63
64 var rootNode = &node{
65 text: "Root",
66 children: []*node{
67 {text: "Expand all", selected: func() { tree.GetRoot().ExpandAll() }},
68 {text: "Collapse all", selected: func() {
69 for _, child := range tree.GetRoot().GetChildren() {
70 child.CollapseAll()
71 }
72 }},
73 {text: "Hide root node", expand: true, children: []*node{
74 {text: "Tree list starts one level down"},
75 {text: "Works better for lists where no top node is needed"},
76 {text: "Switch to this layout", selected: func() {
77 tree.SetAlign(false).SetTopLevel(1).SetGraphics(true).SetPrefixes(nil)
78 treeCode.SetText(strings.Replace(treeAllCode, "$$$", treeTopLevelCode, -1))
79 }},
80 }},
81 {text: "Align node text", expand: true, children: []*node{
82 {text: "For trees that are similar to lists"},
83 {text: "Hierarchy shown only in line drawings"},
84 {text: "Switch to this layout", selected: func() {
85 tree.SetAlign(true).SetTopLevel(0).SetGraphics(true).SetPrefixes(nil)
86 treeCode.SetText(strings.Replace(treeAllCode, "$$$", treeAlignCode, -1))
87 }},
88 }},
89 {text: "Prefixes", expand: true, children: []*node{
90 {text: "Best for hierarchical bullet point lists"},
91 {text: "You can define your own prefixes per level"},
92 {text: "Switch to this layout", selected: func() {
93 tree.SetAlign(false).SetTopLevel(1).SetGraphics(false).SetPrefixes([]string{"[red]* ", "[darkcyan]- ", "[darkmagenta]- "})
94 treeCode.SetText(strings.Replace(treeAllCode, "$$$", treePrefixCode, -1))
95 }},
96 }},
97 {text: "Basic tree with graphics", expand: true, children: []*node{
98 {text: "Lines illustrate hierarchy"},
99 {text: "Basic indentation"},
100 {text: "Switch to this layout", selected: func() {
101 tree.SetAlign(false).SetTopLevel(0).SetGraphics(true).SetPrefixes(nil)
102 treeCode.SetText(strings.Replace(treeAllCode, "$$$", treeBasicCode, -1))
103 }},
104 }},
105 {text: "Next slide", selected: func() { treeNextSlide() }},
106 }}
107
108
109 func TreeView(nextSlide func()) (title string, content tview.Primitive) {
110 treeNextSlide = nextSlide
111 tree.SetBorder(true).
112 SetTitle("TreeView")
113
114
115 var add func(target *node) *tview.TreeNode
116 add = func(target *node) *tview.TreeNode {
117 node := tview.NewTreeNode(target.text).
118 SetSelectable(target.expand || target.selected != nil).
119 SetExpanded(target == rootNode).
120 SetReference(target)
121 if target.expand {
122 node.SetColor(tcell.ColorGreen)
123 } else if target.selected != nil {
124 node.SetColor(tcell.ColorRed)
125 }
126 for _, child := range target.children {
127 node.AddChild(add(child))
128 }
129 return node
130 }
131 root := add(rootNode)
132 tree.SetRoot(root).
133 SetCurrentNode(root).
134 SetSelectedFunc(func(n *tview.TreeNode) {
135 original := n.GetReference().(*node)
136 if original.expand {
137 n.SetExpanded(!n.IsExpanded())
138 } else if original.selected != nil {
139 original.selected()
140 }
141 })
142
143 treeCode.SetText(strings.Replace(treeAllCode, "$$$", treeBasicCode, -1)).
144 SetBorderPadding(1, 1, 2, 0)
145
146 return "Tree", tview.NewFlex().
147 AddItem(tree, 0, 1, true).
148 AddItem(treeCode, codeWidth, 1, false)
149 }
150
View as plain text