aboutsummaryrefslogtreecommitdiffstats
path: root/layout/layer.go
diff options
context:
space:
mode:
Diffstat (limited to 'layout/layer.go')
-rw-r--r--layout/layer.go102
1 files changed, 102 insertions, 0 deletions
diff --git a/layout/layer.go b/layout/layer.go
new file mode 100644
index 0000000..ff6d466
--- /dev/null
+++ b/layout/layer.go
@@ -0,0 +1,102 @@
+package layer
+
+import (
+ "container/list"
+ "errors"
+ "image"
+ "image/draw"
+
+ "github.com/faiface/gui/event"
+)
+
+type ImageFlusher interface {
+ Image() *image.RGBA
+ Flush(r image.Rectangle)
+}
+
+type LayerList struct {
+ event.Dispatch
+ dst ImageFlusher
+ layers list.List
+}
+
+func (l *LayerList) Dst(dst ImageFlusher) {
+ l.dst = dst
+ for e := l.layers.Back(); e != nil; e = e.Prev() {
+ layer := e.Value.(*Layer)
+ rgba := image.NewRGBA(dst.Image().Bounds())
+ draw.Draw(rgba, layer.rgba.Bounds(), layer.rgba, layer.rgba.Bounds().Min, draw.Src)
+ layer.rgba = rgba
+ }
+}
+
+func (l *LayerList) Push() *Layer {
+ layer := &Layer{
+ lst: l,
+ rgba: image.NewRGBA(l.dst.Image().Bounds()),
+ }
+ layer.elm = l.layers.PushFront(layer)
+ return layer
+}
+
+func (l *LayerList) Remove(layer *Layer) {
+ if layer.lst == nil {
+ panic(errors.New("layer: Remove: layer already removed"))
+ }
+ l.layers.Remove(layer.elm)
+ layer.lst = nil
+}
+
+func (l *LayerList) Front(layer *Layer) {
+ if layer.lst == nil {
+ panic(errors.New("layer: Front: layer removed"))
+ }
+ l.layers.MoveToFront(layer.elm)
+}
+
+func (l *LayerList) Flush(r image.Rectangle) {
+ if l.dst == nil {
+ panic(errors.New("layer: Flush: no destination"))
+ }
+ draw.Draw(l.dst.Image(), r, image.Transparent, r.Min, draw.Src)
+ for e := l.layers.Back(); e != nil; e = e.Prev() {
+ layer := e.Value.(*Layer)
+ draw.Draw(l.dst.Image(), r, layer.rgba, r.Min, draw.Over)
+ }
+ l.dst.Flush(r)
+}
+
+func (l *LayerList) Happen(event string) bool {
+ if l.Dispatch.Happen(event) {
+ return true
+ }
+ for e := l.layers.Front(); e != nil; e = e.Next() {
+ layer := e.Value.(*Layer)
+ if layer.Happen(event) {
+ return true
+ }
+ }
+ return false
+}
+
+type Layer struct {
+ event.Dispatch
+ lst *LayerList
+ elm *list.Element
+ rgba *image.RGBA
+}
+
+func (l *Layer) List() *LayerList {
+ return l.lst
+}
+
+func (l *Layer) Image() *image.RGBA {
+ return l.rgba
+}
+
+func (l *Layer) Flush(r image.Rectangle) {
+ if l.lst == nil {
+ panic(errors.New("layer: Flush: layer removed"))
+ }
+ l.lst.Flush(r)
+}