mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-25 18:07:07 +09:00
Implement split resizing
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user