zntg/ui/dockpanel.go

153 lines
3.4 KiB
Go

package ui
import (
"opslag.de/schobers/geom"
)
type DockPanel interface {
Container
Append(o Dock, children ...Control) error
AppendCreate(ctx Context, o Dock, children ...Control) error
}
type Dock int
const (
DockLeft Dock = iota
DockTop
DockRight
DockBottom
)
type dockPanel struct {
ContainerBase
docks []Dock
}
func NewDockPanel(parent Container) DockPanel {
return &dockPanel{ContainerBase: ContainerBase{parent: parent}}
}
func NewDockPanelContent(parent Container, d Dock, controls ...Control) DockPanel {
var p = NewDockPanel(parent)
for _, c := range controls {
p.Append(d, c)
}
return p
}
func (p *dockPanel) Append(d Dock, children ...Control) error {
for _, child := range children {
p.ContainerBase.Append(child)
p.docks = append(p.docks, d)
}
return nil
}
func (p *dockPanel) AppendCreate(ctx Context, d Dock, children ...Control) error {
for _, child := range children {
err := p.ContainerBase.AppendCreate(ctx, child)
if nil != err {
return err
}
p.docks = append(p.docks, d)
}
return nil
}
func (p *dockPanel) DesiredSize(ctx Context) geom.PointF32 {
var width, height float32 = 0, 0
for i, child := range p.children {
var d = p.docks[i]
var desired = child.DesiredSize(ctx)
switch {
case d == DockLeft || d == DockRight:
if !geom.IsNaN32(width) {
if geom.IsNaN32(desired.X) {
width = desired.X
} else {
width += desired.X
}
}
if !geom.IsNaN32(desired.Y) {
height = geom.Max32(height, desired.Y)
}
case d == DockTop || d == DockBottom:
if !geom.IsNaN32(height) {
if geom.IsNaN32(desired.Y) {
height = desired.Y
} else {
height += desired.Y
}
}
if !geom.IsNaN32(desired.X) {
width = geom.Max32(width, desired.X)
}
}
}
return geom.PtF32(width, height)
}
func (p *dockPanel) arrangeChildren(ctx Context) []geom.RectangleF32 {
var n = len(p.children)
var rects = make([]geom.RectangleF32, n)
var rem = p.Bounds
var last = n - 1
for i, child := range p.children {
if last == i {
rects[i] = rem
} else {
var d = p.docks[i]
var desired = child.DesiredSize(ctx)
var width, height, top, left float32
switch {
case d == DockLeft || d == DockRight:
width = rem.Dx()
if !geom.IsNaN32(desired.X) {
width = geom.Min32(desired.X, width)
}
if d == DockLeft {
left = rem.Min.X
} else {
left = rem.Max.X - width
}
top = rem.Min.Y
height = rem.Dy()
case d == DockTop || d == DockBottom:
height = rem.Dy()
if !geom.IsNaN32(desired.Y) {
height = geom.Min32(desired.Y, height)
}
if d == DockTop {
top = rem.Min.Y
} else {
top = rem.Max.Y - height
}
left = rem.Min.X
width = rem.Dx()
}
rects[i] = geom.RectF32(left, top, left+width, top+height)
switch d {
case DockLeft:
rem = geom.RectF32(rem.Min.X+width, rem.Min.Y, rem.Max.X, rem.Max.Y)
case DockTop:
rem = geom.RectF32(rem.Min.X, rem.Min.Y+height, rem.Max.X, rem.Max.Y)
case DockRight:
rem = geom.RectF32(rem.Min.X, rem.Min.Y, rem.Max.X-width, rem.Max.Y)
case DockBottom:
rem = geom.RectF32(rem.Min.X, rem.Min.Y, rem.Max.X, rem.Max.Y-height)
}
}
}
return rects
}
func (p *dockPanel) Arrange(ctx Context, rect geom.RectangleF32) {
p.ContainerBase.SetRect(rect)
var rects = p.arrangeChildren(ctx)
for i, child := range p.children {
Arrange(ctx, child, rects[i])
}
}