Files
gio/ui/layout/stack.go
T
Elias Naur 1a15d7241a ui/layout: rename and sanitize enums
Rename MainAxisAlignment to Spacing and CrossAxisAlignment to just
Alignment.

Drop the untyped Start, End, Center values and add them as Spacing
and Direction values. Center is both a Direction and Alignment, so
use the synonym "Middle" for the alignment.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2019-08-10 12:29:17 +02:00

109 lines
1.8 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
}
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
}
var stack ui.StackOp
stack.Push(s.ops)
ui.TransformOp{}.Offset(toPointF(p)).Add(s.ops)
ch.macro.Add(s.ops)
stack.Pop()
}
b := s.baseline
if b == 0 {
b = s.maxSZ.Y
}
return Dimens{
Size: s.maxSZ,
Baseline: b,
}
}