diff options
Diffstat (limited to 'layout/split.go')
| -rw-r--r-- | layout/split.go | 161 |
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)) + } +} |