package gallery import ( "fmt" "github.com/egoist/mygo/ui" "git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/icon" "git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/layout" "git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel" ) var layoutEntries = []Entry{ {1, "Screen", "屏幕", "layout", "The root of a screen: Back fills the window, with an optional dithered vignette.", demoScreen}, {2, "Window", "窗口", "layout", "A beveled window with a title tab, the shape of every RPG menu.", demoWindow}, {3, "Panel", "面板", "layout", "A box framed raised, sunken, flat, double, window or notched.", demoPanel}, {4, "Card", "卡片", "layout", "A raised panel with a header strip, a body and a footer.", demoCard}, {5, "Section", "分节", "layout", "A titled group inside a dotted rule.", demoSection}, {6, "Divider", "分隔线", "layout", "Rules across or down: solid, dotted, dashed, double, ornament.", demoDivider}, {7, "ScrollArea", "滚动区", "layout", "A scroll view with a pixel scrollbar: arrows step, the track pages, the thumb drags.", demoScrollArea}, {8, "Split", "分栏", "layout", "Two panes and a grip. Drag it, or focus it and use the arrow keys.", demoSplit}, {9, "Grid", "网格", "layout", "Equal columns with solid or dotted lines between the cells.", demoGrid}, {10, "Tiles", "平铺", "layout", "Equal tiles that wrap into rows as the width allows.", demoTiles}, {11, "Masonry", "瀑布流", "layout", "Each item drops into the shortest column.", demoMasonry}, {12, "AspectBox", "比例框", "layout", "Keeps a ratio in whole dots at whatever width it gets.", demoAspectBox}, {13, "Layers", "图层", "layout", "Layers stacked in one box, each over the one before.", demoLayers}, {14, "Viewport", "视口", "layout", "A fixed virtual resolution, drawn at the largest Dot that fits and letterboxed.", demoViewport}, {15, "TitleBar", "标题栏", "layout", "Stripes, a title, a close box and a minimize box.", demoTitleBar}, {16, "StatusBar", "状态栏", "layout", "Segments split by sunken dividers; the first one grows.", demoStatusBar}, {17, "Resizable", "可调尺寸", "layout", "A box with a corner grip. Drag it, or focus it and use the arrow keys.", demoResizable}, {18, "Handheld", "掌机", "layout", "A pocket console: a screen, a power LED, a D-pad, A and B.", demoHandheld}, {19, "CRTFrame", "显像管", "layout", "A monitor bezel with scanlines over the picture.", demoCRTFrame}, {20, "AppFrame", "应用框架", "layout", "Header, sidebar, main and footer; on a narrow screen the sidebar folds above.", demoAppFrame}, } var monsters = []string{"Slime", "Bat", "Goblin", "Mimic", "Ghost", "Golem", "Drake", "Imp"} func demoScreen(c *ui.Context, log func(string)) { k := pixel.K(c) on := ui.Local(c.Root(), demoKey("screen"), func() bool { return true }) 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) }) }) if button(c, "VIGNETTE") { *on = !*on log(fmt.Sprintf("vignette %v", *on)) } }) } func demoWindow(c *ui.Context, log func(string)) { k := pixel.K(c) 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) } }) layout.Window(c, layout.WindowOptions{}, func() { label(c, "HP 32/40", pixel.Ink) label(c, "MP 12/18", pixel.Ink) }) }) } 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) }) } }) } 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") { log("quest accepted") } if button(c, "LATER") { log("quest saved for later") } }}, func() { label(c, "Find the lost cartridge.", pixel.Ink) label(c, "Reward: 300 G", pixel.Faint) }) }) } 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) }) }) } func demoDivider(c *ui.Context, log func(string)) { k := pixel.K(c) names := []string{"SOLID", "DOTTED", "DASHED", "DOUBLE", "ORNAMENT"} 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) layout.Divider(c, layout.DividerOptions{Style: layout.DividerStyle(i)}) } }) for i := range names { layout.Divider(c, layout.DividerOptions{Vertical: true, Style: layout.DividerStyle(i), Slot: pixel.Accent}) } }) } func demoScrollArea(c *ui.Context, log func(string)) { k := pixel.K(c) s := ui.Local(c.Root(), demoKey("scroll"), func() ui.ScrollState { return ui.ScrollState{} }) 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) } }) 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) }) } func demoSplit(c *ui.Context, log func(string)) { k := pixel.K(c) 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() } } ui.Box(c).FillWidth().Height(k.D(96)).Children(func() { r := layout.Split(c, size, layout.SplitOptions{Label: "Map and log"}, pane("MAP"), pane("LOG")) r.Element.Fill() if r.Changed { log(fmt.Sprintf("split %d dots", *size)) } }) } func demoGrid(c *ui.Context, log func(string)) { k := pixel.K(c) items := []*pixel.Sprite{icon.Sword, icon.Shield, icon.Potion, icon.Gem, icon.Key, icon.Coin} ui.Row(c).Gap(k.D(12)).AlignItems(ui.Start).Children(func() { for _, lines := range []layout.GridLines{layout.SolidLines, layout.DottedLines} { layout.Grid(c, len(items), layout.GridOptions{Columns: 3, Lines: lines}, func(i int) { pixel.Icon(c, items[i], pixel.IconOptions{Scale: 2}) }) } }) } func demoTiles(c *ui.Context, log func(string)) { k := pixel.K(c) items := []*pixel.Sprite{icon.Sun, icon.Moon, icon.Cloud, icon.Snowflake, icon.Leaf, icon.Flower, icon.Flame, icon.Drop, icon.Bolt, icon.Star} layout.Tiles(c, len(items), layout.TilesOptions{W: 28}, func(i int) { ui.Box(c).Fill().Center().Draw(func(p *ui.Painter, r ui.Rect) { k.Canvas(p, r).Frame(0, 0, 28, 28, pixel.Raised, pixel.Face) }).Children(func() { pixel.Icon(c, items[i], pixel.IconOptions{}) }) }).Width(k.D(160)) } func demoMasonry(c *ui.Context, log func(string)) { k := pixel.K(c) heights := []int{40, 24, 56, 32, 24, 48, 32, 40} slots := []pixel.Slot{pixel.Accent, pixel.Good, pixel.Info, pixel.Warn, pixel.Magic} layout.Masonry(c, heights, layout.MasonryOptions{}, func(i int) { ui.Box(c).Fill().Draw(func(p *ui.Painter, r ui.Rect) { g := k.Canvas(p, r) g.Frame(0, 0, g.W, g.H, pixel.Flat, slots[i%len(slots)]) g.Micro(3, 3, fmt.Sprint(i+1), pixel.Ink, 1) }) }).Width(k.D(180)) } func demoAspectBox(c *ui.Context, log func(string)) { k := pixel.K(c) ui.Box(c).Width(k.D(160)).Children(func() { layout.AspectBox(c, layout.AspectBoxOptions{W: 16, H: 9}, func() { ui.Box(c).Fill().Draw(func(p *ui.Painter, r ui.Rect) { g := k.Canvas(p, r) for i := range 17 { g.Dither(0, i*g.H/17, g.W, g.H/17+1, pixel.Back, pixel.Info, i) } g.Text(4, 2, fmt.Sprintf("16:9 %d×%d", g.W, g.H), pixel.Ink, 1) }) }) }) } func demoLayers(c *ui.Context, log func(string)) { k := pixel.K(c) layout.Layers(c, func() { ui.Box(c).Fill().Draw(func(p *ui.Painter, r ui.Rect) { g := k.Canvas(p, r) g.Dither(0, 0, g.W, g.H, pixel.Well, pixel.Info, 6) }) }, func() { ui.Box(c).Fill().Center().Children(func() { pixel.Icon(c, icon.Chest, pixel.IconOptions{Scale: 3}) }) }, func() { ui.Box(c).Padding(k.D(3)).Children(func() { label(c, "LAYER 3", pixel.Ink) }) }).Size(k.D(120), k.D(64)) } func demoViewport(c *ui.Context, log func(string)) { k := pixel.K(c) ui.Box(c).FillWidth().Height(k.D(100)).Children(func() { layout.Viewport(c, layout.ViewportOptions{W: 64, H: 40}, func() { kv := pixel.K(c) ui.Box(c).Fill().Draw(func(p *ui.Painter, r ui.Rect) { g := kv.Canvas(p, r) g.Rect(0, 0, g.W, g.H, pixel.Info) g.Rect(0, 30, g.W, 10, pixel.Good) g.Disc(50, 10, 5, pixel.Warn) g.Micro(3, 3, "64X40", pixel.Ink, 1) }) }) }) } func demoTitleBar(c *ui.Context, log func(string)) { k := pixel.K(c) ui.Box(c).Width(k.D(220)).Children(func() { r := layout.TitleBar(c, "Untitled", layout.TitleBarOptions{}) if r.Close { log("close") } if r.Minimize { log("minimize") } }) } func demoStatusBar(c *ui.Context, log func(string)) { k := pixel.K(c) ui.Box(c).Width(k.D(260)).Children(func() { layout.StatusBar(c, "Ready", "Ln 1, Col 1", "UTF-8") }) } func demoResizable(c *ui.Context, log func(string)) { w := ui.Local(c.Root(), demoKey("resize-w"), func() int { return 120 }) 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) }).Fill() }) if r.Changed { log(fmt.Sprintf("size %d×%d", *w, *h)) } } func demoHandheld(c *ui.Context, log func(string)) { k := pixel.K(c) at := ui.Local(c.Root(), demoKey("handheld"), func() [2]int { return [2]int{36, 20} }) r := layout.Handheld(c, layout.HandheldOptions{ScreenW: 80, ScreenH: 56, Brand: "8BIT POCKET", Label: "Pocket console"}, func() { ui.Box(c).Fill().Draw(func(p *ui.Painter, r ui.Rect) { g := k.Canvas(p, r) g.Rect(0, 0, g.W, g.H, pixel.Well) g.Sprite(at[0], at[1], slime, g.Step(2), pixel.Ink, 1) }) }) moves := map[string][2]int{"up": {0, -4}, "down": {0, 4}, "left": {-4, 0}, "right": {4, 0}} for name, on := range map[string]bool{"up": r.Up, "down": r.Down, "left": r.Left, "right": r.Right} { if on { at[0] = max(0, min(at[0]+moves[name][0], 80-slime.W)) at[1] = max(0, min(at[1]+moves[name][1], 56-slime.H)) log(name) } } if r.A { log("A: jump") } if r.B { log("B: run") } } 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) }) }).AlignSelf(ui.Start) } 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) }, func() { for _, s := range []string{"Inbox", "Sent", "Spam"} { if button(c, s) { log("open " + s) } } }, func() { label(c, "No new mail. Go outside.", pixel.Ink) }, func() { label(c, "3 folders", pixel.Faint) }) }) }