aboutsummaryrefslogtreecommitdiffstats
path: root/layout/region.go
blob: 08fa48d893fca9b81f16d587432ef7896b304788 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package layout

import (
	"image"
	"image/color"
	"image/draw"

	"github.com/faiface/gui"
)

// Region is a layout with a single child Env that occupies a sub-area of its parent.
type Region struct {
	events <-chan gui.Event
	draw   chan<- func(draw.Image) image.Rectangle
}

// NewRegion creates a region layout that occupies part of the parent env's area, as determined by the resize function.
// Resize takes the area of the parent and returns the area of the region.
// It returns the child Env.
func NewRegion(env gui.Env, clr color.Color, resize ResizeFunc) gui.Env {
	events := make(chan gui.Event)                       // to child
	draws := make(chan func(draw.Image) image.Rectangle) // from child

	go func(events chan<- gui.Event, draws <-chan func(draw.Image) image.Rectangle) {
		defer close(env.Draw())
		defer close(events)

		redraw := func(area, childArea image.Rectangle) {
			env.Draw() <- drawSubImage(drawBackground(clr), area)
			events <- gui.Resize{childArea}
		}

		// Draw background and forward first resize event to child
		event := (<-env.Events()).(gui.Resize) // first event guaranteed to be Resize
		area := event.Rectangle
		childArea := resize(area)
		go redraw(area, childArea)

		for {
			select {
			case event := <-env.Events(): // event from parent
				switch event := event.(type) {
				case gui.Resize:
					area = event.Rectangle
					childArea = resize(area)
					go redraw(area, childArea)
				default:
					go func() { events <- event }() // forward to child
				}
			case f, ok := <-draws: // draw call from child
				if !ok {
					return
				}
				env.Draw() <- drawSubImage(f, childArea)
			}
		}
	}(events, draws)

	return Region{events, draws}
}

// Events implements the Env interface.
func (r Region) Events() <-chan gui.Event { return r.events }

// Draw implements the Env interface.
func (r Region) Draw() chan<- func(draw.Image) image.Rectangle { return r.draw }