2018-08-03 06:46:10 +00:00
|
|
|
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}}
|
|
|
|
}
|
|
|
|
|
2018-09-09 19:07:53 +00:00
|
|
|
func NewDockPanelContent(parent Container, d Dock, controls ...Control) DockPanel {
|
|
|
|
var p = NewDockPanel(parent)
|
|
|
|
for _, c := range controls {
|
|
|
|
p.Append(d, c)
|
|
|
|
}
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2018-08-03 06:46:10 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2018-09-23 07:42:23 +00:00
|
|
|
func (p *dockPanel) DesiredSize(ctx Context) geom.PointF32 {
|
|
|
|
var width, height float32 = 0, 0
|
2018-08-03 06:46:10 +00:00
|
|
|
for i, child := range p.children {
|
|
|
|
var d = p.docks[i]
|
|
|
|
var desired = child.DesiredSize(ctx)
|
|
|
|
switch {
|
|
|
|
case d == DockLeft || d == DockRight:
|
2018-09-23 07:42:23 +00:00
|
|
|
if !geom.IsNaN32(width) {
|
|
|
|
if geom.IsNaN32(desired.X) {
|
2018-08-03 06:46:10 +00:00
|
|
|
width = desired.X
|
|
|
|
} else {
|
|
|
|
width += desired.X
|
|
|
|
}
|
|
|
|
}
|
2018-09-23 07:42:23 +00:00
|
|
|
if !geom.IsNaN32(desired.Y) {
|
|
|
|
height = geom.Max32(height, desired.Y)
|
2018-08-03 06:46:10 +00:00
|
|
|
}
|
|
|
|
case d == DockTop || d == DockBottom:
|
2018-09-23 07:42:23 +00:00
|
|
|
if !geom.IsNaN32(height) {
|
|
|
|
if geom.IsNaN32(desired.Y) {
|
2018-08-03 06:46:10 +00:00
|
|
|
height = desired.Y
|
|
|
|
} else {
|
|
|
|
height += desired.Y
|
|
|
|
}
|
|
|
|
}
|
2018-09-23 07:42:23 +00:00
|
|
|
if !geom.IsNaN32(desired.X) {
|
|
|
|
width = geom.Max32(width, desired.X)
|
2018-08-03 06:46:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-23 07:42:23 +00:00
|
|
|
return geom.PtF32(width, height)
|
2018-08-03 06:46:10 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 07:42:23 +00:00
|
|
|
func (p *dockPanel) arrangeChildren(ctx Context) []geom.RectangleF32 {
|
2018-08-03 06:46:10 +00:00
|
|
|
var n = len(p.children)
|
2018-09-23 07:42:23 +00:00
|
|
|
var rects = make([]geom.RectangleF32, n)
|
2018-08-03 06:46:10 +00:00
|
|
|
|
|
|
|
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)
|
2018-09-23 07:42:23 +00:00
|
|
|
var width, height, top, left float32
|
2018-08-03 06:46:10 +00:00
|
|
|
switch {
|
|
|
|
case d == DockLeft || d == DockRight:
|
|
|
|
width = rem.Dx()
|
2018-09-23 07:42:23 +00:00
|
|
|
if !geom.IsNaN32(desired.X) {
|
|
|
|
width = geom.Min32(desired.X, width)
|
2018-08-03 06:46:10 +00:00
|
|
|
}
|
|
|
|
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()
|
2018-09-23 07:42:23 +00:00
|
|
|
if !geom.IsNaN32(desired.Y) {
|
|
|
|
height = geom.Min32(desired.Y, height)
|
2018-08-03 06:46:10 +00:00
|
|
|
}
|
|
|
|
if d == DockTop {
|
|
|
|
top = rem.Min.Y
|
|
|
|
} else {
|
|
|
|
top = rem.Max.Y - height
|
|
|
|
}
|
|
|
|
left = rem.Min.X
|
|
|
|
width = rem.Dx()
|
|
|
|
}
|
2018-09-23 07:42:23 +00:00
|
|
|
rects[i] = geom.RectF32(left, top, left+width, top+height)
|
2018-08-03 06:46:10 +00:00
|
|
|
switch d {
|
|
|
|
case DockLeft:
|
2018-09-23 07:42:23 +00:00
|
|
|
rem = geom.RectF32(rem.Min.X+width, rem.Min.Y, rem.Max.X, rem.Max.Y)
|
2018-08-03 06:46:10 +00:00
|
|
|
case DockTop:
|
2018-09-23 07:42:23 +00:00
|
|
|
rem = geom.RectF32(rem.Min.X, rem.Min.Y+height, rem.Max.X, rem.Max.Y)
|
2018-08-03 06:46:10 +00:00
|
|
|
case DockRight:
|
2018-09-23 07:42:23 +00:00
|
|
|
rem = geom.RectF32(rem.Min.X, rem.Min.Y, rem.Max.X-width, rem.Max.Y)
|
2018-08-03 06:46:10 +00:00
|
|
|
case DockBottom:
|
2018-09-23 07:42:23 +00:00
|
|
|
rem = geom.RectF32(rem.Min.X, rem.Min.Y, rem.Max.X, rem.Max.Y-height)
|
2018-08-03 06:46:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rects
|
|
|
|
}
|
|
|
|
|
2018-09-23 07:42:23 +00:00
|
|
|
func (p *dockPanel) Arrange(ctx Context, rect geom.RectangleF32) {
|
2018-08-03 06:46:10 +00:00
|
|
|
p.ContainerBase.SetRect(rect)
|
|
|
|
var rects = p.arrangeChildren(ctx)
|
|
|
|
for i, child := range p.children {
|
|
|
|
Arrange(ctx, child, rects[i])
|
|
|
|
}
|
|
|
|
}
|