mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
layout: change Widget to take explicit Context and return explicit Dimensions
Change the definition of Widget from the implicit
type Widget func()
to the explicit functional
type Widget func(gtx layout.Context) layout.Dimensions
The advantages are numerous:
- Clearer connection between the incoming context and the output dimensions.
- Returning the Dimensions are impossible to omit.
- Contexts passed by value, so its fields can be exported
and freely mutated by the program.
The only disadvantage is the longer function literals and the many "returns".
What tipped the scales in favour of the explicit Widget variant is that type
aliases can dramatically shorten the literals:
type (
C = layout.Context
D = layout.Dimensions
)
widget := func(gtx C) D {
...
}
Note that the aliases are not part of the Gio API and it is up to each user
whether they want to use them.
Finally the Go proposal for lightweight function literals,
https://github.com/golang/go/issues/21498, may remove the disadvantage
completely in future.
Context becomes a plain struct with only public fields, and its Reset is
replaced by a NewContext convenience constructor.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+51
-34
@@ -5,24 +5,29 @@ import (
|
||||
"image"
|
||||
|
||||
"gioui.org/layout"
|
||||
"gioui.org/op"
|
||||
"gioui.org/unit"
|
||||
)
|
||||
|
||||
func ExampleInset() {
|
||||
gtx := new(layout.Context)
|
||||
gtx.Reset(nil, nil, image.Point{X: 100, Y: 100})
|
||||
// Loose constraints with no minimal size.
|
||||
gtx.Constraints.Min = image.Point{}
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
// Loose constraints with no minimal size.
|
||||
Constraints: layout.Constraints{
|
||||
Max: image.Point{X: 100, Y: 100},
|
||||
},
|
||||
}
|
||||
|
||||
// Inset all edges by 10.
|
||||
inset := layout.UniformInset(unit.Dp(10))
|
||||
inset.Layout(gtx, func() {
|
||||
dims := inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
// Lay out a 50x50 sized widget.
|
||||
layoutWidget(gtx, 50, 50)
|
||||
fmt.Println(gtx.Dimensions.Size)
|
||||
dims := layoutWidget(gtx, 50, 50)
|
||||
fmt.Println(dims.Size)
|
||||
return dims
|
||||
})
|
||||
|
||||
fmt.Println(gtx.Dimensions.Size)
|
||||
fmt.Println(dims.Size)
|
||||
|
||||
// Output:
|
||||
// (50,50)
|
||||
@@ -30,17 +35,20 @@ func ExampleInset() {
|
||||
}
|
||||
|
||||
func ExampleDirection() {
|
||||
gtx := new(layout.Context)
|
||||
// Rigid constraints with both minimum and maximum set.
|
||||
gtx.Reset(nil, nil, image.Point{X: 100, Y: 100})
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
// Rigid constraints with both minimum and maximum set.
|
||||
Constraints: layout.Exact(image.Point{X: 100, Y: 100}),
|
||||
}
|
||||
|
||||
layout.Center.Layout(gtx, func() {
|
||||
dims := layout.Center.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
// Lay out a 50x50 sized widget.
|
||||
layoutWidget(gtx, 50, 50)
|
||||
fmt.Println(gtx.Dimensions.Size)
|
||||
dims := layoutWidget(gtx, 50, 50)
|
||||
fmt.Println(dims.Size)
|
||||
return dims
|
||||
})
|
||||
|
||||
fmt.Println(gtx.Dimensions.Size)
|
||||
fmt.Println(dims.Size)
|
||||
|
||||
// Output:
|
||||
// (50,50)
|
||||
@@ -48,19 +56,22 @@ func ExampleDirection() {
|
||||
}
|
||||
|
||||
func ExampleFlex() {
|
||||
gtx := new(layout.Context)
|
||||
gtx.Reset(nil, nil, image.Point{X: 100, Y: 100})
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
// Rigid constraints with both minimum and maximum set.
|
||||
Constraints: layout.Exact(image.Point{X: 100, Y: 100}),
|
||||
}
|
||||
|
||||
layout.Flex{}.Layout(gtx,
|
||||
// Rigid 10x10 widget.
|
||||
layout.Rigid(func() {
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
fmt.Printf("Rigid: %v\n", gtx.Constraints)
|
||||
layoutWidget(gtx, 10, 10)
|
||||
return layoutWidget(gtx, 10, 10)
|
||||
}),
|
||||
// Child with 50% space allowance.
|
||||
layout.Flexed(0.5, func() {
|
||||
layout.Flexed(0.5, func(gtx layout.Context) layout.Dimensions {
|
||||
fmt.Printf("50%%: %v\n", gtx.Constraints)
|
||||
layoutWidget(gtx, 10, 10)
|
||||
return layoutWidget(gtx, 10, 10)
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -70,19 +81,22 @@ func ExampleFlex() {
|
||||
}
|
||||
|
||||
func ExampleStack() {
|
||||
gtx := new(layout.Context)
|
||||
gtx.Reset(nil, nil, image.Point{X: 100, Y: 100})
|
||||
gtx.Constraints.Min = image.Point{}
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
Constraints: layout.Constraints{
|
||||
Max: image.Point{X: 100, Y: 100},
|
||||
},
|
||||
}
|
||||
|
||||
layout.Stack{}.Layout(gtx,
|
||||
// Force widget to the same size as the second.
|
||||
layout.Expanded(func() {
|
||||
layout.Expanded(func(gtx layout.Context) layout.Dimensions {
|
||||
fmt.Printf("Expand: %v\n", gtx.Constraints)
|
||||
layoutWidget(gtx, 10, 10)
|
||||
return layoutWidget(gtx, 10, 10)
|
||||
}),
|
||||
// Rigid 50x50 widget.
|
||||
layout.Stacked(func() {
|
||||
layoutWidget(gtx, 50, 50)
|
||||
layout.Stacked(func(gtx layout.Context) layout.Dimensions {
|
||||
return layoutWidget(gtx, 50, 50)
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -91,17 +105,20 @@ func ExampleStack() {
|
||||
}
|
||||
|
||||
func ExampleList() {
|
||||
gtx := new(layout.Context)
|
||||
gtx.Reset(nil, nil, image.Point{X: 100, Y: 100})
|
||||
gtx := layout.Context{
|
||||
Ops: new(op.Ops),
|
||||
// Rigid constraints with both minimum and maximum set.
|
||||
Constraints: layout.Exact(image.Point{X: 100, Y: 100}),
|
||||
}
|
||||
|
||||
// The list is 1e6 elements, but only 5 fit the constraints.
|
||||
const listLen = 1e6
|
||||
|
||||
var list layout.List
|
||||
count := 0
|
||||
list.Layout(gtx, listLen, func(i int) {
|
||||
list.Layout(gtx, listLen, func(gtx layout.Context, i int) layout.Dimensions {
|
||||
count++
|
||||
layoutWidget(gtx, 20, 20)
|
||||
return layoutWidget(gtx, 20, 20)
|
||||
})
|
||||
|
||||
fmt.Println(count)
|
||||
@@ -110,8 +127,8 @@ func ExampleList() {
|
||||
// 5
|
||||
}
|
||||
|
||||
func layoutWidget(ctx *layout.Context, width, height int) {
|
||||
ctx.Dimensions = layout.Dimensions{
|
||||
func layoutWidget(ctx layout.Context, width, height int) layout.Dimensions {
|
||||
return layout.Dimensions{
|
||||
Size: image.Point{
|
||||
X: width,
|
||||
Y: height,
|
||||
|
||||
Reference in New Issue
Block a user