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 {
52 // VSplit creates a vertical split
53 func (l *LeafNode) VSplit(buf *Buffer) {
54 tab := tabs[l.parent.tabNum]
55 if l.parent.kind == VerticalSplit {
56 newView := NewView(buf)
57 newView.TabNum = l.parent.tabNum
58 newView.Num = len(tab.views)
59 l.parent.children = append(l.parent.children, NewLeafNode(newView, l.parent))
62 tab.views = append(tab.views, newView)
65 s.kind = VerticalSplit
67 s.tabNum = l.parent.tabNum
68 newView := NewView(buf)
69 newView.TabNum = l.parent.tabNum
70 newView.Num = len(tab.views)
71 s.children = []Node{l, NewLeafNode(newView, s)}
72 l.parent.children[search(l.parent.children, l)] = s
76 tab.views = append(tab.views, newView)
80 // HSplit creates a horizontal split
81 func (l *LeafNode) HSplit(buf *Buffer) {
82 tab := tabs[l.parent.tabNum]
83 if l.parent.kind == HorizontalSplit {
84 newView := NewView(buf)
85 newView.TabNum = l.parent.tabNum
86 newView.Num = len(tab.views)
87 l.parent.children = append(l.parent.children, NewLeafNode(newView, l.parent))
90 tab.views = append(tab.views, newView)
93 s.kind = HorizontalSplit
94 s.tabNum = l.parent.tabNum
96 newView := NewView(buf)
97 newView.TabNum = l.parent.tabNum
98 newView.Num = len(tab.views)
99 s.children = []Node{l, NewLeafNode(newView, s)}
100 l.parent.children[search(l.parent.children, l)] = s
104 tab.views = append(tab.views, newView)
108 // Delete deletes a split
109 func (l *LeafNode) Delete() {
110 i := search(l.parent.children, l)
112 copy(l.parent.children[i:], l.parent.children[i+1:])
113 l.parent.children[len(l.parent.children)-1] = nil
114 l.parent.children = l.parent.children[:len(l.parent.children)-1]
116 tab := tabs[l.parent.tabNum]
117 j := findView(tab.views, l.view)
118 copy(tab.views[j:], tab.views[j+1:])
119 tab.views[len(tab.views)-1] = nil // or the zero value of T
120 tab.views = tab.views[:len(tab.views)-1]
122 for i, v := range tab.views {
130 // Cleanup rearranges all the parents after a split has been deleted
131 func (s *SplitTree) Cleanup() {
132 for i, node := range s.children {
133 if n, ok := node.(*SplitTree); ok {
134 if len(n.children) == 1 {
135 if child, ok := n.children[0].(*LeafNode); ok {
136 s.children[i] = child
146 // ResizeSplits resizes all the splits correctly
147 func (s *SplitTree) ResizeSplits() {
148 for i, node := range s.children {
149 if n, ok := node.(*LeafNode); ok {
150 if s.kind == VerticalSplit {
151 n.view.width = s.width / len(s.children)
152 n.view.height = s.height
154 n.view.x = s.x + n.view.width*i
157 n.view.height = s.height / len(s.children)
158 n.view.width = s.width
160 n.view.y = s.y + n.view.height*i
163 if n.view.Buf.Settings["statusline"].(bool) {
167 n.view.ToggleTabbar()
168 n.view.matches = Match(n.view)
169 } else if n, ok := node.(*SplitTree); ok {
170 if s.kind == VerticalSplit {
171 n.width = s.width / len(s.children)
174 n.x = s.x + n.width*i
177 n.height = s.height / len(s.children)
180 n.y = s.y + n.height*i
188 func (l *LeafNode) String() string {
189 return l.view.Buf.Name
192 func search(haystack []Node, needle Node) int {
193 for i, x := range haystack {
201 func findView(haystack []*View, needle *View) int {
202 for i, x := range haystack {
210 // VSplit is here just to make SplitTree fit the Node interface
211 func (s *SplitTree) VSplit(buf *Buffer) {}
213 // HSplit is here just to make SplitTree fit the Node interface
214 func (s *SplitTree) HSplit(buf *Buffer) {}
216 func (s *SplitTree) String() string {
218 for _, child := range s.children {
219 str += child.String() + ", "