examples

package
v0.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 31, 2026 License: MPL-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples (continued)

Package examples — Go-only nested Card demo (callout/code inside a card). Validates docs/GO_FIRST_UI.md: nesting is a Card layout concern, not JSON-only.

Package examples contains self-contained Gru demo scenes.

Package examples — development helpers (Air, local iteration).

Package examples — shared file-dialog helpers (all platforms).

Package examples — native file dialogs for reference apps (Windows, macOS, Linux).

Package examples (continued)

Package examples — FlexCopy helpers for flex-column body copy in demos.

Use FlexCopy / FlexCopyPair instead of NewLabel + form-* styles in scroll pages and panel bodies. Label is for fixed chrome only (see docs/HYGIENE_AUDIT.md §7).

Package examples (continued)

Package examples — docked ListTile list pane in SplitView (Open Notes / master-list pattern). Recipe: CP-SHELL-EDGE + CP-LIST-PANE-01 (see docs/COMPOSITION_PATTERNS.md §11).

Package examples — docked list-pane shell (master list in SplitView).

Package examples — shared Remix icon wiring for Go-first demos.

Package examples (continued)

Package examples provides self-contained Gru demo scenes.

Go is the engine; declarative pages compile to the same widgets via ui.BuildDocumentSpec (see docs/GO_FIRST_UI.md). Scenes here are the native reference for layout patterns that work.

Each demo implements the Scene interface. Register a factory function with Register(); main.go calls Build() on the active scene and Destroy() when switching away — ensuring textures and signals are cleaned up promptly.

To add a new demo:

  1. Create a new file in this package.
  2. Define a struct that embeds BaseScene (or implements Scene directly).
  3. Implement Title(), Build(*ui.Document), and Destroy().
  4. Call Register() in an init() function.

Prefer MountAppPage or MountPageGrid (page_shell.go) in Build so the tree follows Root (absolute) → page shell → Viewport → Panel → flex.

Package examples (continued)

Package examples — desktop settings under MenuBar (no AppBar). Reference for Notepad-style in-shell settings.

Package examples — desktop settings row helpers (panel + flat layouts).

Package examples (continued)

Package examples — shared helpers for SplitView / ResizablePanel demos (Phase A).

Package examples (continued)

Index

Constants

View Source
const DirectorySceneTitle = "Demo Directory"

DirectorySceneTitle is the launcher hub scene; main.go starts here when registered.

View Source
const NotepadSceneTitle = "Notepad (Go)"

NotepadSceneTitle is the Gru Notepad scene id (private product). Kept in a tiny shared file so non-Notepad builds (Studio / grudemo / public export) can reference the name without compiling notepad_demo.go.

View Source
const PublicDemoStartTitle = "Counter Demo"

PublicDemoStartTitle is the first scene when running with -tags grudemo.

View Source
const PublicDirectorySceneTitle = "Demo Index"

PublicDirectorySceneTitle is the grudemo scene picker (footer Scenes button).

Variables

View Source
var ErrFileDialogCancelled = errors.New("file dialog cancelled")

ErrFileDialogCancelled is returned when the user dismisses a native dialog.

View Source
var ErrFileDialogUnavailable = errors.New("file dialog unavailable on this platform")

ErrFileDialogUnavailable is returned on platforms without native pickers yet (Android v1).

View Source
var NavigateToScene func(title string) bool

NavigateToScene is set by main.go to switch demo scenes by Title(). Returns true when the scene exists (even if already active).

Functions

func AppBarBackButton

func AppBarBackButton(id string) *ui.IconButton

AppBarBackButton returns a leading AppBar control (caret-left).

func AppBarLeadingMenu

func AppBarLeadingMenu(id string) *ui.IconButton

AppBarLeadingMenu returns a leading navigation control (list / “hamburger”).

func AppBarMenuButton

func AppBarMenuButton(id string) *ui.IconButton

AppBarMenuButton returns a trailing overflow control (dots-three).

func AppIconPNG

func AppIconPNG() string

AppIconPNG returns the baked OS app icon PNG path, or "" if missing. Regenerate with: go run ./scripts/build/gen_app_icon.go

func ConfigureTitleBar

func ConfigureTitleBar(tb *ui.TitleBar, scene Scene)

ConfigureTitleBar applies scene chrome preferences to the borderless title bar.

func DefaultSaveName

func DefaultSaveName(path string) string

DefaultSaveName returns a filename hint from the current path or untitled.txt.

func DevOpenFilePath

func DevOpenFilePath() string

DevOpenFilePath returns GRU_OPEN_FILE when set (GORY_OPEN_FILE alias; path passed to Notepad on Build).

func DevSceneTitle

func DevSceneTitle() string

DevSceneTitle returns GRU_SCENE when set (GORY_SCENE alias; exact match to Scene.Title()).

func FilterPublicFactories

func FilterPublicFactories(all []func() Scene) []func() Scene

FilterPublicFactories keeps only allowlisted scene factories, in allowlist order. Factories whose Title() is not on the list are dropped. Missing titles are skipped (so a not-yet-registered demo does not break the launcher).

func FinishShellMount

func FinishShellMount(doc *ui.Document)

FinishShellMount runs layout passes after scene Build + Document.Resize. main.go calls this once per loadScene (scenes should not call it from Build — that runs before Resize and freezes wrong AutoHeight measures until a nudge).

func FlexCopy

func FlexCopy(id, style, text string) *ui.RichText

FlexCopy is PlainText for flex-column copy (hints, captions, status, body text).

func FlexCopyMirror

func FlexCopyMirror(id, style string, src *ui.Signal[string], prefix string) *ui.RichText

FlexCopyMirror keeps PlainText in sync with src, optionally with a string prefix.

func FlexCopyPair

func FlexCopyPair(id, style, initial string) (*ui.RichText, *ui.Signal[string])

FlexCopyPair returns PlainText bound to a display signal you update.

func HandleDemoLink(link string, status *ui.RichText)

HandleDemoLink navigates when possible; otherwise writes a status message.

func IndexOfPublicStart

func IndexOfPublicStart(factories []func() Scene) int

IndexOfPublicStart returns the index of PublicDemoStartTitle in factories, or 0 if not found.

func IsPublicDemoTitle

func IsPublicDemoTitle(title string) bool

IsPublicDemoTitle reports whether title is on the frozen public allowlist.

func MountDesktopPageShell

func MountDesktopPageShell(doc *ui.Document, id string) (*ui.Container, *ui.Container)

MountDesktopPageShell mounts the architecture page shell (sole direct child of Root, sized to doc, flex column) with a flex-row workspace for NavigationRail + content.

Root → shell (flex column) → [optional MenuBar] → workspace (flex row, flex-grow) → rail | main
→ [optional StatusBar]

Demos insert full-width MenuBar / StatusBar as direct shell children (not beside the rail). Same resize contract as MountFlexPageShell (Document.fitRootChildrenToContent + applyShellFlexAndSyncRootLayout). Add rail and main to workspace, viewport inside main.

func MountEdgeToEdgeRoot

func MountEdgeToEdgeRoot(doc *ui.Document, id string, row bool) *ui.Container

MountEdgeToEdgeRoot clears the document root and adds a full-content flex row/column shell (no page-shell inset). Prefer MountDesktopPageShell for rail + AppBar scenes.

func MountFlexPageShell

func MountFlexPageShell(doc *ui.Document, id string) (*ui.Container, *ui.Viewport)

MountFlexPageShell mounts a scrollable page without a title header.

func MountPageGrid

func MountPageGrid(doc *ui.Document, id string) *ui.Container

MountPageGrid clears the document root and adds a single full-window responsive page grid (see ui.NewPageGrid). Add grid children with default ColSpan (full row) or SetColSpan for breakpoint-aware spans.

Root (absolute) → **page grid** → your Viewports / panels.

func MountSceneHeader

func MountSceneHeader(vp *ui.Viewport, id, title, subtitle string) *ui.Header

MountSceneHeader adds a page Header inside a scroll viewport (first row of the document). Prefer MountAppPage title/subtitle args for new scenes.

func NavigateFromDemoLink(link string) bool

NavigateFromDemoLink switches scenes for known demo:// page links.

func NewAppShellScrollViewport

func NewAppShellScrollViewport(id string) *ui.Viewport

NewAppShellScrollViewport returns the page-scroll viewport for app-shell scenes. Add as a direct child of the shell (flex-grow 1) between pinned chrome rows.

func NewBatchEqualFillGrid

func NewBatchEqualFillGrid(id string, gap float32) *ui.Container

NewBatchEqualFillGrid fills the viewport band with equal-height rows — use only when the demo intentionally fills one screen with no page scroll (e.g. a single full-viewport fixture). Split showcases with multiple sections should use NewBatchPageGrid + fixed section heights (see batch8_demo.go).

func NewBatchPageGrid

func NewBatchPageGrid(id string, gap float32) *ui.Container

NewBatchPageGrid returns the standard shrink-wrap 12-column grid for batch demos (docs/LAYOUT_CONTRACTS.md §7). Panels use intrinsic height; rows do not equal-fill the viewport unless you opt into NewBatchEqualFillGrid.

func PickHTMLReportSave

func PickHTMLReportSave(defaultName string) (string, error)

PickHTMLReportSave shows the OS save-file dialog for an HTML plan report.

func PickPNGSave

func PickPNGSave(defaultName string) (string, error)

PickPNGSave shows the OS save-file dialog for a PNG image.

func PickPlanJSONOpen

func PickPlanJSONOpen() (string, error)

PickPlanJSONOpen shows the OS open-file dialog for terraform plan JSON.

func PickTextFileOpen

func PickTextFileOpen() (string, error)

PickTextFileOpen shows the OS open-file dialog for text documents.

func PickTextFileSave

func PickTextFileSave(defaultName string) (string, error)

PickTextFileSave shows the OS save-file dialog. defaultName may be empty.

func PreloadSceneIcons

func PreloadSceneIcons(doc *ui.Document)

PreloadSceneIcons warms Remix icon-font glyphs used by shell and form demos.

func PreloadScenePhosphor deprecated

func PreloadScenePhosphor(doc *ui.Document)

Deprecated: use PreloadSceneIcons.

func PublicDemoMode

func PublicDemoMode() bool

PublicDemoMode is false for Studio / Notepad / Prism builds.

func PublicSceneTitles

func PublicSceneTitles() []string

PublicSceneTitles returns a copy of the frozen allowlist (stable order).

func Register

func Register(factory func() Scene)

Register appends a scene factory to the global list. Call from init() in each demo file so main.go doesn't need to import individual scenes.

func RegisterFirst

func RegisterFirst(factory func() Scene)

RegisterFirst prepends a scene so it appears first in Tab order (use for the demo directory).

func Registered

func Registered() []func() Scene

Registered returns a snapshot of all registered factory functions. main.go calls this once after init() functions have run.

func RegisteredSceneCount

func RegisteredSceneCount() int

RegisteredSceneCount returns the number of registered demo scenes.

func RegistryTitle

func RegistryTitle(index int) string

RegistryTitle returns the title for a registered scene index.

func ResolveStartupSceneIndex

func ResolveStartupSceneIndex(factories []func() Scene, defaultIndex int) int

ResolveStartupSceneIndex picks the scene index for main.go startup. When GRU_SCENE (or GORY_SCENE alias) is set, the first factory whose Title() matches wins. On Android, defaults to Notepad when unset.

func SetInstanceOpenFileHandler

func SetInstanceOpenFileHandler(func(string))

func StartupInstance

func StartupInstance(forwardPath string) (exit bool, stop func())

func StartupOpenFilePath

func StartupOpenFilePath() string

StartupOpenFilePath returns a file to open on launch: first non-flag CLI arg, then GRU_OPEN_FILE / GORY_OPEN_FILE (Air/dev). Windows Explorer "Open with" passes the selected file as argv[1].

func UpdateShellFooterAutoHide

func UpdateShellFooterAutoHide(footer ui.Node, doc *ui.Document)

UpdateShellFooterAutoHide shows footer chrome when the pointer is near the bottom of the window; hides it otherwise so scroll content gets full height.

Types

type AppPage

type AppPage struct {
	// Frame is a full-client flex wrapper (transparent, no padding). It exists
	// only for Document.Resize — the scroll viewport is the real page surface.
	Frame  *ui.Container
	Body   *ui.Viewport
	Header *ui.Header // nil when title is empty; lives inside Body (scrolls with the page)
	// Shell aliases Frame for callers that still use page.Shell.
	Shell *ui.Container
}

AppPage is the set-and-forget page chrome from MountAppPage.

func MountAppPage

func MountAppPage(doc *ui.Document, id, title, subtitle string) AppPage

MountAppPage mounts the web-faithful scrollable page:

TitleBar (window chrome, outside doc tree)
Root → frame (full client, no inset) → page-scroll Viewport (1:1 with client area)
      └── [Header] + your grids/panels — all page content scrolls inside the viewport

Pass empty title to omit the header. Add grids and panels to Body. Margins and the scrollbar gutter are owned by page-scroll inside the viewport.

type AppShellMount

type AppShellMount struct {
	Shell *ui.Container
}

AppShellMount is a single flex-column shell filling the document content band. Add AppBar, page-scroll Viewport, and optional footer as direct shell children.

func MountAppShellRoot

func MountAppShellRoot(doc *ui.Document, id string) AppShellMount

MountAppShellRoot clears Root and mounts one transparent flex-column shell. Window chrome (title bar, launcher nav) is handled by Document — do not add an extra appshell-content body wrapper around the scroll viewport.

type BaseScene

type BaseScene struct{}

BaseScene is an embeddable struct that provides no-op implementations of Destroy and OnUpdate. Embed it in your scene struct to avoid boilerplate when you have nothing to clean up or update manually.

func (BaseScene) Destroy

func (BaseScene) Destroy()

Destroy is a no-op. Override in your scene struct if you hold GPU resources.

func (BaseScene) HideDemoNav

func (BaseScene) HideDemoNav() bool

HideDemoNav is false by default; override on product-style scenes (e.g. Notepad).

func (BaseScene) OnUpdate

func (BaseScene) OnUpdate(_ *ui.Document, _ float32)

OnUpdate is a no-op. Override when you need per-frame logic (tweens, focus).

type GRUPageReloader

type GRUPageReloader struct {
	LogicalPath string
	VP          *ui.Viewport
	Ctx         *ui.BuildContext
	MutateSpec  func(*ui.DocumentSpec)
	AfterBuild  func(ui.Node)

	// PreserveControls keeps ControlSnapshot values and viewport ScrollY across reloads.
	PreserveControls bool
	// contains filtered or unexported fields
}

GRUPageReloader watches a .gru file and swaps the compiled page body when it changes. Go-owned shell (header, BuildContext actions) stays mounted; only the spec body rebuilds.

Reload detection uses fsnotify when available, with per-frame ModTime polling as backup. When PreserveControls is true (default), form values and page scroll position survive reload.

func (*GRUPageReloader) Close

func (r *GRUPageReloader) Close()

Close stops the fsnotify watcher. Call from Scene.Destroy when leaving a .gru demo.

func (*GRUPageReloader) Compile

func (r *GRUPageReloader) Compile() (ui.Node, error)

Compile reads and builds the current .gru file.

func (*GRUPageReloader) MountShell

func (r *GRUPageReloader) MountShell(doc *ui.Document, shellID, hdrTitle, hdrSubtitle string, body ui.Node) *ui.Viewport

MountShell mounts the page viewport shell and records the file mod time.

func (*GRUPageReloader) Poll

func (r *GRUPageReloader) Poll(doc *ui.Document)

Poll reloads the body when the .gru file changes on disk.

type ListPane

type ListPane struct {
	Root           *ui.Container
	Hdr            *ui.Container
	Title          *ui.Label
	Collapse       *ui.IconButton
	Scroll         *ui.Viewport
	List           *ui.Container
	PreferredWidth float32
	MinWidth       float32
}

ListPane is a flat grey sidebar: customizable header + flush scroll + row list.

func NewListPane

func NewListPane(doc *ui.Document, opts ListPaneOptions) *ListPane

NewListPane builds a borderless list column. Add rows to List; scrollbar aligns with the split edge.

type ListPaneOptions

type ListPaneOptions struct {
	ID             string
	Title          string
	TitleStyle     string // theme key; default list-pane-header-title
	PreferredWidth float32
	MinWidth       float32
	ShowCollapse   bool
	OnCollapse     func()
}

ListPaneOptions configures a flat, borderless list sidebar.

type Scene

type Scene interface {
	Title() string
	Build(doc *ui.Document)
	Destroy()
	OnUpdate(doc *ui.Document, dt float32)
	// HideDemoNav reports whether the launcher footer (Tab hint + Directory) should
	// be hidden so the scene uses the full client area (reference apps, utilities).
	HideDemoNav() bool
}

Scene is the lifecycle interface every demo scene must implement.

  • Title — short name shown in the window title bar and nav strip.
  • Build — construct the widget tree into doc; called once on activation.
  • Destroy — release any GPU resources (textures, render targets) not managed by doc itself; called before the scene is replaced.
  • OnUpdate — optional per-frame hook; called after doc.Root.Update(dt). Use it for tween ticks, focus management, key shortcuts, etc. Implementations that don't need per-frame work can embed BaseScene, which provides a no-op OnUpdate.

type TitleBarChrome

type TitleBarChrome interface {
	TitleBarShowTitle() bool
	TitleBarShowAppIcon() bool
	TitleBarCenterText() string
}

TitleBarChrome optionally overrides custom title bar content. OS window title (taskbar tooltip) may still be set separately via rl.SetWindowTitle.

Directories

Path Synopsis
Package appinstance forwards startup files to an already-running Gru Notepad.
Package appinstance forwards startup files to an already-running Gru Notepad.
Package startuppath resolves optional file paths from argv and environment.
Package startuppath resolves optional file paths from argv and environment.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL