mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 23:55:39 +00:00
a63e0cb44a
op.Offset is a convenience function most often used by layouts. Layouts usually operate in integer coordinates, and the float32 version of op.Offset needlessly force conversions from int to float32. This change makes op.Offset take integer coordinates, to better match its intended use. Signed-off-by: Elias Naur <mail@eliasnaur.com>
121 lines
2.6 KiB
Go
121 lines
2.6 KiB
Go
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
package layout
|
|
|
|
import (
|
|
"image"
|
|
|
|
"gioui.org/op"
|
|
)
|
|
|
|
// Stack lays out child elements on top of each other,
|
|
// according to an alignment direction.
|
|
type Stack struct {
|
|
// Alignment is the direction to align children
|
|
// smaller than the available space.
|
|
Alignment Direction
|
|
}
|
|
|
|
// StackChild represents a child for a Stack layout.
|
|
type StackChild struct {
|
|
expanded bool
|
|
widget Widget
|
|
|
|
// Scratch space.
|
|
call op.CallOp
|
|
dims Dimensions
|
|
}
|
|
|
|
// Stacked returns a Stack child that is laid out with no minimum
|
|
// constraints and the maximum constraints passed to Stack.Layout.
|
|
func Stacked(w Widget) StackChild {
|
|
return StackChild{
|
|
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 Expanded(w Widget) StackChild {
|
|
return StackChild{
|
|
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 Stack) Layout(gtx Context, children ...StackChild) Dimensions {
|
|
var maxSZ image.Point
|
|
// First lay out Stacked children.
|
|
cgtx := gtx
|
|
cgtx.Constraints.Min = image.Point{}
|
|
for i, w := range children {
|
|
if w.expanded {
|
|
continue
|
|
}
|
|
macro := op.Record(gtx.Ops)
|
|
dims := w.widget(cgtx)
|
|
call := macro.Stop()
|
|
if w := dims.Size.X; w > maxSZ.X {
|
|
maxSZ.X = w
|
|
}
|
|
if h := dims.Size.Y; h > maxSZ.Y {
|
|
maxSZ.Y = h
|
|
}
|
|
children[i].call = call
|
|
children[i].dims = dims
|
|
}
|
|
// Then lay out Expanded children.
|
|
for i, w := range children {
|
|
if !w.expanded {
|
|
continue
|
|
}
|
|
macro := op.Record(gtx.Ops)
|
|
cgtx.Constraints.Min = maxSZ
|
|
dims := w.widget(cgtx)
|
|
call := macro.Stop()
|
|
if w := dims.Size.X; w > maxSZ.X {
|
|
maxSZ.X = w
|
|
}
|
|
if h := dims.Size.Y; h > maxSZ.Y {
|
|
maxSZ.Y = h
|
|
}
|
|
children[i].call = call
|
|
children[i].dims = dims
|
|
}
|
|
|
|
maxSZ = gtx.Constraints.Constrain(maxSZ)
|
|
var baseline int
|
|
for _, ch := range children {
|
|
sz := ch.dims.Size
|
|
var p image.Point
|
|
switch s.Alignment {
|
|
case N, S, Center:
|
|
p.X = (maxSZ.X - sz.X) / 2
|
|
case NE, SE, E:
|
|
p.X = maxSZ.X - sz.X
|
|
}
|
|
switch s.Alignment {
|
|
case W, Center, E:
|
|
p.Y = (maxSZ.Y - sz.Y) / 2
|
|
case SW, S, SE:
|
|
p.Y = maxSZ.Y - sz.Y
|
|
}
|
|
trans := op.Offset(p).Push(gtx.Ops)
|
|
ch.call.Add(gtx.Ops)
|
|
trans.Pop()
|
|
if baseline == 0 {
|
|
if b := ch.dims.Baseline; b != 0 {
|
|
baseline = b + maxSZ.Y - sz.Y - p.Y
|
|
}
|
|
}
|
|
}
|
|
return Dimensions{
|
|
Size: maxSZ,
|
|
Baseline: baseline,
|
|
}
|
|
}
|