/
impl5.go
122 lines (111 loc) · 2.7 KB
/
impl5.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// SPDX-License-Identifier: Unlicense OR MIT
package main
import (
"image"
"gioui.org/layout"
"gioui.org/op"
)
// Stack lays out child elements on top of each other,
// according to an alignment direction.
type Stack5 struct {
// Alignment is the direction to align children
// smaller than the available space.
Alignment layout.Direction
Children []StackChild5
}
// StackChild represents a child for a Stack layout.
type StackChild5 struct {
expanded bool
widget layout.Widget
// Scratch space.
call op.CallOp
dims layout.Dimensions
}
// Stacked returns a Stack child that is laid out with no minimum
// constraints and the maximum constraints passed to Stack.Layout.
func Stacked5(w layout.Widget) StackChild5 {
return StackChild5{
widget: w,
}
}
// Expanded returns a Stack child with the minimum constraints set
// to the largest Stacked child. The maximum constraints are set to
// the same as passed to Stack.Layout.
func Expanded5(w layout.Widget) StackChild5 {
return StackChild5{
expanded: true,
widget: w,
}
}
// Layout a stack of children. The position of the children are
// determined by the specified order, but Stacked children are laid out
// before Expanded children.
func (s Stack5) Layout(gtx layout.Context) layout.Dimensions {
var maxSZ image.Point
// First lay out Stacked children.
cgtx := gtx
cgtx.Constraints.Min = image.Point{}
for i := range s.Children {
w := &s.Children[i]
if w.expanded {
continue
}
macro := op.Record(gtx.Ops)
w.dims = w.widget(cgtx)
w.call = macro.Stop()
if w := w.dims.Size.X; w > maxSZ.X {
maxSZ.X = w
}
if h := w.dims.Size.Y; h > maxSZ.Y {
maxSZ.Y = h
}
}
// Then lay out Expanded children.
for i := range s.Children {
w := &s.Children[i]
if !w.expanded {
continue
}
macro := op.Record(gtx.Ops)
cgtx.Constraints.Min = maxSZ
w.dims = w.widget(cgtx)
w.call = macro.Stop()
if w := w.dims.Size.X; w > maxSZ.X {
maxSZ.X = w
}
if h := w.dims.Size.Y; h > maxSZ.Y {
maxSZ.Y = h
}
}
maxSZ = gtx.Constraints.Constrain(maxSZ)
var baseline int
for i := range s.Children {
w := &s.Children[i]
sz := w.dims.Size
var p image.Point
switch s.Alignment {
case layout.N, layout.S, layout.Center:
p.X = (maxSZ.X - sz.X) / 2
case layout.NE, layout.SE, layout.E:
p.X = maxSZ.X - sz.X
}
switch s.Alignment {
case layout.W, layout.Center, layout.E:
p.Y = (maxSZ.Y - sz.Y) / 2
case layout.SW, layout.S, layout.SE:
p.Y = maxSZ.Y - sz.Y
}
trans := op.Offset(p).Push(gtx.Ops)
w.call.Add(gtx.Ops)
trans.Pop()
if baseline == 0 {
if b := w.dims.Baseline; b != 0 {
baseline = b + maxSZ.Y - sz.Y - p.Y
}
}
}
return layout.Dimensions{
Size: maxSZ,
Baseline: baseline,
}
}