shiny/widget: add OnLifecycleEvent.
Change-Id: Ia2789e5a300a3b89188d3c009b40cc3ad9d39cc2
Reviewed-on: https://go-review.googlesource.com/25520
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/shiny/widget/node/node.go b/shiny/widget/node/node.go
index 03ebfff..bc19870 100644
--- a/shiny/widget/node/node.go
+++ b/shiny/widget/node/node.go
@@ -48,6 +48,7 @@
"golang.org/x/exp/shiny/screen"
"golang.org/x/exp/shiny/widget/theme"
"golang.org/x/image/math/f64"
+ "golang.org/x/mobile/event/lifecycle"
"golang.org/x/mobile/event/mouse"
)
@@ -144,6 +145,10 @@
// needing paint.
OnChildMarked(child Node, newMarks Marks)
+ // OnLifecycleEvent propagates a lifecycle event to a node (and its
+ // children).
+ OnLifecycleEvent(e lifecycle.Event)
+
// OnInputEvent handles a key, mouse, touch or gesture event.
//
// origin is the parent widget's origin with respect to the event origin;
@@ -202,6 +207,8 @@
func (m *LeafEmbed) OnChildMarked(child Node, newMarks Marks) {}
+func (m *LeafEmbed) OnLifecycleEvent(e lifecycle.Event) {}
+
func (m *LeafEmbed) OnInputEvent(e interface{}, origin image.Point) EventHandled { return NotHandled }
// ShellEmbed is designed to be embedded in struct types for nodes with at most
@@ -253,6 +260,12 @@
m.Mark(newMarks)
}
+func (m *ShellEmbed) OnLifecycleEvent(e lifecycle.Event) {
+ if c := m.FirstChild; c != nil {
+ c.Wrapper.OnLifecycleEvent(e)
+ }
+}
+
func (m *ShellEmbed) OnInputEvent(e interface{}, origin image.Point) EventHandled {
if c := m.FirstChild; c != nil {
return c.Wrapper.OnInputEvent(e, origin.Add(m.Rect.Min))
@@ -315,6 +328,12 @@
m.Mark(newMarks)
}
+func (m *ContainerEmbed) OnLifecycleEvent(e lifecycle.Event) {
+ for c := m.FirstChild; c != nil; c = c.NextSibling {
+ c.Wrapper.OnLifecycleEvent(e)
+ }
+}
+
func (m *ContainerEmbed) OnInputEvent(e interface{}, origin image.Point) EventHandled {
origin = origin.Add(m.Rect.Min)
var p image.Point
diff --git a/shiny/widget/sheet.go b/shiny/widget/sheet.go
index 5d76ef1..f55696b 100644
--- a/shiny/widget/sheet.go
+++ b/shiny/widget/sheet.go
@@ -11,6 +11,7 @@
"golang.org/x/exp/shiny/screen"
"golang.org/x/exp/shiny/widget/node"
"golang.org/x/image/math/f64"
+ "golang.org/x/mobile/event/lifecycle"
)
// TODO: scrolling.
@@ -42,35 +43,38 @@
return w
}
+func (w *Sheet) release() {
+ if w.buf != nil {
+ w.buf.Release()
+ w.buf = nil
+ }
+ if w.tex != nil {
+ w.tex.Release()
+ w.tex = nil
+ }
+}
+
func (w *Sheet) Paint(ctx *node.PaintContext, origin image.Point) (retErr error) {
w.Marks.UnmarkNeedsPaint()
c := w.FirstChild
if c == nil {
- if w.buf != nil {
- w.buf.Release()
- w.buf = nil
- w.tex.Release()
- w.tex = nil
- }
+ w.release()
return nil
}
fresh, size := false, w.Rect.Size()
if w.buf != nil && w.buf.Size() != size {
- w.buf.Release()
- w.buf = nil
- w.tex.Release()
- w.tex = nil
+ w.release()
}
if w.buf == nil {
w.buf, retErr = ctx.Screen.NewBuffer(size)
if retErr != nil {
+ w.release()
return retErr
}
w.tex, retErr = ctx.Screen.NewTexture(size)
if retErr != nil {
- w.buf.Release()
- w.buf = nil
+ w.release()
return retErr
}
fresh = true
@@ -115,3 +119,9 @@
}
w.Mark(newMarks)
}
+
+func (w *Sheet) OnLifecycleEvent(e lifecycle.Event) {
+ if e.Crosses(lifecycle.StageVisible) == lifecycle.CrossOff {
+ w.release()
+ }
+}
diff --git a/shiny/widget/widget.go b/shiny/widget/widget.go
index 4c0f3ce..1e35e5e 100644
--- a/shiny/widget/widget.go
+++ b/shiny/widget/widget.go
@@ -109,7 +109,7 @@
switch e := e.(type) {
case lifecycle.Event:
- // TODO: drop buffers and textures when we're not visible.
+ root.OnLifecycleEvent(e)
if e.To == lifecycle.StageDead {
return nil
}