support ratio layouts

This commit is contained in:
David 2021-07-04 13:49:53 -04:00
parent 78d80aef6c
commit a6f958ccfb
2 changed files with 121 additions and 4 deletions

View File

@ -16,6 +16,7 @@ type Offsets struct {
Bottom int Bottom int
Left int Left int
Right int Right int
Percent int
} }
type Contents []struct { type Contents []struct {
@ -27,6 +28,8 @@ const (
LayoutUnmanaged = iota LayoutUnmanaged = iota
LayoutHorizontalEven LayoutHorizontalEven
LayoutVerticalEven LayoutVerticalEven
LayoutHorizontalPercent
LayoutVerticalPercent
) )
// A Container has no visible UI of its own, but arranges sub-components on the screen. // A Container has no visible UI of its own, but arranges sub-components on the screen.
@ -87,6 +90,58 @@ func (c *Container) SetSize(x, y, h, w int) {
} }
c.contents[r].Container.SetSize(x, y, h, w) c.contents[r].Container.SetSize(x, y, h, w)
} }
} else if c.layoutMethod == LayoutHorizontalPercent {
// first, work out overall distribution
total := 0
for r := range c.contents {
// `0` or negatives are set as minimum
if c.contents[r].Offsets.Percent < 1 {
total += 1
} else {
total += c.contents[r].Offsets.Percent
}
}
carry := 0
// push around containers
for r := range c.contents {
ratio := (float64(c.contents[r].Offsets.Percent) / float64(total))
w := int(float64(c.w) * ratio)
h := c.h
x := c.x + carry
y := c.y
carry += w
// and add any remaining space to the last container
if r == len(c.contents)-1 {
w += (c.w - carry)
}
c.contents[r].Container.SetSize(x, y, h, w)
}
} else if c.layoutMethod == LayoutVerticalPercent {
// first, work out overall distribution
total := 0
for r := range c.contents {
// `0` or negatives are set as minimum
if c.contents[r].Offsets.Percent < 1 {
total += 1
} else {
total += c.contents[r].Offsets.Percent
}
}
carry := 0
// push around containers
for r := range c.contents {
ratio := (float64(c.contents[r].Offsets.Percent) / float64(total))
w := c.w
h := int(float64(c.h) * ratio)
x := c.x
y := c.y + carry
carry += h
// and add any remaining space to the last container
if r == len(c.contents)-1 {
h += (c.h - carry)
}
c.contents[r].Container.SetSize(x, y, h, w)
}
} else { } else {
for r := range c.contents { for r := range c.contents {
x := c.x + c.contents[r].Offsets.Left x := c.x + c.contents[r].Offsets.Left

View File

@ -55,6 +55,7 @@ func TestContainerTwoBoxesHStack(t *testing.T) {
t.Fail() t.Fail()
} }
} }
func TestContainerThreeBoxesUnevenHStack(t *testing.T) { func TestContainerThreeBoxesUnevenHStack(t *testing.T) {
expect := ` one two three expect := ` one two three
@ -82,6 +83,34 @@ func TestContainerThreeBoxesUnevenHStack(t *testing.T) {
} }
} }
func TestContainerTwoBoxesHPercentStack(t *testing.T) {
expect := ` one two
`
m := &MockScreen{}
one := NewBox("one", nil, Contents{})
two := NewBox("two", nil, Contents{})
container := NewContainer(
Contents{
{Container: one, Offsets: Offsets{Percent: 2}},
{Container: two, Offsets: Offsets{Percent: 1}}},
LayoutHorizontalPercent,
)
m.Init()
m.Resize(0, 0, 5, 22)
container.SetSize(0, 0, 5, 22)
container.Draw(m)
result := m.DumpContents()
if result != expect {
fmt.Printf("expected:\n%+v", expect)
fmt.Printf("actual:\n%+v", result)
t.Fail()
}
}
func TestContainerTwoBoxesVStack(t *testing.T) { func TestContainerTwoBoxesVStack(t *testing.T) {
expect := ` one expect := ` one
@ -112,3 +141,36 @@ func TestContainerTwoBoxesVStack(t *testing.T) {
t.Fail() t.Fail()
} }
} }
func TestContainerTwoBoxesPercentageVStack(t *testing.T) {
expect := ` one
two
`
m := &MockScreen{}
one := NewBox("one", nil, Contents{})
two := NewBox("two", nil, Contents{})
container := NewContainer(
Contents{
{Container: one, Offsets: Offsets{Percent: 2}},
{Container: two, Offsets: Offsets{Percent: 1}}},
LayoutVerticalPercent,
)
m.Init()
m.Resize(0, 0, 10, 10)
container.SetSize(0, 0, 10, 10)
container.Draw(m)
result := m.DumpContents()
if result != expect {
fmt.Printf("expected:\n%+v", expect)
fmt.Printf("actual:\n%+v", result)
t.Fail()
}
}