forked from joejulian/gio
layout: add resize helpers for constraints
This commit adds two helper methods to layout.Contraints that make it easier to manipulate the constraints while keeping their invariants. In particular, code manually manipulating constraints usually fails to correctly ensure that the max does not become smaller than the min, the min does not exceed the max, and that no value goes below zero. It's quite a few lines to check these invariants yourself in every custom layout, so I think it makes sense to offer helpers for this. Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
@@ -102,6 +102,36 @@ func (c Constraints) Constrain(size image.Point) image.Point {
|
|||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddMin returns a copy of Constraints with the Min constraint enlarged by up to delta
|
||||||
|
// while still fitting within the Max constraint. The Max is unchanged, and the Min constraint
|
||||||
|
// will not go negative.
|
||||||
|
func (c Constraints) AddMin(delta image.Point) Constraints {
|
||||||
|
c.Min = c.Min.Add(delta)
|
||||||
|
if c.Min.X < 0 {
|
||||||
|
c.Min.X = 0
|
||||||
|
}
|
||||||
|
if c.Min.Y < 0 {
|
||||||
|
c.Min.Y = 0
|
||||||
|
}
|
||||||
|
c.Min = c.Constrain(c.Min)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubMax returns a copy of Constraints with the Max constraint shrunk by up to delta
|
||||||
|
// while not going negative. The values of delta are expected to be positive.
|
||||||
|
// The Min constraint is adjusted to fit within the new Max constraint.
|
||||||
|
func (c Constraints) SubMax(delta image.Point) Constraints {
|
||||||
|
c.Max = c.Max.Sub(delta)
|
||||||
|
if c.Max.X < 0 {
|
||||||
|
c.Max.X = 0
|
||||||
|
}
|
||||||
|
if c.Max.Y < 0 {
|
||||||
|
c.Max.Y = 0
|
||||||
|
}
|
||||||
|
c.Min = c.Constrain(c.Min)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
// Inset adds space around a widget by decreasing its maximum
|
// Inset adds space around a widget by decreasing its maximum
|
||||||
// constraints. The minimum constraints will be adjusted to ensure
|
// constraints. The minimum constraints will be adjusted to ensure
|
||||||
// they do not exceed the maximum.
|
// they do not exceed the maximum.
|
||||||
|
|||||||
@@ -76,3 +76,69 @@ func TestDirection(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConstraints(t *testing.T) {
|
||||||
|
type testcase struct {
|
||||||
|
name string
|
||||||
|
in Constraints
|
||||||
|
subMax image.Point
|
||||||
|
addMin image.Point
|
||||||
|
expected Constraints
|
||||||
|
}
|
||||||
|
for _, tc := range []testcase{
|
||||||
|
{
|
||||||
|
name: "no-op",
|
||||||
|
in: Constraints{Max: image.Pt(100, 100)},
|
||||||
|
expected: Constraints{Max: image.Pt(100, 100)},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "shrink max",
|
||||||
|
in: Constraints{Max: image.Pt(100, 100)},
|
||||||
|
subMax: image.Pt(25, 25),
|
||||||
|
expected: Constraints{Max: image.Pt(75, 75)},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "shrink max below min",
|
||||||
|
in: Constraints{Max: image.Pt(100, 100), Min: image.Pt(50, 50)},
|
||||||
|
subMax: image.Pt(75, 75),
|
||||||
|
expected: Constraints{Max: image.Pt(25, 25), Min: image.Pt(25, 25)},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "shrink max below zero",
|
||||||
|
in: Constraints{Max: image.Pt(100, 100), Min: image.Pt(50, 50)},
|
||||||
|
subMax: image.Pt(125, 125),
|
||||||
|
expected: Constraints{Max: image.Pt(0, 0), Min: image.Pt(0, 0)},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "enlarge min",
|
||||||
|
in: Constraints{Max: image.Pt(100, 100)},
|
||||||
|
addMin: image.Pt(25, 25),
|
||||||
|
expected: Constraints{Max: image.Pt(100, 100), Min: image.Pt(25, 25)},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "enlarge min beyond max",
|
||||||
|
in: Constraints{Max: image.Pt(100, 100)},
|
||||||
|
addMin: image.Pt(125, 125),
|
||||||
|
expected: Constraints{Max: image.Pt(100, 100), Min: image.Pt(100, 100)},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "decrease min below zero",
|
||||||
|
in: Constraints{Max: image.Pt(100, 100), Min: image.Pt(50, 50)},
|
||||||
|
addMin: image.Pt(-125, -125),
|
||||||
|
expected: Constraints{Max: image.Pt(100, 100), Min: image.Pt(0, 0)},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
start := tc.in
|
||||||
|
if tc.subMax != (image.Point{}) {
|
||||||
|
start = start.SubMax(tc.subMax)
|
||||||
|
}
|
||||||
|
if tc.addMin != (image.Point{}) {
|
||||||
|
start = start.AddMin(tc.addMin)
|
||||||
|
}
|
||||||
|
if start != tc.expected {
|
||||||
|
t.Errorf("expected %#+v, got %#+v", tc.expected, start)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user