Files
zyedidia.micro/cmd/micro/split_tree.go
2016-08-11 16:59:06 -04:00

208 lines
4.2 KiB
Go

package main
type SplitType bool
const (
VerticalSplit = false
HorizontalSplit = true
)
type Node interface {
VSplit(buf *Buffer)
HSplit(buf *Buffer)
String() string
}
type LeafNode struct {
view *View
parent *SplitTree
}
func NewLeafNode(v *View, parent *SplitTree) *LeafNode {
n := new(LeafNode)
n.view = v
n.view.splitNode = n
n.parent = parent
return n
}
type SplitTree struct {
kind SplitType
parent *SplitTree
children []Node
x int
y int
width int
height int
tabNum int
}
func (l *LeafNode) VSplit(buf *Buffer) {
tab := tabs[l.parent.tabNum]
if l.parent.kind == VerticalSplit {
newView := NewView(buf)
newView.TabNum = l.parent.tabNum
newView.Num = len(tab.views)
l.parent.children = append(l.parent.children, NewLeafNode(newView, l.parent))
tab.curView++
tab.views = append(tab.views, newView)
} else {
s := new(SplitTree)
s.kind = VerticalSplit
s.parent = l.parent
newView := NewView(buf)
newView.TabNum = l.parent.tabNum
newView.Num = len(tab.views)
s.children = []Node{l, NewLeafNode(newView, s)}
l.parent.children[search(l.parent.children, l)] = s
l.parent = s
tab.curView++
tab.views = append(tab.views, newView)
}
}
func (l *LeafNode) HSplit(buf *Buffer) {
tab := tabs[l.parent.tabNum]
if l.parent.kind == HorizontalSplit {
newView := NewView(buf)
newView.TabNum = l.parent.tabNum
newView.Num = len(tab.views)
l.parent.children = append(l.parent.children, NewLeafNode(newView, l.parent))
tab.curView++
tab.views = append(tab.views, newView)
} else {
s := new(SplitTree)
s.kind = HorizontalSplit
s.parent = l.parent
newView := NewView(buf)
newView.TabNum = l.parent.tabNum
newView.Num = len(tab.views)
s.children = []Node{l, NewLeafNode(newView, s)}
l.parent.children[search(l.parent.children, l)] = s
l.parent = s
tab.curView++
tab.views = append(tab.views, newView)
}
}
func (l *LeafNode) Delete() {
i := search(l.parent.children, l)
copy(l.parent.children[i:], l.parent.children[i+1:])
l.parent.children[len(l.parent.children)-1] = nil
l.parent.children = l.parent.children[:len(l.parent.children)-1]
tab := tabs[l.parent.tabNum]
j := findView(tab.views, l.view)
copy(tab.views[j:], tab.views[j+1:])
tab.views[len(tab.views)-1] = nil // or the zero value of T
tab.views = tab.views[:len(tab.views)-1]
for i, v := range tab.views {
v.Num = i
}
if tab.curView > 0 {
tab.curView--
}
}
func (s *SplitTree) Cleanup() {
for i, node := range s.children {
if n, ok := node.(*SplitTree); ok {
if len(n.children) == 1 {
if child, ok := n.children[0].(*LeafNode); ok {
s.children[i] = child
child.parent = s
continue
}
}
n.Cleanup()
}
}
}
func (s *SplitTree) ResizeSplits() {
for i, node := range s.children {
if n, ok := node.(*LeafNode); ok {
if s.kind == VerticalSplit {
n.view.width = s.width / len(s.children)
n.view.height = s.height
n.view.x = s.x + n.view.width*i
n.view.y = s.y
} else {
n.view.height = s.height / len(s.children)
n.view.width = s.width
n.view.y = s.y + n.view.height*i
n.view.x = s.x
}
// n.view.ToggleStatusLine()
_, screenH := screen.Size()
if settings["statusline"].(bool) || (n.view.y+n.view.height) != screenH-1 {
n.view.height--
}
n.view.ToggleTabbar()
n.view.matches = Match(n.view)
} else if n, ok := node.(*SplitTree); ok {
if s.kind == VerticalSplit {
n.width = s.width / len(s.children)
n.height = s.height
n.x = s.x + n.width*i
n.y = s.y
} else {
n.height = s.height / len(s.children)
n.width = s.width
n.y = s.y + n.height*i
n.x = s.x
}
n.ResizeSplits()
}
}
}
func (l *LeafNode) String() string {
return l.view.Buf.Name
}
func search(haystack []Node, needle Node) int {
for i, x := range haystack {
if x == needle {
return i
}
}
return 0
}
func findView(haystack []*View, needle *View) int {
for i, x := range haystack {
if x == needle {
return i
}
}
return 0
}
func (s *SplitTree) VSplit(buf *Buffer) {}
func (s *SplitTree) HSplit(buf *Buffer) {}
func (s *SplitTree) String() string {
str := "["
for _, child := range s.children {
str += child.String() + ", "
}
return str + "]"
}