Implement split resizing

This commit is contained in:
Zachary Yedidia
2019-01-09 18:06:31 -05:00
parent f2cb7d2fc1
commit fe773c00d2
3 changed files with 79 additions and 20 deletions

View File

@@ -1,6 +1,7 @@
package action package action
import ( import (
"github.com/zyedidia/micro/cmd/micro/buffer"
"github.com/zyedidia/micro/cmd/micro/display" "github.com/zyedidia/micro/cmd/micro/display"
"github.com/zyedidia/micro/cmd/micro/screen" "github.com/zyedidia/micro/cmd/micro/screen"
"github.com/zyedidia/micro/cmd/micro/views" "github.com/zyedidia/micro/cmd/micro/views"
@@ -15,7 +16,7 @@ type TabPane struct {
Panes []*EditPane Panes []*EditPane
active int active int
resizing bool resizing *views.Node // node currently being resized
} }
func (t *TabPane) HandleEvent(event tcell.Event) { func (t *TabPane) HandleEvent(event tcell.Event) {
@@ -30,6 +31,24 @@ func (t *TabPane) HandleEvent(event tcell.Event) {
case tcell.Button1: case tcell.Button1:
mx, my := e.Position() mx, my := e.Position()
resizeID := t.GetMouseLoc(buffer.Loc{mx, my}).X
if t.resizing != nil {
var size int
if t.resizing.Kind == views.STVert {
size = mx - t.resizing.X
} else {
size = my - t.resizing.Y + 1
}
t.resizing.ResizeSplit(size)
t.Resize()
return
}
if resizeID != -1 {
t.resizing = t.GetNode(uint64(resizeID))
return
}
for i, p := range t.Panes { for i, p := range t.Panes {
v := p.GetView() v := p.GetView()
inpane := mx >= v.X && mx < v.X+v.Width && my >= v.Y && my < v.Y+v.Height inpane := mx >= v.X && mx < v.X+v.Width && my >= v.Y && my < v.Y+v.Height
@@ -40,7 +59,10 @@ func (t *TabPane) HandleEvent(event tcell.Event) {
p.SetActive(false) p.SetActive(false)
} }
} }
case tcell.ButtonNone:
t.resizing = nil
} }
} }
t.Panes[t.active].HandleEvent(event) t.Panes[t.active].HandleEvent(event)
} }
@@ -72,12 +94,16 @@ func (t *TabPane) RemovePane(i int) {
} }
func (t *TabPane) Resize() { func (t *TabPane) Resize() {
for _, p := range t.Panes { for i, p := range t.Panes {
n := t.GetNode(p.splitID) n := t.GetNode(p.splitID)
pv := p.GetView() pv := p.GetView()
pv.X, pv.Y = n.X, n.Y offset := 0
if i != 0 {
offset = 1
}
pv.X, pv.Y = n.X+offset, n.Y
p.SetView(pv) p.SetView(pv)
p.Resize(n.W, n.H) p.Resize(n.W-offset, n.H)
} }
} }

View File

@@ -45,17 +45,27 @@ func (w *UIWindow) GetMouseLoc(vloc buffer.Loc) buffer.Loc {
mouseLoc = func(n *views.Node) buffer.Loc { mouseLoc = func(n *views.Node) buffer.Loc {
cs := n.Children() cs := n.Children()
for i, c := range cs { for i, c := range cs {
if c.IsLeaf() && c.Kind == views.STVert { if c.Kind == views.STVert {
if i != len(cs)-1 { if i != len(cs)-1 {
if vloc.X == c.X+c.W { if vloc.X == c.X+c.W && vloc.Y >= c.Y && vloc.Y < c.Y+c.H {
return vloc return buffer.Loc{int(c.ID()), 0}
}
}
} else if c.Kind == views.STHoriz {
if i != len(cs)-1 {
if vloc.Y == c.Y+c.H-1 && vloc.X >= c.X && vloc.X < c.X+c.W {
return buffer.Loc{int(c.ID()), 0}
} }
} }
} else {
return mouseLoc(c)
} }
} }
return buffer.Loc{} for _, c := range cs {
m := mouseLoc(c)
if m.X != -1 {
return m
}
}
return buffer.Loc{-1, 0}
} }
return mouseLoc(w.root) return mouseLoc(w.root)
} }

View File

@@ -2,6 +2,7 @@ package views
import ( import (
"fmt" "fmt"
"log"
"strings" "strings"
) )
@@ -154,10 +155,11 @@ func (n *Node) vResizeSplit(i int, size int) bool {
if size >= toth { if size >= toth {
return false return false
} }
c2.Y = size c2.Y = c1.Y + size
c1.Resize(c1.W, size) c1.Resize(c1.W, size)
c2.Resize(c2.W, toth-size) c2.Resize(c2.W, toth-size)
n.markSizes() n.markSizes()
n.alignSizes(n.W, n.H)
return true return true
} }
func (n *Node) hResizeSplit(i int, size int) bool { func (n *Node) hResizeSplit(i int, size int) bool {
@@ -174,17 +176,18 @@ func (n *Node) hResizeSplit(i int, size int) bool {
if size >= totw { if size >= totw {
return false return false
} }
c2.X = size c2.X = c1.X + size
c1.Resize(size, c1.H) c1.Resize(size, c1.H)
c2.Resize(totw-size, c2.H) c2.Resize(totw-size, c2.H)
n.markSizes() n.markSizes()
n.alignSizes(n.W, n.H)
return true return true
} }
// ResizeSplit resizes a certain split to a given size // ResizeSplit resizes a certain split to a given size
func (n *Node) ResizeSplit(size int) bool { func (n *Node) ResizeSplit(size int) bool {
if !n.IsLeaf() || len(n.parent.children) <= 1 { if len(n.parent.children) <= 1 {
// cannot resize a non leaf or a lone node // cannot resize a lone node
return false return false
} }
ind := 0 ind := 0
@@ -224,6 +227,10 @@ func (n *Node) Resize(w, h int) {
} }
} }
n.alignSizes(totw, toth)
}
func (n *Node) alignSizes(totw, toth int) {
// Make sure that there are no off-by-one problems with the rounding // Make sure that there are no off-by-one problems with the rounding
// of the sizes by making the final split fill the screen // of the sizes by making the final split fill the screen
if n.Kind == STVert && toth != n.H { if n.Kind == STVert && toth != n.H {
@@ -242,6 +249,10 @@ func (n *Node) markSizes() {
c.propH = float64(c.H) / float64(n.H) c.propH = float64(c.H) / float64(n.H)
c.markSizes() c.markSizes()
} }
}
func (n *Node) markResize() {
n.markSizes()
n.Resize(n.W, n.H) n.Resize(n.W, n.H)
} }
@@ -318,7 +329,7 @@ func (n *Node) applyNewSize(size int, h bool) {
a += c.H a += c.H
} }
} }
n.markSizes() n.markResize()
} }
// hsplits a vertical split // hsplits a vertical split
@@ -332,7 +343,7 @@ func (n *Node) vHSplit(i int, right bool) uint64 {
} }
n.children = append(n.children, hn1, hn2) n.children = append(n.children, hn1, hn2)
n.markSizes() n.markResize()
return newid return newid
} else { } else {
nonrh, numr := n.getResizeInfo(true) nonrh, numr := n.getResizeInfo(true)
@@ -368,7 +379,7 @@ func (n *Node) hVSplit(i int, right bool) uint64 {
} }
n.children = append(n.children, vn1, vn2) n.children = append(n.children, vn1, vn2)
n.markSizes() n.markResize()
return newid return newid
} else { } else {
nonrw, numr := n.getResizeInfo(false) nonrw, numr := n.getResizeInfo(false)
@@ -429,8 +440,15 @@ func (n *Node) unsplit(i int, h bool) {
copy(n.children[i:], n.children[i+1:]) copy(n.children[i:], n.children[i+1:])
n.children[len(n.children)-1] = nil n.children[len(n.children)-1] = nil
n.children = n.children[:len(n.children)-1] n.children = n.children[:len(n.children)-1]
log.Println(len(n.children))
nonrs, numr := n.getResizeInfo(h) nonrs, numr := n.getResizeInfo(h)
if numr == 0 {
// This means that this was the last child
// The parent will get cleaned up in the next iteration and
// will resolve all sizing issues with its parent
return
}
size := (n.W - nonrs) / numr size := (n.W - nonrs) / numr
if h { if h {
size = (n.H - nonrs) / numr size = (n.H - nonrs) / numr
@@ -441,7 +459,7 @@ func (n *Node) unsplit(i int, h bool) {
// Unsplit deletes this split and resizes everything // Unsplit deletes this split and resizes everything
// else accordingly // else accordingly
func (n *Node) Unsplit() { func (n *Node) Unsplit() {
if !n.IsLeaf() || len(n.parent.children) <= 1 { if !n.IsLeaf() {
return return
} }
ind := 0 ind := 0
@@ -452,9 +470,14 @@ func (n *Node) Unsplit() {
} }
if n.parent.Kind == STVert { if n.parent.Kind == STVert {
n.parent.unsplit(ind, true) n.parent.unsplit(ind, true)
return } else {
n.parent.unsplit(ind, false)
}
if n.parent.IsLeaf() {
log.Println("destroy parent")
n.parent.Unsplit()
} }
n.parent.unsplit(ind, false)
} }
// String returns the string form of the node and all children (used for debugging) // String returns the string form of the node and all children (used for debugging)