]> git.lizzy.rs Git - micro.git/blob - cmd/micro/split_tree.go
Move cursor with search selection
[micro.git] / cmd / micro / split_tree.go
1 package main
2
3 type SplitType bool
4
5 const (
6         VerticalSplit   = false
7         HorizontalSplit = true
8 )
9
10 type Node interface {
11         VSplit(buf *Buffer)
12         HSplit(buf *Buffer)
13         String() string
14 }
15
16 type LeafNode struct {
17         view *View
18
19         parent *SplitTree
20 }
21
22 func NewLeafNode(v *View, parent *SplitTree) *LeafNode {
23         n := new(LeafNode)
24         n.view = v
25         n.view.splitNode = n
26         n.parent = parent
27         return n
28 }
29
30 type SplitTree struct {
31         kind SplitType
32
33         parent   *SplitTree
34         children []Node
35
36         x int
37         y int
38
39         width  int
40         height int
41
42         tabNum int
43 }
44
45 func (l *LeafNode) VSplit(buf *Buffer) {
46         tab := tabs[l.parent.tabNum]
47         if l.parent.kind == VerticalSplit {
48                 newView := NewView(buf)
49                 newView.TabNum = l.parent.tabNum
50                 newView.Num = len(tab.views)
51                 l.parent.children = append(l.parent.children, NewLeafNode(newView, l.parent))
52
53                 tab.curView++
54                 tab.views = append(tab.views, newView)
55         } else {
56                 s := new(SplitTree)
57                 s.kind = VerticalSplit
58                 s.parent = l.parent
59                 newView := NewView(buf)
60                 newView.TabNum = l.parent.tabNum
61                 newView.Num = len(tab.views)
62                 s.children = []Node{l, NewLeafNode(newView, s)}
63                 l.parent.children[search(l.parent.children, l)] = s
64                 l.parent = s
65
66                 tab.curView++
67                 tab.views = append(tab.views, newView)
68         }
69 }
70
71 func (l *LeafNode) HSplit(buf *Buffer) {
72         tab := tabs[l.parent.tabNum]
73         if l.parent.kind == HorizontalSplit {
74                 newView := NewView(buf)
75                 newView.TabNum = l.parent.tabNum
76                 newView.Num = len(tab.views)
77                 l.parent.children = append(l.parent.children, NewLeafNode(newView, l.parent))
78
79                 tab.curView++
80                 tab.views = append(tab.views, newView)
81         } else {
82                 s := new(SplitTree)
83                 s.kind = HorizontalSplit
84                 s.parent = l.parent
85                 newView := NewView(buf)
86                 newView.TabNum = l.parent.tabNum
87                 newView.Num = len(tab.views)
88                 s.children = []Node{l, NewLeafNode(newView, s)}
89                 l.parent.children[search(l.parent.children, l)] = s
90                 l.parent = s
91
92                 tab.curView++
93                 tab.views = append(tab.views, newView)
94         }
95 }
96
97 func (l *LeafNode) Delete() {
98         i := search(l.parent.children, l)
99
100         copy(l.parent.children[i:], l.parent.children[i+1:])
101         l.parent.children[len(l.parent.children)-1] = nil
102         l.parent.children = l.parent.children[:len(l.parent.children)-1]
103
104         tab := tabs[l.parent.tabNum]
105         j := findView(tab.views, l.view)
106         copy(tab.views[j:], tab.views[j+1:])
107         tab.views[len(tab.views)-1] = nil // or the zero value of T
108         tab.views = tab.views[:len(tab.views)-1]
109
110         for i, v := range tab.views {
111                 v.Num = i
112         }
113         if tab.curView > 0 {
114                 tab.curView--
115         }
116 }
117
118 func (s *SplitTree) Cleanup() {
119         for i, node := range s.children {
120                 if n, ok := node.(*SplitTree); ok {
121                         if len(n.children) == 1 {
122                                 if child, ok := n.children[0].(*LeafNode); ok {
123                                         s.children[i] = child
124                                         child.parent = s
125                                         continue
126                                 }
127                         }
128                         n.Cleanup()
129                 }
130         }
131 }
132
133 func (s *SplitTree) ResizeSplits() {
134         for i, node := range s.children {
135                 if n, ok := node.(*LeafNode); ok {
136                         if s.kind == VerticalSplit {
137                                 n.view.width = s.width / len(s.children)
138                                 n.view.height = s.height
139
140                                 n.view.x = s.x + n.view.width*i
141                                 n.view.y = s.y
142                         } else {
143                                 n.view.height = s.height / len(s.children)
144                                 n.view.width = s.width
145
146                                 n.view.y = s.y + n.view.height*i
147                                 n.view.x = s.x
148                         }
149                         // n.view.ToggleStatusLine()
150                         _, screenH := screen.Size()
151                         if settings["statusline"].(bool) || (n.view.y+n.view.height) != screenH-1 {
152                                 n.view.height--
153                         }
154
155                         n.view.ToggleTabbar()
156                         n.view.matches = Match(n.view)
157                 } else if n, ok := node.(*SplitTree); ok {
158                         if s.kind == VerticalSplit {
159                                 n.width = s.width / len(s.children)
160                                 n.height = s.height
161
162                                 n.x = s.x + n.width*i
163                                 n.y = s.y
164                         } else {
165                                 n.height = s.height / len(s.children)
166                                 n.width = s.width
167
168                                 n.y = s.y + n.height*i
169                                 n.x = s.x
170                         }
171                         n.ResizeSplits()
172                 }
173         }
174 }
175
176 func (l *LeafNode) String() string {
177         return l.view.Buf.Name
178 }
179
180 func search(haystack []Node, needle Node) int {
181         for i, x := range haystack {
182                 if x == needle {
183                         return i
184                 }
185         }
186         return 0
187 }
188
189 func findView(haystack []*View, needle *View) int {
190         for i, x := range haystack {
191                 if x == needle {
192                         return i
193                 }
194         }
195         return 0
196 }
197
198 func (s *SplitTree) VSplit(buf *Buffer) {}
199 func (s *SplitTree) HSplit(buf *Buffer) {}
200
201 func (s *SplitTree) String() string {
202         str := "["
203         for _, child := range s.children {
204                 str += child.String() + ", "
205         }
206         return str + "]"
207 }