diff --git a/ui/context.go b/ui/context.go index fa62457..3c08148 100644 --- a/ui/context.go +++ b/ui/context.go @@ -14,7 +14,7 @@ var _ EventTarget = &context{} type context struct { animate bool - quit bool + quit chan struct{} r Renderer view Control ims *Images @@ -23,11 +23,22 @@ type context struct { func (c *context) Animate() { c.animate = true } -func (c *context) HasQuit() bool { return c.quit } +func (c *context) HasQuit() bool { + select { + case <-c.quit: + return true + default: + return false + } +} func (c *context) Images() *Images { return c.ims } -func (c *context) Quit() { c.quit = true } +func (c *context) Quit() { + if !c.HasQuit() { + close(c.quit) + } +} func (c *context) Renderer() Renderer { return c.r } diff --git a/ui/ui.go b/ui/ui.go index c1e36bd..13bb503 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -13,7 +13,7 @@ func Run(r Renderer, s *Style, view Control) error { // RunWait runs the application loop and conditionally waits on events before rendering. func RunWait(r Renderer, s *Style, view Control, wait bool) error { - ctx := &context{r: r, style: s, view: view, ims: NewImages(r)} + ctx := &context{quit: make(chan struct{}), r: r, style: s, view: view, ims: NewImages(r)} root, ok := view.(RootControl) if ok { err := root.Init(ctx) @@ -23,24 +23,30 @@ func RunWait(r Renderer, s *Style, view Control, wait bool) error { } anim := time.NewTicker(30 * time.Millisecond) go func() { - for range anim.C { - if ctx.animate && !ctx.quit { + for { + select { + case <-anim.C: + case <-ctx.quit: + return + } + if ctx.animate { r.Refresh() } ctx.animate = false } }() + defer anim.Stop() + ctx.Renderer().Refresh() - for !ctx.quit { + for !ctx.HasQuit() { var size = r.Size() var bounds = geom.RectF32(0, 0, size.X, size.Y) view.Arrange(ctx, bounds, geom.ZeroPtF32, nil) view.Render(ctx) - if ctx.quit { + if ctx.HasQuit() { return nil } r.PushEvents(ctx, wait) } - anim.Stop() return nil }