aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfaiface <faiface@ksp.sk>2017-08-22 23:52:27 +0200
committerfaiface <faiface@ksp.sk>2017-08-22 23:52:27 +0200
commit4952b441cc664ff941fb59c7a53bc554277c13a5 (patch)
tree756959024672f8b0c1befe80b4b1951ac11962c7
parentdf69ad70ca3c0b7f9d9f22396810188addf6caa9 (diff)
downloadgui-4952b441cc664ff941fb59c7a53bc554277c13a5.zip
layout: add Split
-rw-r--r--layout/split.go161
1 files changed, 161 insertions, 0 deletions
diff --git a/layout/split.go b/layout/split.go
new file mode 100644
index 0000000..0c197b3
--- /dev/null
+++ b/layout/split.go
@@ -0,0 +1,161 @@
+package layout
+
+import (
+ "image"
+
+ "github.com/faiface/gui/event"
+)
+
+type Box struct {
+ event.Dispatch
+ dst EventImageFlusher
+ sub *image.RGBA
+}
+
+func (b *Box) Image() *image.RGBA {
+ return b.sub
+}
+
+func (b *Box) Flush(r image.Rectangle) {
+ r = r.Intersect(b.dst.Image().Bounds())
+ b.dst.Flush(r)
+}
+
+type Splitter func(r image.Rectangle, i, n int) image.Rectangle
+
+func Vertical() Splitter {
+ return func(r image.Rectangle, i, n int) image.Rectangle {
+ width := r.Dx()
+ return image.Rect(
+ r.Min.X+width*i/n,
+ r.Min.Y,
+ r.Min.X+width*(i+1)/n,
+ r.Max.Y,
+ )
+ }
+}
+
+func Horizontal() Splitter {
+ return func(r image.Rectangle, i, n int) image.Rectangle {
+ height := r.Dy()
+ return image.Rect(
+ r.Min.X,
+ r.Min.Y+height*i/n,
+ r.Max.X,
+ r.Min.Y+height*(i+1)/n,
+ )
+ }
+}
+
+func FixedTop(thickness int, rest Splitter) Splitter {
+ return VariableTop(&thickness, rest)
+}
+
+func FixedBottom(thickness int, rest Splitter) Splitter {
+ return VariableBottom(&thickness, rest)
+}
+
+func FixedLeft(thickness int, rest Splitter) Splitter {
+ return VariableLeft(&thickness, rest)
+}
+
+func FixedRight(thickness int, rest Splitter) Splitter {
+ return VariableRight(&thickness, rest)
+}
+
+func VariableTop(thickness *int, rest Splitter) Splitter {
+ return func(r image.Rectangle, i, n int) image.Rectangle {
+ if i == 0 {
+ r.Max.Y = r.Min.Y + *thickness
+ return r
+ }
+ r.Min.Y += *thickness
+ return rest(r, i-1, n-1)
+ }
+}
+
+func VariableBottom(thickness *int, rest Splitter) Splitter {
+ return func(r image.Rectangle, i, n int) image.Rectangle {
+ if i == 0 {
+ r.Min.Y = r.Max.Y - *thickness
+ return r
+ }
+ r.Max.Y -= *thickness
+ return rest(r, i-1, n-1)
+ }
+}
+
+func VariableLeft(thickness *int, rest Splitter) Splitter {
+ return func(r image.Rectangle, i, n int) image.Rectangle {
+ if i == 0 {
+ r.Max.X = r.Min.X + *thickness
+ return r
+ }
+ r.Min.X += *thickness
+ return rest(r, i-1, n-1)
+ }
+}
+
+func VariableRight(thickness *int, rest Splitter) Splitter {
+ return func(r image.Rectangle, i, n int) image.Rectangle {
+ if i == 0 {
+ r.Min.X = r.Max.X - *thickness
+ return r
+ }
+ r.Max.X -= *thickness
+ return rest(r, i-1, n-1)
+ }
+}
+
+type Split struct {
+ event.Dispatch
+ dst EventImageFlusher
+ splitter Splitter
+ boxes []*Box
+}
+
+func NewSplit(dst EventImageFlusher, splitter Splitter) *Split {
+ s := &Split{
+ dst: dst,
+ splitter: splitter,
+ }
+ dst.Event("", s.Happen)
+ s.Event("resize", func(evt string) bool {
+ s.Split()
+ return true
+ })
+ return s
+}
+
+func (s *Split) Happen(evt string) bool {
+ if s.Dispatch.Happen(evt) {
+ return true
+ }
+ for _, box := range s.boxes {
+ if box.Happen(evt) {
+ return true
+ }
+ }
+ return false
+}
+
+func (s *Split) Add() *Box {
+ box := &Box{
+ dst: s.dst,
+ }
+ s.boxes = append(s.boxes, box)
+ return box
+}
+
+func (s *Split) Split() {
+ r := s.dst.Image().Bounds()
+ n := len(s.boxes)
+ for i := range s.boxes {
+ subR := s.splitter(r, i, n)
+ s.boxes[i].sub = s.dst.Image().SubImage(subR).(*image.RGBA)
+ }
+ for i := range s.boxes {
+ subR := s.boxes[i].sub.Bounds()
+ s.boxes[i].Happen(event.Sprint("resize", subR.Min.X, subR.Min.Y, subR.Max.X, subR.Max.Y))
+ }
+}