Add palettes and frame settings
This commit is contained in:
7 files changed
+542
-1
No files matched your search
@@ -0,0 +1,125 @@
|
||||
package pixel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
)
|
||||
|
||||
type Locale uint8
|
||||
|
||||
const (
|
||||
En Locale = iota
|
||||
Zh
|
||||
)
|
||||
|
||||
type Settings struct {
|
||||
Palette *Palette
|
||||
// Dot is DIPs per dot, 1–4; zero means 2.
|
||||
Dot int
|
||||
Locale Locale
|
||||
// Now replaces the frame clock, for tests.
|
||||
Now func() time.Time
|
||||
}
|
||||
|
||||
// Kit is one frame's settings, captured by components.
|
||||
type Kit struct {
|
||||
pal *Palette
|
||||
dot float32
|
||||
locale Locale
|
||||
now time.Time
|
||||
reduce bool
|
||||
}
|
||||
|
||||
func (k Kit) Palette() *Palette { return k.pal }
|
||||
func (k Kit) C(s Slot) ui.Color { return k.pal.Colors[s] }
|
||||
func (k Kit) Dot() float32 { return k.dot }
|
||||
func (k Kit) D(n int) float32 { return float32(n) * k.dot }
|
||||
func (k Kit) Locale() Locale { return k.locale }
|
||||
func (k Kit) Now() time.Time { return k.now }
|
||||
func (k Kit) Reduce() bool { return k.reduce }
|
||||
|
||||
type frame struct {
|
||||
cur Settings
|
||||
at time.Time
|
||||
}
|
||||
|
||||
type frameKey struct{}
|
||||
|
||||
// Use must run once per frame, before any component.
|
||||
func Use(c *ui.Context, s Settings) {
|
||||
s = s.valid()
|
||||
f := frameOf(c)
|
||||
if f.cur.Palette != s.Palette {
|
||||
slog.Debug("8bit: palette", "name", s.Palette.Name)
|
||||
}
|
||||
f.cur, f.at = s, c.Now()
|
||||
c.SetTheme(theme(s.Palette))
|
||||
}
|
||||
|
||||
// Scope builds fn under other settings.
|
||||
func Scope(c *ui.Context, s Settings, fn func()) {
|
||||
f := current(c)
|
||||
prev := f.cur
|
||||
f.cur = s.valid()
|
||||
fn()
|
||||
f.cur = prev
|
||||
}
|
||||
|
||||
// Lazy keeps this scope for rows MyGo builds during layout.
|
||||
func Lazy[T any](c *ui.Context, fn func(T)) func(T) {
|
||||
s := current(c).cur
|
||||
return func(v T) { Scope(c, s, func() { fn(v) }) }
|
||||
}
|
||||
|
||||
func K(c *ui.Context) Kit {
|
||||
s := current(c).cur
|
||||
now := c.Now()
|
||||
if s.Now != nil {
|
||||
now = s.Now()
|
||||
}
|
||||
return Kit{pal: s.Palette, dot: float32(s.Dot), locale: s.Locale, now: now, reduce: c.Preferences().ReduceMotion}
|
||||
}
|
||||
|
||||
func frameOf(c *ui.Context) *frame {
|
||||
return ui.Local(c.Root(), frameKey{}, func() frame { return frame{} })
|
||||
}
|
||||
|
||||
func current(c *ui.Context) *frame {
|
||||
f := frameOf(c)
|
||||
if !f.at.Equal(c.Now()) {
|
||||
panic("pixel: Use was not called in this frame")
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (s Settings) valid() Settings {
|
||||
if s.Palette == nil {
|
||||
panic("pixel: Settings.Palette is nil")
|
||||
}
|
||||
if s.Dot == 0 {
|
||||
s.Dot = 2
|
||||
}
|
||||
if s.Dot < 1 || s.Dot > 4 {
|
||||
panic(fmt.Sprintf("pixel: Settings.Dot %d outside 1–4", s.Dot))
|
||||
}
|
||||
if s.Locale > Zh {
|
||||
panic(fmt.Sprintf("pixel: unknown Locale %d", s.Locale))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// theme keeps MyGo's own drawing inside the palette.
|
||||
func theme(p *Palette) *ui.Theme {
|
||||
t := ui.LightTheme()
|
||||
c := p.Colors
|
||||
t.Dark = p.Night
|
||||
t.Background, t.Surface, t.SurfaceHover, t.SurfacePressed = c[Back], c[Face], c[Lit], c[Shade]
|
||||
t.Border, t.Text, t.TextMuted = c[Edge], c[Ink], c[Faint]
|
||||
t.Accent, t.AccentHover, t.AccentPressed, t.AccentText = c[Accent], c[AccentLit], c[Accent], c[AccentInk]
|
||||
t.Danger, t.Warning, t.Success = c[Bad], c[Warn], c[Good]
|
||||
t.Selection, t.Focus, t.Scrollbar, t.Radius = c[AccentLit], c[Accent], ui.Transparent, 0
|
||||
return t
|
||||
}
|
||||
Reference in new issue
Block a user