Add input components 066-085; gallery chrome on real components; deploy warms the edge
This commit is contained in:
38 files changed
+2340
-172
No files matched your search
+2
-4
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
@@ -19,7 +20,7 @@ type App struct {
|
||||
locale pixel.Locale
|
||||
started bool
|
||||
query string
|
||||
search pixel.Edit
|
||||
search input.TextInputResult
|
||||
logs map[string][]string
|
||||
}
|
||||
|
||||
@@ -61,9 +62,6 @@ func (a *App) View(c *ui.Context) {
|
||||
|
||||
// keys leaves single keys to a field being typed in.
|
||||
func (a *App) keys(c *ui.Context) {
|
||||
if a.search.Focused && c.Shortcut(0, ui.KeyEscape) {
|
||||
a.query = ""
|
||||
}
|
||||
if pixel.Typing(c) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -167,3 +167,54 @@ func TestShortcutsYieldToFields(t *testing.T) {
|
||||
t.Fatalf("typing changed palette %d or path %q", a.palette, a.Path())
|
||||
}
|
||||
}
|
||||
|
||||
func TestFoundationTilesShowFocus(t *testing.T) {
|
||||
for path, tile := range map[string]string{"/f/palettes": "Spring Day", "/f/sprites": "slime"} {
|
||||
_, tt := open(path)
|
||||
r, _ := tt.Find(tile)
|
||||
area := func() []uint32 {
|
||||
img := tt.Image()
|
||||
var out []uint32
|
||||
for y := int(r.Y) - 6; y < int(r.Y+r.H)+6; y++ {
|
||||
for x := int(r.X) - 30; x < int(r.X+r.W)+6; x++ {
|
||||
c := img.RGBAAt(x, y)
|
||||
out = append(out, uint32(c.R)<<16|uint32(c.G)<<8|uint32(c.B))
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
before := area()
|
||||
for range 40 {
|
||||
if tt.Focused(tile) {
|
||||
break
|
||||
}
|
||||
tt.Key(0, ui.KeyTab)
|
||||
}
|
||||
if !tt.Focused(tile) || slices.Equal(before, area()) {
|
||||
t.Fatalf("%s: focus on %s left no mark", path, tile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInputDemosLogEveryClick(t *testing.T) {
|
||||
a, tt := open("/c/066-button")
|
||||
for _, l := range []string{"Small", "Save", "BIG"} {
|
||||
click(t, tt, l)
|
||||
if !slices.Contains(a.logs["066-button"], l) {
|
||||
t.Fatalf("clicking %s logged %q", l, a.logs["066-button"])
|
||||
}
|
||||
}
|
||||
a, tt = open("/c/067-iconbutton")
|
||||
click(t, tt, "Delete")
|
||||
if !slices.Contains(a.logs["067-iconbutton"], "Delete") {
|
||||
t.Fatalf("Delete logged %q", a.logs["067-iconbutton"])
|
||||
}
|
||||
for slug, field := range map[string]string{"082-textinput": "Hero name", "083-passwordinput": "Password", "085-searchfield": "Find items"} {
|
||||
a, tt = open("/c/" + slug)
|
||||
click(t, tt, field)
|
||||
tt.Type("ab")
|
||||
if len(a.logs[slug]) == 0 {
|
||||
t.Fatalf("typing into %s logged nothing", slug)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@ func (a *App) boot(c *ui.Context) {
|
||||
g := k.Canvas(p, r)
|
||||
w := pixel.Measure(logo) * 4
|
||||
x, y := (g.W-w)/2, g.H/2-40
|
||||
shadowText(g, x, y, logo, pixel.Accent, 4)
|
||||
shadow(g, x, y, logo, pixel.Accent, 4)
|
||||
g.Veil(x, y, w+4, 68, pixel.Back, 16-shown)
|
||||
if start {
|
||||
s := "PRESS START"
|
||||
|
||||
+32
-28
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/icon"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/layout"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
@@ -25,29 +27,21 @@ func (a *App) topBar(c *ui.Context) {
|
||||
if st.Hover {
|
||||
ink = pixel.AccentLit
|
||||
}
|
||||
shadowText(g, 0, 1, logo, ink, 1)
|
||||
shadow(g, 0, 1, logo, ink, 1)
|
||||
}) {
|
||||
a.Go("/")
|
||||
}
|
||||
ui.Column(c).Width(k.D(150)).Padding(k.D(2), k.D(4)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
g.Frame(0, 0, g.W, g.H, pixel.Sunken, pixel.Well)
|
||||
}).Children(func() {
|
||||
a.search = pixel.Editor(c, &a.query, pixel.EditorOptions{Placeholder: "/ search 搜索", Label: "Search components"})
|
||||
if m := matches(a.query); a.search.Submitted && len(m) > 0 {
|
||||
a.Go(m[0].Path())
|
||||
}
|
||||
})
|
||||
a.search = input.SearchField(c, "Search components", &a.query, input.SearchFieldOptions{Placeholder: "/ search 搜索", Width: 150})
|
||||
if m := matches(a.query); a.search.Submitted && len(m) > 0 {
|
||||
a.Go(m[0].Path())
|
||||
}
|
||||
ui.Spacer(c)
|
||||
a.paletteControl(c)
|
||||
other, mark := pixel.Zh, "中"
|
||||
if a.locale == pixel.Zh {
|
||||
other, mark = pixel.En, "EN"
|
||||
}
|
||||
if press(c, 20, 16, "language", func(g pixel.Canvas, st pixel.State) {
|
||||
g.Frame(0, 0, g.W, g.H, pixel.Notched, pixel.Face)
|
||||
g.Text((g.W-pixel.Measure(mark))/2, 0, mark, pixel.Ink, 1)
|
||||
}) {
|
||||
if input.Button(c, mark, input.ButtonOptions{Size: input.Small, Label: "language"}).Clicked {
|
||||
a.locale = other
|
||||
}
|
||||
})
|
||||
@@ -55,9 +49,8 @@ func (a *App) topBar(c *ui.Context) {
|
||||
|
||||
func (a *App) paletteControl(c *ui.Context) {
|
||||
pal := pixel.Palettes[a.palette]
|
||||
if press(c, 12, 16, "previous palette", func(g pixel.Canvas, st pixel.State) {
|
||||
g.Sprite(0, 2, icon.ChevronLeft, 0, pixel.Ink, 1)
|
||||
}) {
|
||||
arrows := input.IconButtonOptions{Variant: input.Ghost, Size: input.Small}
|
||||
if input.IconButton(c, icon.ChevronLeft, "previous palette", arrows).Clicked {
|
||||
a.setPalette(a.palette - 1)
|
||||
}
|
||||
name := strings.ToUpper(pal.Name) + " " + pal.Zh
|
||||
@@ -68,9 +61,7 @@ func (a *App) paletteControl(c *ui.Context) {
|
||||
}
|
||||
g.Text(4*pixel.Slots+6, 0, name, pixel.Ink, 1)
|
||||
})
|
||||
if press(c, 12, 16, "next palette", func(g pixel.Canvas, st pixel.State) {
|
||||
g.Sprite(0, 2, icon.ChevronRight, 0, pixel.Ink, 1)
|
||||
}) {
|
||||
if input.IconButton(c, icon.ChevronRight, "next palette", arrows).Clicked {
|
||||
a.setPalette(a.palette + 1)
|
||||
}
|
||||
}
|
||||
@@ -113,17 +104,30 @@ func (a *App) sidebar(c *ui.Context) {
|
||||
}
|
||||
|
||||
func (a *App) statusBar(c *ui.Context) {
|
||||
layout.StatusBar(c, "/ search · P palette · [ ] prev next", fmt.Sprintf("%d entries", len(Entries())))
|
||||
}
|
||||
|
||||
// press is a custom-drawn chrome tile; true when clicked.
|
||||
func press(c *ui.Context, w, h int, name string, draw func(g pixel.Canvas, st pixel.State)) bool {
|
||||
k := pixel.K(c)
|
||||
hints := "/ search · P palette · [ ] prev next"
|
||||
total := fmt.Sprintf("%d ENTRIES", len(Entries()))
|
||||
ui.Row(c).Height(k.D(18)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element { return ui.ButtonBase(c).Label(name) })
|
||||
if w > 0 {
|
||||
shell.Width(k.D(w))
|
||||
}
|
||||
shell.Height(k.D(h)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
g.Rect(0, 0, g.W, g.H, pixel.Face)
|
||||
g.HLine(0, 0, g.W, pixel.Edge)
|
||||
g.HLine(0, 1, g.W, pixel.Lit)
|
||||
g.Text(6, 2, hints, pixel.Faint, 1)
|
||||
g.Micro(g.W-pixel.MicroWidth(total)-6, 8, total, pixel.Faint, 1)
|
||||
draw(g, st)
|
||||
if st.Focus {
|
||||
g.FocusMark(0, 0, g.W, g.H)
|
||||
}
|
||||
})
|
||||
return base.Clicked()
|
||||
}
|
||||
|
||||
// shadow draws s with a shadow one scaled dot down-right.
|
||||
func shadow(g pixel.Canvas, x, y int, s string, ink pixel.Slot, scale int) {
|
||||
g.Text(x+scale, y+scale, s, pixel.Shade, scale)
|
||||
g.Text(x, y, s, ink, scale)
|
||||
}
|
||||
|
||||
func count(cat string) int {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/display"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/icon"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
@@ -125,7 +126,7 @@ func demoTag(c *ui.Context, log func(string)) {
|
||||
}
|
||||
display.Tag(c, "locked", display.TagOptions{Icon: icon.Lock, Removable: true, Disabled: true})
|
||||
})
|
||||
if button(c, "RESET") {
|
||||
if input.Button(c, "RESET", input.ButtonOptions{}).Clicked {
|
||||
*tags = []string{"fire", "ice", "thunder", "wind"}
|
||||
log("tags reset")
|
||||
}
|
||||
@@ -138,7 +139,7 @@ func demoStatusDot(c *ui.Context, log func(string)) {
|
||||
for _, s := range []display.Status{display.Online, display.Away, display.Busy, display.Offline} {
|
||||
ui.Row(c).Gap(k.D(4)).AlignItems(ui.Center).Children(func() {
|
||||
display.StatusDot(c, s, display.StatusDotOptions{Live: true})
|
||||
label(c, []string{"Player 1", "Player 2", "Player 3", "Player 4"}[s], pixel.Ink)
|
||||
pixel.Text(c, []string{"Player 1", "Player 2", "Player 3", "Player 4"}[s], pixel.TextOptions{})
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -227,7 +228,7 @@ func demoRarityFrame(c *ui.Context, log func(string)) {
|
||||
items := []string{"Stick", "Bow", "Rapier", "Dragon Lance", "Excalibur"}
|
||||
ui.Row(c).Wrap().Gap(k.D(6)).Children(func() {
|
||||
for r := display.Common; r <= display.Legendary; r++ {
|
||||
display.RarityFrame(c, r, display.RarityFrameOptions{}, func() { label(c, items[r], pixel.Ink) })
|
||||
display.RarityFrame(c, r, display.RarityFrameOptions{}, func() { pixel.Text(c, items[r], pixel.TextOptions{}) })
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -237,7 +238,7 @@ func demoBubble(c *ui.Context, log func(string)) {
|
||||
lines := []string{"Hey!", "Look up.", "Psst.", "Over here."}
|
||||
ui.Row(c).Wrap().Gap(k.D(8)).AlignItems(ui.Center).Children(func() {
|
||||
for i, side := range []display.Side{display.Bottom, display.Top, display.Left, display.Right} {
|
||||
display.Bubble(c, display.BubbleOptions{Tail: side}, func() { label(c, lines[i], pixel.Ink) })
|
||||
display.Bubble(c, display.BubbleOptions{Tail: side}, func() { pixel.Text(c, lines[i], pixel.TextOptions{}) })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/icon"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/layout"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
@@ -25,7 +27,10 @@ func demoPalettes(c *ui.Context, log func(string)) {
|
||||
ui.Grid(c).Columns(2).Gap(k.D(6)).Children(func() {
|
||||
for _, pal := range pixel.Palettes {
|
||||
pixel.Scope(c, pixel.Settings{Palette: pal}, func() {
|
||||
if press(c, 0, 52, pal.Name, func(g pixel.Canvas, st pixel.State) {
|
||||
kp := pixel.K(c)
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element { return ui.ButtonBase(c).Label(pal.Name) })
|
||||
shell.Height(kp.D(52)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := kp.Canvas(p, r)
|
||||
g.Frame(0, 0, g.W, g.H, pixel.Window, pixel.Face)
|
||||
g.Text(6, 4, pal.Name+" "+pal.Zh, pixel.Ink, 1)
|
||||
g.Rect(5, 23, pixel.Slots*5+2, 10, pixel.Edge)
|
||||
@@ -36,7 +41,11 @@ func demoPalettes(c *ui.Context, log func(string)) {
|
||||
g.Sprite(g.W-32, 4, icon.Star, 0, pixel.Warn, 1)
|
||||
g.Sprite(g.W-18, 4, icon.Coin, 0, pixel.Ink, 1)
|
||||
g.Text(6, 34, "HP 99 · 你好", pixel.Accent, 1)
|
||||
}) {
|
||||
if st.Focus {
|
||||
g.FocusMark(0, 0, g.W, g.H)
|
||||
}
|
||||
})
|
||||
if base.Clicked() {
|
||||
log("palette " + pal.Name)
|
||||
}
|
||||
})
|
||||
@@ -101,12 +110,7 @@ func demoIcons(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Row(c).Wrap().Gap(k.D(2)).Children(func() {
|
||||
for _, n := range icon.All {
|
||||
if press(c, 16, 16, n.Name, func(g pixel.Canvas, st pixel.State) {
|
||||
if st.Hover {
|
||||
g.Rect(0, 0, 16, 16, pixel.Lit)
|
||||
}
|
||||
g.Sprite(2, 2, n.Sprite, 0, pixel.Ink, 1)
|
||||
}) {
|
||||
if input.IconButton(c, n.Sprite, n.Name, input.IconButtonOptions{Variant: input.Ghost}).Clicked {
|
||||
log("icon " + n.Name)
|
||||
}
|
||||
}
|
||||
@@ -151,12 +155,19 @@ func demoSprites(c *ui.Context, log func(string)) {
|
||||
if *left {
|
||||
sp = slimeLeft
|
||||
}
|
||||
if press(c, 120, 48, "slime", func(g pixel.Canvas, st pixel.State) {
|
||||
k := pixel.K(c)
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element { return ui.ButtonBase(c).Label("slime") })
|
||||
shell.Size(k.D(120), k.D(48)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
g.Rect(0, 40, g.W, 8, pixel.Good)
|
||||
g.Dither(0, 40, g.W, 8, pixel.Good, pixel.Shade, 4)
|
||||
step := g.Step(4)
|
||||
g.Sprite(8+step%8*2, 16, sp, step/2, pixel.Ink, 2)
|
||||
}) {
|
||||
if st.Focus {
|
||||
g.FocusMark(0, 0, g.W, g.H)
|
||||
}
|
||||
})
|
||||
if base.Clicked() {
|
||||
*left = !*left
|
||||
log(fmt.Sprintf("turned, facing left %v", *left))
|
||||
}
|
||||
@@ -168,7 +179,7 @@ func demoEditor(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
st := ui.Local(c.Root(), demoKey("editor"), func() editorDemo { return editorDemo{notes: "Two lines\nof notes"} })
|
||||
field := func(v *string, o pixel.EditorOptions) {
|
||||
panel(c, pixel.Sunken, pixel.Well, 3).Children(func() {
|
||||
layout.Panel(c, layout.PanelOptions{Style: pixel.Sunken, Fill: pixel.Well, Padding: 1}, func() {
|
||||
e := pixel.Editor(c, v, o)
|
||||
if e.Changed {
|
||||
log(o.Label + " changed")
|
||||
@@ -189,16 +200,10 @@ func demoFocus(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Row(c).Gap(k.D(16)).Padding(0, k.D(14)).Children(func() {
|
||||
for _, name := range []string{"ATTACK", "MAGIC", "ITEM"} {
|
||||
if button(c, name) {
|
||||
if input.Button(c, name, input.ButtonOptions{}).Clicked {
|
||||
log(name)
|
||||
}
|
||||
}
|
||||
shell, _, _ := pixel.Shell(c, func() *ui.Element { return ui.ButtonBase(c).Label("RUN").Disabled(true) })
|
||||
shell.Size(k.D(pixel.Measure("RUN")+12), k.D(16)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
g.Frame(0, 0, g.W, g.H-1, pixel.Raised, pixel.Face)
|
||||
g.Text(6, 0, "RUN", pixel.Faint, 1)
|
||||
g.Checker(0, 0, g.W, g.H-1, pixel.Face)
|
||||
})
|
||||
input.Button(c, "RUN", input.ButtonOptions{Disabled: true})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
package gallery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/icon"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
var inputEntries = []Entry{
|
||||
{66, "Button", "按钮", "input", "Primary, normal, ghost and danger in three sizes. Pressing sinks the face a dot; loading spins and waits.", demoButton},
|
||||
{67, "IconButton", "图标按钮", "input", "A square button with an icon and a name for screen readers.", demoIconButton},
|
||||
{68, "ButtonGroup", "按钮组", "input", "Buttons joined edge to edge: one Tab stop, arrows move between them.", demoButtonGroup},
|
||||
{69, "Toggle", "开关按钮", "input", "A button that stays sunken while it is on.", demoToggle},
|
||||
{70, "ToggleGroup", "开关组", "input", "Joined toggles, for many choices or just one.", demoToggleGroup},
|
||||
{71, "Checkbox", "复选框", "input", "An 8×8 box with a hand-placed check. Space toggles it.", demoCheckbox},
|
||||
{72, "CheckboxGroup", "复选组", "input", "A parent box over children: mixed while some are checked, all or none on a click.", demoCheckboxGroup},
|
||||
{73, "Radio", "单选", "input", "A pixel radio dot that picks its value.", demoRadio},
|
||||
{74, "RadioGroup", "单选组", "input", "Radios as one Tab stop; the arrows choose.", demoRadioGroup},
|
||||
{75, "Switch", "拨杆", "input", "A lever on an OFF/ON plate. Space flips it.", demoSwitch},
|
||||
{76, "Slider", "滑块", "input", "A Well track, an Accent fill and a beveled knob: drag, arrows, Home, End.", demoSlider},
|
||||
{77, "StepSlider", "刻度滑块", "input", "A slider that snaps to steps, with tick dots and its value.", demoStepSlider},
|
||||
{78, "RangeSlider", "区间滑块", "input", "Two knobs for low and high that never cross.", demoRangeSlider},
|
||||
{79, "Fader", "推子", "input", "A mixing-desk fader with a cap and ticks.", demoFader},
|
||||
{80, "Stepper", "步进器", "input", "◀ value ▶ within bounds. Hold an arrow to repeat; keys step it too.", demoStepper},
|
||||
{81, "NumberInput", "数字框", "input", "Type a number or step it with ▲▼ and the arrow keys; bad text turns the edge red.", demoNumberInput},
|
||||
{82, "TextInput", "文本框", "input", "A one-line pixel field: caret, selection, input methods, clipboard. Enter submits.", demoTextInput},
|
||||
{83, "PasswordInput", "密码框", "input", "Masked with ★; the eye shows the text.", demoPasswordInput},
|
||||
{84, "TextArea", "多行文本", "input", "Many lines in its own scroll, following the caret, with a character count.", demoTextArea},
|
||||
{85, "SearchField", "搜索框", "input", "A field with a magnifier. Escape clears it, Enter searches.", demoSearchField},
|
||||
}
|
||||
|
||||
type inputDemo struct {
|
||||
toggle, music, sound, check, lever bool
|
||||
toggles, mode, party []bool
|
||||
radio string
|
||||
choice, level, count int
|
||||
volume, steps, low, high, fader float64
|
||||
price float64
|
||||
name, secret, notes, query string
|
||||
}
|
||||
|
||||
func inputState(c *ui.Context) *inputDemo {
|
||||
return ui.Local(c.Root(), demoKey("input"), func() inputDemo {
|
||||
return inputDemo{music: true, toggles: []bool{true, false, false}, mode: []bool{false, true, false}, party: []bool{true, false, true},
|
||||
radio: "knight", choice: 1, level: 3, count: 5, volume: 0.6, steps: 40, low: 20, high: 70, fader: 0.3, price: 9.5}
|
||||
})
|
||||
}
|
||||
|
||||
func demoButton(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Column(c).Gap(k.D(6)).Children(func() {
|
||||
ui.Row(c).Gap(k.D(4)).AlignItems(ui.Center).Children(func() {
|
||||
for i, v := range []input.Variant{input.Primary, input.Normal, input.Ghost, input.Danger} {
|
||||
name := []string{"PRIMARY", "NORMAL", "GHOST", "DANGER"}[i]
|
||||
if input.Button(c, name, input.ButtonOptions{Variant: v}).Clicked {
|
||||
log(name)
|
||||
}
|
||||
}
|
||||
})
|
||||
ui.Row(c).Gap(k.D(4)).AlignItems(ui.Center).Children(func() {
|
||||
for _, b := range []struct {
|
||||
name string
|
||||
o input.ButtonOptions
|
||||
}{{"Small", input.ButtonOptions{Size: input.Small}}, {"Save", input.ButtonOptions{Icon: icon.Save}}, {"BIG", input.ButtonOptions{Size: input.Large, Variant: input.Primary}}} {
|
||||
if input.Button(c, b.name, b.o).Clicked {
|
||||
log(b.name)
|
||||
}
|
||||
}
|
||||
input.Button(c, "Saving", input.ButtonOptions{Loading: true})
|
||||
input.Button(c, "Off", input.ButtonOptions{Disabled: true})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func demoIconButton(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Row(c).Gap(k.D(4)).Children(func() {
|
||||
for _, n := range []icon.Named{{Name: "Play", Sprite: icon.Play}, {Name: "Pause", Sprite: icon.Pause}, {Name: "Stop", Sprite: icon.Stop}} {
|
||||
if input.IconButton(c, n.Sprite, n.Name, input.IconButtonOptions{}).Clicked {
|
||||
log(n.Name)
|
||||
}
|
||||
}
|
||||
if input.IconButton(c, icon.Trash, "Delete", input.IconButtonOptions{Variant: input.Danger}).Clicked {
|
||||
log("Delete")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoButtonGroup(c *ui.Context, log func(string)) {
|
||||
labels := []string{"FIGHT", "MAGIC", "ITEM", "RUN"}
|
||||
if r := input.ButtonGroup(c, labels, input.ButtonGroupOptions{Label: "Command"}); r.Clicked >= 0 {
|
||||
log(labels[r.Clicked])
|
||||
}
|
||||
}
|
||||
|
||||
func demoToggle(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := inputState(c)
|
||||
ui.Row(c).Gap(k.D(4)).Children(func() {
|
||||
if input.Toggle(c, "MUSIC", &s.music, input.ToggleOptions{Icon: icon.Music}).Changed {
|
||||
log(fmt.Sprintf("music %v", s.music))
|
||||
}
|
||||
if input.Toggle(c, "SOUND", &s.sound, input.ToggleOptions{Icon: icon.Volume}).Changed {
|
||||
log(fmt.Sprintf("sound %v", s.sound))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoToggleGroup(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := inputState(c)
|
||||
ui.Column(c).Gap(k.D(6)).Children(func() {
|
||||
if input.ToggleGroup(c, []string{"B", "I", "U"}, s.toggles, input.ToggleGroupOptions{Label: "Style"}).Changed {
|
||||
log(fmt.Sprintf("style %v", s.toggles))
|
||||
}
|
||||
if input.ToggleGroup(c, []string{"EASY", "NORMAL", "HARD"}, s.mode, input.ToggleGroupOptions{Single: true, Label: "Mode"}).Changed {
|
||||
log(fmt.Sprintf("mode %v", s.mode))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoCheckbox(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := inputState(c)
|
||||
ui.Column(c).Gap(k.D(2)).Children(func() {
|
||||
if input.Checkbox(c, "Remember me", &s.check, input.CheckboxOptions{}).Changed {
|
||||
log(fmt.Sprintf("remember %v", s.check))
|
||||
}
|
||||
locked := true
|
||||
input.Checkbox(c, "Hard mode (locked)", &locked, input.CheckboxOptions{Disabled: true})
|
||||
})
|
||||
}
|
||||
|
||||
func demoCheckboxGroup(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
if input.CheckboxGroup(c, "Party", []string{"Knight", "Mage", "Thief"}, s.party, input.CheckboxGroupOptions{}).Changed {
|
||||
log(fmt.Sprintf("party %v", s.party))
|
||||
}
|
||||
}
|
||||
|
||||
func demoRadio(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := inputState(c)
|
||||
ui.Column(c).Gap(k.D(2)).Children(func() {
|
||||
for _, class := range []string{"knight", "mage", "thief"} {
|
||||
if input.Radio(c, class, class, &s.radio, input.RadioOptions{}).Changed {
|
||||
log("class " + class)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoRadioGroup(c *ui.Context, log func(string)) {
|
||||
labels := []string{"Spring", "Summer", "Autumn", "Winter"}
|
||||
s := inputState(c)
|
||||
if input.RadioGroup(c, labels, &s.choice, input.RadioGroupOptions{Row: true, Label: "Season"}).Changed {
|
||||
log("season " + labels[s.choice])
|
||||
}
|
||||
}
|
||||
|
||||
func demoSwitch(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
if input.Switch(c, "Power", &s.lever, input.SwitchOptions{}).Changed {
|
||||
log(fmt.Sprintf("power %v", s.lever))
|
||||
}
|
||||
}
|
||||
|
||||
func demoSlider(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := inputState(c)
|
||||
ui.Row(c).Gap(k.D(6)).AlignItems(ui.Center).Children(func() {
|
||||
if input.Slider(c, "Volume", &s.volume, input.SliderOptions{Width: 120}).Changed {
|
||||
log(fmt.Sprintf("volume %.2f", s.volume))
|
||||
}
|
||||
pixel.Text(c, fmt.Sprintf("%3.0f%%", s.volume*100), pixel.TextOptions{})
|
||||
})
|
||||
}
|
||||
|
||||
func demoStepSlider(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
if input.StepSlider(c, "Speed", &s.steps, input.StepSliderOptions{Min: 0, Max: 100, Step: 20, Width: 120}).Changed {
|
||||
log(fmt.Sprintf("speed %g", s.steps))
|
||||
}
|
||||
}
|
||||
|
||||
func demoRangeSlider(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := inputState(c)
|
||||
ui.Row(c).Gap(k.D(6)).AlignItems(ui.Center).Children(func() {
|
||||
if input.RangeSlider(c, "Level range", &s.low, &s.high, input.RangeSliderOptions{Min: 1, Max: 99, Width: 140}).Changed {
|
||||
log(fmt.Sprintf("levels %.0f–%.0f", s.low, s.high))
|
||||
}
|
||||
pixel.Text(c, fmt.Sprintf("LV %.0f–%.0f", s.low, s.high), pixel.TextOptions{})
|
||||
})
|
||||
}
|
||||
|
||||
func demoFader(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
if input.Fader(c, "Master", &s.fader, input.FaderOptions{}).Changed {
|
||||
log(fmt.Sprintf("master %.2f", s.fader))
|
||||
}
|
||||
}
|
||||
|
||||
func demoStepper(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
if input.Stepper(c, "Lives", &s.count, input.StepperOptions{Min: 1, Max: 9}).Changed {
|
||||
log(fmt.Sprintf("lives %d", s.count))
|
||||
}
|
||||
}
|
||||
|
||||
func demoNumberInput(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
if input.NumberInput(c, "Price", &s.price, input.NumberInputOptions{Min: 0, Max: 999, Step: 0.5, Width: 80}).Changed {
|
||||
log(fmt.Sprintf("price %g", s.price))
|
||||
}
|
||||
}
|
||||
|
||||
func demoTextInput(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
r := input.TextInput(c, "Hero name", &s.name, input.TextInputOptions{Placeholder: "Your name 你的名字", MaxLength: 12})
|
||||
if r.Changed {
|
||||
log("name " + s.name)
|
||||
}
|
||||
if r.Submitted {
|
||||
log("submitted " + s.name)
|
||||
}
|
||||
}
|
||||
|
||||
func demoPasswordInput(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
r := input.PasswordInput(c, "Password", &s.secret, input.PasswordInputOptions{Placeholder: "Password"})
|
||||
if r.Changed {
|
||||
log(fmt.Sprintf("%d characters", len([]rune(s.secret))))
|
||||
}
|
||||
if r.Submitted {
|
||||
log("signed in")
|
||||
}
|
||||
}
|
||||
|
||||
func demoTextArea(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
if input.TextArea(c, "Notes", &s.notes, input.TextAreaOptions{Placeholder: "Dear diary...", MaxLength: 140, Width: 200, Lines: 4}).Changed {
|
||||
log(fmt.Sprintf("%d characters", len([]rune(s.notes))))
|
||||
}
|
||||
}
|
||||
|
||||
func demoSearchField(c *ui.Context, log func(string)) {
|
||||
s := inputState(c)
|
||||
r := input.SearchField(c, "Find items", &s.query, input.SearchFieldOptions{Placeholder: "Potion, sword...", Width: 160})
|
||||
if r.Changed {
|
||||
log("query " + s.query)
|
||||
}
|
||||
if r.Submitted {
|
||||
log("search " + s.query)
|
||||
}
|
||||
}
|
||||
+26
-25
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/display"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/icon"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/layout"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
@@ -42,11 +43,11 @@ func demoScreen(c *ui.Context, log func(string)) {
|
||||
ui.Column(c).Gap(k.D(6)).Children(func() {
|
||||
ui.Box(c).FillWidth().Height(k.D(96)).Children(func() {
|
||||
layout.Screen(c, layout.ScreenOptions{Vignette: *on, Padding: 12}, func() {
|
||||
label(c, "A NEW SAVE FILE", pixel.Ink)
|
||||
label(c, "Day 1. The cartridge starts.", pixel.Faint)
|
||||
pixel.Text(c, "A NEW SAVE FILE", pixel.TextOptions{})
|
||||
pixel.Text(c, "Day 1. The cartridge starts.", pixel.TextOptions{Slot: pixel.Faint})
|
||||
})
|
||||
})
|
||||
if button(c, "VIGNETTE") {
|
||||
if input.Button(c, "VIGNETTE", input.ButtonOptions{}).Clicked {
|
||||
*on = !*on
|
||||
log(fmt.Sprintf("vignette %v", *on))
|
||||
}
|
||||
@@ -58,12 +59,12 @@ func demoWindow(c *ui.Context, log func(string)) {
|
||||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.Start).Children(func() {
|
||||
layout.Window(c, layout.WindowOptions{Title: "ITEMS"}, func() {
|
||||
for _, s := range []string{"Potion x3", "Ether x1", "Key x2"} {
|
||||
label(c, s, pixel.Ink)
|
||||
pixel.Text(c, s, pixel.TextOptions{})
|
||||
}
|
||||
})
|
||||
layout.Window(c, layout.WindowOptions{}, func() {
|
||||
label(c, "HP 32/40", pixel.Ink)
|
||||
label(c, "MP 12/18", pixel.Ink)
|
||||
pixel.Text(c, "HP 32/40", pixel.TextOptions{})
|
||||
pixel.Text(c, "MP 12/18", pixel.TextOptions{})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -72,7 +73,7 @@ func demoPanel(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Row(c).Wrap().Gap(k.D(6)).Children(func() {
|
||||
for i, name := range []string{"RAISED", "SUNKEN", "FLAT", "DOUBLE", "WINDOW", "NOTCHED"} {
|
||||
layout.Panel(c, layout.PanelOptions{Style: pixel.FrameStyle(i)}, func() { label(c, name, pixel.Ink) })
|
||||
layout.Panel(c, layout.PanelOptions{Style: pixel.FrameStyle(i)}, func() { pixel.Text(c, name, pixel.TextOptions{}) })
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -81,15 +82,15 @@ func demoCard(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Box(c).Width(k.D(200)).Children(func() {
|
||||
layout.Card(c, layout.CardOptions{Title: "QUEST", Icon: icon.Scroll, Footer: func() {
|
||||
if button(c, "ACCEPT") {
|
||||
if input.Button(c, "ACCEPT", input.ButtonOptions{}).Clicked {
|
||||
log("quest accepted")
|
||||
}
|
||||
if button(c, "LATER") {
|
||||
if input.Button(c, "LATER", input.ButtonOptions{}).Clicked {
|
||||
log("quest saved for later")
|
||||
}
|
||||
}}, func() {
|
||||
label(c, "Find the lost cartridge.", pixel.Ink)
|
||||
label(c, "Reward: 300 G", pixel.Faint)
|
||||
pixel.Text(c, "Find the lost cartridge.", pixel.TextOptions{})
|
||||
pixel.Text(c, "Reward: 300 G", pixel.TextOptions{Slot: pixel.Faint})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -98,8 +99,8 @@ func demoSection(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Box(c).Width(k.D(220)).Children(func() {
|
||||
layout.Section(c, "Sound", layout.SectionOptions{}, func() {
|
||||
label(c, "Music 8", pixel.Ink)
|
||||
label(c, "Effects 5", pixel.Ink)
|
||||
pixel.Text(c, "Music 8", pixel.TextOptions{})
|
||||
pixel.Text(c, "Effects 5", pixel.TextOptions{})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -110,7 +111,7 @@ func demoDivider(c *ui.Context, log func(string)) {
|
||||
ui.Row(c).Gap(k.D(12)).AlignItems(ui.Stretch).Children(func() {
|
||||
ui.Column(c).Grow(1).Gap(k.D(4)).Children(func() {
|
||||
for i, n := range names {
|
||||
label(c, n, pixel.Faint)
|
||||
pixel.Text(c, n, pixel.TextOptions{Slot: pixel.Faint})
|
||||
layout.Divider(c, layout.DividerOptions{Style: layout.DividerStyle(i)})
|
||||
}
|
||||
})
|
||||
@@ -126,14 +127,14 @@ func demoScrollArea(c *ui.Context, log func(string)) {
|
||||
ui.Column(c).Gap(k.D(4)).Children(func() {
|
||||
r := layout.ScrollArea(c, s, layout.ScrollAreaOptions{Label: "Bestiary"}, func() {
|
||||
for i := range 40 {
|
||||
label(c, fmt.Sprintf("No.%03d %s", i+1, monsters[i%len(monsters)]), pixel.Ink)
|
||||
pixel.Text(c, fmt.Sprintf("No.%03d %s", i+1, monsters[i%len(monsters)]), pixel.TextOptions{})
|
||||
}
|
||||
})
|
||||
r.Element.Size(k.D(200), k.D(112))
|
||||
if r.Changed {
|
||||
log(fmt.Sprintf("scrolled to %d dots", int(s.Y/k.Dot())))
|
||||
}
|
||||
label(c, fmt.Sprintf("Y %d of %d dots", int(s.Y/k.Dot()), int(s.MaxY/k.Dot())), pixel.Faint)
|
||||
pixel.Text(c, fmt.Sprintf("Y %d of %d dots", int(s.Y/k.Dot()), int(s.MaxY/k.Dot())), pixel.TextOptions{Slot: pixel.Faint})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -142,7 +143,7 @@ func demoSplit(c *ui.Context, log func(string)) {
|
||||
size := ui.Local(c.Root(), demoKey("split"), func() int { return 120 })
|
||||
pane := func(name string) func() {
|
||||
return func() {
|
||||
layout.Panel(c, layout.PanelOptions{Style: pixel.Sunken, Fill: pixel.Well}, func() { label(c, name, pixel.Ink) }).Fill()
|
||||
layout.Panel(c, layout.PanelOptions{Style: pixel.Sunken, Fill: pixel.Well}, func() { pixel.Text(c, name, pixel.TextOptions{}) }).Fill()
|
||||
}
|
||||
}
|
||||
ui.Box(c).FillWidth().Height(k.D(96)).Children(func() {
|
||||
@@ -214,7 +215,7 @@ func demoLayers(c *ui.Context, log func(string)) {
|
||||
}, func() {
|
||||
ui.Box(c).Fill().Center().Children(func() { display.Icon(c, icon.Chest, display.IconOptions{Scale: 3}) })
|
||||
}, func() {
|
||||
ui.Box(c).Padding(k.D(3)).Children(func() { label(c, "LAYER 3", pixel.Ink) })
|
||||
ui.Box(c).Padding(k.D(3)).Children(func() { pixel.Text(c, "LAYER 3", pixel.TextOptions{}) })
|
||||
}).Size(k.D(120), k.D(64))
|
||||
}
|
||||
|
||||
@@ -259,7 +260,7 @@ func demoResizable(c *ui.Context, log func(string)) {
|
||||
h := ui.Local(c.Root(), demoKey("resize-h"), func() int { return 56 })
|
||||
r := layout.Resizable(c, w, h, layout.ResizableOptions{MinW: 48, MinH: 32, MaxW: 240, MaxH: 120}, func() {
|
||||
layout.Panel(c, layout.PanelOptions{Style: pixel.Sunken, Fill: pixel.Well}, func() {
|
||||
label(c, fmt.Sprintf("%d×%d", *w, *h), pixel.Ink)
|
||||
pixel.Text(c, fmt.Sprintf("%d×%d", *w, *h), pixel.TextOptions{})
|
||||
}).Fill()
|
||||
})
|
||||
if r.Changed {
|
||||
@@ -297,8 +298,8 @@ func demoCRTFrame(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
layout.CRTFrame(c, layout.CRTFrameOptions{Brand: "8BIT CRT"}, func() {
|
||||
ui.Column(c).Size(k.D(180), k.D(72)).Padding(k.D(4)).Children(func() {
|
||||
label(c, "READY.", pixel.Good)
|
||||
label(c, "10 PRINT \"HI\"", pixel.Good)
|
||||
pixel.Text(c, "READY.", pixel.TextOptions{Slot: pixel.Good})
|
||||
pixel.Text(c, "10 PRINT \"HI\"", pixel.TextOptions{Slot: pixel.Good})
|
||||
})
|
||||
}).AlignSelf(ui.Start)
|
||||
}
|
||||
@@ -307,17 +308,17 @@ func demoAppFrame(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Box(c).FillWidth().Height(k.D(150)).Children(func() {
|
||||
layout.AppFrame(c, layout.AppFrameOptions{SidebarWidth: 72}, func() {
|
||||
label(c, "8BIT MAIL", pixel.Ink)
|
||||
pixel.Text(c, "8BIT MAIL", pixel.TextOptions{})
|
||||
}, func() {
|
||||
for _, s := range []string{"Inbox", "Sent", "Spam"} {
|
||||
if button(c, s) {
|
||||
if input.Button(c, s, input.ButtonOptions{}).Clicked {
|
||||
log("open " + s)
|
||||
}
|
||||
}
|
||||
}, func() {
|
||||
label(c, "No new mail. Go outside.", pixel.Ink)
|
||||
pixel.Text(c, "No new mail. Go outside.", pixel.TextOptions{})
|
||||
}, func() {
|
||||
label(c, "3 folders", pixel.Faint)
|
||||
pixel.Text(c, "3 folders", pixel.TextOptions{Slot: pixel.Faint})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/text"
|
||||
)
|
||||
@@ -97,7 +98,7 @@ func demoTypewriter(c *ui.Context, log func(string)) {
|
||||
if r.Done {
|
||||
log(fmt.Sprintf("line %d done", *at+1))
|
||||
}
|
||||
if button(c, "NEXT") {
|
||||
if input.Button(c, "NEXT", input.ButtonOptions{}).Clicked {
|
||||
*at = (*at + 1) % len(lines)
|
||||
log("next line")
|
||||
}
|
||||
@@ -133,9 +134,9 @@ func demoKbd(c *ui.Context, log func(string)) {
|
||||
func demoCode(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Row(c).Gap(k.D(4)).AlignItems(ui.Center).Children(func() {
|
||||
label(c, "Call", pixel.Ink)
|
||||
pixel.Text(c, "Call", pixel.TextOptions{})
|
||||
text.Code(c, "pixel.Use(c, s)", text.CodeOptions{})
|
||||
label(c, "once per frame.", pixel.Ink)
|
||||
pixel.Text(c, "once per frame.", pixel.TextOptions{})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -169,11 +170,11 @@ func demoOdometer(c *ui.Context, log func(string)) {
|
||||
score := ui.Local(c.Root(), demoKey("odometer"), func() int { return 1990 })
|
||||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.Center).Children(func() {
|
||||
text.Odometer(c, *score, text.OdometerOptions{Digits: 6})
|
||||
if button(c, "+15") {
|
||||
if input.Button(c, "+15", input.ButtonOptions{}).Clicked {
|
||||
*score += 15
|
||||
log(fmt.Sprintf("score %d", *score))
|
||||
}
|
||||
if button(c, "+500") {
|
||||
if input.Button(c, "+500", input.ButtonOptions{}).Clicked {
|
||||
*score += 500
|
||||
log(fmt.Sprintf("score %d", *score))
|
||||
}
|
||||
@@ -202,7 +203,7 @@ func demoScrambleText(c *ui.Context, log func(string)) {
|
||||
at := ui.Local(c.Root(), demoKey("scramble"), func() int { return 0 })
|
||||
ui.Column(c).Gap(k.D(6)).Children(func() {
|
||||
text.ScrambleText(c, words[*at], text.ScrambleTextOptions{Slot: pixel.Good, Scale: 2})
|
||||
if button(c, "AGAIN") {
|
||||
if input.Button(c, "AGAIN", input.ButtonOptions{}).Clicked {
|
||||
*at = (*at + 1) % len(words)
|
||||
log("scramble " + words[*at])
|
||||
}
|
||||
|
||||
+23
-26
@@ -8,7 +8,10 @@ import (
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/display"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/icon"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/layout"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/text"
|
||||
)
|
||||
|
||||
func (a *App) content(c *ui.Context) {
|
||||
@@ -46,14 +49,12 @@ func page(c *ui.Context, fn func()) {
|
||||
|
||||
func (a *App) home(c *ui.Context) {
|
||||
k := pixel.K(c)
|
||||
ui.Box(c).Height(k.D(52)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
shadowText(k.Canvas(p, r), 0, 0, logo, pixel.Accent, 3)
|
||||
})
|
||||
text.ShadowText(c, logo, text.ShadowTextOptions{Slot: pixel.Accent, Scale: 3})
|
||||
pixel.Text(c, "Pixel components for MyGo. Every dot sits on the grid; every color comes from sixteen.", pixel.TextOptions{Wrap: true})
|
||||
pixel.Text(c, "为 MyGo 打造的像素组件。每个点落在点阵上,每种颜色来自十六格调色板。", pixel.TextOptions{Wrap: true, Slot: pixel.Faint})
|
||||
comps := len(Entries()) - count("foundations")
|
||||
stats := fmt.Sprintf("%d COMPONENTS %d CATEGORIES %d PALETTES", comps, len(Categories)-1, len(pixel.Palettes))
|
||||
ui.Box(c).Height(k.D(7)).Draw(func(p *ui.Painter, r ui.Rect) { k.Canvas(p, r).Micro(0, 1, stats, pixel.Accent, 1) })
|
||||
text.MicroText(c, stats, text.MicroTextOptions{Slot: pixel.Accent})
|
||||
ui.Grid(c).Columns(3).Gap(k.D(4)).Children(func() {
|
||||
for _, cat := range Categories {
|
||||
n := count(cat.Key)
|
||||
@@ -87,11 +88,10 @@ func (a *App) category(c *ui.Context, key string) {
|
||||
return
|
||||
}
|
||||
k := pixel.K(c)
|
||||
ui.Box(c).Height(k.D(36)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
g.Sprite(0, 4, cat.Icon, 0, pixel.Accent, 2)
|
||||
shadowText(g, 30, 0, cat.Name, pixel.Ink, 2)
|
||||
g.Text(30+pixel.Measure(cat.Name)*2+8, 14, cat.Zh, pixel.Faint, 1)
|
||||
ui.Row(c).Gap(k.D(6)).AlignItems(ui.Center).Children(func() {
|
||||
display.Icon(c, cat.Icon, display.IconOptions{Slot: pixel.Accent, Scale: 2})
|
||||
text.ShadowText(c, cat.Name, text.ShadowTextOptions{Scale: 2})
|
||||
pixel.Text(c, cat.Zh, pixel.TextOptions{Slot: pixel.Faint})
|
||||
})
|
||||
ui.Grid(c).Columns(3).Gap(k.D(4)).Children(func() {
|
||||
for _, e := range Entries() {
|
||||
@@ -121,40 +121,37 @@ func (a *App) card(c *ui.Context, e Entry) {
|
||||
|
||||
func (a *App) entry(c *ui.Context, e Entry) {
|
||||
k := pixel.K(c)
|
||||
ui.Box(c).Height(k.D(36)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
x := 0
|
||||
ui.Row(c).Gap(k.D(6)).AlignItems(ui.Center).Children(func() {
|
||||
if e.ID > 0 {
|
||||
g.Micro(0, 2, fmt.Sprintf("%03d", e.ID), pixel.Accent, 2)
|
||||
x = 30
|
||||
text.MicroText(c, fmt.Sprintf("%03d", e.ID), text.MicroTextOptions{Slot: pixel.Accent, Scale: 2})
|
||||
}
|
||||
shadowText(g, x, 0, e.Name, pixel.Ink, 2)
|
||||
g.Text(x+pixel.Measure(e.Name)*2+8, 14, e.Zh, pixel.Faint, 1)
|
||||
text.ShadowText(c, e.Name, text.ShadowTextOptions{Scale: 2})
|
||||
pixel.Text(c, e.Zh, pixel.TextOptions{Slot: pixel.Faint})
|
||||
})
|
||||
pixel.Text(c, e.Summary, pixel.TextOptions{Wrap: true})
|
||||
panel(c, pixel.Window, pixel.Face, 10).MinHeight(k.D(80)).Children(func() { e.Demo(c, a.logger(e)) })
|
||||
layout.Panel(c, layout.PanelOptions{Style: pixel.Window, Padding: 8}, func() { e.Demo(c, a.logger(e)) }).MinHeight(k.D(80))
|
||||
code := strings.ReplaceAll(e.Code(), "\t", " ")
|
||||
ui.Row(c).Gap(k.D(4)).AlignItems(ui.Start).Children(func() {
|
||||
panel(c, pixel.Sunken, pixel.Well, 4).Grow(1).Children(func() {
|
||||
layout.Panel(c, layout.PanelOptions{Style: pixel.Sunken, Fill: pixel.Well, Padding: 2}, func() {
|
||||
ui.ScrollBoth(c).Height(k.D(160)).Children(func() { codeBlock(c, code) })
|
||||
})
|
||||
}).Grow(1)
|
||||
ui.Column(c).Width(k.D(140)).Gap(k.D(4)).Children(func() {
|
||||
if button(c, "COPY CODE") {
|
||||
if input.Button(c, "COPY CODE", input.ButtonOptions{}).Clicked {
|
||||
c.WriteClipboard(code)
|
||||
a.logger(e)("code copied")
|
||||
}
|
||||
panel(c, pixel.Sunken, pixel.Well, 4).Height(k.D(140)).Children(func() {
|
||||
layout.Panel(c, layout.PanelOptions{Style: pixel.Sunken, Fill: pixel.Well, Padding: 2}, func() {
|
||||
for _, l := range a.logs[e.Slug()] {
|
||||
pixel.Text(c, "> "+l, pixel.TextOptions{Slot: pixel.Faint, MaxLines: 1})
|
||||
}
|
||||
})
|
||||
}).Height(k.D(140))
|
||||
})
|
||||
})
|
||||
ui.Row(c).Gap(k.D(4)).Children(func() {
|
||||
if button(c, "◀ PREV") {
|
||||
if input.Button(c, "◀ PREV", input.ButtonOptions{}).Clicked {
|
||||
a.step(-1)
|
||||
}
|
||||
if button(c, "NEXT ▶") {
|
||||
if input.Button(c, "NEXT ▶", input.ButtonOptions{}).Clicked {
|
||||
a.step(1)
|
||||
}
|
||||
})
|
||||
@@ -203,11 +200,11 @@ func GameOver(c *ui.Context, why string) bool {
|
||||
cont := false
|
||||
ui.Column(c).Gap(k.D(8)).AlignItems(ui.Center).Padding(k.D(24)).Children(func() {
|
||||
ui.Box(c).Size(k.D(pixel.Measure(k.Msg("game_over"))*3), k.D(48)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
shadowText(k.Canvas(p, r), 0, 0, k.Msg("game_over"), pixel.Bad, 3)
|
||||
shadow(k.Canvas(p, r), 0, 0, k.Msg("game_over"), pixel.Bad, 3)
|
||||
})
|
||||
pixel.Text(c, why, pixel.TextOptions{Slot: pixel.Faint, Wrap: true, MaxLines: 6}).Width(k.D(min(pixel.Measure(why), 280)))
|
||||
display.Icon(c, icon.Skull, display.IconOptions{Scale: 3})
|
||||
cont = button(c, k.Msg("continue"))
|
||||
cont = input.Button(c, k.Msg("continue"), input.ButtonOptions{}).Clicked
|
||||
})
|
||||
return cont
|
||||
}
|
||||
+1
-1
@@ -56,7 +56,7 @@ var Categories = []Category{
|
||||
{"tabletop", "Tabletop", "桌游", icon.Crown},
|
||||
}
|
||||
|
||||
var entries = slices.Concat(foundationEntries, layoutEntries, textEntries, displayEntries)
|
||||
var entries = slices.Concat(foundationEntries, layoutEntries, textEntries, displayEntries, inputEntries)
|
||||
|
||||
func Entries() []Entry { return entries }
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package gallery
|
||||
|
||||
import (
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
// press is a clickable box; w ≤ 0 stretches.
|
||||
func press(c *ui.Context, w, h int, label string, draw func(g pixel.Canvas, st pixel.State)) bool {
|
||||
k := pixel.K(c)
|
||||
shell, base, st := pixel.Shell(c, func() *ui.Element { return ui.ButtonBase(c).Label(label) })
|
||||
if w > 0 {
|
||||
shell.Width(k.D(w))
|
||||
}
|
||||
shell.Height(k.D(h)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
draw(g, st)
|
||||
if st.Focus {
|
||||
g.FocusMark(0, 0, g.W, g.H)
|
||||
}
|
||||
})
|
||||
return base.Clicked()
|
||||
}
|
||||
|
||||
// button is a raised pixel button with a centered label.
|
||||
func button(c *ui.Context, label string) bool {
|
||||
return press(c, pixel.Measure(label)+12, 16, label, func(g pixel.Canvas, st pixel.State) {
|
||||
y := 0
|
||||
if st.Press {
|
||||
y = 1
|
||||
}
|
||||
g.Frame(0, y, g.W, g.H-1, pixel.Raised, pixel.Face)
|
||||
g.Text((g.W-pixel.Measure(label))/2, y, label, pixel.Ink, 1)
|
||||
})
|
||||
}
|
||||
|
||||
// panel is a framed box with padding for children.
|
||||
func panel(c *ui.Context, style pixel.FrameStyle, fill pixel.Slot, pad int) *ui.Element {
|
||||
k := pixel.K(c)
|
||||
return ui.Column(c).Padding(k.D(pad)).Draw(func(p *ui.Painter, r ui.Rect) {
|
||||
g := k.Canvas(p, r)
|
||||
g.Frame(0, 0, g.W, g.H, style, fill)
|
||||
})
|
||||
}
|
||||
|
||||
// shadowText draws text with a one-dot shadow.
|
||||
func shadowText(g pixel.Canvas, x, y int, s string, ink pixel.Slot, scale int) {
|
||||
g.Text(x+scale, y+scale, s, pixel.Shade, scale)
|
||||
g.Text(x, y, s, ink, scale)
|
||||
}
|
||||
|
||||
// label is non-wrapping pixel text.
|
||||
func label(c *ui.Context, s string, ink pixel.Slot) *ui.Element {
|
||||
return pixel.Text(c, s, pixel.TextOptions{Slot: ink})
|
||||
}
|
||||
Reference in new issue
Block a user