Files
gio/ui/layout/stack.go
T
Elias Naur 94a913a371 ui: move macro recording from Ops to MacroOp
Move the Record and Stop methods from Ops to MacroOp itself.

Before this change, Ops.Stop stopped the recording of the most
recent macro, which could be a different macro than intended.
After this change, there is no such confusion.

As a bonus, the Ops API becomes less cluttered.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2019-07-16 13:21:51 +02:00

121 lines
1.9 KiB
Go

// SPDX-License-Identifier: Unlicense OR MIT
package layout
import (
"image"
"gioui.org/ui"
)
type Stack struct {
Alignment Direction
macro ui.MacroOp
ops *ui.Ops
constrained bool
cs Constraints
begun bool
maxSZ image.Point
baseline int
}
type StackChild struct {
macro ui.MacroOp
dims Dimens
}
type Direction uint8
const (
NW Direction = iota
N
NE
E
SE
S
SW
W
)
func (s *Stack) Init(ops *ui.Ops, cs Constraints) *Stack {
s.ops = ops
s.cs = cs
s.constrained = true
s.maxSZ = image.Point{}
s.baseline = 0
return s
}
func (s *Stack) begin() {
if !s.constrained {
panic("must Init before adding a child")
}
if s.begun {
panic("must End before adding a child")
}
s.begun = true
s.macro.Record(s.ops)
}
func (s *Stack) Rigid() Constraints {
s.begin()
return s.cs
}
func (s *Stack) Expand() Constraints {
s.begin()
return Constraints{
Width: Constraint{Min: s.maxSZ.X, Max: s.maxSZ.X},
Height: Constraint{Min: s.maxSZ.Y, Max: s.maxSZ.Y},
}
}
func (s *Stack) End(dims Dimens) StackChild {
s.macro.Stop()
s.begun = false
if w := dims.Size.X; w > s.maxSZ.X {
s.maxSZ.X = w
}
if h := dims.Size.Y; h > s.maxSZ.Y {
s.maxSZ.Y = h
}
if s.baseline == 0 {
if b := dims.Baseline; b != dims.Size.Y {
s.baseline = b
}
}
return StackChild{s.macro, dims}
}
func (s *Stack) Layout(children ...StackChild) Dimens {
for _, ch := range children {
sz := ch.dims.Size
var p image.Point
switch s.Alignment {
case N, S, Center:
p.X = (s.maxSZ.X - sz.X) / 2
case NE, SE, E:
p.X = s.maxSZ.X - sz.X
}
switch s.Alignment {
case W, Center, E:
p.Y = (s.maxSZ.Y - sz.Y) / 2
case SW, S, SE:
p.Y = s.maxSZ.Y - sz.Y
}
ui.PushOp{}.Add(s.ops)
ui.TransformOp{Transform: ui.Offset(toPointF(p))}.Add(s.ops)
ch.macro.Add(s.ops)
ui.PopOp{}.Add(s.ops)
}
b := s.baseline
if b == 0 {
b = s.maxSZ.Y
}
return Dimens{
Size: s.maxSZ,
Baseline: b,
}
}