Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 64 additions & 16 deletions lib/pager_stack.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package rat

import (
"math"
)

// PagerStack is a stack of Pagers
type PagerStack interface {
Widget
Show(int)
Expand All @@ -17,9 +22,11 @@ type pagerStack struct {
lastEl *pagerStackElement
size int
numToShow int
widthToBreak int
eventHandlers HandlerRegistry
box Box
validLayout bool
splitFunction func(n, totalSize int) []section
}

type pagerStackElement struct {
Expand All @@ -28,11 +35,14 @@ type pagerStackElement struct {
creatingKeys string
}

// NewPagerStack creates a new instance of PagerStack
func NewPagerStack() PagerStack {
ps := &pagerStack{}

ps.numToShow = 3
ps.eventHandlers = NewHandlerRegistry()
ps := &pagerStack{
numToShow: 3,
widthToBreak: 100,
eventHandlers: NewHandlerRegistry(),
splitFunction: goldenSizes,
}

return ps
}
Expand Down Expand Up @@ -109,35 +119,35 @@ func (ps *pagerStack) visiblePagers() []Pager {
}

func (ps *pagerStack) splitHorizontal() bool {
return ps.box.Width() > 180
return ps.box.Width() > ps.widthToBreak
}

func (ps *pagerStack) layout() {
pagers := ps.visiblePagers()
n := len(pagers)
offset := 0

var totalSize, size int
var totalSize int

if ps.splitHorizontal() {
totalSize = ps.box.Width()
} else {
totalSize = ps.box.Height()
}

remaining := totalSize
sections := ps.splitFunction(n, totalSize)

for i, p := range pagers {
size = (remaining - (n - i - 1)) / (n - i)
bs := sections[i]

if ps.splitHorizontal() {
p.SetBox(NewBox(offset, 0, size, ps.box.Height()))
p.SetBox(NewBox(
bs.offset, 0,
bs.size, ps.box.Height()))
} else {
p.SetBox(NewBox(0, offset, ps.box.Width(), size))
p.SetBox(NewBox(
0, bs.offset,
ps.box.Width(), bs.size))
}

offset = offset + size + 1
remaining = totalSize - offset
}
}

Expand Down Expand Up @@ -197,9 +207,8 @@ func (ps *pagerStack) parentPager() Pager {

if ps.size > 1 {
return ps.lastEl.previous.pager
} else {
return ps.lastEl.pager
}
return ps.lastEl.pager
}

func (ps *pagerStack) ParentCursorUp() {
Expand All @@ -215,3 +224,42 @@ func (ps *pagerStack) ParentCursorDown() {
ps.parentPager().HandleEvent(KeySequenceFromString(ps.lastEl.creatingKeys))
}
}

type section struct {
offset int
size int
}

// evenSizes is a function that splits the panes in even sizes
// this was the default behaviour of rat and
// maybe desirable as a setting
func evenSizes(n, totalSize int) []section {
boxes := make([]section, n)
remaining := totalSize
var size, offset int

for i := 0; i < n; i++ {
size = (remaining - (n - i - 1)) / (n - i)
boxes[i] = section{offset, size}
offset = offset + size + 1
remaining = totalSize - offset
}
return boxes
}

func golden(n, totalSize, offset int) []section {
if n <= 1 {
return []section{section{offset, totalSize}}
}
// Split total size
big := int(math.Floor(float64(totalSize) / math.Phi))
small := totalSize - big - 1

return append(golden(n-1, small, offset), section{offset + small + 1, big})
}

// goldenSizes splits panes using the golden ratio
// of Phi making the active pane bigger
func goldenSizes(n, totalSize int) []section {
return golden(n, totalSize, 0)
}
44 changes: 44 additions & 0 deletions lib/pager_stack_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package rat

import (
"reflect"
"testing"
)

func TestEvenSizes(t *testing.T) {
tests := []struct {
n int
totalSize int
expected []section
}{
{1, 120, []section{section{0, 120}}},
{2, 120, []section{section{0, 59}, section{60, 60}}},
{3, 120, []section{section{0, 39}, section{40, 39}, section{80, 40}}},
}

for _, tt := range tests {
sections := evenSizes(tt.n, tt.totalSize)
if !reflect.DeepEqual(sections, tt.expected) {
t.Errorf("evenSizes(%d, %d): expected %v, got %v", tt.n, tt.totalSize, tt.expected, sections)
}
}
}

func TestGoldenSizes(t *testing.T) {
tests := []struct {
n int
totalSize int
expected []section
}{
{1, 120, []section{section{0, 120}}},
{2, 120, []section{section{0, 45}, section{46, 74}}},
{3, 120, []section{section{0, 17}, section{18, 27}, section{46, 74}}},
}

for _, tt := range tests {
sections := goldenSizes(tt.n, tt.totalSize)
if !reflect.DeepEqual(sections, tt.expected) {
t.Errorf("goldenSizes(%d, %d): expected %v, got %v", tt.n, tt.totalSize, tt.expected, sections)
}
}
}