94 lines
2.3 KiB
Go
94 lines
2.3 KiB
Go
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()
|
||
}
|