Added a Warp method to Container for batch updates

This commit is contained in:
Sasha Koshka 2023-01-12 16:02:33 -05:00
parent 9710e57b2b
commit 588c52b30a
2 changed files with 72 additions and 31 deletions

View File

@ -6,16 +6,19 @@ import "git.tebibyte.media/sashakoshka/tomo/theme"
import "git.tebibyte.media/sashakoshka/tomo/artist" import "git.tebibyte.media/sashakoshka/tomo/artist"
import "git.tebibyte.media/sashakoshka/tomo/elements/core" import "git.tebibyte.media/sashakoshka/tomo/elements/core"
// Container is an element capable of containg other elements, and arranging
// them in a layout.
type Container struct { type Container struct {
*core.Core *core.Core
core core.CoreControl core core.CoreControl
layout tomo.Layout layout tomo.Layout
children []tomo.LayoutEntry children []tomo.LayoutEntry
drags [10]tomo.Element
drags [10]tomo.Element warping bool
} }
// NewContainer creates a new container.
func NewContainer (layout tomo.Layout) (element *Container) { func NewContainer (layout tomo.Layout) (element *Container) {
element = &Container { } element = &Container { }
element.Core, element.core = core.NewCore(element) element.Core, element.core = core.NewCore(element)
@ -23,6 +26,7 @@ func NewContainer (layout tomo.Layout) (element *Container) {
return return
} }
// SetLayout sets the layout of this container.
func (element *Container) SetLayout (layout tomo.Layout) { func (element *Container) SetLayout (layout tomo.Layout) {
element.layout = layout element.layout = layout
if element.core.HasImage() { if element.core.HasImage() {
@ -32,6 +36,9 @@ func (element *Container) SetLayout (layout tomo.Layout) {
} }
} }
// Adopt adds a new child element to the container. If expand is set to true,
// the element will expand (instead of contract to its minimum size), in
// whatever way is defined by the current layout.
func (element *Container) Adopt (child tomo.Element, expand bool) { func (element *Container) Adopt (child tomo.Element, expand bool) {
child.SetParentHooks (tomo.ParentHooks { child.SetParentHooks (tomo.ParentHooks {
MinimumSizeChange: func (int, int) { MinimumSizeChange: func (int, int) {
@ -61,6 +68,29 @@ func (element *Container) Adopt (child tomo.Element, expand bool) {
element.updateMinimumSize() element.updateMinimumSize()
element.updateSelectable() element.updateSelectable()
if element.core.HasImage() && !element.warping {
element.recalculate()
element.draw()
element.core.PushAll()
}
}
// Warp runs the specified callback, deferring all layout and rendering updates
// until the callback has finished executing. This allows for aplications to
// perform batch gui updates without flickering and stuff.
func (element *Container) Warp (callback func ()) {
if element.warping {
callback()
return
}
element.warping = true
callback()
element.warping = false
// TODO: create some sort of task list so we don't do a full recalculate
// and redraw every time, because although that is the most likely use
// case, it is not the only one.
if element.core.HasImage() { if element.core.HasImage() {
element.recalculate() element.recalculate()
element.draw() element.draw()
@ -83,7 +113,7 @@ func (element *Container) Disown (child tomo.Element) {
element.updateMinimumSize() element.updateMinimumSize()
element.updateSelectable() element.updateSelectable()
if element.core.HasImage() { if element.core.HasImage() && !element.warping {
element.recalculate() element.recalculate()
element.draw() element.draw()
element.core.PushAll() element.core.PushAll()
@ -96,7 +126,7 @@ func (element *Container) DisownAll () {
element.updateMinimumSize() element.updateMinimumSize()
element.updateSelectable() element.updateSelectable()
if element.core.HasImage() { if element.core.HasImage() && !element.warping {
element.recalculate() element.recalculate()
element.draw() element.draw()
element.core.PushAll() element.core.PushAll()
@ -300,6 +330,7 @@ func (element *Container) draw () {
} }
func (element *Container) drawChildRegion (child tomo.Element, region tomo.Image) { func (element *Container) drawChildRegion (child tomo.Element, region tomo.Image) {
if element.warping { return }
for _, entry := range element.children { for _, entry := range element.children {
if entry.Element == child { if entry.Element == child {
artist.Paste(element.core, region, entry.Position) artist.Paste(element.core, region, entry.Position)

View File

@ -22,50 +22,55 @@ func run () {
"start": func () { "start": func () {
label := basic.NewLabel ( label := basic.NewLabel (
"you are standing next to a river.", false) "you are standing next to a river.", false)
container.Adopt(label, true)
button0 := basic.NewButton("go in the river") button0 := basic.NewButton("go in the river")
button0.OnClick(world.SwitchFunc("wet")) button0.OnClick(world.SwitchFunc("wet"))
container.Adopt(button0, false)
button0.Select()
button1 := basic.NewButton("walk along the river") button1 := basic.NewButton("walk along the river")
button1.OnClick(world.SwitchFunc("house")) button1.OnClick(world.SwitchFunc("house"))
container.Adopt(button1, false)
button2 := basic.NewButton("turn around") button2 := basic.NewButton("turn around")
button2.OnClick(world.SwitchFunc("bear")) button2.OnClick(world.SwitchFunc("bear"))
container.Adopt(button2, false)
container.Warp ( func () {
container.Adopt(label, true)
container.Adopt(button0, false)
container.Adopt(button1, false)
container.Adopt(button2, false)
button0.Select()
})
}, },
"wet": func () { "wet": func () {
label := basic.NewLabel ( label := basic.NewLabel (
"you get completely soaked.\n" + "you get completely soaked.\n" +
"you die of hypothermia.", false) "you die of hypothermia.", false)
container.Adopt(label, true)
button0 := basic.NewButton("try again") button0 := basic.NewButton("try again")
button0.OnClick(world.SwitchFunc("start")) button0.OnClick(world.SwitchFunc("start"))
container.Adopt(button0, false)
button0.Select()
button1 := basic.NewButton("exit") button1 := basic.NewButton("exit")
button1.OnClick(tomo.Stop) button1.OnClick(tomo.Stop)
container.Adopt(button1, false)
container.Warp (func () {
container.Adopt(label, true)
container.Adopt(button0, false)
container.Adopt(button1, false)
button0.Select()
})
}, },
"house": func () { "house": func () {
label := basic.NewLabel ( label := basic.NewLabel (
"you are standing in front of a delapidated " + "you are standing in front of a delapidated " +
"house.", false) "house.", false)
container.Adopt(label, true)
button1 := basic.NewButton("go inside") button1 := basic.NewButton("go inside")
button1.OnClick(world.SwitchFunc("inside")) button1.OnClick(world.SwitchFunc("inside"))
container.Adopt(button1, false)
button1.Select()
button0 := basic.NewButton("turn back") button0 := basic.NewButton("turn back")
button0.OnClick(world.SwitchFunc("start")) button0.OnClick(world.SwitchFunc("start"))
container.Adopt(button0, false)
container.Warp (func () {
container.Adopt(label, true)
container.Adopt(button1, false)
container.Adopt(button0, false)
button1.Select()
})
}, },
"inside": func () { "inside": func () {
label := basic.NewLabel ( label := basic.NewLabel (
@ -74,27 +79,32 @@ func run () {
"through the window.\n" + "through the window.\n" +
"there is nothing particularly interesting " + "there is nothing particularly interesting " +
"here.", false) "here.", false)
container.Adopt(label, true)
button0 := basic.NewButton("go back outside") button0 := basic.NewButton("go back outside")
button0.OnClick(world.SwitchFunc("house")) button0.OnClick(world.SwitchFunc("house"))
container.Adopt(button0, false)
button0.Select() container.Warp (func () {
container.Adopt(label, true)
container.Adopt(button0, false)
button0.Select()
})
}, },
"bear": func () { "bear": func () {
label := basic.NewLabel ( label := basic.NewLabel (
"you come face to face with a bear.\n" + "you come face to face with a bear.\n" +
"it eats you (it was hungry).", false) "it eats you (it was hungry).", false)
container.Adopt(label, true)
button0 := basic.NewButton("try again") button0 := basic.NewButton("try again")
button0.OnClick(world.SwitchFunc("start")) button0.OnClick(world.SwitchFunc("start"))
container.Adopt(button0, false)
button0.Select()
button1 := basic.NewButton("exit") button1 := basic.NewButton("exit")
button1.OnClick(tomo.Stop) button1.OnClick(tomo.Stop)
container.Adopt(button1, false)
container.Warp (func () {
container.Adopt(label, true)
container.Adopt(button0, false)
container.Adopt(button1, false)
button0.Select()
})
}, },
} }
world.Switch("start") world.Switch("start")