mirror of
https://github.com/zyedidia/micro
synced 2024-09-30 13:14:00 +00:00
Add split_tree and ability to create splits
This commit is contained in:
parent
2cbd9428aa
commit
cbbe312762
|
@ -768,6 +768,8 @@ func (v *View) Quit() bool {
|
|||
if v.CanClose("Quit anyway? (yes, no, save) ") {
|
||||
v.CloseBuffer()
|
||||
if len(tabs[curTab].views) > 1 {
|
||||
screen.Fini()
|
||||
os.Exit(0)
|
||||
} else if len(tabs) > 1 {
|
||||
if len(tabs[v.TabNum].views) == 1 {
|
||||
tabs = tabs[:v.TabNum+copy(tabs[v.TabNum:], tabs[v.TabNum+1:])]
|
||||
|
@ -778,7 +780,7 @@ func (v *View) Quit() bool {
|
|||
curTab--
|
||||
}
|
||||
if curTab == 0 {
|
||||
CurView().Resize(screen.Size())
|
||||
// CurView().Resize(screen.Size())
|
||||
CurView().matches = Match(CurView())
|
||||
}
|
||||
}
|
||||
|
@ -796,13 +798,13 @@ func (v *View) AddTab() bool {
|
|||
tab.SetNum(len(tabs))
|
||||
tabs = append(tabs, tab)
|
||||
curTab++
|
||||
if len(tabs) == 2 {
|
||||
for _, t := range tabs {
|
||||
for _, v := range t.views {
|
||||
v.Resize(screen.Size())
|
||||
}
|
||||
}
|
||||
}
|
||||
// if len(tabs) == 2 {
|
||||
// for _, t := range tabs {
|
||||
// for _, v := range t.views {
|
||||
// v.Resize(screen.Size())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -126,13 +126,13 @@ func NewTab(args []string) {
|
|||
tab.SetNum(len(tabs))
|
||||
tabs = append(tabs, tab)
|
||||
curTab++
|
||||
if len(tabs) == 2 {
|
||||
for _, t := range tabs {
|
||||
for _, v := range t.views {
|
||||
v.Resize(screen.Size())
|
||||
}
|
||||
}
|
||||
}
|
||||
// if len(tabs) == 2 {
|
||||
// for _, t := range tabs {
|
||||
// for _, v := range t.views {
|
||||
// v.Resize(screen.Size())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -247,11 +247,11 @@ func main() {
|
|||
tab := NewTabFromView(NewView(buf))
|
||||
tab.SetNum(len(tabs))
|
||||
tabs = append(tabs, tab)
|
||||
for _, t := range tabs {
|
||||
for _, v := range t.views {
|
||||
v.Resize(screen.Size())
|
||||
}
|
||||
}
|
||||
// for _, t := range tabs {
|
||||
// for _, v := range t.views {
|
||||
// v.Resize(screen.Size())
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// Load all the plugin stuff
|
||||
|
|
|
@ -126,7 +126,7 @@ func SetOption(view *View, args []string) {
|
|||
}
|
||||
|
||||
if option == "statusline" {
|
||||
view.Resize(screen.Size())
|
||||
// view.Resize(screen.Size())
|
||||
}
|
||||
|
||||
err := WriteSettings(filename)
|
||||
|
|
152
cmd/micro/split_tree.go
Normal file
152
cmd/micro/split_tree.go
Normal file
|
@ -0,0 +1,152 @@
|
|||
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
|
||||
|
||||
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
|
||||
|
||||
tab.curView++
|
||||
tab.views = append(tab.views, newView)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
} 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 (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 + "]"
|
||||
}
|
|
@ -15,6 +15,8 @@ type Tab struct {
|
|||
curView int
|
||||
// Generally this is the name of the current view's buffer
|
||||
name string
|
||||
|
||||
tree *SplitTree
|
||||
}
|
||||
|
||||
// NewTabFromView creates a new tab and puts the given view in the tab
|
||||
|
@ -22,6 +24,14 @@ func NewTabFromView(v *View) *Tab {
|
|||
t := new(Tab)
|
||||
t.views = append(t.views, v)
|
||||
t.views[0].Num = 0
|
||||
|
||||
t.tree = new(SplitTree)
|
||||
t.tree.kind = VerticalSplit
|
||||
t.tree.children = []Node{NewLeafNode(t.views[0], t.tree)}
|
||||
|
||||
w, h := screen.Size()
|
||||
t.tree.width = w
|
||||
t.tree.height = h
|
||||
return t
|
||||
}
|
||||
|
||||
|
@ -32,6 +42,10 @@ func (t *Tab) SetNum(num int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *Tab) Resize() {
|
||||
t.tree.ResizeSplits()
|
||||
}
|
||||
|
||||
// CurView returns the current view
|
||||
func CurView() *View {
|
||||
curTab := tabs[curTab]
|
||||
|
|
|
@ -82,11 +82,14 @@ type View struct {
|
|||
matches SyntaxMatches
|
||||
// The matches from the last frame
|
||||
lastMatches SyntaxMatches
|
||||
|
||||
splitNode *LeafNode
|
||||
}
|
||||
|
||||
// NewView returns a new fullscreen view
|
||||
func NewView(buf *Buffer) *View {
|
||||
return NewViewWidthHeight(buf, 100, 100)
|
||||
screenW, screenH := screen.Size()
|
||||
return NewViewWidthHeight(buf, screenW, screenH-1)
|
||||
}
|
||||
|
||||
// NewViewWidthHeight returns a new view with the specified width and height percentages
|
||||
|
@ -96,9 +99,8 @@ func NewViewWidthHeight(buf *Buffer, w, h int) *View {
|
|||
|
||||
v.x, v.y = 0, 0
|
||||
|
||||
v.widthPercent = w
|
||||
v.heightPercent = h
|
||||
v.Resize(screen.Size())
|
||||
v.width = w
|
||||
v.height = h
|
||||
|
||||
v.OpenBuffer(buf)
|
||||
|
||||
|
@ -108,34 +110,11 @@ func NewViewWidthHeight(buf *Buffer, w, h int) *View {
|
|||
view: v,
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// Resize recalculates the actual width and height of the view from the width and height
|
||||
// percentages
|
||||
// This is usually called when the window is resized, or when a split has been added and
|
||||
// the percentages have changed
|
||||
func (v *View) Resize(w, h int) {
|
||||
// Always include 1 line for the command line at the bottom
|
||||
h--
|
||||
if len(tabs) > 1 {
|
||||
if v.y == 0 {
|
||||
// Include one line for the tab bar at the top
|
||||
h--
|
||||
v.y = 1
|
||||
}
|
||||
} else {
|
||||
if v.y == 1 {
|
||||
v.y = 0
|
||||
}
|
||||
}
|
||||
v.width = int(float32(w) * float32(v.widthPercent) / 100)
|
||||
// We subtract 1 for the statusline
|
||||
v.height = int(float32(h) * float32(v.heightPercent) / 100)
|
||||
if settings["statusline"].(bool) {
|
||||
// Make room for the status line if it is enabled
|
||||
v.height--
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// ScrollUp scrolls the view up n lines (if possible)
|
||||
|
@ -219,11 +198,15 @@ func (v *View) ReOpen() {
|
|||
|
||||
// HSplit opens a horizontal split with the given buffer
|
||||
func (v *View) HSplit(buf *Buffer) bool {
|
||||
v.splitNode.HSplit(buf)
|
||||
tabs[v.TabNum].Resize()
|
||||
return false
|
||||
}
|
||||
|
||||
// VSplit opens a vertical split with the given buffer
|
||||
func (v *View) VSplit(buf *Buffer) bool {
|
||||
v.splitNode.VSplit(buf)
|
||||
tabs[v.TabNum].Resize()
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -297,7 +280,7 @@ func (v *View) HandleEvent(event tcell.Event) {
|
|||
switch e := event.(type) {
|
||||
case *tcell.EventResize:
|
||||
// Window resized
|
||||
v.Resize(e.Size())
|
||||
// v.Resize(e.Size())
|
||||
case *tcell.EventKey:
|
||||
if e.Key() == tcell.KeyRune && (e.Modifiers() == 0 || e.Modifiers() == tcell.ModShift) {
|
||||
// Insert a character
|
||||
|
|
Loading…
Reference in a new issue