aboutsummaryrefslogtreecommitdiffstats
path: root/layout
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2026-02-09 21:01:34 -0500
committerSam Anthony <sam@samanthony.xyz>2026-02-09 21:01:34 -0500
commit5fde17eafa11bf397bbf1f18864b8ee26d9a701d (patch)
tree6a49da06e7a9ef1faa3c99a4067e561ed077349d /layout
parent5de30aee491087fa3b58c8bd629353e1133f28ba (diff)
downloadgui-5fde17eafa11bf397bbf1f18864b8ee26d9a701d.zip
add region layout
Diffstat (limited to 'layout')
-rw-r--r--layout/doc.go15
-rw-r--r--layout/region.go63
-rw-r--r--layout/subimage.go17
3 files changed, 95 insertions, 0 deletions
diff --git a/layout/doc.go b/layout/doc.go
new file mode 100644
index 0000000..bae4673
--- /dev/null
+++ b/layout/doc.go
@@ -0,0 +1,15 @@
+/*
+Package layout provides means of partitioning screen space.
+
+A layout exists in a parent Env, and has one or more child Envs. It
+acts as a multiplexer for the children. The parent Env may be a window,
+another layout, or whatever... Several layers of layouts can be composed.
+
+A layout allocates screen area to its children by intercepting Resize
+events from the parent Env. Upon reception by the layout, a Resize event
+is transformed for each child, and forwarded to them.
+
+Draw calls from the children are intercepted and translated onto their
+respective areas before being forwarded to the parent Env.
+*/
+package layout
diff --git a/layout/region.go b/layout/region.go
new file mode 100644
index 0000000..1e92455
--- /dev/null
+++ b/layout/region.go
@@ -0,0 +1,63 @@
+package layout
+
+import (
+ "image"
+ "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.
+func NewRegion(env gui.Env, resize func(image.Rectangle) image.Rectangle) gui.Env {
+ events := make(chan gui.Event) // to child
+ drw := make(chan func(draw.Image) image.Rectangle) // from child
+
+ go func(events chan<- gui.Event, drw <-chan func(draw.Image) image.Rectangle) {
+ // Forward first resize event to child
+ event := <-env.Events()
+ area := resize(event.(gui.Resize).Rectangle) // first event guaranteed to be Resize
+ events <- gui.Resize{area}
+
+ for {
+ select {
+ case event := <-env.Events():
+ switch event := event.(type) {
+ case gui.Resize:
+ area = resize(event.Rectangle)
+ events <- gui.Resize{area}
+ default:
+ events <- event
+ }
+ case f, ok := <-drw:
+ if !ok {
+ close(events)
+ close(env.Draw())
+ return
+ }
+ env.Draw() <- drawRegion(f, area)
+ }
+ }
+ }(events, drw)
+
+ return Region{events, drw}
+}
+
+// Translate a draw call to the given area.
+func drawRegion(f func(draw.Image) image.Rectangle, area image.Rectangle) func(draw.Image) image.Rectangle {
+ return func(img draw.Image) image.Rectangle {
+ return f(subimage(img, area))
+ }
+}
+
+// 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 }
diff --git a/layout/subimage.go b/layout/subimage.go
new file mode 100644
index 0000000..ecbe931
--- /dev/null
+++ b/layout/subimage.go
@@ -0,0 +1,17 @@
+package layout
+
+import (
+ "image"
+ "image/draw"
+)
+
+type subimager interface {
+ SubImage(image.Rectangle) image.Image
+}
+
+// Subimage returns an image representing the portion of the image m visible through r.
+// The returned value shares pixels with the original.
+// Panics if the concrete image type does not have a SubImage() method.
+func subimage(m draw.Image, r image.Rectangle) draw.Image {
+ return m.(subimager).SubImage(r).(draw.Image)
+}