3 // SpltType specifies whether a split is horizontal or vertical
9 // HorizontalSplit type
10 HorizontalSplit = true
13 // A Node on the split tree
20 // A LeafNode is an actual split so it contains a view
21 type LeafNode struct {
27 // NewLeafNode returns a new leaf node containing the given view
28 func NewLeafNode(v *View, parent *SplitTree) *LeafNode {
36 // A SplitTree is a Node itself and it contains other nodes
37 type SplitTree struct {
54 // VSplit creates a vertical split
55 func (l *LeafNode) VSplit(buf *Buffer) {
56 tab := tabs[l.parent.tabNum]
57 if l.parent.kind == VerticalSplit {
58 newView := NewView(buf)
59 newView.TabNum = l.parent.tabNum
60 newView.Num = len(tab.views)
61 l.parent.children = append(l.parent.children, NewLeafNode(newView, l.parent))
64 tab.views = append(tab.views, newView)
67 s.kind = VerticalSplit
69 s.tabNum = l.parent.tabNum
70 newView := NewView(buf)
71 newView.TabNum = l.parent.tabNum
72 newView.Num = len(tab.views)
73 s.children = []Node{l, NewLeafNode(newView, s)}
74 l.parent.children[search(l.parent.children, l)] = s
78 tab.views = append(tab.views, newView)
82 // HSplit creates a horizontal split
83 func (l *LeafNode) HSplit(buf *Buffer) {
84 tab := tabs[l.parent.tabNum]
85 if l.parent.kind == HorizontalSplit {
86 newView := NewView(buf)
87 newView.TabNum = l.parent.tabNum
88 newView.Num = len(tab.views)
89 l.parent.children = append(l.parent.children, NewLeafNode(newView, l.parent))
92 tab.views = append(tab.views, newView)
95 s.kind = HorizontalSplit
96 s.tabNum = l.parent.tabNum
98 newView := NewView(buf)
99 newView.TabNum = l.parent.tabNum
100 newView.Num = len(tab.views)
101 s.children = []Node{l, NewLeafNode(newView, s)}
102 l.parent.children[search(l.parent.children, l)] = s
106 tab.views = append(tab.views, newView)
110 // Delete deletes a split
111 func (l *LeafNode) Delete() {
112 i := search(l.parent.children, l)
114 copy(l.parent.children[i:], l.parent.children[i+1:])
115 l.parent.children[len(l.parent.children)-1] = nil
116 l.parent.children = l.parent.children[:len(l.parent.children)-1]
118 tab := tabs[l.parent.tabNum]
119 j := findView(tab.views, l.view)
120 copy(tab.views[j:], tab.views[j+1:])
121 tab.views[len(tab.views)-1] = nil // or the zero value of T
122 tab.views = tab.views[:len(tab.views)-1]
124 for i, v := range tab.views {
132 // Cleanup rearranges all the parents after a split has been deleted
133 func (s *SplitTree) Cleanup() {
134 for i, node := range s.children {
135 if n, ok := node.(*SplitTree); ok {
136 if len(n.children) == 1 {
137 if child, ok := n.children[0].(*LeafNode); ok {
138 s.children[i] = child
148 // ResizeSplits resizes all the splits correctly
149 func (s *SplitTree) ResizeSplits() {
153 for _, node := range s.children {
154 if n, ok := node.(*LeafNode); ok {
155 if s.kind == VerticalSplit {
156 if n.view.lockWidth {
157 lockedWidth += n.view.width
161 if n.view.lockHeight {
162 lockedHeight += n.view.height
166 } else if n, ok := node.(*SplitTree); ok {
167 if s.kind == VerticalSplit {
169 lockedWidth += n.width
174 lockedHeight += n.height
181 for _, node := range s.children {
182 if n, ok := node.(*LeafNode); ok {
183 if s.kind == VerticalSplit {
184 if !n.view.lockWidth {
185 n.view.width = (s.width - lockedWidth) / (len(s.children) - lockedChildren)
187 n.view.height = s.height
193 if !n.view.lockHeight {
194 n.view.height = (s.height - lockedHeight) / (len(s.children) - lockedChildren)
196 n.view.width = s.width
202 if n.view.Buf.Settings["statusline"].(bool) {
206 n.view.ToggleTabbar()
207 n.view.matches = Match(n.view)
208 } else if n, ok := node.(*SplitTree); ok {
209 if s.kind == VerticalSplit {
211 n.width = (s.width - lockedWidth) / (len(s.children) - lockedChildren)
220 n.height = (s.height - lockedHeight) / (len(s.children) - lockedChildren)
233 func (l *LeafNode) String() string {
234 return l.view.Buf.Name
237 func search(haystack []Node, needle Node) int {
238 for i, x := range haystack {
246 func findView(haystack []*View, needle *View) int {
247 for i, x := range haystack {
255 // VSplit is here just to make SplitTree fit the Node interface
256 func (s *SplitTree) VSplit(buf *Buffer) {}
258 // HSplit is here just to make SplitTree fit the Node interface
259 func (s *SplitTree) HSplit(buf *Buffer) {}
261 func (s *SplitTree) String() string {
263 for _, child := range s.children {
264 str += child.String() + ", "