aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2024-08-24 15:39:09 -0400
committerSam Anthony <sam@samanthony.xyz>2024-08-24 15:39:09 -0400
commit9bf3236dc993a3d8dbf4caf14bd448ab4de70a72 (patch)
tree59a2249503e680eb24a2ed68ec775c3dac8d2b57
parente725799ad17c575a7a3cd2536f57bd82f85782e5 (diff)
downloadgui-9bf3236dc993a3d8dbf4caf14bd448ab4de70a72.zip
adapt scroller to new layout design
-rw-r--r--layout/doc.go10
-rw-r--r--layout/scroller.go132
-rw-r--r--scroller.go127
3 files changed, 127 insertions, 142 deletions
diff --git a/layout/doc.go b/layout/doc.go
deleted file mode 100644
index 8305d43..0000000
--- a/layout/doc.go
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
-Package layout provides a Layout system for faiface/gui.
-
-The core of the package is the Layout interface, everything else is just
-implementation.
-
-The Layouts represent a Layout, and the Mux makes them usable.
-The Mux basically acts as a sort of driver.
-*/
-package layout
diff --git a/layout/scroller.go b/layout/scroller.go
deleted file mode 100644
index c532f93..0000000
--- a/layout/scroller.go
+++ /dev/null
@@ -1,132 +0,0 @@
-package layout
-
-import (
- "image"
- "image/color"
- "image/draw"
- // "log"
- "sync"
-
- "github.com/faiface/gui"
- "github.com/faiface/gui/win"
-)
-
-var _ Layout = &Scroller{}
-
-type Scroller struct {
- Background color.Color
- Length int
- ChildHeight int
- Offset int
- Gap int
- Vertical bool
-}
-
-func (s Scroller) redraw(drw draw.Image, bounds image.Rectangle) {
- col := s.Background
- if col == nil {
- col = image.Black
- }
- draw.Draw(drw, bounds, image.NewUniform(col), image.ZP, draw.Src)
-}
-
-func clamp(val, a, b int) int {
- if a > b {
- if val < b {
- return b
- }
- if val > a {
- return a
- }
- } else {
- if val > b {
- return b
- }
- if val < a {
- return a
- }
- }
- return val
-}
-
-func (s *Scroller) Intercept(env gui.Env) gui.Env {
- out, in := gui.MakeEventsChan()
- drawChan := make(chan func(draw.Image) image.Rectangle)
- ret := &muxEnv{out, drawChan}
- var lastResize gui.Resize
- var img draw.Image
- img = image.NewRGBA(image.ZR)
- var mu sync.Mutex
- var over bool
-
- go func() {
- for dc := range drawChan {
- mu.Lock()
- // draw.Draw will not draw out of bounds, call should be inexpensive if element not visible
- res := dc(img)
- // Only send a draw call up if visibly changed
- if res.Intersect(img.Bounds()) != image.ZR {
- env.Draw() <- func(drw draw.Image) image.Rectangle {
- draw.Draw(drw, lastResize.Rectangle, img, lastResize.Rectangle.Min, draw.Over)
- return img.Bounds()
- }
- }
- mu.Unlock()
- }
- }()
-
- go func() {
- for ev := range env.Events() {
- switch ev := ev.(type) {
- case win.MoMove:
- mu.Lock()
- over = ev.Point.In(lastResize.Rectangle)
- mu.Unlock()
- case win.MoScroll:
- if !over {
- continue
- }
- mu.Lock()
- oldoff := s.Offset
- v := s.Length*s.ChildHeight + ((s.Length + 1) * s.Gap)
- if s.Vertical {
- h := lastResize.Dx()
- s.Offset = clamp(s.Offset+ev.Point.X*16, h-v, 0)
- } else {
- h := lastResize.Dy()
- s.Offset = clamp(s.Offset+ev.Point.Y*16, h-v, 0)
- }
- if oldoff != s.Offset {
- s.redraw(img, img.Bounds())
- in <- lastResize
- }
- mu.Unlock()
- case gui.Resize:
- mu.Lock()
- lastResize = ev
- img = image.NewRGBA(lastResize.Rectangle)
- s.redraw(img, img.Bounds())
- mu.Unlock()
- in <- ev
- default:
- in <- ev
- }
- }
- }()
- return ret
-}
-
-func (s Scroller) Lay(bounds image.Rectangle) []image.Rectangle {
- items := s.Length
- ch := s.ChildHeight
- gap := s.Gap
-
- ret := make([]image.Rectangle, items)
- Y := bounds.Min.Y + s.Offset + gap
- for i := 0; i < items; i++ {
- r := image.Rect(bounds.Min.X+gap, Y, bounds.Max.X-gap, Y+ch)
- ret[i] = r
- Y += ch + gap
- }
- return ret
-}
diff --git a/scroller.go b/scroller.go
new file mode 100644
index 0000000..fe411f3
--- /dev/null
+++ b/scroller.go
@@ -0,0 +1,127 @@
+package gui
+
+import (
+ "image"
+ "image/color"
+ "image/draw"
+
+ "git.samanthony.xyz/share"
+)
+
+var _ Scheme = Scroller{}
+
+type Scroller struct {
+ Background color.Color
+ Length int
+ ChildHeight int
+ Offset int
+ Gap int
+ Vertical bool
+}
+
+func (s Scroller) redraw(drw draw.Image, bounds image.Rectangle) {
+ col := s.Background
+ if col == nil {
+ col = image.Black
+ }
+ draw.Draw(drw, bounds, image.NewUniform(col), image.ZP, draw.Src)
+}
+
+func clamp(val, a, b int) int {
+ if a > b {
+ if val < b {
+ return b
+ }
+ if val > a {
+ return a
+ }
+ } else {
+ if val > b {
+ return b
+ }
+ if val < a {
+ return a
+ }
+ }
+ return val
+}
+
+func (s Scroller) Partition(bounds image.Rectangle) []image.Rectangle {
+ items := s.Length
+ ch := s.ChildHeight
+ gap := s.Gap
+
+ ret := make([]image.Rectangle, items)
+ Y := bounds.Min.Y + s.Offset + gap
+ for i := 0; i < items; i++ {
+ r := image.Rect(bounds.Min.X+gap, Y, bounds.Max.X-gap, Y+ch)
+ ret[i] = r
+ Y += ch + gap
+ }
+ return ret
+}
+
+func (s Scroller) Intercept(parent Env) Env {
+ lastResize := share.NewVal[image.Rectangle]()
+ img := share.NewVal[draw.Image]()
+ mouseOver := share.NewVal[bool]()
+
+ lastResize.Set <- image.Rectangle{}
+ img.Set <- image.NewRGBA(image.Rectangle{})
+ mouseOver.Set <- false
+
+ return newEnv(parent,
+ func(event Event, events chan<- Event) {
+ switch event := event.(type) {
+ case MoMove:
+ mouseOver.Set <- event.Point.In(lastResize.Get())
+ case MoScroll:
+ if !mouseOver.Get() {
+ break
+ }
+
+ oldoff := s.Offset
+ v := s.Length*s.ChildHeight + ((s.Length + 1) * s.Gap)
+ bounds := lastResize.Get()
+
+ if s.Vertical {
+ h := bounds.Dx()
+ s.Offset = clamp(s.Offset+event.Point.X*16, h-v, 0)
+ } else {
+ h := bounds.Dy()
+ s.Offset = clamp(s.Offset+event.Point.Y*16, h-v, 0)
+ }
+
+ if oldoff != s.Offset {
+ m := img.Get()
+ s.redraw(m, m.Bounds())
+ events <- Resize{bounds}
+ }
+ case Resize:
+ lastResize.Set <- event.Rectangle
+
+ m := image.NewRGBA(event.Rectangle)
+ img.Set <- m
+ s.redraw(m, m.Bounds())
+
+ events <- event
+ default:
+ events <- event
+ }
+ },
+ func(drawFunc func(draw.Image) image.Rectangle, drawChan chan<- func(draw.Image) image.Rectangle) {
+ m := img.Get()
+ if drawFunc(m).Intersect(m.Bounds()) != image.ZR {
+ drawChan <- func(drw draw.Image) image.Rectangle {
+ bounds := lastResize.Get()
+ draw.Draw(drw, bounds, m, bounds.Min, draw.Over)
+ return m.Bounds()
+ }
+ }
+ },
+ func() {
+ lastResize.Close()
+ img.Close()
+ mouseOver.Close()
+ })
+}