forked from joejulian/gio
ui/layout: replace implicit begin/end scopes with explicit function scopes
Before this change, layout objects followed a pattern where a
begin method would set up the layout and return a tweaked set
of constraints, and a end method would take the widget dimensions
and return the tweaked dimensions.
As has been pointed out, this process is error prone, because the
scope of the layout objects are not clear and because it is easy
to swap two begins or two ends.
It turns out that it is possible to implement layout with function
scopes in garbage free way. A typical layout changes from
al := layout.Align{Alignment: layout.NE}
cs = al.Begin(ops, cs)
in := layout.Inset{Top: ui.Dp(16)}
cs = in.Begin(c, ops, cs)
txt := fmt.Sprintf("m: %d %s", mallocs, u.profile.Timings)
dims := text.Label{Material: theme.text, Face: u.face(fonts.mono, 10), Text: txt}.Layout(ops, cs)
dims = in.End(dims)
return al.End(dims)
to
al := layout.Align{Alignment: layout.NE}
return al.Layout(ops, cs, func(cs layout.Constraints) layout.Dimensions {
in := layout.Inset{Top: ui.Dp(16)}
return in.Layout(c, ops, cs, func(cs layout.Constraints) layout.Dimensions {
txt := fmt.Sprintf("m: %d %s", mallocs, u.profile.Timings)
return text.Label{Material: theme.text, Face: u.face(fonts.mono, 10), Text: txt}.Layout(ops, cs)
})
})
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+11
-9
@@ -94,21 +94,22 @@ func (f *Flex) begin(mode flexMode) {
|
||||
f.macro.Record(f.ops)
|
||||
}
|
||||
|
||||
// Rigid begins a child and return its constraints. The main axis is constrained
|
||||
// to the range from 0 to the remaining space.
|
||||
func (f *Flex) Rigid() Constraints {
|
||||
// Rigid lays out a widget with the main axis constrained to the range
|
||||
// from 0 to the remaining space.
|
||||
func (f *Flex) Rigid(w Widget) FlexChild {
|
||||
f.begin(modeRigid)
|
||||
mainc := axisMainConstraint(f.Axis, f.cs)
|
||||
mainMax := mainc.Max - f.size
|
||||
if mainMax < 0 {
|
||||
mainMax = 0
|
||||
}
|
||||
return axisConstraints(f.Axis, Constraint{Max: mainMax}, axisCrossConstraint(f.Axis, f.cs))
|
||||
cs := axisConstraints(f.Axis, Constraint{Max: mainMax}, axisCrossConstraint(f.Axis, f.cs))
|
||||
return f.end(w(cs))
|
||||
}
|
||||
|
||||
// Flexible is like Rigid, where the main axis size is also constrained to a
|
||||
// fraction of the space not taken up by Rigid children.
|
||||
func (f *Flex) Flexible(weight float32) Constraints {
|
||||
func (f *Flex) Flexible(weight float32, w Widget) FlexChild {
|
||||
f.begin(modeFlex)
|
||||
mainc := axisMainConstraint(f.Axis, f.cs)
|
||||
var flexSize int
|
||||
@@ -124,12 +125,13 @@ func (f *Flex) Flexible(weight float32) Constraints {
|
||||
}
|
||||
}
|
||||
submainc := Constraint{Max: flexSize}
|
||||
return axisConstraints(f.Axis, submainc, axisCrossConstraint(f.Axis, f.cs))
|
||||
cs := axisConstraints(f.Axis, submainc, axisCrossConstraint(f.Axis, f.cs))
|
||||
return f.end(w(cs))
|
||||
}
|
||||
|
||||
// End a child by specifying its dimensions. Pass the returned layout result
|
||||
// to Layout.
|
||||
func (f *Flex) End(dims Dimensions) FlexChild {
|
||||
func (f *Flex) end(dims Dimensions) FlexChild {
|
||||
if f.mode <= modeBegun {
|
||||
panic("End called without an active child")
|
||||
}
|
||||
@@ -263,9 +265,9 @@ func axisCrossConstraint(a Axis, cs Constraints) Constraint {
|
||||
|
||||
func axisConstraints(a Axis, mainc, crossc Constraint) Constraints {
|
||||
if a == Horizontal {
|
||||
return Constraints{mainc, crossc}
|
||||
return Constraints{Width: mainc, Height: crossc}
|
||||
} else {
|
||||
return Constraints{crossc, mainc}
|
||||
return Constraints{Width: crossc, Height: mainc}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user