support ratio layouts
This commit is contained in:
parent
78d80aef6c
commit
a6f958ccfb
63
ui/ui.go
63
ui/ui.go
@ -12,10 +12,11 @@ type Drawable interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Offsets struct {
|
type Offsets struct {
|
||||||
Top int
|
Top int
|
||||||
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
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user