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]) } }