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
|
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.
|
// 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
|
// 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
|
// fill remaining space. Boxes can be nested and used together to create more
|
||||||
// complex layouts.
|
// complex layouts.
|
||||||
type Box struct {
|
type Box struct {
|
||||||
entity tomo.ContainerEntity
|
container
|
||||||
scratch map[tomo.Element] scratchEntry
|
|
||||||
theme theme.Wrapped
|
theme theme.Wrapped
|
||||||
padding bool
|
padding bool
|
||||||
margin bool
|
margin bool
|
||||||
@ -46,9 +39,10 @@ func NewHBox (space Space, children ...tomo.Element) (element *Box) {
|
|||||||
padding: space.Includes(SpacePadding),
|
padding: space.Includes(SpacePadding),
|
||||||
margin: space.Includes(SpaceMargin),
|
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.entity = tomo.NewEntity(element).(tomo.ContainerEntity)
|
||||||
|
element.minimumSize = element.updateMinimumSize
|
||||||
|
element.init()
|
||||||
|
element.theme.Case = tomo.C("tomo", "box")
|
||||||
element.Adopt(children...)
|
element.Adopt(children...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -60,17 +54,14 @@ func NewVBox (space Space, children ...tomo.Element) (element *Box) {
|
|||||||
margin: space.Includes(SpaceMargin),
|
margin: space.Includes(SpaceMargin),
|
||||||
vertical: true,
|
vertical: true,
|
||||||
}
|
}
|
||||||
element.scratch = make(map[tomo.Element] scratchEntry)
|
|
||||||
element.theme.Case = tomo.C("tomo", "box")
|
|
||||||
element.entity = tomo.NewEntity(element).(tomo.ContainerEntity)
|
element.entity = tomo.NewEntity(element).(tomo.ContainerEntity)
|
||||||
|
element.minimumSize = element.updateMinimumSize
|
||||||
|
element.init()
|
||||||
|
element.theme.Case = tomo.C("tomo", "box")
|
||||||
element.Adopt(children...)
|
element.Adopt(children...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Box) Entity () tomo.Entity {
|
|
||||||
return element.entity
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Box) Draw (destination canvas.Canvas) {
|
func (element *Box) Draw (destination canvas.Canvas) {
|
||||||
rocks := make([]image.Rectangle, element.entity.CountChildren())
|
rocks := make([]image.Rectangle, element.entity.CountChildren())
|
||||||
for index := 0; index < element.entity.CountChildren(); index ++ {
|
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) {
|
func (element *Box) AdoptExpand (children ...tomo.Element) {
|
||||||
for _, child := range children {
|
element.adopt(true, 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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Box) DrawBackground (destination canvas.Canvas) {
|
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 {
|
type Document struct {
|
||||||
|
container
|
||||||
entity documentEntity
|
entity documentEntity
|
||||||
|
|
||||||
scratch map[tomo.Element] scratchEntry
|
|
||||||
scroll image.Point
|
scroll image.Point
|
||||||
contentBounds image.Rectangle
|
contentBounds image.Rectangle
|
||||||
|
|
||||||
@ -25,17 +25,15 @@ type Document struct {
|
|||||||
|
|
||||||
func NewDocument (children ...tomo.Element) (element *Document) {
|
func NewDocument (children ...tomo.Element) (element *Document) {
|
||||||
element = &Document { }
|
element = &Document { }
|
||||||
element.scratch = make(map[tomo.Element] scratchEntry)
|
|
||||||
element.theme.Case = tomo.C("tomo", "document")
|
element.theme.Case = tomo.C("tomo", "document")
|
||||||
element.entity = tomo.NewEntity(element).(documentEntity)
|
element.entity = tomo.NewEntity(element).(documentEntity)
|
||||||
|
element.container.entity = element.entity
|
||||||
|
element.minimumSize = element.updateMinimumSize
|
||||||
|
element.init()
|
||||||
element.Adopt(children...)
|
element.Adopt(children...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Document) Entity () tomo.Entity {
|
|
||||||
return element.entity
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *Document) Draw (destination canvas.Canvas) {
|
func (element *Document) Draw (destination canvas.Canvas) {
|
||||||
rocks := make([]image.Rectangle, element.entity.CountChildren())
|
rocks := make([]image.Rectangle, element.entity.CountChildren())
|
||||||
for index := 0; index < element.entity.CountChildren(); index ++ {
|
for index := 0; index < element.entity.CountChildren(); index ++ {
|
||||||
@ -111,63 +109,11 @@ func (element *Document) Layout () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (element *Document) Adopt (children ...tomo.Element) {
|
func (element *Document) Adopt (children ...tomo.Element) {
|
||||||
for _, child := range children {
|
element.adopt(true, children...)
|
||||||
element.entity.Adopt(child)
|
|
||||||
element.scratch[child] = scratchEntry { expand: true }
|
|
||||||
}
|
|
||||||
element.updateMinimumSize()
|
|
||||||
element.entity.Invalidate()
|
|
||||||
element.entity.InvalidateLayout()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Document) AdoptInline (children ...tomo.Element) {
|
func (element *Document) AdoptInline (children ...tomo.Element) {
|
||||||
for _, child := range children {
|
element.adopt(false, 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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *Document) HandleChildFlexibleHeightChange (child tomo.Flexible) {
|
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/artist"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/default/theme"
|
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 {
|
type listEntity interface {
|
||||||
tomo.ContainerEntity
|
tomo.ContainerEntity
|
||||||
tomo.ScrollableEntity
|
tomo.ScrollableEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
type List struct {
|
type List struct {
|
||||||
|
container
|
||||||
entity listEntity
|
entity listEntity
|
||||||
|
|
||||||
scratch map[tomo.Element] scratchEntry
|
|
||||||
scroll image.Point
|
scroll image.Point
|
||||||
contentBounds image.Rectangle
|
contentBounds image.Rectangle
|
||||||
columnSizes []int
|
columnSizes []int
|
||||||
@ -41,18 +32,16 @@ type List struct {
|
|||||||
func NewList (columns int, children ...tomo.Element) (element *List) {
|
func NewList (columns int, children ...tomo.Element) (element *List) {
|
||||||
if columns < 1 { columns = 1 }
|
if columns < 1 { columns = 1 }
|
||||||
element = &List { selected: -1 }
|
element = &List { selected: -1 }
|
||||||
element.scratch = make(map[tomo.Element] scratchEntry)
|
|
||||||
element.columnSizes = make([]int, columns)
|
element.columnSizes = make([]int, columns)
|
||||||
element.theme.Case = tomo.C("tomo", "list")
|
element.theme.Case = tomo.C("tomo", "list")
|
||||||
element.entity = tomo.NewEntity(element).(listEntity)
|
element.entity = tomo.NewEntity(element).(listEntity)
|
||||||
|
element.container.entity = element.entity
|
||||||
|
element.minimumSize = element.updateMinimumSize
|
||||||
|
element.init()
|
||||||
element.Adopt(children...)
|
element.Adopt(children...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (element *List) Entity () tomo.Entity {
|
|
||||||
return element.entity
|
|
||||||
}
|
|
||||||
|
|
||||||
func (element *List) Draw (destination canvas.Canvas) {
|
func (element *List) Draw (destination canvas.Canvas) {
|
||||||
rocks := make([]image.Rectangle, element.entity.CountChildren())
|
rocks := make([]image.Rectangle, element.entity.CountChildren())
|
||||||
for index := 0; index < element.entity.CountChildren(); index ++ {
|
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) {
|
func (element *List) HandleChildMouseDown (x, y int, button input.Button, child tomo.Element) {
|
||||||
if child, ok := child.(tomo.Selectable); ok {
|
if child, ok := child.(tomo.Selectable); ok {
|
||||||
index := element.entity.IndexOf(child)
|
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) 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) {
|
func (element *List) HandleChildFlexibleHeightChange (child tomo.Flexible) {
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
element.entity.Invalidate()
|
element.entity.Invalidate()
|
||||||
|
Reference in New Issue
Block a user