From 853c1436968ba5658d5cf12f1627837f9a07ee53 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Wed, 9 Jan 2019 18:06:31 -0500 Subject: [PATCH] Implement split resizing --- cmd/micro/action/tab.go | 34 +++++++++++++++++++++++---- cmd/micro/display/uiwindow.go | 22 +++++++++++++----- cmd/micro/views/splits.go | 43 +++++++++++++++++++++++++++-------- 3 files changed, 79 insertions(+), 20 deletions(-) diff --git a/cmd/micro/action/tab.go b/cmd/micro/action/tab.go index 8b820263..b4c23d22 100644 --- a/cmd/micro/action/tab.go +++ b/cmd/micro/action/tab.go @@ -1,6 +1,7 @@ package action import ( + "github.com/zyedidia/micro/cmd/micro/buffer" "github.com/zyedidia/micro/cmd/micro/display" "github.com/zyedidia/micro/cmd/micro/screen" "github.com/zyedidia/micro/cmd/micro/views" @@ -15,7 +16,7 @@ type TabPane struct { Panes []*EditPane active int - resizing bool + resizing *views.Node // node currently being resized } func (t *TabPane) HandleEvent(event tcell.Event) { @@ -30,6 +31,24 @@ func (t *TabPane) HandleEvent(event tcell.Event) { case tcell.Button1: 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 { v := p.GetView() 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) } } + case tcell.ButtonNone: + t.resizing = nil } + } t.Panes[t.active].HandleEvent(event) } @@ -72,12 +94,16 @@ func (t *TabPane) RemovePane(i int) { } func (t *TabPane) Resize() { - for _, p := range t.Panes { + for i, p := range t.Panes { n := t.GetNode(p.splitID) 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.Resize(n.W, n.H) + p.Resize(n.W-offset, n.H) } } diff --git a/cmd/micro/display/uiwindow.go b/cmd/micro/display/uiwindow.go index 6d866aef..1c9210eb 100644 --- a/cmd/micro/display/uiwindow.go +++ b/cmd/micro/display/uiwindow.go @@ -45,17 +45,27 @@ func (w *UIWindow) GetMouseLoc(vloc buffer.Loc) buffer.Loc { mouseLoc = func(n *views.Node) buffer.Loc { cs := n.Children() for i, c := range cs { - if c.IsLeaf() && c.Kind == views.STVert { + if c.Kind == views.STVert { if i != len(cs)-1 { - if vloc.X == c.X+c.W { - return vloc + if vloc.X == c.X+c.W && vloc.Y >= c.Y && vloc.Y < c.Y+c.H { + 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) } diff --git a/cmd/micro/views/splits.go b/cmd/micro/views/splits.go index 170ec680..6c1a6c01 100644 --- a/cmd/micro/views/splits.go +++ b/cmd/micro/views/splits.go @@ -2,6 +2,7 @@ package views import ( "fmt" + "log" "strings" ) @@ -154,10 +155,11 @@ func (n *Node) vResizeSplit(i int, size int) bool { if size >= toth { return false } - c2.Y = size + c2.Y = c1.Y + size c1.Resize(c1.W, size) c2.Resize(c2.W, toth-size) n.markSizes() + n.alignSizes(n.W, n.H) return true } 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 { return false } - c2.X = size + c2.X = c1.X + size c1.Resize(size, c1.H) c2.Resize(totw-size, c2.H) n.markSizes() + n.alignSizes(n.W, n.H) return true } // ResizeSplit resizes a certain split to a given size func (n *Node) ResizeSplit(size int) bool { - if !n.IsLeaf() || len(n.parent.children) <= 1 { - // cannot resize a non leaf or a lone node + if len(n.parent.children) <= 1 { + // cannot resize a lone node return false } 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 // of the sizes by making the final split fill the screen if n.Kind == STVert && toth != n.H { @@ -242,6 +249,10 @@ func (n *Node) markSizes() { c.propH = float64(c.H) / float64(n.H) c.markSizes() } +} + +func (n *Node) markResize() { + n.markSizes() n.Resize(n.W, n.H) } @@ -318,7 +329,7 @@ func (n *Node) applyNewSize(size int, h bool) { a += c.H } } - n.markSizes() + n.markResize() } // 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.markSizes() + n.markResize() return newid } else { 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.markSizes() + n.markResize() return newid } else { 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:]) n.children[len(n.children)-1] = nil n.children = n.children[:len(n.children)-1] + log.Println(len(n.children)) 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 if h { size = (n.H - nonrs) / numr @@ -441,7 +459,7 @@ func (n *Node) unsplit(i int, h bool) { // Unsplit deletes this split and resizes everything // else accordingly func (n *Node) Unsplit() { - if !n.IsLeaf() || len(n.parent.children) <= 1 { + if !n.IsLeaf() { return } ind := 0 @@ -452,9 +470,14 @@ func (n *Node) Unsplit() { } if n.parent.Kind == STVert { 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)