Files
8bitMyGoUI/display/signpost.go
T

94 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package display
import (
"fmt"
"log/slog"
"github.com/egoist/mygo/ui"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
)
type SignpostOptions struct {
Disabled bool
}
type SignpostResult struct {
Element *ui.Element
// Clicked is the board clicked this frame, or -1.
Clicked int
}
// Signpost is a post with one to three arrow boards.
func Signpost(c *ui.Context, boards []string, o SignpostOptions) SignpostResult {
if len(boards) < 1 || len(boards) > 3 {
panic(fmt.Sprintf("display: Signpost needs 1–3 boards, got %d", len(boards)))
}
k := pixel.K(c)
w := 0
for _, b := range boards {
w = max(w, pixel.Measure(b))
}
w += 18
res := SignpostResult{Clicked: -1}
res.Element = ui.Column(c).Width(k.D(w+8)).Gap(k.D(3)).AlignItems(ui.Center).Padding(0, 0, k.D(20), 0).Role(ui.RoleGroup).FocusGroup(ui.Vertical).Draw(func(p *ui.Painter, r ui.Rect) {
g := k.Canvas(p, r)
g.Rect(g.W/2-2, 2, 4, g.H-2, pixel.Shade)
g.VLine(g.W/2-2, 2, g.H-2, pixel.Edge)
g.VLine(g.W/2+1, 2, g.H-2, pixel.Edge)
}).Children(func() {
for i, b := range boards {
if board(c, k, b, w, i%2 == 1, o.Disabled) {
res.Clicked = i
}
}
})
if res.Clicked >= 0 {
slog.Debug("8bit: signpost", "board", boards[res.Clicked])
}
return res
}
// board is one wooden arrow, pointing left if asked.
func board(c *ui.Context, k pixel.Kit, label string, w int, left, disabled bool) bool {
shell, base, st := pixel.Shell(c, func() *ui.Element { return ui.ButtonBase(c).Label(label).Disabled(disabled) })
h := pixel.LineHeight + 2
shell.Size(k.D(w), k.D(h)).Draw(func(p *ui.Painter, r ui.Rect) {
g := k.Canvas(p, r)
dy := 0
if st.Press {
dy = 1
}
for j := range h - dy {
cut := abs(j - (h-1)/2)
x0, x1 := 0, w-cut
if left {
x0, x1 = cut, w
}
fill := pixel.Warn
if j == 0 || j == h-1-dy {
fill = pixel.Edge
}
g.HLine(x0, j+dy, x1-x0, fill)
g.Dot(x0, j+dy, pixel.Edge)
g.Dot(x1-1, j+dy, pixel.Edge)
}
g.Veil(1, 1+dy, w-2, h-3, pixel.Shade, 4)
tx := 6
if left {
tx = w - 6 - pixel.Measure(label)
}
g.Text(tx, 1+dy, label, pixel.Ink, 1)
if st.Hover {
g.Veil(1, 1+dy, w-2, h-3, pixel.Lit, 4)
}
if st.Disabled {
g.Checker(0, 0, w, h, pixel.Face)
}
if st.Focus {
g.FocusMark(0, 0, w, h)
}
})
return base.Clicked()
}