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:
1 parent
1f3d38110e
commit
03e1f91706
532 files changed
+828
-735
No files matched your search
@@ -15,7 +15,7 @@ type BackForwardOptions struct {
|
||||
}
|
||||
|
||||
type BackForwardResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Moved reports a step through the history.
|
||||
Moved bool
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ type BottomNavOptions struct {
|
||||
}
|
||||
|
||||
type BottomNavResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ func BottomNav(c *ui.Context, text string, items []NavItem, selected *int, o Bot
|
||||
v := *selected
|
||||
res.Element = ui.RadioGroup(c, func() {
|
||||
for i, it := range items {
|
||||
shell, _, st := pixel.Shell(c, func() *ui.Element {
|
||||
shell, _, st := pixel.Shell(c, func() ui.Element {
|
||||
return ui.RadioBase(c, &v, i).Label(it.Label).Disabled(o.Disabled)
|
||||
})
|
||||
w := max(pixel.Measure(it.Label), 12) + 12
|
||||
|
||||
@@ -13,7 +13,7 @@ type BreadcrumbsOptions struct {
|
||||
}
|
||||
|
||||
type BreadcrumbsResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Clicked is the part clicked, or -1.
|
||||
Clicked int
|
||||
}
|
||||
@@ -28,7 +28,7 @@ func Breadcrumbs(c *ui.Context, text string, parts []string, o BreadcrumbsOption
|
||||
pixel.Text(c, part, pixel.TextOptions{})
|
||||
break
|
||||
}
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element {
|
||||
shell, base, st := pixel.Shell(c, func() ui.Element {
|
||||
return ui.ButtonBase(c).Role(ui.RoleLink).Label(part).Disabled(o.Disabled)
|
||||
})
|
||||
if base.Clicked() {
|
||||
|
||||
@@ -15,7 +15,7 @@ type CommandMenuOptions struct {
|
||||
}
|
||||
|
||||
type CommandMenuResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Chosen is the item taken this frame, or -1.
|
||||
Chosen int
|
||||
Canceled bool
|
||||
@@ -26,12 +26,12 @@ type cursorKey struct{}
|
||||
// CommandMenu is a JRPG command window with a bobbing ▶.
|
||||
func CommandMenu(c *ui.Context, text string, items []MenuItem, o CommandMenuOptions) CommandMenuResult {
|
||||
k := pixel.K(c)
|
||||
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)
|
||||
})
|
||||
// An off menu never takes the focus.
|
||||
if o.AutoFocus && !base.IsDisabled() {
|
||||
base.AutoFocus()
|
||||
pixel.AutoFocus(c, base)
|
||||
}
|
||||
cur := ui.Local(base, cursorKey{}, func() int { return 0 })
|
||||
res := CommandMenuResult{Element: shell, Chosen: -1}
|
||||
|
||||
@@ -15,7 +15,7 @@ type CommandPaletteOptions struct {
|
||||
}
|
||||
|
||||
type CommandPaletteResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Ran is the command run this frame, or -1.
|
||||
Ran int
|
||||
}
|
||||
@@ -54,7 +54,7 @@ func CommandPalette(c *ui.Context, text string, commands []MenuItem, open *bool,
|
||||
res.Ran, *open = i, false
|
||||
}
|
||||
}
|
||||
res.Element = ui.DialogBase(c, open, func(back, panel *ui.Element) {
|
||||
res.Element = ui.DialogBase(c, open, func(back, panel ui.Element) {
|
||||
back.Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
g.Checker(0, 0, g.W, g.H, pixel.Back)
|
||||
@@ -64,7 +64,7 @@ func CommandPalette(c *ui.Context, text string, commands []MenuItem, open *bool,
|
||||
g.Frame(0, 0, g.W, g.H, pixel.Window, pixel.Face)
|
||||
}).Children(func() {
|
||||
f := input.TextInput(c, text, &st.query, input.TextInputOptions{Placeholder: "> …", Width: 228})
|
||||
f.Input.AutoFocus()
|
||||
pixel.AutoFocus(c, f.Input)
|
||||
if f.Changed {
|
||||
st.lit = 0
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ type ContextMenuOptions struct {
|
||||
}
|
||||
|
||||
type ContextMenuResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Chosen is the item taken this frame, or -1.
|
||||
Chosen int
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func ContextMenu(c *ui.Context, text string, items []MenuItem, o ContextMenuOpti
|
||||
if clicked >= 0 {
|
||||
res.Chosen = clicked
|
||||
}
|
||||
if panel != nil {
|
||||
if panel.Valid() {
|
||||
b := area.Bounds()
|
||||
panel.Left(b.X + s.x).Top(b.Y + s.y)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ type DocumentTabsOptions struct {
|
||||
}
|
||||
|
||||
type DocumentTabsResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
// Closed is the tab × or Delete closed, or -1.
|
||||
Closed int
|
||||
@@ -46,8 +46,8 @@ func DocumentTabs(c *ui.Context, text string, titles []string, selected *int, o
|
||||
for i, t := range titles {
|
||||
// Keyed by title, so focus follows its tab.
|
||||
ui.Box(c).Key(t).Children(func() {
|
||||
var x *ui.Element
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element {
|
||||
var x ui.Element
|
||||
shell, base, st := pixel.Shell(c, func() ui.Element {
|
||||
tab := p.Tab(i).Label(t).Disabled(o.Disabled)
|
||||
// The × is no Tab stop; Delete closes by keyboard.
|
||||
tab.Children(func() {
|
||||
|
||||
@@ -14,7 +14,7 @@ type DropdownMenuOptions struct {
|
||||
}
|
||||
|
||||
type DropdownMenuResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Chosen is the item taken this frame, or -1.
|
||||
Chosen int
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ type LevelSelectOptions struct {
|
||||
}
|
||||
|
||||
type LevelSelectResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Chosen is Enter or a click on an open stage.
|
||||
Changed, Chosen bool
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ type MenuBarOptions struct {
|
||||
}
|
||||
|
||||
type MenuBarResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Menu and Item are this frame's choice, else -1.
|
||||
Menu, Item int
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func MenuBar(c *ui.Context, text string, menus []Menu, o MenuBarOptions) MenuBar
|
||||
px, py, over := row.PointerPosition()
|
||||
moved := over && [2]float32{px, py} != b.ptr
|
||||
b.ptr = [2]float32{px, py}
|
||||
var anchor *ui.Element
|
||||
var anchor ui.Element
|
||||
row.Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
g.Rect(0, 0, g.W, g.H, pixel.Face)
|
||||
@@ -92,7 +92,7 @@ func MenuBar(c *ui.Context, text string, menus []Menu, o MenuBarOptions) MenuBar
|
||||
}
|
||||
}
|
||||
})
|
||||
if b.open >= 0 && anchor != nil {
|
||||
if b.open >= 0 && anchor.Valid() {
|
||||
items := menus[b.open].Items
|
||||
res.Item = b.m.keys(row.Shortcut, items)
|
||||
if _, clicked := b.m.list(c, anchor, items); clicked >= 0 {
|
||||
|
||||
+3
-3
@@ -62,10 +62,10 @@ func (m *menu) keys(short func(ui.Modifiers, ui.Key) bool, items []MenuItem) int
|
||||
}
|
||||
|
||||
// list shows the menu under anchor and returns clicks.
|
||||
func (m *menu) list(c *ui.Context, anchor *ui.Element, items []MenuItem) (panel *ui.Element, clicked int) {
|
||||
func (m *menu) list(c *ui.Context, anchor ui.Element, items []MenuItem) (panel ui.Element, clicked int) {
|
||||
k := pixel.K(c)
|
||||
clicked = -1
|
||||
panel = ui.PopoverBase(c, anchor, &m.open, func(panel *ui.Element) {
|
||||
panel = ui.PopoverBase(c, anchor, &m.open, func(panel ui.Element) {
|
||||
// Only a pointer that moves lights the item under it.
|
||||
px, py, over := panel.PointerPosition()
|
||||
moved := over && [2]float32{px, py} != m.ptr
|
||||
@@ -104,7 +104,7 @@ func (m *menu) list(c *ui.Context, anchor *ui.Element, items []MenuItem) (panel
|
||||
})
|
||||
})
|
||||
// Clicks on a rule or the edge close it too.
|
||||
if panel != nil && panel.Clicked() {
|
||||
if panel.Valid() && panel.Clicked() {
|
||||
m.open = false
|
||||
}
|
||||
return panel, clicked
|
||||
|
||||
@@ -14,7 +14,7 @@ type PageDotsOptions struct {
|
||||
}
|
||||
|
||||
type PageDotsResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ type PageDotsResult struct {
|
||||
func PageDots(c *ui.Context, text string, page *int, total int, o PageDotsOptions) PageDotsResult {
|
||||
k := pixel.K(c)
|
||||
check(*page, total)
|
||||
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.RoleSlider).Label(text).Description(fmt.Sprintf("%d/%d", *page, total)).Disabled(o.Disabled)
|
||||
})
|
||||
old := *page
|
||||
|
||||
@@ -17,7 +17,7 @@ type PaginationOptions struct {
|
||||
}
|
||||
|
||||
type PaginationResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ type NavRailOptions struct {
|
||||
}
|
||||
|
||||
type NavRailResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func NavRail(c *ui.Context, text string, items []NavItem, selected *int, o NavRa
|
||||
v := *selected
|
||||
res.Element = ui.RadioGroup(c, func() {
|
||||
for i, it := range items {
|
||||
shell, _, st := pixel.Shell(c, func() *ui.Element {
|
||||
shell, _, st := pixel.Shell(c, func() ui.Element {
|
||||
return ui.RadioBase(c, &v, i).Label(it.Label).Disabled(o.Disabled)
|
||||
})
|
||||
shell.Size(k.D(22), k.D(22)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
|
||||
@@ -27,7 +27,7 @@ type SidebarOptions struct {
|
||||
}
|
||||
|
||||
type SidebarResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func Sidebar(c *ui.Context, text string, sections []SidebarSection, selected *in
|
||||
for _, it := range sec.Items {
|
||||
i := n
|
||||
n++
|
||||
shell, _, st := pixel.Shell(c, func() *ui.Element {
|
||||
shell, _, st := pixel.Shell(c, func() ui.Element {
|
||||
return ui.RadioBase(c, &v, i).Label(it.Label).Disabled(o.Disabled)
|
||||
})
|
||||
shell.Size(k.D(w), k.D(pixel.LineHeight+2)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ var waving = pixel.MustSprite(`
|
||||
type StepsOptions struct{}
|
||||
|
||||
// Steps are flags on a path: done, waving, then locked.
|
||||
func Steps(c *ui.Context, labels []string, current int, o StepsOptions) *ui.Element {
|
||||
func Steps(c *ui.Context, labels []string, current int, o StepsOptions) ui.Element {
|
||||
k := pixel.K(c)
|
||||
if current < 0 || current >= len(labels) {
|
||||
panic(fmt.Sprintf("navigation: step %d of %d", current, len(labels)))
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ type TabsOptions struct {
|
||||
}
|
||||
|
||||
type TabsResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func tabs(c *ui.Context, text string, labels []string, selected *int, side bool,
|
||||
}
|
||||
p.List.Label(text).Children(func() {
|
||||
for i, l := range labels {
|
||||
shell, _, st := pixel.Shell(c, func() *ui.Element { return p.Tab(i).Label(l).Disabled(o.Disabled) })
|
||||
shell, _, st := pixel.Shell(c, func() ui.Element { return p.Tab(i).Label(l).Disabled(o.Disabled) })
|
||||
w, h := size(i), th
|
||||
if side {
|
||||
w = tw
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ type TableOfContentsOptions struct {
|
||||
}
|
||||
|
||||
type TableOfContentsResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func TableOfContents(c *ui.Context, text string, items []TocItem, current *int,
|
||||
v := *current
|
||||
res.Element = ui.RadioGroup(c, func() {
|
||||
for i, it := range items {
|
||||
shell, _, st := pixel.Shell(c, func() *ui.Element {
|
||||
shell, _, st := pixel.Shell(c, func() ui.Element {
|
||||
return ui.RadioBase(c, &v, i).Label(it.Title).Disabled(o.Disabled)
|
||||
})
|
||||
shell.Size(k.D(w), k.D(pixel.LineHeight)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
type ToolbarOptions struct{}
|
||||
|
||||
// Toolbar holds tool buttons as one Tab stop; arrows move.
|
||||
func Toolbar(c *ui.Context, text string, o ToolbarOptions, content func()) *ui.Element {
|
||||
func Toolbar(c *ui.Context, text string, o ToolbarOptions, content func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
return ui.Row(c).AlignSelf(ui.Start).Gap(k.D(2)).Padding(k.D(3)).AlignItems(ui.Center).Role(ui.RoleToolbar).Label(text).FocusGroup(ui.Horizontal).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
|
||||
@@ -9,7 +9,7 @@ type VerticalTabsOptions struct {
|
||||
}
|
||||
|
||||
type VerticalTabsResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ type WorldMapOptions struct {
|
||||
}
|
||||
|
||||
type WorldMapResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Entered reports Enter, or a click, at the hero's node.
|
||||
Changed, Entered bool
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func WorldMap(c *ui.Context, text string, nodes []MapNode, paths [][2]int, at *i
|
||||
panic(fmt.Sprintf("navigation: node %d of %d", *at, len(nodes)))
|
||||
}
|
||||
w, h := pixel.Or("WorldMap Width", o.Width, 240), pixel.Or("WorldMap Height", o.Height, 140)
|
||||
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.RoleGroup).Label(text).Description(nodes[*at].Name).Disabled(o.Disabled)
|
||||
})
|
||||
wk := ui.Local(base, walkKey{}, func() walk { return walk{from: *at} })
|
||||
|
||||
Reference in new issue
Block a user