Skip to content

Commit

Permalink
Send resize event to leaf node models
Browse files Browse the repository at this point in the history
  • Loading branch information
Evertras committed Jan 28, 2024
1 parent ffbb3a2 commit b8d4001
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 25 deletions.
2 changes: 1 addition & 1 deletion pkg/panes/alignment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func TestWithAlignment(t *testing.T) {

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
p := panes.NewLeaf(newDummyModel("foo", nil, nil)).WithDimensions(14, 5)
p, _ := panes.NewLeaf(newDummyModel("foo", nil, nil)).WithDimensions(14, 5)

p = p.WithAlignment(tc.vertical, tc.horizontal)

Expand Down
8 changes: 6 additions & 2 deletions pkg/panes/dummymodel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ func newDummyModel(text string, initCmd func() tea.Msg, updateCallback func(tea.
}

func (m dummyModel) Init() tea.Cmd {
m.initCmd()
if m.initCmd != nil {
m.initCmd()
}

return m.initCmd
}

func (m dummyModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.updateCallback(msg)
if m.updateCallback != nil {
m.updateCallback(msg)
}

return m, nil
}
Expand Down
34 changes: 26 additions & 8 deletions pkg/panes/layout.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package panes

func (m Pane) WithDimensions(width, height int) Pane {
import tea "github.com/charmbracelet/bubbletea"

type ViewableSize struct {
Width int
Height int
}

func (m Pane) WithDimensions(width, height int) (Pane, tea.Cmd) {
m.width = width
m.height = height

m = m.recalculateDimensions()

return m
return m.recalculateDimensions()
}

func (m Pane) WithDirection(direction Direction) Pane {
Expand All @@ -29,10 +34,17 @@ func (m Pane) Children() []Pane {
return m.children
}

func (m Pane) recalculateDimensions() Pane {
func (m Pane) recalculateDimensions() (Pane, tea.Cmd) {
numChildren := len(m.children)
if numChildren == 0 {
return m
var cmd tea.Cmd = nil
if m.model != nil {
m.model, cmd = m.model.Update(ViewableSize{
Width: m.width - 2,
Height: m.height - 2,
})
}
return m, cmd
}
width := m.width
height := m.height
Expand All @@ -43,9 +55,15 @@ func (m Pane) recalculateDimensions() Pane {
width = width / numChildren
}

var (
cmd tea.Cmd
cmds []tea.Cmd
)

for i := range m.children {
m.children[i] = m.children[i].WithDimensions(width, height)
m.children[i], cmd = m.children[i].WithDimensions(width, height)
cmds = append(cmds, cmd)
}

return m
return m, tea.Batch(cmds...)
}
10 changes: 5 additions & 5 deletions pkg/panes/layout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import (

func TestFullPaneTakesFullDimensions(t *testing.T) {
// Ensure a single pane with no children takes the entire dimensions
pane := panes.NewLeaf(nil).WithDimensions(200, 100)
pane, _ := panes.NewLeaf(nil).WithDimensions(200, 100)
assert.Equal(t, 200, pane.Width(), "Wrong width")
assert.Equal(t, 100, pane.Height(), "Wrong height")
}

func TestHorizontalPanesSplitHorizontally(t *testing.T) {
// Ensure a single pane with ten children horizontally splits the width
pane := panes.NewNode(panes.DirectionHorizontal, panes.NewLeaf(nil), panes.NewLeaf(nil)).WithDimensions(100, 100)
pane, _ := panes.NewNode(panes.DirectionHorizontal, panes.NewLeaf(nil), panes.NewLeaf(nil)).WithDimensions(100, 100)
for i, child := range pane.Children() {
assert.Equal(t, 50, child.Width(), "Wrong width for child %d", i)
assert.Equal(t, 100, child.Height(), "Wrong height for child %d", i)
Expand All @@ -25,7 +25,7 @@ func TestHorizontalPanesSplitHorizontally(t *testing.T) {

func TestVerticalPanesSplitVertically(t *testing.T) {
// Ensure a single pane with ten children vertically splits the height
pane := panes.NewNode(panes.DirectionVertical, panes.NewLeaf(nil), panes.NewLeaf(nil)).WithDimensions(100, 100)
pane, _ := panes.NewNode(panes.DirectionVertical, panes.NewLeaf(nil), panes.NewLeaf(nil)).WithDimensions(100, 100)
for i, child := range pane.Children() {
assert.Equal(t, 100, child.Width(), "Wrong width for child %d", i)
assert.Equal(t, 50, child.Height(), "Wrong height for child %d", i)
Expand All @@ -42,7 +42,7 @@ func TestNestedPanesSplitWithinParent(t *testing.T) {
sideChildren[i] = panes.NewLeaf(nil)
}

pane := panes.NewNode(panes.DirectionHorizontal,
pane, _ := panes.NewNode(panes.DirectionHorizontal,
panes.NewLeaf(nil),
panes.NewNode(panes.DirectionVertical, sideChildren...),
).WithDimensions(100, 100)
Expand All @@ -66,7 +66,7 @@ func TestNestedPanesSplitWithinParent(t *testing.T) {
func TestChangingDirectionChangesLayout(t *testing.T) {
// With a parent pane that contains two leaf children split horizontally,
// switch to vertical and make sure the layout changes.
pane := panes.NewNode(panes.DirectionHorizontal, panes.NewLeaf(nil), panes.NewLeaf(nil)).WithDimensions(100, 100)
pane, _ := panes.NewNode(panes.DirectionHorizontal, panes.NewLeaf(nil), panes.NewLeaf(nil)).WithDimensions(100, 100)

for _, child := range pane.Children() {
assert.Equal(t, 50, child.Width(), "Wrong width for child")
Expand Down
39 changes: 31 additions & 8 deletions pkg/panes/panes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,34 @@ func TestUpdateParentNodeSendsUpdateToChildren(t *testing.T) {
assert.True(t, sawUpdate, "Model should have seen update")
}

func TestUpdateSendsResizeEventToLeafNodes(t *testing.T) {
// Given a parent node with nested children,
// the model should receive the update message
var resizeMsg panes.ViewableSize
dummy := newDummyModel("testing", nil, func(msg tea.Msg) {
switch msg := msg.(type) {
case panes.ViewableSize:
resizeMsg = msg
}
})
parent := panes.NewNode(panes.DirectionHorizontal, panes.NewLeaf(dummy))

const (
newWidth = 48
newHeight = 24
)

parent.WithDimensions(newWidth, newHeight)

assert.Equal(t, newWidth-2, resizeMsg.Width, "Model should have seen new width")
assert.Equal(t, newHeight-2, resizeMsg.Height, "Model should have seen new height")
}

func TestViewLeafNodeShowsInnerModel(t *testing.T) {
// Given a leaf node with a simple model,
// the view should return the inner model's view
dummy := newDummyModel("testing", nil, nil)
pane := panes.NewLeaf(dummy).WithDimensions(100, 100)
pane, _ := panes.NewLeaf(dummy).WithDimensions(100, 100)

assert.Contains(t, pane.View(), "testing", "View should return inner model's view")
}
Expand All @@ -73,7 +96,7 @@ func TestViewLeafNodeCropsInnerModel(t *testing.T) {
// the view should crop the text to the pane's dimensions.
const expectedLines = 2
text := strings.Repeat("testing\n", 100)
pane := panes.NewLeaf(newDummyModel(text, nil, nil)).
pane, _ := panes.NewLeaf(newDummyModel(text, nil, nil)).
WithDimensions(10, expectedLines+2) // Account for border

numTesting := strings.Count(pane.View(), "testing")
Expand All @@ -86,7 +109,7 @@ func TestViewParentNodeShowsInnerModelsOfChildren(t *testing.T) {
// the view should return the inner model's view
dummyLeft := newDummyModel("left", nil, nil)
dummyRight := newDummyModel("right", nil, nil)
pane := panes.NewNode(
pane, _ := panes.NewNode(
panes.DirectionHorizontal,
panes.NewLeaf(dummyLeft),
panes.NewLeaf(dummyRight),
Expand All @@ -99,7 +122,7 @@ func TestViewParentNodeShowsInnerModelsOfChildren(t *testing.T) {
func TestViewHorizontalGoesLeftToRight(t *testing.T) {
dummyLeft := newDummyModel("left", nil, nil)
dummyRight := newDummyModel("right", nil, nil)
pane := panes.NewNode(
pane, _ := panes.NewNode(
panes.DirectionHorizontal,
panes.NewLeaf(dummyLeft),
panes.NewLeaf(dummyRight),
Expand All @@ -114,7 +137,7 @@ func TestViewHorizontalGoesLeftToRight(t *testing.T) {
func TestViewVerticalGoesTopToBottom(t *testing.T) {
dummyTop := newDummyModel("top", nil, nil)
dummyBottom := newDummyModel("bottom", nil, nil)
pane := panes.NewNode(panes.DirectionVertical, panes.NewLeaf(dummyTop), panes.NewLeaf(dummyBottom)).WithDimensions(10, 100)
pane, _ := panes.NewNode(panes.DirectionVertical, panes.NewLeaf(dummyTop), panes.NewLeaf(dummyBottom)).WithDimensions(10, 100)

indexTop := strings.Index(pane.View(), "top")
indexBottom := strings.Index(pane.View(), "bottom")
Expand All @@ -127,7 +150,7 @@ func TestViewTitleIsShown(t *testing.T) {
│testing │
╰────────╯`
dummy := newDummyModel("testing", nil, nil)
pane := panes.NewLeaf(dummy).WithName("title").WithDimensions(10, 3)
pane, _ := panes.NewLeaf(dummy).WithName("title").WithDimensions(10, 3)

assert.Equal(t, expectedView, pane.View())
}
Expand All @@ -137,7 +160,7 @@ func TestViewNoTitleShowsBorderProperly(t *testing.T) {
│testing │
╰────────╯`
dummy := newDummyModel("testing", nil, nil)
pane := panes.NewLeaf(dummy).WithDimensions(10, 3)
pane, _ := panes.NewLeaf(dummy).WithDimensions(10, 3)

assert.Equal(t, expectedView, pane.View())
}
Expand All @@ -147,7 +170,7 @@ func TestViewRemovingTitleShowsBorderProperly(t *testing.T) {
│testing │
╰────────╯`
dummy := newDummyModel("testing", nil, nil)
pane := panes.NewLeaf(dummy).WithName("title").WithDimensions(10, 3)
pane, _ := panes.NewLeaf(dummy).WithName("title").WithDimensions(10, 3)

pane = pane.WithName("")

Expand Down
3 changes: 2 additions & 1 deletion pkg/yakdash/yakdash.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

case tea.WindowSizeMsg:
m.rootPane = m.rootPane.WithDimensions(msg.Width, msg.Height)
m.rootPane, cmd = m.rootPane.WithDimensions(msg.Width, msg.Height)
cmds = append(cmds, cmd)
}

m.rootPane, cmd = m.rootPane.Update(msg)
Expand Down

0 comments on commit b8d4001

Please sign in to comment.