/
row.go
95 lines (86 loc) · 2.7 KB
/
row.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package layout
import (
"gioui.org/layout"
)
// Row lays out a central widget with gutters either side.
// The central widget can be arbitrarily aligned and gutters can have
// supplementary widgets stacked atop them.
type Row struct {
// Margin between rows.
Margin VerticalMarginStyle
// InternalMargin between internal rows.
// Leave unset if you want to control spacing between RowChild individually.
InternalMargin VerticalMarginStyle
// Gutter handles the left-right gutters of the row that provides padding and
// can contain other widgets.
Gutter GutterStyle
// Direction of widgets within this row.
// Typically, non-local widgets are aligned W, and local widgets aligned E.
Direction layout.Direction
}
// RowChild specifies a content widget and two gutter widgets either side.
// RowChild is used to layout composite rows made up of any number of interal
// rows.
type RowChild struct {
Left layout.Widget
Content layout.Widget
Right layout.Widget
Unified bool
}
// FullRow returns a RowChild that lays out content with optional gutter widgets
// either side.
func FullRow(l, w, r layout.Widget) RowChild {
return RowChild{
Left: l,
Content: w,
Right: r,
}
}
// ContentRow returns a RowChild that lays out a content with no gutter widgets.
func ContentRow(w layout.Widget) RowChild {
return RowChild{Content: w}
}
// UnifiedRow ignores gutters, taking up all available space.
func UnifiedRow(w layout.Widget) RowChild {
return RowChild{Content: w, Unified: true}
}
// Layout the Row with any number of internal rows.
func (r Row) Layout(gtx layout.Context, w ...RowChild) layout.Dimensions {
var (
// array is a stack allocated array to avoid heap allocation if number
// of RowChild is small.
// Otherwise, slice append will allocate as needed.
// 16 is a magic number subject to change upon further analysis.
array [4]layout.FlexChild
// slice based on the stack allocated array.
slice = array[0:0]
)
content := func(ii int) layout.Widget {
return func(gtx layout.Context) layout.Dimensions {
if w[ii].Content == nil {
return layout.Dimensions{}
}
return w[ii].Content(gtx)
}
}
for ii := range w {
ii := ii
slice = append(slice, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return r.InternalMargin.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
if w[ii].Unified {
return content(ii)(gtx)
}
return r.Gutter.Layout(gtx,
w[ii].Left,
func(gtx layout.Context) layout.Dimensions {
return r.Direction.Layout(gtx, content(ii))
},
w[ii].Right,
)
})
}))
}
return r.Margin.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx, slice...)
})
}