Gallery shell: AppShell, search, sidebar, theme/density/locale, palette, code, keys, events, Overture
This commit is contained in:
4 files changed
+430
-15
No files matched your search
+137
-15
@@ -1,35 +1,157 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
mujica "mujicaui"
|
||||
"mujicaui/icons"
|
||||
"mujicaui/theme"
|
||||
)
|
||||
|
||||
// event is one line of the gallery's event log.
|
||||
type event struct {
|
||||
at time.Time
|
||||
page string
|
||||
text string
|
||||
}
|
||||
|
||||
type gallery struct {
|
||||
pages []page
|
||||
selected int
|
||||
events []string
|
||||
byID map[string]int
|
||||
selected string
|
||||
query string
|
||||
mode int
|
||||
density int
|
||||
zh bool
|
||||
folded bool
|
||||
autoFold bool
|
||||
palette bool
|
||||
events []event
|
||||
scrolls map[string]*ui.ScrollState
|
||||
overture overtureState
|
||||
}
|
||||
|
||||
func newGallery() *gallery { return &gallery{pages: catalog()} }
|
||||
// densities maps the density control's segments to theme densities.
|
||||
var densities = []theme.Density{theme.Compact, theme.Default, theme.Comfortable}
|
||||
|
||||
func (g *gallery) log(s string) { g.events = append(g.events, s) }
|
||||
func newGallery() *gallery {
|
||||
g := &gallery{pages: catalog(), byID: map[string]int{}, selected: overtureID, density: 1, scrolls: map[string]*ui.ScrollState{}}
|
||||
for i, p := range g.pages {
|
||||
if _, dup := g.byID[p.ID]; dup {
|
||||
panic("gallery: duplicate page " + p.ID)
|
||||
}
|
||||
g.byID[p.ID] = i
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
// logFor returns the event logger of one page.
|
||||
func (g *gallery) logFor(id string) func(string) {
|
||||
return func(s string) {
|
||||
g.events = append(g.events, event{time.Now(), id, s})
|
||||
if len(g.events) > 200 {
|
||||
g.events = g.events[len(g.events)-200:]
|
||||
}
|
||||
slog.Info("gallery: event", "page", id, "event", s)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *gallery) settings() mujica.Settings {
|
||||
s := mujica.Settings{Mode: mujica.Mode(g.mode), Density: densities[g.density], Locale: mujica.EnUS}
|
||||
if g.zh {
|
||||
s.Locale = mujica.ZhCN
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (g *gallery) view(c *ui.Context) {
|
||||
mujica.Use(c, mujica.Settings{})
|
||||
ui.Row(c).Fill().Children(func() {
|
||||
ui.Scroll(c).Width(240).FillHeight().Children(func() {
|
||||
for i, p := range g.pages {
|
||||
if mujica.Button(c, p.ID+" "+p.Name, mujica.ButtonOptions{Variant: mujica.Ghost}).Key(p.ID).Clicked() {
|
||||
g.selected = i
|
||||
}
|
||||
mujica.Use(c, g.settings())
|
||||
w, _ := c.Size()
|
||||
if narrow := w < 900; narrow != g.autoFold {
|
||||
g.autoFold, g.folded = narrow, narrow
|
||||
}
|
||||
scroll := g.scrolls[g.selected]
|
||||
if scroll == nil {
|
||||
scroll = &ui.ScrollState{}
|
||||
g.scrolls[g.selected] = scroll
|
||||
}
|
||||
mujica.AppShell(c, &g.folded, mujica.AppShellOptions{
|
||||
TitleBar: func() { g.titleBar(c) },
|
||||
Sidebar: func() { g.sidebar(c) },
|
||||
Content: func() { g.content(c) },
|
||||
StatusBar: func() { g.statusBar(c) },
|
||||
ContentScroll: scroll,
|
||||
})
|
||||
g.commandPalette(c)
|
||||
mujica.Toaster(c)
|
||||
}
|
||||
|
||||
func (g *gallery) titleBar(c *ui.Context) {
|
||||
mujica.TitleBar(c, "MujicaUI", mujica.TitleBarOptions{Trailing: func() {
|
||||
ui.Row(c).Gap(8).AlignItems(ui.Center).Children(func() {
|
||||
mode := g.mode
|
||||
if mujica.SegmentedControl(c, &g.mode, []mujica.Segment{
|
||||
{Label: g.t("System", "跟随系统"), Icon: icons.Must("settings"), HideLabel: true},
|
||||
{Label: g.t("Light", "浅色"), Icon: icons.Must("sun"), HideLabel: true},
|
||||
{Label: g.t("Dark", "深色"), Icon: icons.Must("moon"), HideLabel: true},
|
||||
}, mujica.SegmentedControlOptions{Label: g.t("Theme", "主题")}).Changed() && mode != g.mode {
|
||||
g.logFor("shell")("theme " + mujica.Mode(g.mode).String())
|
||||
g.overture.switches++
|
||||
}
|
||||
density := g.density
|
||||
if mujica.SegmentedControl(c, &g.density, []mujica.Segment{
|
||||
{Label: g.t("Compact", "紧凑")}, {Label: g.t("Default", "默认")}, {Label: g.t("Comfortable", "宽松")},
|
||||
}, mujica.SegmentedControlOptions{Label: g.t("Density", "密度")}).Changed() && density != g.density {
|
||||
g.logFor("shell")("density " + densities[g.density].String())
|
||||
g.overture.switches++
|
||||
}
|
||||
if mujica.Button(c, g.t("中文", "English"), mujica.ButtonOptions{Variant: mujica.Ghost}).Clicked() {
|
||||
g.zh = !g.zh
|
||||
g.logFor("shell")(fmt.Sprintf("locale %s", g.settings().Locale))
|
||||
}
|
||||
if mujica.IconButton(c, icons.Must("command"), g.t("Command palette", "命令面板"), mujica.IconButtonOptions{Variant: mujica.Ghost}).Clicked() {
|
||||
g.palette = true
|
||||
}
|
||||
})
|
||||
ui.Scroll(c).Fill().Padding(24).Children(func() {
|
||||
if len(g.pages) > 0 {
|
||||
g.pages[g.selected].Demo(c, g.log)
|
||||
}})
|
||||
}
|
||||
|
||||
func (g *gallery) statusBar(c *ui.Context) {
|
||||
left := []mujica.StatusItem{
|
||||
{ID: "count", Text: fmt.Sprintf(g.t("%d components", "%d 个组件"), len(g.pages)), Icon: icons.Must("layout-grid")},
|
||||
{ID: "look", Text: fmt.Sprintf("%s · %s", mujica.Mode(g.mode), densities[g.density]), Secondary: true},
|
||||
}
|
||||
var right []mujica.StatusItem
|
||||
if n := len(g.events); n > 0 {
|
||||
e := g.events[n-1]
|
||||
right = append(right, mujica.StatusItem{ID: "last", Text: e.page + " · " + e.text, Icon: icons.Must("bell"), Secondary: true})
|
||||
}
|
||||
mujica.StatusBar(c, mujica.StatusBarOptions{Left: left, Right: right})
|
||||
}
|
||||
|
||||
func (g *gallery) content(c *ui.Context) {
|
||||
ui.Box(c).Key(g.selected).FillWidth().Children(func() {
|
||||
switch g.selected {
|
||||
case overtureID:
|
||||
g.overturePage(c)
|
||||
default:
|
||||
i, ok := g.byID[g.selected]
|
||||
if !ok {
|
||||
panic("gallery: no page " + g.selected)
|
||||
}
|
||||
})
|
||||
g.componentPage(c, g.pages[i])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// t picks the English or Chinese copy for the gallery's own text.
|
||||
func (g *gallery) t(en, zh string) string {
|
||||
if g.zh {
|
||||
return zh
|
||||
}
|
||||
return en
|
||||
}
|
||||
Reference in new issue
Block a user