Documentation
¶
Overview ¶
Package ui is a thin façade over github.com/gogpu/ui (+ desktop, gg) that hides the bootstrap boilerplate (NewApp → ui/app.New → SetRoot → desktop.Run, plus the blank gg/gpu import) behind one small public surface.
It follows the same philosophy as the engine's logx, window and input packages: engine code imports only aqwabor/ui and never reaches into gogpu/ui/... internals.
Two run loops exist in the engine and must not be mixed for the same window:
- window.Run: raw goGPU vertex drawing (low-level engine render path).
- ui.Run: widget toolkit driven by desktop.Run (UI shell / HUD path).
See docs/ui.md and docs/window.md for the split between the UI shell and the engine render path.
Index ¶
- Constants
- Variables
- func BackgroundColor(t *Theme) widget.Color
- func Hex(hex uint32) widget.Color
- func OnPrimary(t *Theme) widget.Color
- func OnSurfaceColor(t *Theme) widget.Color
- func Primary(t *Theme) widget.Color
- func RGB(r, g, b float32) widget.Color
- func RGBA(r, g, b, a float32) widget.Color
- func SurfaceColor(t *Theme) widget.Color
- type App
- type BoxWidget
- type Config
- type CrossAxisAlignment
- type ImageAsset
- type ImageFit
- type ImageManager
- type ImageWidget
- func (w ImageWidget) Fit(fit ImageFit) ImageWidget
- func (w ImageWidget) Height(height int) ImageWidget
- func (w ImageWidget) OnClick(fn func()) Widget
- func (w ImageWidget) Opacity(alpha float32) ImageWidget
- func (w ImageWidget) Size(width, height int) ImageWidget
- func (w ImageWidget) Width(width int) ImageWidget
- type LabelWidget
- type TextAlign
- type Theme
- type Widget
Constants ¶
const ( // CrossStart aligns children to the start (left for Column, top for Row). CrossStart = uiprim.CrossAxisStart // CrossCenter centers children on the cross axis. CrossCenter = uiprim.CrossAxisCenter // CrossEnd aligns children to the end (right for Column, bottom for Row). CrossEnd = uiprim.CrossAxisEnd // CrossStretch stretches children to fill the cross axis (default). CrossStretch = uiprim.CrossAxisStretch )
const ( // AlignLeft aligns text to the left (default). AlignLeft = widget.TextAlignLeft // AlignCenter centers text horizontally. AlignCenter = widget.TextAlignCenter // AlignRight aligns text to the right. AlignRight = widget.TextAlignRight )
Variables ¶
var ( // LightPurple — brand light purple. LightPurple = &Theme{ Primary: widget.Hex(0x6750A4), OnPrimary: widget.Hex(0xFFFFFFFF), Secondary: widget.Hex(0x9A7BD0), OnSecondary: widget.Hex(0xFFFFFFFF), Background: widget.Hex(0xF6F2FA), Surface: widget.Hex(0xFFFFFFFF), OnSurface: widget.Hex(0x2A2433), Error: widget.Hex(0xB00020), OnError: widget.Hex(0xFFFFFFFF), } // DarkPurple — brand dark purple. DarkPurple = &Theme{ Primary: widget.Hex(0xBB86FC), OnPrimary: widget.Hex(0x1B1622), Secondary: widget.Hex(0x9A7BD0), OnSecondary: widget.Hex(0x1B1622), Background: widget.Hex(0x1B1622), Surface: widget.Hex(0x251E30), OnSurface: widget.Hex(0xE6E1F0), Error: widget.Hex(0xCF6679), OnError: widget.Hex(0x1B1622), Dark: true, } // Light — neutral light (gray) theme. Light = &Theme{ Primary: widget.Hex(0x37474F), OnPrimary: widget.Hex(0xFFFFFFFF), Secondary: widget.Hex(0x607D8B), OnSecondary: widget.Hex(0xFFFFFFFF), Background: widget.Hex(0xFFFFFF), Surface: widget.Hex(0xF5F5F5), OnSurface: widget.Hex(0x101010), Error: widget.Hex(0xB00020), OnError: widget.Hex(0xFFFFFFFF), } // Dark — neutral dark (gray) theme. Dark = &Theme{ Primary: widget.Hex(0xB0BEC5), OnPrimary: widget.Hex(0x121212), Secondary: widget.Hex(0x78909C), OnSecondary: widget.Hex(0x121212), Background: widget.Hex(0x121212), Surface: widget.Hex(0x1E1E1E), OnSurface: widget.Hex(0xE0E0E0), Error: widget.Hex(0xCF6679), OnError: widget.Hex(0x121212), Dark: true, } // LightBlue — light blue theme. LightBlue = &Theme{ Primary: widget.Hex(0x2196F3), OnPrimary: widget.Hex(0xFFFFFFFF), Secondary: widget.Hex(0x64B5F6), OnSecondary: widget.Hex(0xFFFFFFFF), Background: widget.Hex(0xEAF2FF), Surface: widget.Hex(0xFFFFFFFF), OnSurface: widget.Hex(0x0E1A2B), Error: widget.Hex(0xB00020), OnError: widget.Hex(0xFFFFFFFF), } // DarkBlue — dark blue theme. DarkBlue = &Theme{ Primary: widget.Hex(0x448AFF), OnPrimary: widget.Hex(0x0A0F1E), Secondary: widget.Hex(0x2979FF), OnSecondary: widget.Hex(0x0A0F1E), Background: widget.Hex(0x0A0F1E), Surface: widget.Hex(0x121A2E), OnSurface: widget.Hex(0xDCE6FF), Error: widget.Hex(0xCF6679), OnError: widget.Hex(0x0A0F1E), Dark: true, } )
Six ready-made themes. Each is a plain *Theme you can also tweak, and you can build your own from scratch with &ui.Theme{...}.
Functions ¶
func BackgroundColor ¶
func OnSurfaceColor ¶
func Primary ¶
Primary Color accessors for the most useful theme roles. Each returns a widget.Color ready to pass to .Background(...) / .Color(...) on a widget builder, e.g.
ui.Column(...).Background(ui.SurfaceColor(app.Theme()))
ui.Label("x").Color(ui.OnSurfaceColor(app.Theme()))
func SurfaceColor ¶
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App owns a goGPU application and its gogpu/ui App.
func New ¶
New creates a UI application. It builds a goGPU app window and the matching gogpu/ui App (window/event/platform providers wired from the goGPU app).
func (*App) Button ¶
Button builds a themed button: its background uses the active theme's primary and its text uses on-primary, with hover/press feedback. Unlike the raw core/button (which hardcodes grey/black), this reflects the chosen theme.
func (*App) Close ¶
func (a *App) Close()
Close requests the UI window to close. Safe to call from a button callback.
func (*App) GogpuApp ¶
GogpuApp returns the underlying goGPU app as an escape hatch (e.g. to wire the input backend or request custom redraws).
func (*App) Images ¶
func (a *App) Images() *ImageManager
Images returns the app's image manager. The same manager is returned on every call, so assets loaded through it are shared across the whole application and released through TryRelease / ForceRelease.
func (*App) SetRoot ¶
SetRoot sets the root widget of the UI tree. The theme's Background is painted as a full-window surface behind the content so changing the theme actually repaints the window background (relying solely on the toolkit's backdrop is fragile and easy to cover with a child widget).
type BoxWidget ¶
BoxWidget is the builder returned by Box/Column/Row; it supports chaining methods such as Padding, Gap, Background and Rounded.
func Align ¶
func Align(w BoxWidget, cross CrossAxisAlignment) BoxWidget
Align sets a box's cross-axis alignment, letting you choose how children are positioned instead of hardcoding a center. Pick CrossStart (left for a Column, top for a Row), CrossCenter, CrossEnd, or CrossStretch.
Note: the underlying gogpu/ui BoxWidget only supports cross-axis alignment; main-axis (vertical for a Column) alignment is start-only in this version.
type Config ¶
type Config struct {
Title string
W, H int
Resizable bool
// Theme, if set, replaces the default theme (LightPurple). Use one of the
// pre-made themes (ui.DarkBlue, ...) or build your own with &ui.Theme{...}.
Theme *Theme
}
Config configures a UI application window.
type CrossAxisAlignment ¶
type CrossAxisAlignment = uiprim.CrossAxisAlignment
CrossAxisAlignment selects how a box aligns its children on the cross axis. For a Column the cross axis is horizontal; for a Row it is vertical.
type ImageAsset ¶
type ImageAsset struct {
// contains filtered or unexported fields
}
ImageAsset is an opaque handle to a loaded image resource. It is returned by ImageManager.Load and consumed by Image / ImageButton / Clickable. Treat it as an opaque token: never reach into its fields and never hold a raw copy of the underlying pixel data past the asset's lifetime.
Asset lifetime is explicit and deterministic:
asset, err := images.Load("logo.png")
root = ui.Image(asset) // asset now has 1 active user
images.TryRelease(asset) // refuses while still used
// ...remove the widget from the tree (Unmount)...
images.TryRelease(asset) // ok: resource freed
func (*ImageAsset) Acquire ¶
func (a *ImageAsset) Acquire()
Acquire registers an active consumer of the asset (e.g. a widget that will render it). The asset is not released by TryRelease while any user remains.
func (*ImageAsset) IsReleased ¶
func (a *ImageAsset) IsReleased() bool
IsReleased reports whether the asset's resource has been released (via TryRelease or ForceRelease). A released asset must not be rendered.
func (*ImageAsset) Path ¶
func (a *ImageAsset) Path() string
Path returns the normalized source path the asset was loaded from.
func (*ImageAsset) ReleaseUser ¶
func (a *ImageAsset) ReleaseUser() int
ReleaseUser unregisters one active consumer. It returns the remaining user count. When the count reaches zero the asset becomes eligible for release.
func (*ImageAsset) Size ¶
func (a *ImageAsset) Size() (int, int)
Size returns the natural pixel dimensions of the asset.
func (*ImageAsset) Take ¶
func (a *ImageAsset) Take() (image.Image, bool)
Take returns the pixel data and whether it is still valid (not released). It is the only supported way to read the image, so that a concurrent ForceRelease cannot be observed mid-draw as a use-after-free.
func (*ImageAsset) Users ¶
func (a *ImageAsset) Users() int
Users returns the current number of active consumers referencing the asset.
type ImageFit ¶
type ImageFit int
ImageFit controls how an image is scaled to fit its allocated bounds.
const ( // Fill stretches the image to exactly fill the bounds (may distort aspect ratio). Fill ImageFit = iota // Contain fits the image fully inside the bounds, preserving aspect ratio. Contain // Cover fills the bounds, preserving aspect ratio and cropping overflow. Cover // None draws the image at its natural size (top-left anchored, may overflow). None )
type ImageManager ¶
type ImageManager struct {
// contains filtered or unexported fields
}
ImageManager loads, caches and owns image assets. It is the single owner of image resources; widgets only consume assets handed out by a manager.
Typical integration: app.Images(). A standalone manager can also be created with ui.NewImageManager().
func NewImageManager ¶
func NewImageManager() *ImageManager
NewImageManager creates an empty image manager. Decoding is CPU-only, so a manager can be constructed before any window/GPU context exists.
func (*ImageManager) ForceRelease ¶
func (m *ImageManager) ForceRelease(asset *ImageAsset)
ForceRelease destroys the asset's resource immediately, even if active users still reference it. This is intentionally unsafe: widgets that keep using the released asset will render nothing (deterministic), but they are now holding a dead reference. The caller is responsible for removing/replacing those users.
Calling ForceRelease twice (or after TryRelease) is a no-op and never frees a resource twice.
func (*ImageManager) Load ¶
func (m *ImageManager) Load(path string) (*ImageAsset, error)
Load reads, decodes and uploads the image at path. Repeated loads of the same normalized source return the same canonical asset without re-decoding or duplicating the resource. Use TryRelease / ForceRelease to free it.
Supported formats are PNG, JPEG (.jpg/.jpeg) and SVG (.svg/.svgz). SVG is rasterized once at load time (see decodeSVG) into a fixed-resolution bitmap, so it behaves like any other raster image from the widget's point of view. Malformed or missing files return an error.
func (*ImageManager) TryRelease ¶
func (m *ImageManager) TryRelease(asset *ImageAsset) bool
TryRelease releases the asset only if it has no active users. It returns true on success. If the asset is still used by one or more widgets, or has already been released, or is owned by another manager, it returns false and leaves the resource intact.
type ImageWidget ¶
type ImageWidget = *imageWidget
ImageWidget is the builder returned by Image. It supports fluent configuration (Size / Width / Height / Fit / Opacity) and composes with the existing layout widgets (Row, Column, Box, Clickable, ...).
func Image ¶
func Image(asset *ImageAsset) ImageWidget
Image creates an image widget that consumes the given asset. The asset must be loaded via ImageManager.Load; widgets never perform I/O or decoding.
func (ImageWidget) Fit ¶
func (w ImageWidget) Fit(fit ImageFit) ImageWidget
Fit sets how the image is scaled within its bounds.
func (ImageWidget) Height ¶
func (w ImageWidget) Height(height int) ImageWidget
Height sets an explicit height in logical pixels.
func (ImageWidget) OnClick ¶
func (w ImageWidget) OnClick(fn func()) Widget
OnClick makes the image directly clickable. It is a convenience shorthand for ui.Clickable(image, fn): clicks anywhere within the image's bounds invoke fn. The returned Widget is no longer an ImageWidget, so chain OnClick last.
func (ImageWidget) Opacity ¶
func (w ImageWidget) Opacity(alpha float32) ImageWidget
Opacity sets the image opacity in [0,1]. Values < 1 are baked into a derived copy at draw time.
func (ImageWidget) Size ¶
func (w ImageWidget) Size(width, height int) ImageWidget
Size sets explicit width and height (in logical pixels). Zero keeps the natural dimension on that axis.
func (ImageWidget) Width ¶
func (w ImageWidget) Width(width int) ImageWidget
Width sets an explicit width in logical pixels.
type LabelWidget ¶
type LabelWidget = *uiprim.TextWidget
LabelWidget is the builder returned by Label; it supports chaining methods such as FontSize and Bold.
func CenterText ¶
func CenterText(l LabelWidget) LabelWidget
CenterText centers a label's text horizontally. Returns l so calls can keep chaining.
func Label ¶
func Label(text string) LabelWidget
Label creates a text label. Chain .FontSize(n), .Bold(), .Color(c), etc.
func LabelFn ¶
func LabelFn(fn func() string) LabelWidget
LabelFn creates a reactive text label whose content is recomputed on every draw from fn. Use it for live readouts (e.g. a camera HUD) without rebuilding the widget tree.
type Theme ¶
type Theme struct {
Primary widget.Color
OnPrimary widget.Color
Secondary widget.Color
OnSecondary widget.Color
Background widget.Color
Surface widget.Color
OnSurface widget.Color
Error widget.Color
OnError widget.Color
// Dark selects the dark color scheme (affects default shadows/mode). Set it
// when you want a dark look, typically together with dark Background/Surface.
Dark bool
}
Theme is a plain, editable color scheme. Fill the roles you care about and apply it with app.SetTheme. Because widgets capture their colors when the tree is built, re-call app.SetTheme — and rebuild the root (or the subtree) — after mutating fields to reskin a live UI.
type Widget ¶
Widget is the gogpu/ui widget interface, re-exported so engine code never imports gogpu/ui/widget directly.
func Button ¶
Button creates a clickable button painted with the engine brand theme's primary/on-primary colors. For an app-specific theme, use App.Button.
func Clickable ¶
Clickable wraps any widget so a click anywhere inside its bounds invokes onClick. It is a thin interaction layer over the toolkit's gesture pipeline (the same one core/button uses) and introduces no separate input system.
ui.Clickable(ui.Image(play), startGame)
ui.Clickable(ui.Row(ui.Image(play).Size(20, 20), ui.Label("Play")), startGame)
func ImageButton ¶
func ImageButton(asset *ImageAsset, onClick func()) Widget
ImageButton is a clickable image. It is a thin, unopinionated wrapper over Clickable + Image: the image keeps its natural/default sizing and the caller is free to size it explicitly (e.g. ui.Image(icon).Size(32, 32)). No fixed dimensions or fit mode are baked in.
ui.ImageButton(play, startGame) ui.Clickable(ui.Image(play).Size(32, 32), startGame) // explicit sizing