aboutsummaryrefslogtreecommitdiffstats
path: root/gui/widget
diff options
context:
space:
mode:
Diffstat (limited to 'gui/widget')
-rw-r--r--gui/widget/concurrent_face.go51
-rw-r--r--gui/widget/text.go78
-rw-r--r--gui/widget/widget.go73
3 files changed, 67 insertions, 135 deletions
diff --git a/gui/widget/concurrent_face.go b/gui/widget/concurrent_face.go
deleted file mode 100644
index 98db572..0000000
--- a/gui/widget/concurrent_face.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package widget
-
-import (
- "image"
- "sync"
-
- "golang.org/x/image/font"
- "golang.org/x/image/math/fixed"
-)
-
-type concurrentFace struct {
- mu sync.Mutex
- face font.Face
-}
-
-func (cf *concurrentFace) Close() error {
- cf.mu.Lock()
- defer cf.mu.Unlock()
- return cf.face.Close()
-}
-
-func (cf *concurrentFace) Glyph(dot fixed.Point26_6, r rune) (
- dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
- cf.mu.Lock()
- defer cf.mu.Unlock()
- return cf.face.Glyph(dot, r)
-}
-
-func (cf *concurrentFace) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
- cf.mu.Lock()
- defer cf.mu.Unlock()
- return cf.face.GlyphBounds(r)
-}
-
-func (cf *concurrentFace) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
- cf.mu.Lock()
- defer cf.mu.Unlock()
- return cf.face.GlyphAdvance(r)
-}
-
-func (cf *concurrentFace) Kern(r0, r1 rune) fixed.Int26_6 {
- cf.mu.Lock()
- defer cf.mu.Unlock()
- return cf.face.Kern(r0, r1)
-}
-
-func (cf *concurrentFace) Metrics() font.Metrics {
- cf.mu.Lock()
- defer cf.mu.Unlock()
- return cf.face.Metrics()
-}
diff --git a/gui/widget/text.go b/gui/widget/text.go
deleted file mode 100644
index 1b40096..0000000
--- a/gui/widget/text.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package widget
-
-import (
- "log"
- "sync"
-
- "image"
- "image/color"
- "image/draw"
-
- "golang.org/x/image/font"
- "golang.org/x/image/font/gofont/goregular"
- "golang.org/x/image/font/opentype"
- "golang.org/x/image/math/fixed"
-)
-
-var (
- FONT = goregular.TTF
- FONT_SIZE = 15
- DPI = 72
- PAD = 3
-)
-
-var face *concurrentFace
-
-func init() {
- fnt, err := opentype.Parse(FONT)
- if err != nil {
- log.Fatal(err)
- }
- fce, err := opentype.NewFace(fnt, &opentype.FaceOptions{
- Size: float64(FONT_SIZE),
- DPI: float64(DPI),
- })
- if err != nil {
- log.Fatal(err)
- }
- face = &concurrentFace{sync.Mutex{}, fce}
-}
-
-func TextSize(text string) image.Point {
- bounds := textBounds([]byte(text), font.Drawer{Face: face})
- return image.Point{bounds.Max.X - bounds.Min.X + 2*PAD, bounds.Max.Y - bounds.Min.Y + 2*PAD}
-}
-
-func drawText(text []byte, dst draw.Image, r image.Rectangle, fg, bg color.Color) {
- drawer := font.Drawer{
- Src: &image.Uniform{fg},
- Face: face,
- Dot: fixed.P(0, 0),
- }
-
- // background
- draw.Draw(dst, r, &image.Uniform{bg}, image.ZP, draw.Src)
-
- // text image
- bounds := textBounds(text, drawer)
- textImg := image.NewRGBA(bounds)
- draw.Draw(textImg, bounds, &image.Uniform{bg}, image.ZP, draw.Src)
- drawer.Dst = textImg
- drawer.DrawBytes(text)
-
- // draw text image over background
- leftCentre := image.Pt(bounds.Min.X, (bounds.Min.Y+bounds.Max.Y)/2)
- target := image.Pt(r.Max.X-bounds.Max.X-PAD, (r.Min.Y+r.Max.Y)/2)
- delta := target.Sub(leftCentre)
- draw.Draw(dst, bounds.Add(delta).Intersect(r), drawer.Dst, bounds.Min, draw.Src)
-}
-
-func textBounds(text []byte, drawer font.Drawer) image.Rectangle {
- b, _ := drawer.BoundBytes(text)
- return image.Rect(
- b.Min.X.Floor(),
- b.Min.Y.Floor(),
- b.Max.X.Ceil(),
- b.Max.Y.Ceil(),
- )
-}
diff --git a/gui/widget/widget.go b/gui/widget/widget.go
index 2e7c671..3fd9637 100644
--- a/gui/widget/widget.go
+++ b/gui/widget/widget.go
@@ -11,6 +11,8 @@ import (
"image/draw"
"volute/gui"
+ "volute/gui/layout"
+ "volute/gui/text"
"volute/gui/win"
)
@@ -23,12 +25,71 @@ var (
interpolator = xdraw.ApproxBiLinear
)
-func Label(text string, r image.Rectangle, env gui.Env, wg *sync.WaitGroup) {
+type Node[T any] struct {
+ Label string
+ Value T
+ Children []Node[T]
+
+ expanded bool
+}
+
+func Tree[T any](trees []Node[T], r image.Rectangle, focus FocusSlave, mux *gui.Mux, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ var nodes []string
+ for _, root := range trees {
+ nodes = append(nodes, flatten(root, 0)...)
+ }
+
+ bounds := layout.Grid{
+ Rows: populate(make([]int, len(nodes)), 1),
+ Background: color.Gray{255},
+ Gap: 1,
+ Split: layout.EvenSplit,
+ SplitRows: layout.TextRowSplit,
+ Margin: 0,
+ Border: 0,
+ BorderColor: color.Gray{16},
+ Flip: false,
+ }.Lay(r)
+ for i := range nodes {
+ wg.Add(1)
+ go Label(nodes[i], bounds[i], mux.MakeEnv(), wg)
+ }
+
+ /*
+ globalFocus := focus;
+ localFocus := NewFocusMaster([]int{1, 1, 1});
+ defer localFocus.Close()
+ */
+ // TODO
+}
+
+func flatten[T any](root Node[T], depth int) []string {
+ indent := string(populate(make([]byte, 2*depth), ' '))
+ nodes := []string{indent + root.Label}
+ root.expanded = true // TODO: remove me
+ if root.expanded {
+ for _, c := range root.Children {
+ nodes = append(nodes, flatten(c, depth+1)...)
+ }
+ }
+ return nodes
+}
+
+func populate[T any](arr []T, v T) []T {
+ for i := range arr {
+ arr[i] = v
+ }
+ return arr
+}
+
+func Label(str string, r image.Rectangle, env gui.Env, wg *sync.WaitGroup) {
defer wg.Done()
defer close(env.Draw())
redraw := func(drw draw.Image) image.Rectangle {
- drawText([]byte(text), drw, r, BLACK, WHITE)
+ text.Draw([]byte(str), drw, r, BLACK, WHITE)
return r
}
@@ -93,12 +154,12 @@ Loop:
}
}
-func inputDraw(text []byte, focused bool, r image.Rectangle) func(draw.Image) image.Rectangle {
+func inputDraw(str []byte, focused bool, r image.Rectangle) func(draw.Image) image.Rectangle {
return func(drw draw.Image) image.Rectangle {
if focused {
- drawText(text, drw, r, GREEN, FOCUS_COLOR)
+ text.Draw(str, drw, r, GREEN, FOCUS_COLOR)
} else {
- drawText(text, drw, r, GREEN, WHITE)
+ text.Draw(str, drw, r, GREEN, WHITE)
}
return r
}
@@ -128,7 +189,7 @@ Loop:
func outputDraw(v float64, r image.Rectangle) func(draw.Image) image.Rectangle {
return func(drw draw.Image) image.Rectangle {
- drawText([]byte(fmt.Sprintf("%.3f", v)), drw, r, BLACK, WHITE)
+ text.Draw([]byte(fmt.Sprintf("%.3f", v)), drw, r, BLACK, WHITE)
return r
}
}