zntg/ui/spacing.go
Sander Schobers 3ea0d76efb Created unified spacing control.
Build control methods now accept nil as visitor method.
2019-03-12 21:11:43 +01:00

96 lines
2.3 KiB
Go

package ui
import (
"opslag.de/schobers/geom"
)
type Spacing struct {
Proxy
Margin SideLengths
Width *Length
Height *Length
}
func BuildSpacing(content Control, fn func(*Spacing)) *Spacing {
s := &Spacing{}
s.Content = content
if fn != nil {
fn(s)
}
return s
}
func sumLengths(lengths ...float32) (float32, int) {
var fixed float32
var infinite int
for _, l := range lengths {
if geom.IsNaN32(l) {
infinite++
} else {
fixed += l
}
}
return fixed, infinite
}
func addMargin(bounds geom.PointF32, size geom.PointF32, margin SideLengths) geom.RectangleF32 {
var left = margin.Left.Value()
var top = margin.Top.Value()
var w, hor = sumLengths(left, size.X, margin.Right.Value())
var h, ver = sumLengths(top, size.Y, margin.Bottom.Value())
var rem = geom.PtF32(geom.Max32(0, bounds.X-w), geom.Max32(0, bounds.Y-h))
if geom.IsNaN32(left) {
left = rem.X / float32(hor)
} else if rem.X == 0 {
left = (left * bounds.X) / w
}
if geom.IsNaN32(size.X) {
size.X = rem.X / float32(hor)
} else if rem.X == 0 {
size.X = (size.X * bounds.X) / w
} else if hor == 0 { // nothing stretches
size.X += rem.X
}
if geom.IsNaN32(top) {
top = rem.Y / float32(ver)
} else if rem.Y == 0 {
top = (top * bounds.Y) / h
}
if geom.IsNaN32(size.Y) {
size.Y = rem.Y / float32(ver)
} else if rem.Y == 0 {
size.Y = (size.Y * bounds.Y) / h
} else if ver == 0 { // nothing stretches
size.Y += rem.Y
}
return geom.RectF32(left, top, left+size.X, top+size.Y)
}
func (s *Spacing) Arrange(ctx Context, bounds geom.RectangleF32, offset geom.PointF32) {
var size = s.Proxy.DesiredSize(ctx)
var w, h = s.Width.Zero(size.X), s.Height.Zero(size.Y)
var content = addMargin(geom.PtF32(bounds.Dx(), bounds.Dy()), geom.PtF32(w.Value(), h.Value()), s.Margin).Add(bounds.Min)
s.Proxy.Arrange(ctx, content, offset)
}
func (s *Spacing) Center() {
s.Margin.Left = Infinite()
s.Margin.Top = Infinite()
s.Margin.Right = Infinite()
s.Margin.Bottom = Infinite()
}
func (s *Spacing) DesiredSize(ctx Context) geom.PointF32 {
var size = s.Proxy.DesiredSize(ctx)
var w, h = s.Width.Zero(size.X), s.Height.Zero(size.Y)
return geom.PtF32(
s.Margin.Left.Value()+w.Value()+s.Margin.Right.Value(),
s.Margin.Top.Value()+h.Value()+s.Margin.Bottom.Value())
}
func (s *Spacing) SetSize(w, h float32) {
s.Width = Fixed(w)
s.Height = Fixed(h)
}