Upgrade MyGo to v0.5.5

Elements are now pass-scoped value handles: tests that read bounds
after a frame bind a ui.Handle. pixel tells frames apart by the build
pass's root, since the Tester clock no longer moves on its own.

Fix the regressions the upgrade brought:
- Clipboard reads in input handlers go through c.Services().
- MyGo notes an overlay's opener after building it, so AutoFocus
  inside lost it; pixel.AutoFocus focuses through a Handle, and
  archtest bans the raw call. Dialogs hand the focus back again.
- Elements around a press stay hovered: Tooltip tells a press-given
  focus by focus arriving under the pointer.
- The web host moves the Tester clock with real time, at most 500 ms
  a call, and gives components the real clock.

The gallery's source index also accepts CRLF checkouts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-17 01:31:08 -04:00
1 parent 1f3d38110e
commit 03e1f91706
532 files changed
+828 -735

No files matched your search

+1 -1
View File
@@ -16,7 +16,7 @@ type AccordionOptions struct {
}
type AccordionResult struct {
Element *ui.Element
Element ui.Element
Changed bool
}
+1 -1
View File
@@ -26,7 +26,7 @@ type BestiaryOptions struct {
}
// Bestiary is a monster card; unseen ones are silhouettes.
func Bestiary(c *ui.Context, m Monster, o BestiaryOptions) *ui.Element {
func Bestiary(c *ui.Context, m Monster, o BestiaryOptions) ui.Element {
k := pixel.K(c)
sc := pixel.Or("Bestiary Scale", o.Scale, 2)
if m.Sprite == nil || sc > 4 {
+1 -1
View File
@@ -13,7 +13,7 @@ type CardGridOptions struct {
}
// CardGrid fits as many card columns as width allows.
func CardGrid(c *ui.Context, n int, o CardGridOptions, card func(i int)) *ui.Element {
func CardGrid(c *ui.Context, n int, o CardGridOptions, card func(i int)) ui.Element {
mw := pixel.Or("CardGrid MinWidth", o.MinWidth, 96)
box := ui.Box(c).FillWidth()
w, check := pixel.WrapWidth(c, box)
+1 -1
View File
@@ -19,7 +19,7 @@ type CarouselOptions struct {
}
type CarouselResult struct {
Element *ui.Element
Element ui.Element
Changed bool
}
+2 -2
View File
@@ -13,7 +13,7 @@ type CollapsibleOptions struct {
}
type CollapsibleResult struct {
Element *ui.Element
Element ui.Element
Changed bool
}
@@ -25,7 +25,7 @@ func Collapsible(c *ui.Context, title string, open *bool, o CollapsibleOptions,
col.Children(func() {
// The base turns before it learns it is off.
v := *open
shell, base, st := pixel.Shell(c, func() *ui.Element {
shell, base, st := pixel.Shell(c, func() ui.Element {
return ui.CollapsibleBase(c, &v).Trigger.Label(title).Disabled(o.Disabled)
})
if res.Changed = v != *open && !base.IsDisabled(); res.Changed {
+1 -1
View File
@@ -28,7 +28,7 @@ var (
)
// well sinks box and finishes it as st says.
func well(c *ui.Context, box *ui.Element, st pixel.State) {
func well(c *ui.Context, box ui.Element, st pixel.State) {
k := pixel.K(c)
box.Padding(k.D(2)).Draw(func(p *ui.Painter, r ui.Rect) {
g := k.Canvas(p, r)
+1 -1
View File
@@ -13,7 +13,7 @@ type DescriptionListOptions struct {
}
// DescriptionList sets terms beside their descriptions.
func DescriptionList(c *ui.Context, pairs [][2]string, o DescriptionListOptions) *ui.Element {
func DescriptionList(c *ui.Context, pairs [][2]string, o DescriptionListOptions) ui.Element {
k := pixel.K(c)
tw := pixel.Or("DescriptionList TermWidth", o.TermWidth, 80)
return ui.Column(c).FillWidth().Gap(k.D(4)).Children(func() {
+1 -1
View File
@@ -16,7 +16,7 @@ type Activity struct {
type FeedOptions struct{}
// Feed lists activity: icon, text and time, dotted apart.
func Feed(c *ui.Context, entries []Activity, o FeedOptions) *ui.Element {
func Feed(c *ui.Context, entries []Activity, o FeedOptions) ui.Element {
k := pixel.K(c)
return ui.Column(c).FillWidth().Children(func() {
for i, a := range entries {
+1 -1
View File
@@ -16,7 +16,7 @@ type FilterBarOptions struct {
}
type FilterBarResult struct {
Element *ui.Element
Element ui.Element
Changed bool
}
+1 -1
View File
@@ -18,7 +18,7 @@ type GridViewOptions struct {
}
type GridViewResult struct {
Element *ui.Element
Element ui.Element
// Submitted is Enter or a double click on an item.
Changed, Submitted bool
}
+2 -2
View File
@@ -17,7 +17,7 @@ type InfiniteListOptions struct {
}
type InfiniteListResult struct {
Element *ui.Element
Element ui.Element
// More asks for rows past the n there are.
More bool
}
@@ -42,7 +42,7 @@ func InfiniteList(c *ui.Context, text string, n int, o InfiniteListOptions, row
if o.Done {
rows = n
}
var e *ui.Element
var e ui.Element
box.Children(func() {
e = ui.List(c, &s.list, rows, pixel.Lazy(c, func(i int) {
if i < n {
+1 -1
View File
@@ -16,7 +16,7 @@ type InventoryOptions struct {
}
type InventoryResult struct {
Element *ui.Element
Element ui.Element
// Swapped reports two slots traded by a drag.
Changed, Swapped bool
}
+1 -1
View File
@@ -26,7 +26,7 @@ type ItemSlotOptions struct {
}
// ItemSlot shows an item, count, rarity edge and cooldown.
func ItemSlot(c *ui.Context, it Item, o ItemSlotOptions) *ui.Element {
func ItemSlot(c *ui.Context, it Item, o ItemSlotOptions) ui.Element {
k := pixel.K(c)
o.check()
return ui.Box(c).Role(ui.RoleImage).Label(it.String()).Size(k.D(SlotSize), k.D(SlotSize)).Draw(func(p *ui.Painter, r ui.Rect) {
+1 -1
View File
@@ -23,7 +23,7 @@ type LeaderboardOptions struct {
}
// Leaderboard ranks scores; the top three wear medals.
func Leaderboard(c *ui.Context, scores []Score, o LeaderboardOptions) *ui.Element {
func Leaderboard(c *ui.Context, scores []Score, o LeaderboardOptions) ui.Element {
k := pixel.K(c)
if o.Player < -1 || o.Player >= len(scores) {
panic(fmt.Sprintf("data: Leaderboard Player %d of %d", o.Player, len(scores)))
+2 -2
View File
@@ -15,7 +15,7 @@ type ListOptions struct {
}
type ListResult struct {
Element *ui.Element
Element ui.Element
// Submitted is Enter or a double click on a row.
Changed, Submitted bool
}
@@ -33,7 +33,7 @@ func List(c *ui.Context, text string, n int, selected *int, o ListOptions, name
if off {
st.Selected = nil
}
var e *ui.Element
var e ui.Element
box.Children(func() {
e = ui.List(c, st, n, pixel.Lazy(c, func(i int) {
on := i == *selected
+1 -1
View File
@@ -14,7 +14,7 @@ type MatrixOptions struct {
}
type MatrixResult struct {
Element *ui.Element
Element ui.Element
Changed bool
}
+2 -2
View File
@@ -15,7 +15,7 @@ type OutlineOptions struct {
}
type OutlineResult struct {
Element *ui.Element
Element ui.Element
Changed, Submitted bool
}
@@ -47,7 +47,7 @@ func Outline[K comparable](c *ui.Context, text string, roots []K, children func(
if off {
st.list.Selected = nil
}
var e *ui.Element
var e ui.Element
box.Children(func() {
e = ui.List(c, &st.list, len(rows), pixel.Lazy(c, func(i int) {
r, on, ink := rows[i], i == st.at, pixel.Ink
+1 -1
View File
@@ -20,7 +20,7 @@ type PagerOptions struct {
}
type PagerResult struct {
Element *ui.Element
Element ui.Element
Changed bool
}
+1 -1
View File
@@ -27,7 +27,7 @@ type PropertyGridOptions struct {
}
type PropertyGridResult struct {
Element *ui.Element
Element ui.Element
Changed bool
}
+2 -2
View File
@@ -16,7 +16,7 @@ type SortableOptions struct {
}
type SortableResult struct {
Element *ui.Element
Element ui.Element
Changed bool
}
@@ -33,7 +33,7 @@ func Sortable(c *ui.Context, text string, items *[]string, o SortableOptions) So
k := pixel.K(c)
n := len(*items)
off := o.Disabled || pixel.Current(c).Inert
shell, base, st := pixel.Shell(c, func() *ui.Element {
shell, base, st := pixel.Shell(c, func() ui.Element {
return ui.Box(c).Focusable().Role(ui.RoleList).Label(text).Disabled(o.Disabled)
})
s := ui.Local(base, sortKey{}, func() sorting { return sorting{} })
+1 -1
View File
@@ -18,7 +18,7 @@ type Change struct {
type StatCompareOptions struct{}
// StatCompare lists stats old → new with ▲▼ deltas.
func StatCompare(c *ui.Context, changes []Change, o StatCompareOptions) *ui.Element {
func StatCompare(c *ui.Context, changes []Change, o StatCompareOptions) ui.Element {
k := pixel.K(c)
lw, ow, nw, dw := 0, 0, 0, 0
deltas := make([]string, len(changes))
+3 -3
View File
@@ -28,7 +28,7 @@ type TableOptions struct {
}
type TableResult struct {
Element *ui.Element
Element ui.Element
// Sorted reports a header click; sort the rows by *sort.
Changed, Submitted, Sorted bool
}
@@ -51,11 +51,11 @@ func Table(c *ui.Context, text string, cols []Column, rows int, sort *Sort, sele
st.Selected = nil
}
res := TableResult{Element: box}
var list *ui.Element
var list ui.Element
box.Children(func() {
ui.Row(c).FocusGroup(ui.Horizontal).Role(ui.RoleRow).Children(func() {
for i, col := range cols {
shell, base, hs := pixel.Shell(c, func() *ui.Element {
shell, base, hs := pixel.Shell(c, func() ui.Element {
return ui.ButtonBase(c).Role(ui.RoleColumnHeader).Label(col.Title).Disabled(o.Disabled)
})
if base.Clicked() {
+1 -1
View File
@@ -15,7 +15,7 @@ type Event struct {
type TimelineOptions struct{}
// Timeline strings dated events down a line of markers.
func Timeline(c *ui.Context, events []Event, o TimelineOptions) *ui.Element {
func Timeline(c *ui.Context, events []Event, o TimelineOptions) ui.Element {
k := pixel.K(c)
return ui.Column(c).FillWidth().Children(func() {
for i, ev := range events {
+1 -1
View File
@@ -18,7 +18,7 @@ type TransferOptions struct {
}
type TransferResult struct {
Element *ui.Element
Element ui.Element
Changed bool
}
+2 -2
View File
@@ -25,7 +25,7 @@ type TreeOptions struct {
}
type TreeResult struct {
Element *ui.Element
Element ui.Element
Changed, Toggled bool
}
@@ -55,7 +55,7 @@ func Tree(c *ui.Context, text string, roots []TreeNode, selected *string, o Tree
for i := range roots {
tops = append(tops, strconv.Itoa(i))
}
shell, base, st := pixel.Shell(c, func() *ui.Element {
shell, base, st := pixel.Shell(c, func() ui.Element {
return ui.Box(c).Focusable().Role(ui.RoleTree).Label(text).Disabled(o.Disabled)
})
opened := ui.Local(base, treeKey{}, func() map[string]bool { return map[string]bool{} })