diff --git a/elements/box.go b/elements/box.go index 143060d..dab9117 100644 --- a/elements/box.go +++ b/elements/box.go @@ -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) { diff --git a/elements/container.go b/elements/container.go new file mode 100644 index 0000000..49d2c88 --- /dev/null +++ b/elements/container.go @@ -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() +} diff --git a/elements/document.go b/elements/document.go index ec916a2..276b61c 100644 --- a/elements/document.go +++ b/elements/document.go @@ -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) { diff --git a/elements/list.go b/elements/list.go index dcc9b19..b7429f6 100644 --- a/elements/list.go +++ b/elements/list.go @@ -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()