Files
8bitMyGoUI/gallery/demos_data.go
T
ZacharyZhang-NY 03680980da Add data components 151-175; clear MyGo row highlights
Lists, tables, trees, grids, inventories and records in data/.
Outline and GridView build on ui.List: ui.Outline strokes its arrows
and ui.GridView spaces and tints items. The pixel theme keeps MyGo's
row highlights clear so scrolled rows stay on whole dots; off lists
take a veil against the wheel. Adds Canvas.Silhouette, SwitchOptions
Label and exports Rarity.Slot.
2026-10-11 22:29:07 -04:00

265 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package gallery
import (
"cmp"
"fmt"
"slices"
"strings"
"time"
"github.com/egoist/mygo/ui"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/data"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/display"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/icon"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/text"
)
var dataEntries = []Entry{
{151, "List", "列表", "data", "Thousands of rows, built as they scroll in. ▶ marks the chosen one.", demoList},
{152, "Table", "表格", "data", "Click a header to sort ▲, again for ▼. Odd rows are dithered.", demoTable},
{153, "Tree", "树", "data", "▸ opens, ▾ closes. Right opens, Left climbs back out.", demoTree},
{154, "Outline", "大纲", "data", "A tree of 2,000 floors that only builds what shows.", demoOutline},
{155, "GridView", "网格视图", "data", "Whole-dot cells in as many columns as fit; arrows go both ways.", demoGridView},
{156, "DescriptionList", "描述列表", "data", "Terms on the left, what they mean on the right.", demoDescriptionList},
{157, "Leaderboard", "排行榜", "data", "Medals for the top three; your row lights up.", demoLeaderboard},
{158, "Inventory", "物品栏", "data", "Arrows pick a slot. Drag one item onto another to swap them.", demoInventory},
{159, "ItemSlot", "物品格", "data", "An item with its stack, rarity edge and cooldown veil.", demoItemSlot},
{160, "Accordion", "手风琴", "data", "Open one answer and the others fold away.", demoAccordion},
{161, "Collapsible", "折叠区", "data", "One header that shows and hides what is under it.", demoCollapsible},
{162, "Carousel", "轮播", "data", "◀ ▶ turn the pages; it turns by itself unless you point at it.", demoCarousel},
{163, "Timeline", "时间线", "data", "Dated events down a line of markers.", demoTimeline},
}
type dataDemo struct {
list, row, tile, slot, page, size, carousel, hit int
sort data.Sort
tree, floor string
faq []bool
secret bool
quests, bench, party []string
bag []data.Item
rights [][]bool
filters []bool
name string
level float64
hard bool
logs int
loading time.Time
query string
}
func dataState(c *ui.Context) *dataDemo {
return ui.Local(c.Root(), demoKey("data"), func() dataDemo {
return dataDemo{size: 20, tree: "0", floor: "R1", faq: []bool{true, false, false},
quests: []string{"Find the key", "Save the cat", "Beat the boss", "Buy a potion"},
bench: []string{"Dax", "Eko", "Fay"}, party: []string{"Aria", "Brom"},
bag: []data.Item{{Sprite: icon.Potion, Name: "Potion", Count: 5}, {Sprite: icon.Drop, Name: "Ether", Count: 2, Rarity: display.Uncommon},
{Sprite: icon.Sword, Name: "Sword", Rarity: display.Rare}, {Sprite: icon.Shield, Name: "Shield", Rarity: display.Epic},
{Sprite: icon.Crown, Name: "Crown", Rarity: display.Legendary}, {Sprite: icon.Gem, Name: "Gem", Count: 12, Rarity: display.Rare},
{}, {Sprite: icon.Key, Name: "Key"}, {}, {}, {Sprite: icon.Scroll, Name: "Map scroll"}, {}},
rights: [][]bool{{true, false, false}, {false, true, false}, {true, true, true}},
filters: []bool{false, true, false, false}, name: "Aria", level: 7, logs: 20}
})
}
var horde = strings.Fields("Slime Bat Goblin Ghost Golem Imp Kobold Lich Mimic Ogre Orc Pixie Rat Skeleton Snake Spider Troll Wisp Wolf Wyrm Zombie Harpy Hydra Kraken Basilisk Djinn Gargoyle Manticore Wyvern Yeti")
func demoList(c *ui.Context, log func(string)) {
s := dataState(c)
r := data.List(c, "Monsters", len(horde), &s.list, data.ListOptions{}, func(i int) {
pixel.Text(c, horde[i], pixel.TextOptions{})
})
r.Element.Width(pixel.K(c).D(140))
if r.Changed {
log("chose " + horde[s.list])
}
if r.Submitted {
log("opened " + horde[s.list])
}
}
var roster = []struct {
name, class string
lv int
}{{"Aria", "Knight", 7}, {"Brom", "Monk", 5}, {"Cyra", "Mage", 9}, {"Dax", "Thief", 4}, {"Eko", "Bard", 6},
{"Fay", "Cleric", 8}, {"Gus", "Ranger", 3}, {"Hal", "Knight", 10}, {"Ivy", "Mage", 2}, {"Jun", "Monk", 11}}
func demoTable(c *ui.Context, log func(string)) {
s := dataState(c)
order := make([]int, len(roster))
for i := range order {
order[i] = i
}
slices.SortStableFunc(order, func(a, b int) int {
x, y := roster[a], roster[b]
d := [3]int{cmp.Compare(x.name, y.name), cmp.Compare(x.class, y.class), cmp.Compare(x.lv, y.lv)}[s.sort.Column]
if s.sort.Desc {
return -d
}
return d
})
cols := []data.Column{{Title: "Name", Width: 50}, {Title: "Class", Width: 56}, {Title: "LV", Width: 30}}
r := data.Table(c, "Roster", cols, len(roster), &s.sort, &s.row, data.TableOptions{}, func(row, col int) string {
h := roster[order[row]]
return [3]string{h.name, h.class, fmt.Sprint(h.lv)}[col]
})
if r.Sorted {
log(fmt.Sprintf("sorted by %s, desc %v", cols[s.sort.Column].Title, s.sort.Desc))
}
if r.Changed {
log("chose row " + fmt.Sprint(s.row))
}
if r.Submitted {
log("opened " + roster[order[s.row]].name)
}
}
func demoTree(c *ui.Context, log func(string)) {
s := dataState(c)
roots := []data.TreeNode{
{Label: "Bag", Children: []data.TreeNode{{Label: "Potions", Children: []data.TreeNode{{Label: "Potion ×5"}, {Label: "Ether ×2"}}}, {Label: "Tent"}}},
{Label: "Key items", Children: []data.TreeNode{{Label: "Old key"}, {Label: "Map scroll"}}},
{Label: "Gold: 120"},
}
r := data.Tree(c, "Items", roots, &s.tree, data.TreeOptions{})
if r.Changed {
log("chose " + s.tree)
}
if r.Toggled {
log("opened or closed " + s.tree)
}
}
func demoOutline(c *ui.Context, log func(string)) {
s := dataState(c)
roots := make([]string, 8)
for i := range roots {
roots[i] = fmt.Sprintf("R%d", i+1)
}
children := func(k string) []string {
n := map[int]int{0: 12, 1: 20}[strings.Count(k, "/")]
var out []string
for i := range n {
out = append(out, fmt.Sprintf("%s/%d", k, i+1))
}
return out
}
label := func(k string) string {
parts := strings.Split(k, "/")
name := []string{"Region " + parts[0][1:], "Dungeon ", "Floor B"}[len(parts)-1]
if len(parts) > 1 {
name += parts[len(parts)-1]
}
return name
}
r := data.Outline(c, "World", roots, children, label, &s.floor, data.OutlineOptions{})
r.Element.Width(pixel.K(c).D(160))
if r.Changed {
log("chose " + label(s.floor))
}
if r.Submitted {
log("entered " + label(s.floor))
}
}
var tiles = []*pixel.Sprite{icon.Coin, icon.Gem, icon.Potion, icon.Sword, icon.Shield, icon.Chest, icon.Crown, icon.Scroll, icon.Flame, icon.Leaf}
func demoGridView(c *ui.Context, log func(string)) {
k := pixel.K(c)
s := dataState(c)
r := data.GridView(c, "Loot", 200, &s.tile, data.GridViewOptions{CellWidth: 24, CellHeight: 24, Height: 100}, func(i int) {
ui.Box(c).Grow(1).AlignItems(ui.Center).Justify(ui.Center).Children(func() {
display.Icon(c, tiles[i%len(tiles)], display.IconOptions{Label: fmt.Sprintf("loot %d", i)})
})
})
r.Element.Width(k.D(200))
if r.Changed {
log(fmt.Sprintf("chose loot %d", s.tile))
}
if r.Submitted {
log(fmt.Sprintf("took loot %d", s.tile))
}
}
func demoDescriptionList(c *ui.Context, log func(string)) {
ui.Box(c).Width(pixel.K(c).D(220)).Children(func() {
data.DescriptionList(c, [][2]string{{"Class", "Knight"}, {"Weapon", "Rusty sword"},
{"Home", "Castle Town, two screens west of the cave"}, {"Motto", "It is dangerous to go alone."}}, data.DescriptionListOptions{TermWidth: 50})
})
}
func demoLeaderboard(c *ui.Context, log func(string)) {
scores := []data.Score{{Name: "ZAK", Score: 98400}, {Name: "MOM", Score: 87150}, {Name: "AAA", Score: 80000}, {Name: "BOB", Score: 64200}, {Name: "YOU", Score: 51300}, {Name: "KEN", Score: 32000}}
ui.Box(c).Width(pixel.K(c).D(160)).Children(func() {
data.Leaderboard(c, scores, data.LeaderboardOptions{Player: 4})
})
}
func demoInventory(c *ui.Context, log func(string)) {
s := dataState(c)
r := data.Inventory(c, "Bag", s.bag, &s.slot, data.InventoryOptions{})
if r.Swapped {
log("swapped slots")
}
if r.Changed {
log(fmt.Sprintf("slot %d: %s", s.slot, s.bag[s.slot].Name))
}
}
func demoItemSlot(c *ui.Context, log func(string)) {
ui.Row(c).Gap(pixel.K(c).D(6)).Children(func() {
data.ItemSlot(c, data.Item{Sprite: icon.Potion, Name: "Potion", Count: 3}, data.ItemSlotOptions{})
data.ItemSlot(c, data.Item{Sprite: icon.Crown, Name: "Crown", Rarity: display.Legendary}, data.ItemSlotOptions{Selected: true})
data.ItemSlot(c, data.Item{Sprite: icon.Bolt, Name: "Bolt scroll", Rarity: display.Rare}, data.ItemSlotOptions{Cooldown: 0.5})
data.ItemSlot(c, data.Item{Name: "Empty"}, data.ItemSlotOptions{})
})
}
func demoAccordion(c *ui.Context, log func(string)) {
s := dataState(c)
qs := []string{"How do I save?", "Where is the key?", "Can I pet the dog?"}
as := []string{"Visit any inn, or press START.", "Under the third torch.", "Yes. Always yes."}
ui.Box(c).Width(pixel.K(c).D(180)).Children(func() {
if data.Accordion(c, "Help", qs, s.faq, data.AccordionOptions{}, func(i int) {
text.Paragraph(c, as[i], text.ParagraphOptions{})
}).Changed {
log(fmt.Sprintf("open %v", s.faq))
}
})
}
func demoCollapsible(c *ui.Context, log func(string)) {
s := dataState(c)
if data.Collapsible(c, "Secret moves", &s.secret, data.CollapsibleOptions{}, func() {
pixel.Text(c, "↑ ↑ ↓ ↓ ← → ← → B A", pixel.TextOptions{})
}).Changed {
log(fmt.Sprintf("open %v", s.secret))
}
}
func demoCarousel(c *ui.Context, log func(string)) {
k := pixel.K(c)
s := dataState(c)
tips := []struct {
art *pixel.Sprite
line string
}{{icon.Heart, "Hearts heal you."}, {icon.Key, "Keys open doors."}, {icon.Coin, "Coins buy things."}}
if data.Carousel(c, "Tips", len(tips), &s.carousel, data.CarouselOptions{Every: 4}, func(i int) {
ui.Column(c).Width(k.D(120)).AlignItems(ui.Center).Gap(k.D(4)).Children(func() {
display.Icon(c, tips[i].art, display.IconOptions{Scale: 2})
pixel.Text(c, tips[i].line, pixel.TextOptions{})
})
}).Changed {
log(fmt.Sprintf("page %d", s.carousel+1))
}
}
func demoTimeline(c *ui.Context, log func(string)) {
ui.Box(c).Width(pixel.K(c).D(200)).Children(func() {
data.Timeline(c, []data.Event{{Date: "1985", Text: "A plumber jumps into a pipe."}, {Date: "1986", Text: "A boy in green finds a sword."},
{Date: "1987", Text: "A last fantasy begins."}, {Date: "1991", Text: "A blue hedgehog runs very fast."}}, data.TimelineOptions{})
})
}