guie

module
v0.0.0-...-e7caca3 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2026 License: Apache-2.0

README

guie

A cross-platform GUI framework for Go: windows, layouts and a catalogue of widgets (buttons, lists, trees, tables, text fields, menus, dialogs, drag-and- drop, toasts, …) with theming, events and animations. It renders on Ebiten, but that is an internal detail — application code imports only ui, geom, render and theme, never Ebiten.

See design.md for the architecture and decisions, and internals.md for the implementation guide.

Quick start

package main

import (
	"log"

	"github.com/kpfaulkner/guie/geom"
	"github.com/kpfaulkner/guie/ui"
)

func main() {
	app := ui.NewApp(ui.WithTitle("Hello"), ui.WithSize(400, 200))

	quit := ui.NewButton("Quit")
	quit.OnClick(func() { app.Quit() })

	root := ui.NewContainer()
	root.SetLayout(ui.VBox(10))
	root.SetPadding(geom.UniformInsets(16))
	root.Add(ui.NewLabel("Hello, guie!"))
	root.Add(quit)

	app.SetContent(root)
	if err := app.Run(); err != nil {
		log.Fatal(err)
	}
}

Runnable examples live in examples/:

go run ./examples/hello       # smallest program
go run ./examples/tree        # Tree widget + Toast notifications
go run ./examples/dragdrop    # drag-and-drop between panels

Testing

guie ships a headless test backend, the guitest package, so you can integration-test a UI with no window, GPU or display — it runs anywhere go test runs, including CI. It implements the render seam (driver, canvas, font) and a Harness that drives an App one frame at a time: synthesize input, step the loop, and assert against widget state or the recorded drawing operations.

Writing a UI test

Put it in a normal _test.go file and run it with go test — there is no separate runner:

package myui_test

import (
	"testing"

	"github.com/kpfaulkner/guie/guitest"
	"github.com/kpfaulkner/guie/ui"
)

func TestSaveButtonFires(t *testing.T) {
	h := guitest.New(200, 100) // headless app, 200x100 logical pixels

	clicked := false
	btn := ui.NewButton("Save")
	btn.OnClick(func() { clicked = true })
	h.SetContent(btn) // the root fills the surface

	h.Click(100, 50) // press + release at the center (lays out, then dispatches)

	if !clicked {
		t.Fatal("button did not fire")
	}
	if rec := h.Frame(); !rec.HasText("Save") {
		t.Fatalf("label not drawn; texts = %v", rec.Texts())
	}
}
go test ./...            # run everything
go test ./path/to/myui   # just your package
Driving the app
  • h.Step() runs one frame (Update then Draw) with the input accumulated so far and returns that frame's *Recording.
  • Low-level input (build a frame, then Step): MoveMouse, PressMouse / ReleaseMouse, ScrollBy, PressKey / ReleaseKey, TypeText / TypeRune, SetModifiers.
  • Gestures (each performs its own steps): Click, RightClick, Drag, TypeKey.
  • h.Resize(w, h) reports a new surface size; h.App exposes the app so you can read widget state in assertions.
  • h.DropFiles(map[string][]byte) simulates dropping files from a file manager at the current mouse position (name → content) and steps one frame to deliver them, so OnFileDrop routing and bubbling are testable headlessly.
  • h.RequestClose() simulates the user closing the window and reports whether the close was allowed — false when an App.OnCloseRequest handler vetoed it (the loop keeps running, so Step still works afterwards). h.CloseHandled() reports whether the app asked the backend to stop closing the window by itself.
Asserting what was drawn

Step()/Frame() return a *Recording — the ordered list of drawing ops for that frame. Query it without a real surface:

  • HasText(s), TextContaining(substr), Texts()
  • Count(kind), OpsOfKind(kind)
  • FillsOfColour(c) — rectangles filled with a colour (e.g. a selection highlight)
  • TextAt(x, y, tol) — text drawn near a point

The headless font (guitest.NewFont) has simple, deterministic metrics (fixed per-rune advance and line height), so measurements and layout are predictable and independent of the bundled font.

Caveat: ui.NewRenderTarget still uses the real Ebiten backend (it is not part of the driver seam), so avoid it in headless tests. For a drag, set a custom DragGhost instead of relying on the default snapshot ghost. See guitest/harness_test.go for worked examples.

Running the framework's own tests
go test ./...            # unit + black-box tests across all packages
go test ./guitest/ -v    # the headless harness self-tests

GUI examples can't run headlessly (they open a window); they all compile and are the manual "does it actually render" check via go run ./examples/<name>.

Directories

Path Synopsis
Package clipboard provides an OS-backed render.Clipboard so guie text widgets can exchange text with other applications via the system clipboard.
Package clipboard provides an OS-backed render.Clipboard so guie text widgets can exchange text with other applications via the system clipboard.
examples
animation command
Command animation demonstrates the per-frame hook and the tween system.
Command animation demonstrates the per-frame hook and the tween system.
canvas command
Command canvas demonstrates building a custom widget by embedding ui.BaseWidget and drawing directly with the render.Canvas primitives: FillRect, StrokeRect, DrawLine, DrawText and MeasureText.
Command canvas demonstrates building a custom widget by embedding ui.BaseWidget and drawing directly with the render.Canvas primitives: FillRect, StrokeRect, DrawLine, DrawText and MeasureText.
clipboard command
Command clipboard demonstrates OS clipboard integration.
Command clipboard demonstrates OS clipboard integration.
colourpicker command
Command colourpicker demonstrates the ColourPicker: a preview swatch (showing the hex value) over hue/saturation/value/alpha gradient sliders.
Command colourpicker demonstrates the ColourPicker: a preview swatch (showing the hex value) over hue/saturation/value/alpha gradient sliders.
colours command
Command colours demonstrates per-widget colour control.
Command colours demonstrates per-widget colour control.
comprehensive command
Command comprehensive is a single-window tour of (nearly) the entire guie feature set, intended as a general-purpose demo and a living reference for the public API.
Command comprehensive is a single-window tour of (nearly) the entire guie feature set, intended as a general-purpose demo and a living reference for the public API.
controls command
Command controls demonstrates the form widgets added in step 6: TextField, Checkbox, RadioButton/RadioGroup, Slider and ProgressBar.
Command controls demonstrates the form widgets added in step 6: TextField, Checkbox, RadioButton/RadioGroup, Slider and ProgressBar.
datepicker command
Command datepicker demonstrates the DatePicker: an inline month calendar.
Command datepicker demonstrates the DatePicker: an inline month calendar.
dialog command
Command dialog demonstrates modal dialogs.
Command dialog demonstrates modal dialogs.
dragdrop command
Command dragdrop demonstrates drag-and-drop: drag the labelled items between the two panels.
Command dragdrop demonstrates drag-and-drop: drag the labelled items between the two panels.
editor command
Command editor is a small general-purpose text editor built with guie.
Command editor is a small general-purpose text editor built with guie.
events command
Command events demonstrates the event system: keyboard focus traversal with Tab / Shift+Tab (the focused button shows an accent ring), activation with Space or Enter, and a global event-bus subscriber that observes every click in the UI.
Command events demonstrates the event system: keyboard focus traversal with Tab / Shift+Tab (the focused button shows an accent ring), activation with Space or Enter, and a global event-bus subscriber that observes every click in the UI.
fonts command
Command fonts demonstrates adjusting both font type and size at runtime.
Command fonts demonstrates adjusting both font type and size at runtime.
hello command
Command hello is the smallest possible guie program: a window with a single centered label.
Command hello is the smallest possible guie program: a window with a single centered label.
images command
Command images demonstrates displaying images and image buttons.
Command images demonstrates displaying images and image buttons.
ime command
Command ime demonstrates guie's inline IME preedit rendering.
Command ime demonstrates guie's inline IME preedit rendering.
layouts command
Command layouts demonstrates the layout engine: nested containers using VBox / HBox / Grid / Stack, per-child weights and alignment, padding and themed panel colours.
Command layouts demonstrates the layout engine: nested containers using VBox / HBox / Grid / Stack, per-child weights and alignment, padding and themed panel colours.
paint command
Command paint is a tiny freehand drawing program built with guie.
Command paint is a tiny freehand drawing program built with guie.
scroll command
Command scroll demonstrates ScrollView: a viewport over content taller than the window.
Command scroll demonstrates ScrollView: a viewport over content taller than the window.
showcase command
Command showcase combines the third-wave widgets: a MenuBar across the top, a selectable List, and a DropdownCombo.
Command showcase combines the third-wave widgets: a MenuBar across the top, a selectable List, and a DropdownCombo.
splitter command
Command splitter demonstrates SplitPane: draggable dividers that resize adjacent panes.
Command splitter demonstrates SplitPane: draggable dividers that resize adjacent panes.
table command
Command table demonstrates the Table widget: a header row over scrollable, selectable body rows with weighted columns.
Command table demonstrates the Table widget: a header row over scrollable, selectable body rows with weighted columns.
tabs command
Command tabs demonstrates the TabContainer: a tab strip that switches between panes.
Command tabs demonstrates the TabContainer: a tab strip that switches between panes.
textarea command
Command textarea demonstrates the multi-line TextArea widget: type across multiple lines (Enter for a new line), navigate with the arrow keys, and scroll with the wheel when the text outgrows the box.
Command textarea demonstrates the multi-line TextArea widget: type across multiple lines (Enter for a new line), navigate with the arrow keys, and scroll with the wheel when the text outgrows the box.
theming command
Command theming demonstrates restyling the whole UI at runtime: swapping the colour palette, recolouring the accent, and changing the control corner radius (sharp vs.
Command theming demonstrates restyling the whole UI at runtime: swapping the colour palette, recolouring the accent, and changing the control corner radius (sharp vs.
tooltips command
Command tooltips demonstrates hover tooltips: rest the pointer on a widget for about half a second and a hint appears near the cursor.
Command tooltips demonstrates hover tooltips: rest the pointer on a widget for about half a second and a hint appears near the cursor.
tree command
Command tree demonstrates the Tree widget and Toast notifications.
Command tree demonstrates the Tree widget and Toast notifications.
widgets command
Command widgets demonstrates the Label and Button widgets and pointer interaction: a counter driven by buttons, plus a toggle that enables and disables another button at runtime.
Command widgets demonstrates the Label and Button widgets and pointer interaction: a counter driven by buttons, plus a toggle that enables and disables another button at runtime.
widgets2 command
Command widgets2 demonstrates the Stepper (numeric input) and the busy Spinner.
Command widgets2 demonstrates the Stepper (numeric input) and the busy Spinner.
Package geom provides backend-neutral 2D geometry types used throughout the framework.
Package geom provides backend-neutral 2D geometry types used throughout the framework.
Package guitest is a headless backend and harness for testing guie apps without a window or GPU.
Package guitest is a headless backend and harness for testing guie apps without a window or GPU.
internal
ebiten
Package ebitenbackend implements the render package's backend interfaces (Canvas, FontFace, Image and Driver) on top of EBiten.
Package ebitenbackend implements the render package's backend interfaces (Canvas, FontFace, Image and Driver) on top of EBiten.
Package render defines the backend-neutral rendering and input abstractions that sit between the framework core and a concrete graphics backend.
Package render defines the backend-neutral rendering and input abstractions that sit between the framework core and a concrete graphics backend.
Package theme defines the colour palette and font defaults used by widgets.
Package theme defines the colour palette and font defaults used by widgets.
Package ui is the public API of the framework: the App, windows, widgets, layouts, events and styling helpers that applications use.
Package ui is the public API of the framework: the App, windows, widgets, layouts, events and styling helpers that applications use.

Jump to

Keyboard shortcuts

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