WIP components (as built)
This commit is contained in:
71 files changed
+3241
-468
No files matched your search
+17
-20
@@ -2,6 +2,7 @@ package mujica
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -12,19 +13,10 @@ import (
|
||||
type TypewriterOptions struct {
|
||||
// Speed is characters per second; zero means 40.
|
||||
Speed float64
|
||||
// Skippable adds a Skip button that shows the rest at once.
|
||||
// Skippable adds a Skip button.
|
||||
Skippable bool
|
||||
}
|
||||
|
||||
// TypewriterResult is a built Typewriter and its events.
|
||||
type TypewriterResult struct {
|
||||
Element *ui.Element
|
||||
done bool
|
||||
}
|
||||
|
||||
// Finished reports the frame the whole text came into view.
|
||||
func (r TypewriterResult) Finished() bool { return r.done }
|
||||
|
||||
type typewriterState struct {
|
||||
text []rune
|
||||
shown int
|
||||
@@ -33,26 +25,31 @@ type typewriterState struct {
|
||||
done bool
|
||||
}
|
||||
|
||||
// Typewriter reveals text a character at a time; text that grows continues where it was.
|
||||
func Typewriter(c *ui.Context, text string, opts TypewriterOptions) TypewriterResult {
|
||||
// Typewriter reveals text one character at a time.
|
||||
func Typewriter(c *ui.Context, text string, opts TypewriterOptions) ChoiceResult {
|
||||
speed := opts.Speed
|
||||
if speed == 0 {
|
||||
speed = 40
|
||||
}
|
||||
if speed < 0 {
|
||||
panic("mujica: Typewriter Speed is negative")
|
||||
if math.IsNaN(speed) || math.IsInf(speed, 0) || speed < float64(time.Second)/float64(math.MaxInt64) || speed > float64(time.Second) {
|
||||
panic("mujica: Typewriter Speed must give a finite positive interval")
|
||||
}
|
||||
step := time.Duration(float64(time.Second) / speed)
|
||||
if step <= 0 {
|
||||
panic("mujica: Typewriter Speed interval exceeds time.Duration")
|
||||
}
|
||||
col := ui.Column(c).AlignItems(ui.Start).Gap(Density(c).Unit() * 2).Role(ui.RoleGroup).Label(text)
|
||||
res := TypewriterResult{Element: col}
|
||||
res := ChoiceResult{Element: col}
|
||||
st := ui.Local(col, "typing", func() *typewriterState { return &typewriterState{last: c.Now()} })
|
||||
s := *st
|
||||
runes := []rune(text)
|
||||
if !strings.HasPrefix(text, string(s.text)) {
|
||||
s.shown, s.skipped, s.done = 0, false, false
|
||||
s.last = c.Now()
|
||||
slog.Debug("mujica: typewriter restart")
|
||||
}
|
||||
if len(runes) > len(s.text) && s.done {
|
||||
// New text continues from where it stood, at the typing speed.
|
||||
// Appended text continues at the typing speed.
|
||||
s.done, s.skipped, s.last = false, false, c.Now()
|
||||
}
|
||||
s.text = runes
|
||||
@@ -60,13 +57,12 @@ func Typewriter(c *ui.Context, text string, opts TypewriterOptions) TypewriterRe
|
||||
if c.Preferences().ReduceMotion || s.skipped {
|
||||
s.shown = len(runes)
|
||||
} else if s.shown < len(runes) {
|
||||
step := time.Duration(float64(time.Second) / speed)
|
||||
if n := int(now.Sub(s.last) / step); n > 0 {
|
||||
s.shown = min(len(runes), s.shown+n)
|
||||
s.last = s.last.Add(time.Duration(n) * step)
|
||||
}
|
||||
if s.shown < len(runes) {
|
||||
c.After(s.last.Add(step).Sub(now))
|
||||
col.DrawOver(func(*ui.Painter, ui.Rect) { c.After(s.last.Add(step).Sub(c.Now())) })
|
||||
}
|
||||
} else {
|
||||
s.last = now
|
||||
@@ -74,14 +70,15 @@ func Typewriter(c *ui.Context, text string, opts TypewriterOptions) TypewriterRe
|
||||
col.Children(func() {
|
||||
ui.Text(c, string(runes[:s.shown]))
|
||||
if opts.Skippable && s.shown < len(runes) {
|
||||
if Button(c, msg(c, "typewriter.skip"), ButtonOptions{Variant: Ghost}).Clicked() {
|
||||
b := Button(c, msg(c, "typewriter.skip"), ButtonOptions{Variant: Ghost})
|
||||
if b.Clicked() && !b.IsDisabled() {
|
||||
s.skipped, s.shown = true, len(runes)
|
||||
slog.Debug("mujica: typewriter skip")
|
||||
}
|
||||
}
|
||||
})
|
||||
if s.shown == len(runes) && !s.done {
|
||||
s.done, res.done = true, true
|
||||
s.done, res.changed = true, true
|
||||
}
|
||||
return res
|
||||
}
|
||||
Reference in new issue
Block a user