This repository has been archived on 2023-08-08. You can view files and clone it, but cannot push or open issues or pull requests.
tomo-old/elements/containers/vbox.go

179 lines
4.6 KiB
Go
Raw Normal View History

2023-04-15 22:09:49 +00:00
package containers
import "image"
import "git.tebibyte.media/sashakoshka/tomo"
import "git.tebibyte.media/sashakoshka/tomo/canvas"
import "git.tebibyte.media/sashakoshka/tomo/shatter"
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
type scratchEntry struct {
expand bool
minimum float64
}
type VBox struct {
entity tomo.ContainerEntity
scratch map[tomo.Element] scratchEntry
theme theme.Wrapped
padding bool
margin bool
}
func NewVBox (padding, margin bool) (element *VBox) {
element = &VBox { padding: padding, margin: margin }
element.scratch = make(map[tomo.Element] scratchEntry)
element.theme.Case = tomo.C("tomo", "vBox")
element.entity = tomo.NewEntity(element).(tomo.ContainerEntity)
return
}
func (element *VBox) Entity () tomo.Entity {
return element.entity
}
func (element *VBox) Draw (destination canvas.Canvas) {
rocks := make([]image.Rectangle, element.entity.CountChildren())
for index := 0; index < element.entity.CountChildren(); index ++ {
rocks[index] = element.entity.Child(index).Entity().Bounds()
}
tiles := shatter.Shatter(element.entity.Bounds(), rocks...)
for _, tile := range tiles {
element.entity.DrawBackground(canvas.Cut(destination, tile))
}
}
func (element *VBox) Layout () {
margin := element.theme.Margin(tomo.PatternBackground)
padding := element.theme.Padding(tomo.PatternBackground)
bounds := element.entity.Bounds()
if element.padding { bounds = padding.Apply(bounds) }
freeSpace, nExpanding := element.freeSpace()
expandingElementHeight := freeSpace / nExpanding
// set the size and position of each element
x := float64(bounds.Min.X)
y := float64(bounds.Min.Y)
for index := 0; index < element.entity.CountChildren(); index ++ {
entry := element.scratch[element.entity.Child(index)]
var height float64; if entry.expand {
height = expandingElementHeight
} else {
height = entry.minimum
}
element.entity.PlaceChild (index, tomo.Bounds (
int(x), int(y),
bounds.Dx(), int(height)))
y += height
if element.margin { y += float64(margin.Y) }
}
}
func (element *VBox) Adopt (child tomo.Element, expand bool) {
element.entity.Adopt(child)
element.scratch[child] = scratchEntry { expand: expand }
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *VBox) Disown (child tomo.Element) {
index := element.entity.IndexOf(child)
if index < 0 { return }
element.entity.Disown(index)
delete(element.scratch, child)
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *VBox) DisownAll () {
func () {
for index := 0; index < element.entity.CountChildren(); index ++ {
index := index
defer element.entity.Disown(index)
}
} ()
element.scratch = make(map[tomo.Element] scratchEntry)
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *VBox) HandleChildMinimumSizeChange (child tomo.Element) {
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *VBox) DrawBackground (destination canvas.Canvas) {
element.entity.DrawBackground(destination)
}
// SetTheme sets the element's theme.
func (element *VBox) SetTheme (theme tomo.Theme) {
if theme == element.theme.Theme { return }
element.theme.Theme = theme
element.updateMinimumSize()
element.entity.Invalidate()
element.entity.InvalidateLayout()
}
func (element *VBox) freeSpace () (space float64, nExpanding float64) {
margin := element.theme.Margin(tomo.PatternBackground)
padding := element.theme.Padding(tomo.PatternBackground)
space = float64(element.entity.Bounds().Dy())
for _, entry := range element.scratch {
if entry.expand {
nExpanding ++;
} else {
space -= float64(entry.minimum)
}
}
if element.padding {
space -= float64(padding.Vertical())
}
if element.margin {
2023-04-15 22:33:37 +00:00
space -= float64(margin.Y * (len(element.scratch) - 1))
2023-04-15 22:09:49 +00:00
}
return
}
func (element *VBox) updateMinimumSize () {
margin := element.theme.Margin(tomo.PatternBackground)
padding := element.theme.Padding(tomo.PatternBackground)
var width, height int
for index := 0; index < element.entity.CountChildren(); index ++ {
childWidth, childHeight := element.entity.ChildMinimumSize(index)
key := element.entity.Child(index)
entry := element.scratch[key]
entry.minimum = float64(childHeight)
element.scratch[key] = entry
if childWidth > width {
width = childWidth
}
height += childHeight
if element.margin && index > 0 {
height += margin.Y
}
}
if element.padding {
width += padding.Horizontal()
height += padding.Vertical()
}
element.entity.SetMinimumSize(width, height)
}