Containers now share a bunch of code
This commit is contained in:
parent
ac58a43220
commit
afdecc2c8b
@ -21,19 +21,12 @@ func (space Space) Includes (sub Space) bool {
|
||||
return (space & sub) > 0
|
||||
}
|
||||
|
||||
type scratchEntry struct {
|
||||
expand bool
|
||||
minSize float64
|
||||
minBreadth float64
|
||||
}
|
||||
|
||||
// Box is a container that lays out its children horizontally or vertically.
|
||||
// Child elements can be set to contract to their minimum size, or expand to
|
||||
// fill remaining space. Boxes can be nested and used together to create more
|
||||
// complex layouts.
|
||||
type Box struct {
|
||||
entity tomo.ContainerEntity
|
||||
scratch map[tomo.Element] scratchEntry
|
||||
container
|
||||
theme theme.Wrapped
|
||||
padding bool
|
||||
margin bool
|
||||
@ -46,9 +39,10 @@ func NewHBox (space Space, children ...tomo.Element) (element *Box) {
|
||||
padding: space.Includes(SpacePadding),
|
||||
margin: space.Includes(SpaceMargin),
|
||||
}
|
||||
element.scratch = make(map[tomo.Element] scratchEntry)
|
||||
element.theme.Case = tomo.C("tomo", "box")
|
||||
element.entity = tomo.NewEntity(element).(tomo.ContainerEntity)
|
||||
element.minimumSize = element.updateMinimumSize
|
||||
element.init()
|
||||
element.theme.Case = tomo.C("tomo", "box")
|
||||
element.Adopt(children...)
|
||||
return
|
||||
}
|
||||
@ -60,17 +54,14 @@ func NewVBox (space Space, children ...tomo.Element) (element *Box) {
|
||||
margin: space.Includes(SpaceMargin),
|
||||
vertical: true,
|
||||
}
|
||||
element.scratch = make(map[tomo.Element] scratchEntry)
|
||||
element.theme.Case = tomo.C("tomo", "box")
|
||||
element.entity = tomo.NewEntity(element).(tomo.ContainerEntity)
|
||||
element.minimumSize = element.updateMinimumSize
|
||||
element.init()
|
||||
element.theme.Case = tomo.C("tomo", "box")
|
||||
element.Adopt(children...)
|
||||
return
|
||||
}
|
||||
|
||||
func (element *Box) Entity () tomo.Entity {
|
||||
return element.entity
|
||||
}
|
||||
|
||||
func (element *Box) Draw (destination canvas.Canvas) {
|
||||
rocks := make([]image.Rectangle, element.entity.CountChildren())
|
||||
for index := 0; index < element.entity.CountChildren(); index ++ {
|
||||
@ -127,64 +118,8 @@ func (element *Box) Layout () {
|
||||
}
|
||||
}
|
||||
|
||||
func (element *Box) Adopt (children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
element.entity.Adopt(child)
|
||||
element.scratch[child] = scratchEntry { expand: false }
|
||||
}
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (element *Box) AdoptExpand (children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
element.entity.Adopt(child)
|
||||
element.scratch[child] = scratchEntry { expand: true }
|
||||
}
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (element *Box) Disown (children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
index := element.entity.IndexOf(child)
|
||||
if index < 0 { continue }
|
||||
element.entity.Disown(index)
|
||||
delete(element.scratch, child)
|
||||
}
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (element *Box) 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 *Box) Child (index int) tomo.Element {
|
||||
if index < 0 || index >= element.entity.CountChildren() { return nil }
|
||||
return element.entity.Child(index)
|
||||
}
|
||||
|
||||
func (element *Box) CountChildren () int {
|
||||
return element.entity.CountChildren()
|
||||
}
|
||||
|
||||
func (element *Box) HandleChildMinimumSizeChange (child tomo.Element) {
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
element.adopt(true, children...)
|
||||
}
|
||||
|
||||
func (element *Box) DrawBackground (destination canvas.Canvas) {
|
||||
|
77
elements/container.go
Normal file
77
elements/container.go
Normal file
@ -0,0 +1,77 @@
|
||||
package elements
|
||||
|
||||
import "git.tebibyte.media/sashakoshka/tomo"
|
||||
|
||||
type scratchEntry struct {
|
||||
expand bool
|
||||
minSize float64
|
||||
minBreadth float64
|
||||
}
|
||||
|
||||
type container struct {
|
||||
entity tomo.ContainerEntity
|
||||
scratch map[tomo.Element] scratchEntry
|
||||
minimumSize func ()
|
||||
}
|
||||
|
||||
func (container *container) Entity () tomo.Entity {
|
||||
return container.entity
|
||||
}
|
||||
|
||||
func (container *container) Adopt (children ...tomo.Element) {
|
||||
container.adopt(false, children...)
|
||||
}
|
||||
|
||||
func (container *container) init () {
|
||||
container.scratch = make(map[tomo.Element] scratchEntry)
|
||||
}
|
||||
|
||||
func (container *container) adopt (expand bool, children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
container.entity.Adopt(child)
|
||||
container.scratch[child] = scratchEntry { expand: expand }
|
||||
}
|
||||
container.minimumSize()
|
||||
container.entity.Invalidate()
|
||||
container.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (container *container) Disown (children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
index := container.entity.IndexOf(child)
|
||||
if index < 0 { continue }
|
||||
container.entity.Disown(index)
|
||||
delete(container.scratch, child)
|
||||
}
|
||||
container.minimumSize()
|
||||
container.entity.Invalidate()
|
||||
container.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (container *container) DisownAll () {
|
||||
func () {
|
||||
for index := 0; index < container.entity.CountChildren(); index ++ {
|
||||
index := index
|
||||
defer container.entity.Disown(index)
|
||||
}
|
||||
} ()
|
||||
container.scratch = make(map[tomo.Element] scratchEntry)
|
||||
container.minimumSize()
|
||||
container.entity.Invalidate()
|
||||
container.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (container *container) Child (index int) tomo.Element {
|
||||
if index < 0 || index >= container.entity.CountChildren() { return nil }
|
||||
return container.entity.Child(index)
|
||||
}
|
||||
|
||||
func (container *container) CountChildren () int {
|
||||
return container.entity.CountChildren()
|
||||
}
|
||||
|
||||
func (container *container) HandleChildMinimumSizeChange (child tomo.Element) {
|
||||
container.minimumSize()
|
||||
container.entity.Invalidate()
|
||||
container.entity.InvalidateLayout()
|
||||
}
|
@ -12,9 +12,9 @@ type documentEntity interface {
|
||||
}
|
||||
|
||||
type Document struct {
|
||||
container
|
||||
entity documentEntity
|
||||
|
||||
scratch map[tomo.Element] scratchEntry
|
||||
scroll image.Point
|
||||
contentBounds image.Rectangle
|
||||
|
||||
@ -25,17 +25,15 @@ type Document struct {
|
||||
|
||||
func NewDocument (children ...tomo.Element) (element *Document) {
|
||||
element = &Document { }
|
||||
element.scratch = make(map[tomo.Element] scratchEntry)
|
||||
element.theme.Case = tomo.C("tomo", "document")
|
||||
element.entity = tomo.NewEntity(element).(documentEntity)
|
||||
element.container.entity = element.entity
|
||||
element.minimumSize = element.updateMinimumSize
|
||||
element.init()
|
||||
element.Adopt(children...)
|
||||
return
|
||||
}
|
||||
|
||||
func (element *Document) Entity () tomo.Entity {
|
||||
return element.entity
|
||||
}
|
||||
|
||||
func (element *Document) Draw (destination canvas.Canvas) {
|
||||
rocks := make([]image.Rectangle, element.entity.CountChildren())
|
||||
for index := 0; index < element.entity.CountChildren(); index ++ {
|
||||
@ -111,63 +109,11 @@ func (element *Document) Layout () {
|
||||
}
|
||||
|
||||
func (element *Document) Adopt (children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
element.entity.Adopt(child)
|
||||
element.scratch[child] = scratchEntry { expand: true }
|
||||
}
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
element.adopt(true, children...)
|
||||
}
|
||||
|
||||
func (element *Document) AdoptInline (children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
element.entity.Adopt(child)
|
||||
element.scratch[child] = scratchEntry { expand: false }
|
||||
}
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (element *Document) Disown (children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
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 *Document) 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 *Document) Child (index int) tomo.Element {
|
||||
if index < 0 || index >= element.entity.CountChildren() { return nil }
|
||||
return element.entity.Child(index)
|
||||
}
|
||||
|
||||
func (element *Document) CountChildren () int {
|
||||
return element.entity.CountChildren()
|
||||
}
|
||||
|
||||
func (element *Document) HandleChildMinimumSizeChange (child tomo.Element) {
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
element.adopt(false, children...)
|
||||
}
|
||||
|
||||
func (element *Document) HandleChildFlexibleHeightChange (child tomo.Flexible) {
|
||||
|
@ -7,24 +7,15 @@ import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
||||
|
||||
// TODO: make hidden variants:
|
||||
// vertical: one column.
|
||||
// flow: acts like DocumentContainer with all inline elements.
|
||||
// create wrapper elements for making a plain version of each of these, but keep
|
||||
// the implementations private (but with public methods) so they can be included
|
||||
// in other elements.
|
||||
// have table be a very tabular thing with named columns that can be sorted,
|
||||
// resized, etc.
|
||||
|
||||
type listEntity interface {
|
||||
tomo.ContainerEntity
|
||||
tomo.ScrollableEntity
|
||||
}
|
||||
|
||||
type List struct {
|
||||
container
|
||||
entity listEntity
|
||||
|
||||
scratch map[tomo.Element] scratchEntry
|
||||
scroll image.Point
|
||||
contentBounds image.Rectangle
|
||||
columnSizes []int
|
||||
@ -41,18 +32,16 @@ type List struct {
|
||||
func NewList (columns int, children ...tomo.Element) (element *List) {
|
||||
if columns < 1 { columns = 1 }
|
||||
element = &List { selected: -1 }
|
||||
element.scratch = make(map[tomo.Element] scratchEntry)
|
||||
element.columnSizes = make([]int, columns)
|
||||
element.theme.Case = tomo.C("tomo", "list")
|
||||
element.entity = tomo.NewEntity(element).(listEntity)
|
||||
element.container.entity = element.entity
|
||||
element.minimumSize = element.updateMinimumSize
|
||||
element.init()
|
||||
element.Adopt(children...)
|
||||
return
|
||||
}
|
||||
|
||||
func (element *List) Entity () tomo.Entity {
|
||||
return element.entity
|
||||
}
|
||||
|
||||
func (element *List) Draw (destination canvas.Canvas) {
|
||||
rocks := make([]image.Rectangle, element.entity.CountChildren())
|
||||
for index := 0; index < element.entity.CountChildren(); index ++ {
|
||||
@ -123,54 +112,6 @@ func (element *List) Layout () {
|
||||
}
|
||||
}
|
||||
|
||||
func (element *List) Adopt (children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
element.entity.Adopt(child)
|
||||
element.scratch[child] = scratchEntry { }
|
||||
}
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (element *List) Disown (children ...tomo.Element) {
|
||||
for _, child := range children {
|
||||
index := element.entity.IndexOf(child)
|
||||
if index < 0 { return }
|
||||
if index == element.selected {
|
||||
element.selected = -1
|
||||
element.entity.SelectChild(index, false)
|
||||
}
|
||||
element.entity.Disown(index)
|
||||
delete(element.scratch, child)
|
||||
}
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (element *List) 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 *List) Child (index int) tomo.Element {
|
||||
if index < 0 || index >= element.entity.CountChildren() { return nil }
|
||||
return element.entity.Child(index)
|
||||
}
|
||||
|
||||
func (element *List) CountChildren () int {
|
||||
return element.entity.CountChildren()
|
||||
}
|
||||
|
||||
func (element *List) HandleChildMouseDown (x, y int, button input.Button, child tomo.Element) {
|
||||
if child, ok := child.(tomo.Selectable); ok {
|
||||
index := element.entity.IndexOf(child)
|
||||
@ -185,12 +126,6 @@ func (element *List) HandleChildMouseDown (x, y int, button input.Button, child
|
||||
|
||||
func (element *List) HandleChildMouseUp (int, int, input.Button, tomo.Element) { }
|
||||
|
||||
func (element *List) HandleChildMinimumSizeChange (child tomo.Element) {
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
element.entity.InvalidateLayout()
|
||||
}
|
||||
|
||||
func (element *List) HandleChildFlexibleHeightChange (child tomo.Flexible) {
|
||||
element.updateMinimumSize()
|
||||
element.entity.Invalidate()
|
||||
|
Reference in New Issue
Block a user