aboutsummaryrefslogtreecommitdiffstats
path: root/env.go
diff options
context:
space:
mode:
Diffstat (limited to 'env.go')
-rw-r--r--env.go102
1 files changed, 102 insertions, 0 deletions
diff --git a/env.go b/env.go
index 05276b5..f5f31cf 100644
--- a/env.go
+++ b/env.go
@@ -28,3 +28,105 @@ type Env interface {
killer
}
+
+type env struct {
+ events <-chan Event
+ draw chan<- func(draw.Image) image.Rectangle
+ attachChan chan<- attachable
+ kill chan<- bool
+ dead <-chan bool
+ detachChan <-chan bool
+}
+
+// newEnv makes an Env that receives Events from, and sends draw functions to, the parent.
+//
+// Each Event received from parent is passed to filterEvents() along with the Events() channel
+// of the Env. Each draw function received from the Env's Draw() channel is passed to
+// filterDraws() along with the Draw() channel of the parent Env.
+//
+// filterEvents() and filterDraws() can be used to, e.g., simply forward the Event or draw function
+// to the channel, modify it before sending, not send it at all, or produce some other side-effects.
+//
+// shutdown() is called before the Env dies.
+func newEnv(parent Env,
+ filterEvents func(Event, chan<- Event),
+ filterDraws func(func(draw.Image) image.Rectangle, chan<- func(draw.Image) image.Rectangle),
+ shutdown func(),
+) Env {
+ eventsOut, eventsIn := makeEventsChan()
+ drawChan := make(chan func(draw.Image) image.Rectangle)
+ child := newAttachHandler()
+ kill := make(chan bool)
+ dead := make(chan bool)
+ detachFromParent := make(chan bool)
+
+ go func() {
+ defer func() {
+ dead <- true
+ close(dead)
+ }()
+ defer func() {
+ detachFromParent <- true
+ close(detachFromParent)
+ }()
+ defer shutdown()
+ defer close(eventsIn)
+ defer close(drawChan)
+ defer close(kill)
+ defer func() {
+ go drain(drawChan)
+ child.kill <- true
+ <-child.dead
+ }()
+
+ for {
+ select {
+ case e := <-parent.Events():
+ filterEvents(e, eventsIn)
+ case d := <-drawChan:
+ filterDraws(d, parent.Draw())
+ case <-kill:
+ return
+ }
+ }
+ }()
+
+ e := env{
+ events: eventsOut,
+ draw: drawChan,
+ attachChan: child.attach(),
+ kill: kill,
+ dead: dead,
+ detachChan: detachFromParent,
+ }
+ parent.attach() <- e
+ return e
+}
+
+func (e env) Events() <-chan Event {
+ return e.events
+}
+
+func (e env) Draw() chan<- func(draw.Image) image.Rectangle {
+ return e.draw
+}
+
+func (e env) Kill() chan<- bool {
+ return e.kill
+}
+
+func (e env) Dead() <-chan bool {
+ return e.dead
+}
+
+func (e env) attach() chan<- attachable {
+ return e.attachChan
+}
+
+func (e env) detach() <-chan bool {
+ return e.detachChan
+}
+
+func send[T any](v T, c chan<- T) {
+ c <- v
+}