From c7e85efc275f5beac7ebcc1d5bee7a7226dc9e82 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 11 Jul 2019 19:03:45 +0200 Subject: [PATCH] ui/layout: ensure that flex weights add to 1 Before this change, the weight applied to the space left, not the total space available after rigid children. While here, ensure that weight sums > 1 are capped to the available space. Signed-off-by: Elias Naur --- ui/layout/flex.go | 68 +++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/ui/layout/flex.go b/ui/layout/flex.go index a54b15ea..bfacbdee 100644 --- a/ui/layout/flex.go +++ b/ui/layout/flex.go @@ -16,10 +16,10 @@ type Flex struct { MainAxisSize MainAxisSize ops *ui.Ops - constrained bool cs Constraints - begun bool - taken int + mode flexMode + size int + rigidSize int maxCross int maxBaseline int } @@ -34,6 +34,8 @@ type MainAxisSize uint8 type MainAxisAlignment uint8 type CrossAxisAlignment uint8 +type flexMode uint8 + const ( Max MainAxisSize = iota Min @@ -52,55 +54,75 @@ const ( Stretch ) +const ( + modeNone flexMode = iota + modeBegun + modeRigid + modeFlex +) + func (f *Flex) Init(ops *ui.Ops, cs Constraints) *Flex { + if f.mode > modeBegun { + panic("must End the current child before calling Init again") + } + f.mode = modeBegun f.ops = ops f.cs = cs - f.constrained = true - f.taken = 0 + f.size = 0 + f.rigidSize = 0 f.maxCross = 0 f.maxBaseline = 0 return f } -func (f *Flex) begin() { - if !f.constrained { +func (f *Flex) begin(mode flexMode) { + switch { + case f.mode == modeNone: panic("must Init before adding a child") - } - if f.begun { + case f.mode > modeBegun: panic("must End before adding a child") } - f.begun = true + f.mode = mode f.ops.Begin() } func (f *Flex) Rigid() Constraints { - f.begin() + f.begin(modeRigid) mainc := axisMainConstraint(f.Axis, f.cs) mainMax := mainc.Max if mainc.Max != ui.Inf { - mainMax -= f.taken + mainMax -= f.size } return axisConstraints(f.Axis, Constraint{Max: mainMax}, f.crossConstraintChild(f.cs)) } func (f *Flex) Flexible(weight float32) Constraints { - f.begin() + f.begin(modeFlex) mainc := axisMainConstraint(f.Axis, f.cs) var flexSize int - if mainc.Max != ui.Inf && mainc.Max > f.taken { - flexSize = mainc.Max - f.taken + if mainc.Max != ui.Inf && mainc.Max > f.size { + maxSize := mainc.Max - f.size + flexSize = mainc.Max - f.rigidSize + flexSize = int(float32(flexSize) * weight) + if flexSize > maxSize { + flexSize = maxSize + } } - submainc := Constraint{Max: int(float32(flexSize) * weight)} + submainc := Constraint{Max: flexSize} return axisConstraints(f.Axis, submainc, f.crossConstraintChild(f.cs)) } func (f *Flex) End(dims Dimens) FlexChild { - if !f.begun { + if f.mode <= modeBegun { panic("End called without an active child") } - f.begun = false block := f.ops.End() - f.taken += axisMain(f.Axis, dims.Size) + sz := axisMain(f.Axis, dims.Size) + f.size += sz + if f.mode == modeRigid { + f.rigidSize += sz + } + f.mode = modeBegun if c := axisCross(f.Axis, dims.Size); c > f.maxCross { f.maxCross = c } @@ -115,11 +137,11 @@ func (f *Flex) Layout(children ...FlexChild) Dimens { crossSize := axisCrossConstraint(f.Axis, f.cs).Constrain(f.maxCross) var space int if mainc.Max != ui.Inf && f.MainAxisSize == Max { - if mainc.Max > f.taken { - space = mainc.Max - f.taken + if mainc.Max > f.size { + space = mainc.Max - f.size } - } else if mainc.Min > f.taken { - space = mainc.Min - f.taken + } else if mainc.Min > f.size { + space = mainc.Min - f.size } var mainSize int var baseline int