Skip to content

Commit 080d216

Browse files
Fixing chained parents by flattening the tree on unsplit
1 parent f4d62a4 commit 080d216

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

internal/views/splits.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,9 +479,58 @@ func (n *Node) Unsplit() bool {
479479
if n.parent.IsLeaf() {
480480
return n.parent.Unsplit()
481481
}
482+
483+
n.parent.flatten()
482484
return true
483485
}
484486

487+
// flattens the tree by removing unnecessary intermediate parents that have only one child
488+
// and handles the side effect of it
489+
func (n *Node) flatten() {
490+
if n.parent == nil || len(n.children) != 1 {
491+
return
492+
}
493+
494+
ind := 0
495+
for i, c := range n.parent.children {
496+
if c.id == n.id {
497+
ind = i
498+
}
499+
}
500+
501+
// Replace current node with its child node to remove chained parent
502+
successor := n.children[0]
503+
n.parent.children[ind] = successor
504+
successor.parent = n.parent
505+
506+
// Maintain the tree in a consistent state: any child node's kind (horiz vs vert)
507+
// should be the opposite of its parent's kind.
508+
if successor.IsLeaf() {
509+
successor.Kind = n.Kind
510+
} else {
511+
// If the successor node has children, that means it is a chained parent as well.
512+
// Therefore it can be replaced by its own children.
513+
origsize := len(n.parent.children)
514+
515+
// Let's say we have 5 children and want to replace [2] with its children [a] [b] [c]
516+
// [0] [1] [2] [3] [4] --> [0] [1] [a] [b] [c] [3] [4]
517+
// insertcount will be `3 - 1 = 2` in this case
518+
insertcount := len(successor.children) - 1
519+
520+
n.parent.children = append(n.parent.children, make([]*Node, insertcount)...)
521+
copy(n.parent.children[ind+insertcount+1:], n.parent.children[ind+1:origsize])
522+
copy(n.parent.children[ind:], successor.children)
523+
524+
for i := 0; i < len(successor.children); i++ {
525+
n.parent.children[ind+i].parent = n.parent
526+
}
527+
}
528+
529+
// Update propW and propH since the parent of the children has been updated,
530+
// so the children have new siblings
531+
n.parent.markSizes()
532+
}
533+
485534
// String returns the string form of the node and all children (used for debugging)
486535
func (n *Node) String() string {
487536
var strf func(n *Node, ident int) string

0 commit comments

Comments
 (0)