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.
This commit is contained in:
47 files changed
+3379
-17
No files matched your search
@@ -238,6 +238,25 @@ func TestControlDemosLogTheirEvents(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDataDemosLogSubmits(t *testing.T) {
|
||||
for slug, row := range map[string]string{"152-table": "Brom, Monk, 5", "154-outline": "Region 3", "174-searchresults": "Fira"} {
|
||||
a, tt := open("/c/" + slug)
|
||||
click(t, tt, row)
|
||||
n := len(a.logs[slug])
|
||||
tt.Key(0, ui.KeyEnter)
|
||||
if len(a.logs[slug]) == n {
|
||||
t.Errorf("%s logged no submit: %q", slug, a.logs[slug])
|
||||
}
|
||||
}
|
||||
a, tt := open("/c/153-tree")
|
||||
click(t, tt, "Items")
|
||||
n := len(a.logs["153-tree"])
|
||||
tt.Key(0, ui.KeyRight)
|
||||
if len(a.logs["153-tree"]) == n {
|
||||
t.Errorf("opening a branch logged nothing: %q", a.logs["153-tree"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldDemoLogsSubmit(t *testing.T) {
|
||||
a, tt := open("/c/100-field")
|
||||
// The group shares its name; the input sits below.
|
||||
@@ -250,3 +269,26 @@ func TestFieldDemoLogsSubmit(t *testing.T) {
|
||||
t.Fatal("Enter in the field logged nothing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDataDemosLogTheirEvents(t *testing.T) {
|
||||
for slug, act := range map[string]func(tt *ui.Tester){
|
||||
"151-list": func(tt *ui.Tester) { click(t, tt, "Bat") },
|
||||
"152-table": func(tt *ui.Tester) { click(t, tt, "LV") },
|
||||
"153-tree": func(tt *ui.Tester) { click(t, tt, "Items"); tt.Key(0, ui.KeyRight) },
|
||||
"154-outline": func(tt *ui.Tester) { click(t, tt, "Region 2") },
|
||||
"174-searchresults": func(tt *ui.Tester) { click(t, tt, "Fira") },
|
||||
"155-gridview": func(tt *ui.Tester) { click(t, tt, "loot 3") },
|
||||
"160-accordion": func(tt *ui.Tester) { click(t, tt, "Where is the key?") },
|
||||
"162-carousel": func(tt *ui.Tester) { click(t, tt, "NEXT") },
|
||||
"167-pager": func(tt *ui.Tester) { click(t, tt, "NEXT") },
|
||||
"170-sortable": func(tt *ui.Tester) { click(t, tt, "Quest order"); tt.Key(ui.Alt, ui.KeyDown) },
|
||||
"171-transfer": func(tt *ui.Tester) { click(t, tt, "RIGHT") },
|
||||
"173-filterbar": func(tt *ui.Tester) { click(t, tt, "FIRE") },
|
||||
} {
|
||||
a, tt := open("/c/" + slug)
|
||||
act(tt)
|
||||
if len(a.logs[slug]) == 0 {
|
||||
t.Errorf("%s logged nothing", slug)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
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{})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package gallery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/data"
|
||||
"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"
|
||||
)
|
||||
|
||||
var recordEntries = []Entry{
|
||||
{164, "StatCompare", "属性对比", "data", "What a new sword does to you: ▲ in green, ▼ in red.", demoStatCompare},
|
||||
{165, "Bestiary", "图鉴", "data", "Monsters you met, and ??? shadows of those you have not.", demoBestiary},
|
||||
{166, "PropertyGrid", "属性表", "data", "Edit text, numbers and switches row by row.", demoPropertyGrid},
|
||||
{167, "Pager", "分页器", "data", "Pick a page size; ◀ ▶ step through 312 items.", demoPager},
|
||||
{168, "Feed", "动态流", "data", "What happened, newest first, with icons and times.", demoFeed},
|
||||
{169, "Matrix", "矩阵", "data", "Who knows which spell. Arrows move; Space flips.", demoMatrix},
|
||||
{170, "Sortable", "可排序列表", "data", "Drag a quest by its grip, or move it with Alt and the arrows.", demoSortable},
|
||||
{171, "Transfer", "穿梭框", "data", "Pick a hero, then → or ← to swap benches.", demoTransfer},
|
||||
{172, "InfiniteList", "无限列表", "data", "Scroll to the end; it loads twenty more.", demoInfiniteList},
|
||||
{173, "FilterBar", "筛选栏", "data", "Chips turn filters on; CLEAR turns them all off.", demoFilterBar},
|
||||
{174, "SearchResults", "搜索结果", "data", "Type a spell name; matches light up.", demoSearchResults},
|
||||
{175, "CardGrid", "卡片网格", "data", "As many columns of cards as the width holds.", demoCardGrid},
|
||||
}
|
||||
|
||||
func demoStatCompare(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Column(c).Gap(k.D(4)).Children(func() {
|
||||
pixel.Text(c, "Iron sword → Flame sword", pixel.TextOptions{Slot: pixel.Faint})
|
||||
data.StatCompare(c, []data.Change{{Label: "ATK", Old: 12, New: 18}, {Label: "DEF", Old: 9, New: 7}, {Label: "SPD", Old: 5, New: 5}, {Label: "MAG", Old: 3, New: 6}}, data.StatCompareOptions{})
|
||||
})
|
||||
}
|
||||
|
||||
func demoBestiary(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Row(c).Gap(k.D(6)).Children(func() {
|
||||
ui.Box(c).Width(k.D(130)).Children(func() {
|
||||
data.Bestiary(c, data.Monster{Sprite: slime, Name: "Slime", Seen: true, Stats: [][2]string{{"HP", "8"}, {"ATK", "2"}},
|
||||
Notes: "Wobbles happily. Mostly harmless."}, data.BestiaryOptions{})
|
||||
})
|
||||
ui.Box(c).Width(k.D(130)).Children(func() {
|
||||
data.Bestiary(c, data.Monster{Sprite: icon.Bug, Name: "Cave beetle", Stats: [][2]string{{"HP", "30"}, {"ATK", "9"}},
|
||||
Notes: "Clicks in the dark."}, data.BestiaryOptions{Scale: 3})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func demoPropertyGrid(c *ui.Context, log func(string)) {
|
||||
s := dataState(c)
|
||||
props := []data.Property{{Name: "Name", Text: &s.name}, {Name: "Level", Number: &s.level, Min: 1, Max: 99}, {Name: "Hard mode", Switch: &s.hard}}
|
||||
if data.PropertyGrid(c, "Hero", props, data.PropertyGridOptions{NameWidth: 56}).Changed {
|
||||
log(fmt.Sprintf("%s, level %g, hard %v", s.name, s.level, s.hard))
|
||||
}
|
||||
}
|
||||
|
||||
func demoPager(c *ui.Context, log func(string)) {
|
||||
s := dataState(c)
|
||||
if data.Pager(c, "Items", 312, &s.page, &s.size, data.PagerOptions{}).Changed {
|
||||
log(fmt.Sprintf("page %d, %d per page", s.page+1, s.size))
|
||||
}
|
||||
}
|
||||
|
||||
func demoFeed(c *ui.Context, log func(string)) {
|
||||
ui.Box(c).Width(pixel.K(c).D(200)).Children(func() {
|
||||
data.Feed(c, []data.Activity{{Icon: icon.Star, Text: "Aria found a star shard.", Time: "1 min ago"}, {Icon: icon.Coin, Text: "Brom sold three slime jellies.", Time: "4 min ago"},
|
||||
{Icon: icon.Trophy, Text: "You cleared World 1-2.", Time: "9 min ago"}, {Icon: icon.Heart, Text: "Cyra healed the party.", Time: "12 min ago"}}, data.FeedOptions{})
|
||||
})
|
||||
}
|
||||
|
||||
func demoMatrix(c *ui.Context, log func(string)) {
|
||||
s := dataState(c)
|
||||
heroes, spells := []string{"Aria", "Brom", "Cyra"}, []string{"FIRE", "ICE", "BOLT"}
|
||||
if data.Matrix(c, "Spells known", heroes, spells, s.rights, data.MatrixOptions{}).Changed {
|
||||
log(fmt.Sprintf("%v", s.rights))
|
||||
}
|
||||
}
|
||||
|
||||
func demoSortable(c *ui.Context, log func(string)) {
|
||||
s := dataState(c)
|
||||
if data.Sortable(c, "Quest order", &s.quests, data.SortableOptions{}).Changed {
|
||||
log(strings.Join(s.quests, " · "))
|
||||
}
|
||||
}
|
||||
|
||||
func demoTransfer(c *ui.Context, log func(string)) {
|
||||
s := dataState(c)
|
||||
if data.Transfer(c, "Party", &s.bench, &s.party, data.TransferOptions{Height: 70}).Changed {
|
||||
log("party: " + strings.Join(s.party, ", "))
|
||||
}
|
||||
}
|
||||
|
||||
func demoInfiniteList(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := dataState(c)
|
||||
// A pretend server answers after one second.
|
||||
if !s.loading.IsZero() && k.Since(c, s.loading, 1, 1) == 1 {
|
||||
s.logs, s.loading = s.logs+20, time.Time{}
|
||||
log(fmt.Sprintf("loaded %d rows", s.logs))
|
||||
}
|
||||
r := data.InfiniteList(c, "Battle log", s.logs, data.InfiniteListOptions{Height: 100, Done: s.logs >= 100}, func(i int) {
|
||||
pixel.Text(c, fmt.Sprintf("Turn %d: the slime wobbles.", i+1), pixel.TextOptions{})
|
||||
})
|
||||
r.Element.Width(k.D(180))
|
||||
if r.More {
|
||||
s.loading = k.Now()
|
||||
log("asked for more")
|
||||
}
|
||||
}
|
||||
|
||||
func demoFilterBar(c *ui.Context, log func(string)) {
|
||||
s := dataState(c)
|
||||
labels := []string{"FIRE", "ICE", "BOLT", "HOLY"}
|
||||
if data.FilterBar(c, "Elements", labels, s.filters, data.FilterBarOptions{}).Changed {
|
||||
log(fmt.Sprintf("%v", s.filters))
|
||||
}
|
||||
}
|
||||
|
||||
var spellBook = []data.Hit{{Title: "Fire", Text: "A small burst of fire."}, {Title: "Fira", Text: "A bigger fire. Warm."}, {Title: "Blizzard", Text: "Ice falls from nowhere."},
|
||||
{Title: "Thunder", Text: "Bolts strike one foe."}, {Title: "Cure", Text: "Heals a little."}, {Title: "Firaga", Text: "All the fire at once."}}
|
||||
|
||||
func demoSearchResults(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := dataState(c)
|
||||
var hits []data.Hit
|
||||
for _, h := range spellBook {
|
||||
if strings.Contains(strings.ToLower(h.Title+" "+h.Text), strings.ToLower(s.query)) {
|
||||
hits = append(hits, h)
|
||||
}
|
||||
}
|
||||
s.hit = min(s.hit, len(hits)-1)
|
||||
ui.Column(c).Gap(k.D(4)).Width(k.D(180)).Children(func() {
|
||||
if input.SearchField(c, "Search spells", &s.query, input.SearchFieldOptions{Placeholder: "fire"}).Changed {
|
||||
log("query " + s.query)
|
||||
}
|
||||
r := data.SearchResults(c, "Spells", s.query, hits, &s.hit, data.SearchResultsOptions{Height: 90})
|
||||
if r.Changed {
|
||||
log("chose " + hits[s.hit].Title)
|
||||
}
|
||||
if r.Submitted {
|
||||
log("cast " + hits[s.hit].Title)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoCardGrid(c *ui.Context, log func(string)) {
|
||||
cards := []struct {
|
||||
art *pixel.Sprite
|
||||
name, line string
|
||||
}{{icon.Sword, "Sword", "Pointy end first."}, {icon.Shield, "Shield", "Blocks most things."}, {icon.Potion, "Potion", "Tastes like cherry."},
|
||||
{icon.Crown, "Crown", "Heavy is the head."}, {icon.Map, "Map", "X marks the spot."}, {icon.Key, "Key", "Opens one door."}}
|
||||
data.CardGrid(c, len(cards), data.CardGridOptions{MinWidth: 90}, func(i int) {
|
||||
layout.Card(c, layout.CardOptions{Title: cards[i].name, Icon: cards[i].art}, func() {
|
||||
text.Paragraph(c, cards[i].line, text.ParagraphOptions{})
|
||||
})
|
||||
})
|
||||
}
|
||||
+1
-1
@@ -56,7 +56,7 @@ var Categories = []Category{
|
||||
{"tabletop", "Tabletop", "桌游", icon.Crown},
|
||||
}
|
||||
|
||||
var entries = slices.Concat(foundationEntries, layoutEntries, textEntries, displayEntries, inputEntries, controlEntries, feedbackEntries, navigationEntries)
|
||||
var entries = slices.Concat(foundationEntries, layoutEntries, textEntries, displayEntries, inputEntries, controlEntries, feedbackEntries, navigationEntries, dataEntries, recordEntries)
|
||||
|
||||
func Entries() []Entry { return entries }
|
||||
|
||||
|
||||
Reference in new issue
Block a user