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
+2
-2
@@ -14,7 +14,7 @@ type AppFrameOptions struct {
|
||||
}
|
||||
|
||||
// AppFrame arranges header, sidebar, main and footer; nil ones vanish.
|
||||
func AppFrame(c *ui.Context, o AppFrameOptions, header, sidebar, main, footer func()) *ui.Element {
|
||||
func AppFrame(c *ui.Context, o AppFrameOptions, header, sidebar, main, footer func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
sw := pixel.Or("AppFrame SidebarWidth", o.SidebarWidth, 96)
|
||||
fold := pixel.Or("AppFrame FoldBelow", o.FoldBelow, 320)
|
||||
@@ -43,7 +43,7 @@ func AppFrame(c *ui.Context, o AppFrameOptions, header, sidebar, main, footer fu
|
||||
if header != nil {
|
||||
strip(header, true)
|
||||
}
|
||||
var body *ui.Element
|
||||
var body ui.Element
|
||||
if folded {
|
||||
body = ui.Column(c)
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ type AspectBoxOptions struct {
|
||||
}
|
||||
|
||||
// AspectBox fills the width and keeps W:H in whole dots.
|
||||
func AspectBox(c *ui.Context, o AspectBoxOptions, children func()) *ui.Element {
|
||||
func AspectBox(c *ui.Context, o AspectBoxOptions, children func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
rw, rh := pixel.Or("AspectBox W", o.W, 1), pixel.Or("AspectBox H", o.H, 1)
|
||||
e := ui.Box(c).FillWidth().Clip()
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ type CardOptions struct {
|
||||
}
|
||||
|
||||
// Card is a raised panel: header strip, body, footer.
|
||||
func Card(c *ui.Context, o CardOptions, body func()) *ui.Element {
|
||||
func Card(c *ui.Context, o CardOptions, body func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
e := ui.Column(c).Padding(k.D(2)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
box(k.Canvas(p, r), pixel.Raised, pixel.Face)
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ type CRTFrameOptions struct {
|
||||
const crtSide, crtChin = 10, 16
|
||||
|
||||
// CRTFrame shows children on a monitor with scanlines.
|
||||
func CRTFrame(c *ui.Context, o CRTFrameOptions, children func()) *ui.Element {
|
||||
func CRTFrame(c *ui.Context, o CRTFrameOptions, children func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
return ui.Column(c).Padding(k.D(crtSide), k.D(crtSide), k.D(crtChin), k.D(crtSide)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ var diamond = pixel.MustSprite(`
|
||||
`)
|
||||
|
||||
// Divider is a rule across its parent.
|
||||
func Divider(c *ui.Context, o DividerOptions) *ui.Element {
|
||||
func Divider(c *ui.Context, o DividerOptions) ui.Element {
|
||||
k := pixel.K(c)
|
||||
ink := o.Slot
|
||||
if ink == pixel.Ink {
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ type GridOptions struct {
|
||||
}
|
||||
|
||||
// Grid lays n cells in equal columns, lines between them.
|
||||
func Grid(c *ui.Context, n int, o GridOptions, cell func(i int)) *ui.Element {
|
||||
func Grid(c *ui.Context, n int, o GridOptions, cell func(i int)) ui.Element {
|
||||
k := pixel.K(c)
|
||||
cols := pixel.Or("Grid Columns", o.Columns, 2)
|
||||
pad := pixel.Or("Grid Pad", o.Pad, 4)
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ type HandheldOptions struct {
|
||||
}
|
||||
|
||||
type HandheldResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Up, Down, Left, Right, A, B bool
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ func Handheld(c *ui.Context, o HandheldOptions, screen func()) HandheldResult {
|
||||
|
||||
// key is a d-pad arm, or a round button.
|
||||
func key(c *ui.Context, k pixel.Kit, name string, x, y, w, h int, round, disabled bool) bool {
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element { return ui.ButtonBase(c).Label(name).Disabled(disabled) })
|
||||
shell, base, st := pixel.Shell(c, func() ui.Element { return ui.ButtonBase(c).Label(name).Disabled(disabled) })
|
||||
shell.Absolute().Left(k.D(x)).Top(k.D(y)).Size(k.D(w), k.D(h)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
dy := 0
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import "github.com/egoist/mygo/ui"
|
||||
type LayersOptions struct{}
|
||||
|
||||
// Layers stacks layers in a box; the first sizes it.
|
||||
func Layers(c *ui.Context, o LayersOptions, layers ...func()) *ui.Element {
|
||||
func Layers(c *ui.Context, o LayersOptions, layers ...func()) ui.Element {
|
||||
if len(layers) == 0 {
|
||||
panic("layout: Layers needs a layer")
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ func rule(g pixel.Canvas, x, y, n int, vertical bool, on, off int, s pixel.Slot)
|
||||
type dragKey struct{}
|
||||
|
||||
// drag is enabled e's pointer travel this frame, in dots.
|
||||
func drag(k pixel.Kit, e *ui.Element) (dx, dy int, ok bool) {
|
||||
func drag(k pixel.Kit, e ui.Element) (dx, dy int, ok bool) {
|
||||
rest := ui.Local(e, dragKey{}, func() [2]float32 { return [2]float32{} })
|
||||
fx, fy, ok := e.Dragged()
|
||||
if !ok || e.IsDisabled() {
|
||||
|
||||
+15
-11
@@ -302,44 +302,48 @@ func TestAppFrameFolds(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAspectBoxAndViewport(t *testing.T) {
|
||||
var aspect, screen *ui.Element
|
||||
var aspect, screen ui.Handle
|
||||
var ctx *ui.Context
|
||||
tt := ui.NewTester(func(c *ui.Context) {
|
||||
ctx = c
|
||||
use(c)
|
||||
ui.Column(c).Children(func() {
|
||||
ui.Box(c).Width(300).Children(func() {
|
||||
aspect = layout.AspectBox(c, layout.AspectBoxOptions{W: 16, H: 9}, func() {})
|
||||
layout.AspectBox(c, layout.AspectBoxOptions{W: 16, H: 9}, func() {}).Bind(&aspect)
|
||||
})
|
||||
ui.Box(c).Size(400, 300).Children(func() {
|
||||
layout.Viewport(c, layout.ViewportOptions{W: 64, H: 40}, func() { screen = ui.Box(c).Fill() })
|
||||
layout.Viewport(c, layout.ViewportOptions{W: 64, H: 40}, func() { ui.Box(c).Fill().Bind(&screen) })
|
||||
})
|
||||
})
|
||||
}, 500, 700)
|
||||
tt.Frame()
|
||||
if b := aspect.Bounds(); b.W != 300 || b.H != 2*(150*9/16) {
|
||||
if b := aspect.Bounds(ctx); b.W != 300 || b.H != 2*(150*9/16) {
|
||||
t.Fatalf("aspect box %v", b)
|
||||
}
|
||||
if b := screen.Bounds(); b.X != 72 || b.Y != aspect.Bounds().H+70 || b.W != 256 || b.H != 160 {
|
||||
if b := screen.Bounds(ctx); b.X != 72 || b.Y != aspect.Bounds(ctx).H+70 || b.W != 256 || b.H != 160 {
|
||||
t.Fatalf("viewport screen %v", b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLayersSizes(t *testing.T) {
|
||||
var auto, sized, fill *ui.Element
|
||||
var auto, sized, fill ui.Handle
|
||||
var ctx *ui.Context
|
||||
tt := ui.NewTester(func(c *ui.Context) {
|
||||
ctx = c
|
||||
use(c)
|
||||
ui.Column(c).AlignItems(ui.Start).Children(func() {
|
||||
auto = layout.Layers(c, layout.LayersOptions{}, func() { ui.Box(c).Size(50, 30) }, func() { ui.Box(c).Fill() })
|
||||
sized = layout.Layers(c, layout.LayersOptions{}, func() { fill = ui.Box(c).Fill() }).Size(120, 64)
|
||||
layout.Layers(c, layout.LayersOptions{}, func() { ui.Box(c).Size(50, 30) }, func() { ui.Box(c).Fill() }).Bind(&auto)
|
||||
layout.Layers(c, layout.LayersOptions{}, func() { ui.Box(c).Fill().Bind(&fill) }).Size(120, 64).Bind(&sized)
|
||||
})
|
||||
}, 400, 300)
|
||||
tt.Frame()
|
||||
if b := auto.Bounds(); b.W != 50 || b.H != 30 {
|
||||
if b := auto.Bounds(ctx); b.W != 50 || b.H != 30 {
|
||||
t.Fatalf("first layer did not size the box: %v", b)
|
||||
}
|
||||
if b := fill.Bounds(); b.W != 120 || b.H != 64 {
|
||||
if b := fill.Bounds(ctx); b.W != 120 || b.H != 64 {
|
||||
t.Fatalf("first layer did not fill a sized box: %v", b)
|
||||
}
|
||||
if b := sized.Bounds(); b.H != 64 {
|
||||
if b := sized.Bounds(ctx); b.H != 64 {
|
||||
t.Fatalf("sized box %v", b)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ type MasonryOptions struct {
|
||||
}
|
||||
|
||||
// Masonry puts each item into the shortest column.
|
||||
func Masonry(c *ui.Context, heights []int, o MasonryOptions, item func(i int)) *ui.Element {
|
||||
func Masonry(c *ui.Context, heights []int, o MasonryOptions, item func(i int)) ui.Element {
|
||||
k := pixel.K(c)
|
||||
gap := pixel.Or("Masonry Gap", o.Gap, 4)
|
||||
n := pixel.Or("Masonry Columns", o.Columns, 3)
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ type PanelOptions struct {
|
||||
}
|
||||
|
||||
// Panel frames children in a style.
|
||||
func Panel(c *ui.Context, o PanelOptions, children func()) *ui.Element {
|
||||
func Panel(c *ui.Context, o PanelOptions, children func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
fill := o.Fill
|
||||
if fill == pixel.Ink {
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ type ResizableOptions struct {
|
||||
}
|
||||
|
||||
type ResizableResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ func Resizable(c *ui.Context, w, h *int, o ResizableOptions, children func()) Re
|
||||
e := ui.Box(c).Clip()
|
||||
e.Children(func() {
|
||||
children()
|
||||
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.RoleSplitter).Label(label(k, o.Label, "resize")).Disabled(o.Disabled).Cursor(ui.CursorResizeNWSE)
|
||||
})
|
||||
if dx, dy, ok := drag(k, base); ok {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ type ScreenOptions struct {
|
||||
}
|
||||
|
||||
// Screen fills the window with Back; children form a column.
|
||||
func Screen(c *ui.Context, o ScreenOptions, children func()) *ui.Element {
|
||||
func Screen(c *ui.Context, o ScreenOptions, children func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
pad := pixel.Or("Screen Padding", o.Padding, 0)
|
||||
return ui.Column(c).Fill().Padding(k.D(pad)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
|
||||
@@ -32,7 +32,7 @@ type ScrollAreaOptions struct {
|
||||
}
|
||||
|
||||
type ScrollAreaResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
// Changed reports the view moved since the last frame.
|
||||
Changed bool
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func ScrollArea(c *ui.Context, s *ui.ScrollState, o ScrollAreaOptions, children
|
||||
}
|
||||
st.end = s.MaxY
|
||||
}
|
||||
var v *ui.Element
|
||||
var v ui.Element
|
||||
row.Children(func() {
|
||||
scrollBar(c, k, s, view, o.Disabled || inert, o.Disabled)
|
||||
// A disabled view is a new element; the focus leaves.
|
||||
@@ -161,7 +161,7 @@ func thumb(h, view, y, maxY, dot float32) (size, at float32) {
|
||||
|
||||
// arrow is a scrollbar button; keys scroll the view instead.
|
||||
func arrow(c *ui.Context, k pixel.Kit, sp *pixel.Sprite, label string, disabled bool) bool {
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element {
|
||||
shell, base, st := pixel.Shell(c, func() ui.Element {
|
||||
return ui.Box(c).Role(ui.RoleButton).Label(label).Disabled(disabled)
|
||||
})
|
||||
shell.Size(k.D(barW), k.D(barW)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ type SectionOptions struct {
|
||||
}
|
||||
|
||||
// Section titles a group inside a dotted rule.
|
||||
func Section(c *ui.Context, title string, o SectionOptions, children func()) *ui.Element {
|
||||
func Section(c *ui.Context, title string, o SectionOptions, children func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
up := strings.ToUpper(title)
|
||||
return ui.Column(c).Gap(k.D(pixel.Or("Section Gap", o.Gap, 4))).Role(ui.RoleGroup).Label(title).Children(func() {
|
||||
|
||||
+3
-3
@@ -20,7 +20,7 @@ type SplitOptions struct {
|
||||
}
|
||||
|
||||
type SplitResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Changed bool
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ type SplitResult struct {
|
||||
func Split(c *ui.Context, size *int, o SplitOptions, first, second func()) SplitResult {
|
||||
k := pixel.K(c)
|
||||
least := pixel.Or("Split Min", o.Min, 24)
|
||||
var e *ui.Element
|
||||
var e ui.Element
|
||||
var total float32
|
||||
back, fwd := ui.KeyLeft, ui.KeyRight
|
||||
if o.Vertical {
|
||||
@@ -47,7 +47,7 @@ func Split(c *ui.Context, size *int, o SplitOptions, first, second func()) Split
|
||||
start := *size
|
||||
e.AlignItems(ui.Stretch).Children(func() {
|
||||
pane := ui.Box(c).Clip().Children(first)
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element {
|
||||
shell, base, st := pixel.Shell(c, func() ui.Element {
|
||||
cur := ui.CursorResizeEW
|
||||
if o.Vertical {
|
||||
cur = ui.CursorResizeNS
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import (
|
||||
type StatusBarOptions struct{}
|
||||
|
||||
// StatusBar shows segments split by sunken dividers; the first grows.
|
||||
func StatusBar(c *ui.Context, segments []string, o StatusBarOptions) *ui.Element {
|
||||
func StatusBar(c *ui.Context, segments []string, o StatusBarOptions) ui.Element {
|
||||
k := pixel.K(c)
|
||||
return ui.Row(c).FillWidth().Height(k.D(pixel.LineHeight + 3)).AlignItems(ui.Stretch).Role(ui.RoleStatus).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ type TilesOptions struct {
|
||||
}
|
||||
|
||||
// Tiles wraps n equal tiles into rows.
|
||||
func Tiles(c *ui.Context, n int, o TilesOptions, tile func(i int)) *ui.Element {
|
||||
func Tiles(c *ui.Context, n int, o TilesOptions, tile func(i int)) ui.Element {
|
||||
k := pixel.K(c)
|
||||
w := pixel.Or("Tiles W", o.W, 48)
|
||||
h := pixel.Or("Tiles H", o.H, w)
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@ type TitleBarOptions struct {
|
||||
}
|
||||
|
||||
type TitleBarResult struct {
|
||||
Element *ui.Element
|
||||
Element ui.Element
|
||||
Close bool
|
||||
Minimize bool
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func TitleBar(c *ui.Context, title string, o TitleBarOptions) TitleBarResult {
|
||||
|
||||
// windowBox is a framed button showing its glyph on hover.
|
||||
func windowBox(c *ui.Context, k pixel.Kit, glyph *pixel.Sprite, name string, disabled bool) bool {
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element { return ui.ButtonBase(c).Label(name).Disabled(disabled) })
|
||||
shell, base, st := pixel.Shell(c, func() ui.Element { return ui.ButtonBase(c).Label(name).Disabled(disabled) })
|
||||
shell.Size(k.D(11), k.D(11)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
fill := pixel.Face
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ type ViewportOptions struct {
|
||||
}
|
||||
|
||||
// Viewport fills its parent and draws children at W×H dots.
|
||||
func Viewport(c *ui.Context, o ViewportOptions, children func()) *ui.Element {
|
||||
func Viewport(c *ui.Context, o ViewportOptions, children func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
vw, vh := pixel.Or("Viewport W", o.W, 160), pixel.Or("Viewport H", o.H, 144)
|
||||
base := int(k.Dot())
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ type WindowOptions struct {
|
||||
}
|
||||
|
||||
// Window is a beveled window with an optional title tab.
|
||||
func Window(c *ui.Context, o WindowOptions, children func()) *ui.Element {
|
||||
func Window(c *ui.Context, o WindowOptions, children func()) ui.Element {
|
||||
k := pixel.K(c)
|
||||
pad := 3 + pixel.Or("Window Padding", o.Padding, 6)
|
||||
top := 0
|
||||
|
||||
Reference in new issue
Block a user