mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 18:05:35 +00:00
ui: switch to (more) explicit layout
The layout package switched from interfaces to functions for composing layouts. The switch made sure that no garbage is generated for transient layouts such as Align, Inset, Stack, Flex. Unfortunately, that left the stateful widgets and layouts: as soon as their layout methods are embedded in a transient layout, a closure is generated that escapes to the heap. To avoid garbage for both transient as well as stateful widgets, replace the functional approach with explicit begin/end methods. A begin method generally starts an op block and returns the adjusted constraints. An end method takes computed dimensions, ends its op block and returns adjusted dimensions. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+43
-25
@@ -10,13 +10,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Flex struct {
|
type Flex struct {
|
||||||
Constraints Constraints
|
|
||||||
|
|
||||||
Axis Axis
|
Axis Axis
|
||||||
MainAxisAlignment MainAxisAlignment
|
MainAxisAlignment MainAxisAlignment
|
||||||
CrossAxisAlignment CrossAxisAlignment
|
CrossAxisAlignment CrossAxisAlignment
|
||||||
MainAxisSize MainAxisSize
|
MainAxisSize MainAxisSize
|
||||||
|
|
||||||
|
constrained bool
|
||||||
|
cs Constraints
|
||||||
|
begun bool
|
||||||
taken int
|
taken int
|
||||||
maxCross int
|
maxCross int
|
||||||
maxBaseline int
|
maxBaseline int
|
||||||
@@ -56,29 +57,42 @@ const (
|
|||||||
Stretch
|
Stretch
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f *Flex) Rigid(ops *ui.Ops, w Widget) FlexChild {
|
func (f *Flex) Init(cs Constraints) {
|
||||||
mainc := axisMainConstraint(f.Axis, f.Constraints)
|
if f.constrained {
|
||||||
|
panic("Constrain must be called exactly once")
|
||||||
|
}
|
||||||
|
f.constrained = true
|
||||||
|
f.cs = cs
|
||||||
|
f.taken = 0
|
||||||
|
f.maxCross = 0
|
||||||
|
f.maxBaseline = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Flex) begin(ops *ui.Ops) {
|
||||||
|
if !f.constrained {
|
||||||
|
panic("must Constrain before adding a child")
|
||||||
|
}
|
||||||
|
if f.begun {
|
||||||
|
panic("must End before adding a child")
|
||||||
|
}
|
||||||
|
f.begun = true
|
||||||
|
ops.Begin()
|
||||||
|
ui.OpLayer{}.Add(ops)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Flex) Rigid(ops *ui.Ops) Constraints {
|
||||||
|
f.begin(ops)
|
||||||
|
mainc := axisMainConstraint(f.Axis, f.cs)
|
||||||
mainMax := mainc.Max
|
mainMax := mainc.Max
|
||||||
if mainc.Max != ui.Inf {
|
if mainc.Max != ui.Inf {
|
||||||
mainMax -= f.taken
|
mainMax -= f.taken
|
||||||
}
|
}
|
||||||
cs := axisConstraints(f.Axis, Constraint{Max: mainMax}, f.crossConstraintChild(f.Constraints))
|
return axisConstraints(f.Axis, Constraint{Max: mainMax}, f.crossConstraintChild(f.cs))
|
||||||
ops.Begin()
|
|
||||||
ui.OpLayer{}.Add(ops)
|
|
||||||
dims := w(ops, cs)
|
|
||||||
block := ops.End()
|
|
||||||
f.taken += axisMain(f.Axis, dims.Size)
|
|
||||||
if c := axisCross(f.Axis, dims.Size); c > f.maxCross {
|
|
||||||
f.maxCross = c
|
|
||||||
}
|
|
||||||
if b := dims.Baseline; b > f.maxBaseline {
|
|
||||||
f.maxBaseline = b
|
|
||||||
}
|
|
||||||
return FlexChild{block, dims}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flex) Flexible(ops *ui.Ops, flex float32, mode FlexMode, w Widget) FlexChild {
|
func (f *Flex) Flexible(ops *ui.Ops, flex float32, mode FlexMode) Constraints {
|
||||||
mainc := axisMainConstraint(f.Axis, f.Constraints)
|
f.begin(ops)
|
||||||
|
mainc := axisMainConstraint(f.Axis, f.cs)
|
||||||
var flexSize int
|
var flexSize int
|
||||||
if mainc.Max != ui.Inf && mainc.Max > f.taken {
|
if mainc.Max != ui.Inf && mainc.Max > f.taken {
|
||||||
flexSize = mainc.Max - f.taken
|
flexSize = mainc.Max - f.taken
|
||||||
@@ -87,10 +101,14 @@ func (f *Flex) Flexible(ops *ui.Ops, flex float32, mode FlexMode, w Widget) Flex
|
|||||||
if mode == Fit {
|
if mode == Fit {
|
||||||
submainc.Min = submainc.Max
|
submainc.Min = submainc.Max
|
||||||
}
|
}
|
||||||
cs := axisConstraints(f.Axis, submainc, f.crossConstraintChild(f.Constraints))
|
return axisConstraints(f.Axis, submainc, f.crossConstraintChild(f.cs))
|
||||||
ops.Begin()
|
}
|
||||||
ui.OpLayer{}.Add(ops)
|
|
||||||
dims := w(ops, cs)
|
func (f *Flex) End(ops *ui.Ops, dims Dimens) FlexChild {
|
||||||
|
if !f.begun {
|
||||||
|
panic("End called without an active child")
|
||||||
|
}
|
||||||
|
f.begun = false
|
||||||
block := ops.End()
|
block := ops.End()
|
||||||
f.taken += axisMain(f.Axis, dims.Size)
|
f.taken += axisMain(f.Axis, dims.Size)
|
||||||
if c := axisCross(f.Axis, dims.Size); c > f.maxCross {
|
if c := axisCross(f.Axis, dims.Size); c > f.maxCross {
|
||||||
@@ -103,8 +121,8 @@ func (f *Flex) Flexible(ops *ui.Ops, flex float32, mode FlexMode, w Widget) Flex
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flex) Layout(ops *ui.Ops, children ...FlexChild) Dimens {
|
func (f *Flex) Layout(ops *ui.Ops, children ...FlexChild) Dimens {
|
||||||
mainc := axisMainConstraint(f.Axis, f.Constraints)
|
mainc := axisMainConstraint(f.Axis, f.cs)
|
||||||
crossSize := axisCrossConstraint(f.Axis, f.Constraints).Constrain(f.maxCross)
|
crossSize := axisCrossConstraint(f.Axis, f.cs).Constrain(f.maxCross)
|
||||||
var space int
|
var space int
|
||||||
if mainc.Max != ui.Inf && f.MainAxisSize == Max {
|
if mainc.Max != ui.Inf && f.MainAxisSize == Max {
|
||||||
if mainc.Max > f.taken {
|
if mainc.Max > f.taken {
|
||||||
|
|||||||
+25
-19
@@ -9,8 +9,6 @@ import (
|
|||||||
"gioui.org/ui"
|
"gioui.org/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Widget func(ops *ui.Ops, cs Constraints) Dimens
|
|
||||||
|
|
||||||
type Constraints struct {
|
type Constraints struct {
|
||||||
Width Constraint
|
Width Constraint
|
||||||
Height Constraint
|
Height Constraint
|
||||||
@@ -70,12 +68,13 @@ func ExactConstraints(size image.Point) Constraints {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Insets struct {
|
type Insets struct {
|
||||||
C Widget
|
|
||||||
|
|
||||||
Top, Right, Bottom, Left float32
|
Top, Right, Bottom, Left float32
|
||||||
|
|
||||||
|
cs Constraints
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in Insets) W(ops *ui.Ops, cs Constraints) Dimens {
|
func (in *Insets) Begin(ops *ui.Ops, cs Constraints) Constraints {
|
||||||
|
in.cs = cs
|
||||||
mcs := cs
|
mcs := cs
|
||||||
t, r, b, l := int(math.Round(float64(in.Top))), int(math.Round(float64(in.Right))), int(math.Round(float64(in.Bottom))), int(math.Round(float64(in.Left)))
|
t, r, b, l := int(math.Round(float64(in.Top))), int(math.Round(float64(in.Right))), int(math.Round(float64(in.Bottom))), int(math.Round(float64(in.Left)))
|
||||||
if mcs.Width.Max != ui.Inf {
|
if mcs.Width.Max != ui.Inf {
|
||||||
@@ -100,16 +99,20 @@ func (in Insets) W(ops *ui.Ops, cs Constraints) Dimens {
|
|||||||
}
|
}
|
||||||
ops.Begin()
|
ops.Begin()
|
||||||
ui.OpTransform{Transform: ui.Offset(toPointF(image.Point{X: l, Y: t}))}.Add(ops)
|
ui.OpTransform{Transform: ui.Offset(toPointF(image.Point{X: l, Y: t}))}.Add(ops)
|
||||||
dims := in.C(ops, mcs)
|
return mcs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (in *Insets) End(ops *ui.Ops, dims Dimens) Dimens {
|
||||||
ops.End().Add(ops)
|
ops.End().Add(ops)
|
||||||
|
t, r, b, l := int(math.Round(float64(in.Top))), int(math.Round(float64(in.Right))), int(math.Round(float64(in.Bottom))), int(math.Round(float64(in.Left)))
|
||||||
return Dimens{
|
return Dimens{
|
||||||
Size: cs.Constrain(dims.Size.Add(image.Point{X: r + l, Y: t + b})),
|
Size: in.cs.Constrain(dims.Size.Add(image.Point{X: r + l, Y: t + b})),
|
||||||
Baseline: dims.Baseline + t,
|
Baseline: dims.Baseline + t,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func EqualInsets(v float32, w Widget) Insets {
|
func EqualInsets(v float32) Insets {
|
||||||
return Insets{C: w, Top: v, Right: v, Bottom: v, Left: v}
|
return Insets{Top: v, Right: v, Bottom: v, Left: v}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isInf(v ui.Value) bool {
|
func isInf(v ui.Value) bool {
|
||||||
@@ -117,11 +120,10 @@ func isInf(v ui.Value) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Sized struct {
|
type Sized struct {
|
||||||
C Widget
|
|
||||||
Width, Height float32
|
Width, Height float32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Sized) W(ops *ui.Ops, cs Constraints) Dimens {
|
func (s Sized) Constrain(cs Constraints) Constraints {
|
||||||
if h := int(s.Height + 0.5); h != 0 {
|
if h := int(s.Height + 0.5); h != 0 {
|
||||||
if cs.Height.Min < h {
|
if cs.Height.Min < h {
|
||||||
cs.Height.Min = h
|
cs.Height.Min = h
|
||||||
@@ -138,24 +140,28 @@ func (s Sized) W(ops *ui.Ops, cs Constraints) Dimens {
|
|||||||
cs.Width.Max = w
|
cs.Width.Max = w
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s.C(ops, cs)
|
return cs
|
||||||
}
|
}
|
||||||
|
|
||||||
type Align struct {
|
type Align struct {
|
||||||
C Widget
|
|
||||||
Alignment Direction
|
Alignment Direction
|
||||||
|
cs Constraints
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a Align) W(ops *ui.Ops, cs Constraints) Dimens {
|
func (a *Align) Begin(ops *ui.Ops, cs Constraints) Constraints {
|
||||||
|
a.cs = cs
|
||||||
ops.Begin()
|
ops.Begin()
|
||||||
dims := a.C(ops, cs.Loose())
|
return cs.Loose()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Align) End(ops *ui.Ops, dims Dimens) Dimens {
|
||||||
block := ops.End()
|
block := ops.End()
|
||||||
sz := dims.Size
|
sz := dims.Size
|
||||||
if cs.Width.Max != ui.Inf {
|
if a.cs.Width.Max != ui.Inf {
|
||||||
sz.X = cs.Width.Max
|
sz.X = a.cs.Width.Max
|
||||||
}
|
}
|
||||||
if cs.Height.Max != ui.Inf {
|
if a.cs.Height.Max != ui.Inf {
|
||||||
sz.Y = cs.Height.Max
|
sz.Y = a.cs.Height.Max
|
||||||
}
|
}
|
||||||
var p image.Point
|
var p image.Point
|
||||||
switch a.Alignment {
|
switch a.Alignment {
|
||||||
|
|||||||
+47
-45
@@ -31,31 +31,31 @@ type List struct {
|
|||||||
offset int
|
offset int
|
||||||
first int
|
first int
|
||||||
|
|
||||||
ops *ui.Ops
|
|
||||||
cs Constraints
|
cs Constraints
|
||||||
len int
|
len int
|
||||||
|
|
||||||
maxSize int
|
maxSize int
|
||||||
children []scrollChild
|
children []scrollChild
|
||||||
elemForward bool
|
dir iterationDir
|
||||||
|
|
||||||
size image.Point
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) Init(ops *ui.Ops, cs Constraints, len int) (int, bool) {
|
type iterationDir uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
iterateNone iterationDir = iota
|
||||||
|
iterateForward
|
||||||
|
iterateBackward
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *List) Init(cs Constraints, len int) {
|
||||||
|
l.dir = iterateNone
|
||||||
l.maxSize = 0
|
l.maxSize = 0
|
||||||
l.children = l.children[:0]
|
l.children = l.children[:0]
|
||||||
l.ops = ops
|
|
||||||
l.cs = cs
|
l.cs = cs
|
||||||
l.len = len
|
l.len = len
|
||||||
if l.first > len {
|
if l.first > len {
|
||||||
l.first = len
|
l.first = len
|
||||||
}
|
}
|
||||||
if len == 0 {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
l.scroll.Op(ops, &l.area)
|
|
||||||
return l.Index()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) Dragging() bool {
|
func (l *List) Dragging() bool {
|
||||||
@@ -70,24 +70,28 @@ func (l *List) Scroll(c *ui.Config, q pointer.Events) {
|
|||||||
l.offset += d
|
l.offset += d
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) Index() (int, bool) {
|
func (l *List) Next(ops *ui.Ops) (int, Constraints, bool) {
|
||||||
i, ok := l.next()
|
if l.dir != iterateNone {
|
||||||
if !ok {
|
panic("a previous Next was not finished with Elem")
|
||||||
l.draw()
|
|
||||||
}
|
}
|
||||||
return i, ok
|
i, ok := l.next()
|
||||||
}
|
var cs Constraints
|
||||||
|
if ok {
|
||||||
func (l *List) Layout() Dimens {
|
if len(l.children) == 0 {
|
||||||
l.area.Size = l.size
|
l.scroll.Op(ops, &l.area)
|
||||||
return Dimens{Size: l.size}
|
}
|
||||||
|
cs = axisConstraints(l.Axis, Constraint{Max: ui.Inf}, l.crossConstraintChild(l.cs))
|
||||||
|
ops.Begin()
|
||||||
|
ui.OpLayer{}.Add(ops)
|
||||||
|
}
|
||||||
|
return i, cs, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) next() (int, bool) {
|
func (l *List) next() (int, bool) {
|
||||||
mainc := axisMainConstraint(l.Axis, l.cs)
|
mainc := axisMainConstraint(l.Axis, l.cs)
|
||||||
if l.offset <= 0 {
|
if l.offset <= 0 {
|
||||||
if l.first > 0 {
|
if l.first > 0 {
|
||||||
l.elemForward = false
|
l.dir = iterateBackward
|
||||||
return l.first - 1, true
|
return l.first - 1, true
|
||||||
}
|
}
|
||||||
l.offset = 0
|
l.offset = 0
|
||||||
@@ -95,7 +99,7 @@ func (l *List) next() (int, bool) {
|
|||||||
if l.maxSize-l.offset < mainc.Max {
|
if l.maxSize-l.offset < mainc.Max {
|
||||||
i := l.first + len(l.children)
|
i := l.first + len(l.children)
|
||||||
if i < l.len {
|
if i < l.len {
|
||||||
l.elemForward = true
|
l.dir = iterateForward
|
||||||
return i, true
|
return i, true
|
||||||
}
|
}
|
||||||
missing := mainc.Max - (l.maxSize - l.offset)
|
missing := mainc.Max - (l.maxSize - l.offset)
|
||||||
@@ -107,31 +111,27 @@ func (l *List) next() (int, bool) {
|
|||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) Elem(w Widget) {
|
func (l *List) End(ops *ui.Ops, dims Dimens) {
|
||||||
child := l.add(w)
|
block := ops.End()
|
||||||
if l.elemForward {
|
child := scrollChild{dims.Size, block}
|
||||||
|
switch l.dir {
|
||||||
|
case iterateForward:
|
||||||
mainSize := axisMain(l.Axis, child.size)
|
mainSize := axisMain(l.Axis, child.size)
|
||||||
l.maxSize += mainSize
|
l.maxSize += mainSize
|
||||||
l.children = append(l.children, child)
|
l.children = append(l.children, child)
|
||||||
} else {
|
case iterateBackward:
|
||||||
l.first--
|
l.first--
|
||||||
mainSize := axisMain(l.Axis, child.size)
|
mainSize := axisMain(l.Axis, child.size)
|
||||||
l.offset += mainSize
|
l.offset += mainSize
|
||||||
l.maxSize += mainSize
|
l.maxSize += mainSize
|
||||||
l.children = append([]scrollChild{child}, l.children...)
|
l.children = append([]scrollChild{child}, l.children...)
|
||||||
|
default:
|
||||||
|
panic("call Next before End")
|
||||||
}
|
}
|
||||||
|
l.dir = iterateNone
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) add(w Widget) scrollChild {
|
func (l *List) Layout(ops *ui.Ops) Dimens {
|
||||||
subcs := axisConstraints(l.Axis, Constraint{Max: ui.Inf}, l.crossConstraintChild(l.cs))
|
|
||||||
l.ops.Begin()
|
|
||||||
ui.OpLayer{}.Add(l.ops)
|
|
||||||
dims := w(l.ops, subcs)
|
|
||||||
block := l.ops.End()
|
|
||||||
return scrollChild{dims.Size, block}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) draw() {
|
|
||||||
mainc := axisMainConstraint(l.Axis, l.cs)
|
mainc := axisMainConstraint(l.Axis, l.cs)
|
||||||
for len(l.children) > 0 {
|
for len(l.children) > 0 {
|
||||||
sz := l.children[0].size
|
sz := l.children[0].size
|
||||||
@@ -178,13 +178,13 @@ func (l *List) draw() {
|
|||||||
Min: axisPoint(l.Axis, min, -ui.Inf),
|
Min: axisPoint(l.Axis, min, -ui.Inf),
|
||||||
Max: axisPoint(l.Axis, max, ui.Inf),
|
Max: axisPoint(l.Axis, max, ui.Inf),
|
||||||
}
|
}
|
||||||
l.ops.Begin()
|
ops.Begin()
|
||||||
draw.OpClip{Path: draw.RectPath(r)}.Add(l.ops)
|
draw.OpClip{Path: draw.RectPath(r)}.Add(ops)
|
||||||
ui.OpTransform{
|
ui.OpTransform{
|
||||||
Transform: ui.Offset(toPointF(axisPoint(l.Axis, pos, cross))),
|
Transform: ui.Offset(toPointF(axisPoint(l.Axis, pos, cross))),
|
||||||
}.Add(l.ops)
|
}.Add(ops)
|
||||||
child.block.Add(l.ops)
|
child.block.Add(ops)
|
||||||
l.ops.End().Add(l.ops)
|
ops.End().Add(ops)
|
||||||
pos += axisMain(l.Axis, sz)
|
pos += axisMain(l.Axis, sz)
|
||||||
}
|
}
|
||||||
atStart := l.first == 0 && l.offset <= 0
|
atStart := l.first == 0 && l.offset <= 0
|
||||||
@@ -192,7 +192,9 @@ func (l *List) draw() {
|
|||||||
if atStart && l.scrollDir < 0 || atEnd && l.scrollDir > 0 {
|
if atStart && l.scrollDir < 0 || atEnd && l.scrollDir > 0 {
|
||||||
l.scroll.Stop()
|
l.scroll.Stop()
|
||||||
}
|
}
|
||||||
l.size = axisPoint(l.Axis, mainc.Constrain(pos), maxCross)
|
dims := axisPoint(l.Axis, mainc.Constrain(pos), maxCross)
|
||||||
|
l.area.Size = dims
|
||||||
|
return Dimens{Size: dims}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *List) crossConstraintChild(cs Constraints) Constraint {
|
func (l *List) crossConstraintChild(cs Constraints) Constraint {
|
||||||
|
|||||||
+41
-24
@@ -9,11 +9,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Stack struct {
|
type Stack struct {
|
||||||
Alignment Direction
|
Alignment Direction
|
||||||
Constraints Constraints
|
|
||||||
|
|
||||||
maxSZ image.Point
|
constrained bool
|
||||||
baseline int
|
cs Constraints
|
||||||
|
begun bool
|
||||||
|
maxSZ image.Point
|
||||||
|
baseline int
|
||||||
}
|
}
|
||||||
|
|
||||||
type StackChild struct {
|
type StackChild struct {
|
||||||
@@ -34,10 +36,42 @@ const (
|
|||||||
W
|
W
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Stack) Rigid(ops *ui.Ops, w Widget) StackChild {
|
func (s *Stack) Init(cs Constraints) {
|
||||||
|
s.cs = cs
|
||||||
|
s.constrained = true
|
||||||
|
s.maxSZ = image.Point{}
|
||||||
|
s.baseline = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stack) begin(ops *ui.Ops) {
|
||||||
|
if !s.constrained {
|
||||||
|
panic("must Constrain before adding a child")
|
||||||
|
}
|
||||||
|
if s.begun {
|
||||||
|
panic("must End before adding a child")
|
||||||
|
}
|
||||||
|
s.begun = true
|
||||||
ops.Begin()
|
ops.Begin()
|
||||||
ui.OpLayer{}.Add(ops)
|
ui.OpLayer{}.Add(ops)
|
||||||
dims := w(ops, s.Constraints)
|
}
|
||||||
|
|
||||||
|
func (s *Stack) Rigid(ops *ui.Ops) Constraints {
|
||||||
|
ops.Begin()
|
||||||
|
ui.OpLayer{}.Add(ops)
|
||||||
|
return s.cs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stack) Expand(ops *ui.Ops) Constraints {
|
||||||
|
cs := Constraints{
|
||||||
|
Width: Constraint{Min: s.maxSZ.X, Max: s.maxSZ.X},
|
||||||
|
Height: Constraint{Min: s.maxSZ.Y, Max: s.maxSZ.Y},
|
||||||
|
}
|
||||||
|
ops.Begin()
|
||||||
|
ui.OpLayer{}.Add(ops)
|
||||||
|
return cs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stack) End(ops *ui.Ops, dims Dimens) StackChild {
|
||||||
b := ops.End()
|
b := ops.End()
|
||||||
if w := dims.Size.X; w > s.maxSZ.X {
|
if w := dims.Size.X; w > s.maxSZ.X {
|
||||||
s.maxSZ.X = w
|
s.maxSZ.X = w
|
||||||
@@ -45,29 +79,12 @@ func (s *Stack) Rigid(ops *ui.Ops, w Widget) StackChild {
|
|||||||
if h := dims.Size.Y; h > s.maxSZ.Y {
|
if h := dims.Size.Y; h > s.maxSZ.Y {
|
||||||
s.maxSZ.Y = h
|
s.maxSZ.Y = h
|
||||||
}
|
}
|
||||||
s.addjustBaseline(dims)
|
|
||||||
return StackChild{b, dims}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stack) Expand(ops *ui.Ops, w Widget) StackChild {
|
|
||||||
cs := Constraints{
|
|
||||||
Width: Constraint{Min: s.maxSZ.X, Max: s.maxSZ.X},
|
|
||||||
Height: Constraint{Min: s.maxSZ.Y, Max: s.maxSZ.Y},
|
|
||||||
}
|
|
||||||
ops.Begin()
|
|
||||||
ui.OpLayer{}.Add(ops)
|
|
||||||
dims := w(ops, cs)
|
|
||||||
b := ops.End()
|
|
||||||
s.addjustBaseline(dims)
|
|
||||||
return StackChild{b, dims}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stack) addjustBaseline(dims Dimens) {
|
|
||||||
if s.baseline == 0 {
|
if s.baseline == 0 {
|
||||||
if b := dims.Baseline; b != dims.Size.Y {
|
if b := dims.Baseline; b != dims.Size.Y {
|
||||||
s.baseline = b
|
s.baseline = b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return StackChild{b, dims}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stack) Layout(ops *ui.Ops, children ...StackChild) Dimens {
|
func (s *Stack) Layout(ops *ui.Ops, children ...StackChild) Dimens {
|
||||||
|
|||||||
+1
-1
@@ -128,7 +128,7 @@ func (e *Editor) caretWidth() fixed.Int26_6 {
|
|||||||
return fixed.Int26_6(oneDp * 64)
|
return fixed.Int26_6(oneDp * 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Editor) W(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
func (e *Editor) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
||||||
twoDp := int(e.cfg.Val(ui.Dp(2)) + 0.5)
|
twoDp := int(e.cfg.Val(ui.Dp(2)) + 0.5)
|
||||||
e.padLeft, e.padRight = twoDp, twoDp
|
e.padLeft, e.padRight = twoDp, twoDp
|
||||||
maxWidth := cs.Width.Max
|
maxWidth := cs.Width.Max
|
||||||
|
|||||||
+1
-1
@@ -80,7 +80,7 @@ func (l *lineIterator) Next() (String, f32.Point, bool) {
|
|||||||
return String{}, f32.Point{}, false
|
return String{}, f32.Point{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l Label) W(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
func (l Label) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
||||||
textLayout := l.Face.Layout(l.Text, false, cs.Width.Max)
|
textLayout := l.Face.Layout(l.Text, false, cs.Width.Max)
|
||||||
lines := textLayout.Lines
|
lines := textLayout.Lines
|
||||||
dims := linesDimens(lines)
|
dims := linesDimens(lines)
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ type Image struct {
|
|||||||
Rect image.Rectangle
|
Rect image.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (im Image) W(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
func (im Image) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens {
|
||||||
d := image.Point{X: cs.Width.Max, Y: cs.Height.Max}
|
d := image.Point{X: cs.Width.Max, Y: cs.Height.Max}
|
||||||
if d.X == ui.Inf {
|
if d.X == ui.Inf {
|
||||||
d.X = cs.Width.Min
|
d.X = cs.Width.Min
|
||||||
|
|||||||
Reference in New Issue
Block a user