diff options
Diffstat (limited to 'env.go')
| -rw-r--r-- | env.go | 102 |
1 files changed, 102 insertions, 0 deletions
@@ -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 +} |