goui

package module
v0.0.0-...-3b3a925 Latest Latest
Warning

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

Go to latest
Published: Jan 20, 2026 License: MIT Imports: 16 Imported by: 0

README

goui

A declarative GUI framework in Go.

⚠️ Status

Goui is in very early stage of development and currently only works on Windows platform.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrNoSuchWindow = errors.New("no such window exists")

ErrNoSuchWindow is returned when trying to access a window using an ID that does not exist.

View Source
var ErrWrongParent = errors.New("wrong parent")

ErrWrongParent is returned when build element tree fails due to invalid parent element. For example, a native control widget is created under a native menu element or vice versa.

Functions

func CloseWindow

func CloseWindow(windowID ID) error

CloseWindow closes the window with the given ID. If no such window exists, it returns ErrNoSuchWindow.

func CreateWindow

func CreateWindow(config *Window) (err error)

CreateWindow creates a new window with the given configuration. If config is nil, a default configuration is used. If a window with the same ID already exists, it returns an error.

func Exit

func Exit(exitCode int)

Exit quits the main event loop of the application with the given exit code. The exit code will be returned by the Run function.

func OS

func OS() native.OS

OS returns the native OS interface used by the application.

func Post

func Post(f func()) error

Post posts a function to be executed on the main GUI goroutine.

func Run

func Run(f func(), config *AppConfig) int

Run does the following things sequentially:

  • initializes the application
  • calls f
  • runs the main event loop

It returns the exit code passed to Exit. No other goui functions should be called before or after Run.

func RunAndExit

func RunAndExit(f func(), config *AppConfig)

RunAndExit calls os.Exit(Run(f, config)). It is convenience for applications that want to exit with the exit code returned by Run.

func WidgetNativeParent

func WidgetNativeParent(ctx *Context, element Element) (native.Handle, error)

WidgetNativeParent returns the native handle of the given widget element or its nearest ancestor that is a ControlElement. If element is nil or there is no such ancestor, ctx.NativeWindow() is returned. If element does not belong to a widget tree, ErrWrongParent is returned.

Types

type AppConfig

type AppConfig struct {
	// Debug is the debug configuration for the app.
	// If Debug is non-nil, debug mode is on, and the fields in Debug control which features are enabled.
	// If Debug is nil, debug mode is off.
	Debug *Debug
}

AppConfig is the configuration for creating a new App.

type Component

type Component interface {
	// WidgetID returns the identifier of this widget within its parent container. Can be nil.
	WidgetID() ID
	// CreateElement creates the Element for this widget.
	// [Element] is used to represent and manage the widget in the UI tree.
	CreateElement(ctx *Context, parent Element) (Element, error)
}

Component is the base interface for all widgets, menus and menu items.

type ComponentState

type ComponentState interface {
	// Destroy is called when the state is destroyed.
	// It can be used to clean up any resources associated with the state.
	Destroy()

	// Update calls updater and then updates the state.
	// Use [StateUpdater] to implement this method.
	Update(updater func()) error
	// Build builds the component tree for this state.
	// It is called during the initial creation of the state
	// and whenever the state is updated via [State.Update].
	Build() Component
}

ComponentState is the state associated with a StatefulComponent.

type Container

type Container interface {
	ContainerComponent
	ExclusiveType(marker.TypeWidget)
}

Container is a Widget that can contain child widgets.

type ContainerComponent

type ContainerComponent interface {
	Component
	// NumChildren returns the number of child widgets.
	NumChildren() int
	// Child returns the n-th child widget. Panics if n is out of range.
	Child(n int) Component
	ExclusiveKind(marker.KindContainer)
}

ContainerComponent is an Component that can contain child components.

type Context

type Context struct {
	// contains filtered or unexported fields
}

func (*Context) NativeWindow

func (ctx *Context) NativeWindow() native.Handle

NativeWindow returns the native window handle associated with this context.

type ControlElement

type ControlElement interface {
	Element
	// Returns the native handle of the control.
	NativeControl() native.Handle
}

ControlElement is the element that represent a native GUI control.

type ControlElementHelper

type ControlElementHelper struct {
	ElementHelper
	Handle native.Handle
	// DestroyFunc is called to destroy the native handle.
	// A nil value means no special destruction is needed.
	DestroyFunc func(ctx *Context, handle native.Handle) error
}

ControlElementHelper is an Element that represents a native GUI control. This type can be used to implement ControlElement for native control widgets.

func (*ControlElementHelper) Destroy

func (e *ControlElementHelper) Destroy(ctx *Context) error

Destroy implements the [ControlElement.Destroy] method.

func (*ControlElementHelper) NativeControl

func (e *ControlElementHelper) NativeControl() native.Handle

NativeControl implements the [ControlElement.NativeControl] method.

type Debug

type Debug struct {
	// LayoutOutline specifies whether layout outlines are drawn in debug mode.
	LayoutOutline bool
}

Debug is the debug configuration for the app.

type Element

type Element interface {
	Widget() Component
	SetWidget(ctx *Context, widget Component) error
	// Layouter returns the layouter of the element. Can be nil.
	Layouter() Layouter
	// Parent returns the parent element, or nil if this is the root element of a window.
	Parent() Element
	// Destroy destroys the element and releases any associated resources.
	Destroy(ctx *Context) error
	// NumChildren returns the number of child elements.
	NumChildren() int
	// Child returns the nth child element.
	Child(n int) Element
	// contains filtered or unexported methods
}

Element is the persistent representation of a Widget in the GUI tree.

func BuildElementTree

func BuildElementTree(ctx *Context, widget Component) (Element, error)

BuildElementTree builds the element tree for the given widget. The returned element is the root element of the built tree.

type ElementHelper

type ElementHelper struct {
	// ElementLayouter is the layouter of the element. Can be nil.
	// This field is returned by Layouter() method.
	ElementLayouter Layouter
	// contains filtered or unexported fields
}

ElementHelper implements Element, and is the building block for other Element types.

func (*ElementHelper) Child

func (e *ElementHelper) Child(n int) Element

func (*ElementHelper) Destroy

func (e *ElementHelper) Destroy(ctx *Context) (err error)

Destroy implements [Element.Destroy].

func (*ElementHelper) Layouter

func (e *ElementHelper) Layouter() Layouter

func (*ElementHelper) NumChildren

func (e *ElementHelper) NumChildren() int

func (*ElementHelper) Parent

func (e *ElementHelper) Parent() Element

func (*ElementHelper) SetWidget

func (e *ElementHelper) SetWidget(ctx *Context, widget Component) error

func (*ElementHelper) Widget

func (e *ElementHelper) Widget() Component

type ID

type ID interface {
	// contains filtered or unexported methods
}

ID is an opaque identifier only comparable for equality. IDs are process-local and must not be serialized or passed across process boundaries.

func UniqueID

func UniqueID() ID

UniqueID creates and returns a process-wide unique ID.

func ValueID

func ValueID[T comparable](value T) ID

ValueID returns an ID backed by a comparable value. Two IDs created with ValueID are equal when their underlying values are equal; otherwise they are not. Do not use pointers to zero-sized types for T, as their equality is undefined according to Go spec.

type Layouter

type Layouter interface {
	// Layout computes the size of the element given the constraints.
	Layout(ctx *Context, constraints metrics.Constraints) (metrics.Size, error)
	// PositionAt puts the element at the given position.
	// The position is relative to the native parent element's top-left corner.
	PositionAt(ctx *Context, pt metrics.Point) error
	// Replayer returns a function that can replay the last layout operations,
	// or nil if replay is not supported (e.g., when the layout depends on children).
	Replayer() func(*Context) error
	// Children returns an iterator of child layouters.
	Children() iter.Seq[Layouter]
	// Parent returns the parent layouter, or nil.
	Parent() Layouter
	// Element returns the element that creates this layouter.
	Element() Element
	// contains filtered or unexported methods
}

Layouter is the interface for laying out elements.

type LayouterHelper

type LayouterHelper struct {
	// contains filtered or unexported fields
}

LayouterHelper is a helper struct for implementing Layouter. Embedding LayouterHelper in a struct and implementing [Layouter.Layout] and [Layouter.PositionAt] methods implements the Layouter interface.

func (*LayouterHelper) Children

func (l *LayouterHelper) Children() iter.Seq[Layouter]

func (*LayouterHelper) Element

func (l *LayouterHelper) Element() Element

func (*LayouterHelper) Parent

func (l *LayouterHelper) Parent() (parent Layouter)

func (*LayouterHelper) Replayer

func (l *LayouterHelper) Replayer() func(*Context) error
type Menu interface {
	Component
	ExclusiveType(marker.TypeMenu)
}

Menu represents a menu, such as window menu, context menu, or submenu. A Menu can contain MenuItems or wrap another Menu in which case it is a stateless or stateful menu.

type MenuItem interface {
	Component
	ExclusiveType(marker.TypeMenuItem)
}

MenuItem represents an item in a menu.

type NativeMenuElement

type NativeMenuElement interface {
	Element
	// NativeMenu returns the native handle of the menu.
	NativeMenu() native.Handle
}

NativeMenuElement is an Element that represents a native menu.

type NativeMenuItemElement

type NativeMenuItemElement interface {
	Element
	// NativeMenuItem returns the native handle of the menu item.
	NativeMenuItem() native.Handle
}

type NopDestroyer

type NopDestroyer struct{}

NopDestroyer implements a no-op Destroy method. Embedding NopDestroyer in a struct provides a default implementation of Destroy method.

func (NopDestroyer) Destroy

func (NopDestroyer) Destroy()

Destroy does nothing.

type OverflowConstraintsError

type OverflowConstraintsError struct {
	Widget      Component
	Size        metrics.Size
	Constraints metrics.Constraints
}

OverflowConstraintsError is returned when a widget's size exceeds its constraints in debug mode. Widget can be nil and if it is not nil, it is included in the error message for better debugging.

func (*OverflowConstraintsError) Error

func (e *OverflowConstraintsError) Error() string

type StateContext

type StateContext struct {
	*Context
	// contains filtered or unexported fields
}

StateContext is the context used by NewStateUpdater.

type StateUpdater

type StateUpdater stateUpdater

StateUpdater implements ComponentState.Update method. Embedding StateUpdater in a struct and implementing other methods of WidgetState allows the struct type to satisfy the WidgetState interface.

func NewStateUpdater

func NewStateUpdater(ctx *StateContext) StateUpdater

NewStateUpdater creates a new StateUpdater with the given context.

func (StateUpdater) Update

func (h StateUpdater) Update(updater func()) error

Update implements WidgetState.Update.

type StatefulComponent

type StatefulComponent interface {
	Component
	CreateState(ctx *StateContext) ComponentState
	ExclusiveKind(marker.KindStateful)
}

StatefulComponent is a Component that has mutable state. The state is stored in a separate State object associated with the widget. The state can be updated via WidgetState.Update method, which triggers a rebuild of the widget tree.

type StatefulElement

type StatefulElement struct {
	ElementHelper
	State ComponentState
}

StatefulElement is the element for stateful widgets, menus and menu items.

func (*StatefulElement) Destroy

func (e *StatefulElement) Destroy(ctx *Context) error

Destroy implements Element.Destroy method. It calls State.Destroy before destroying the element.

type StatefulHelper

type StatefulHelper struct {
	ID ID
	// StateCreator creates the state associated with this widget.
	StateCreator func(ctx *StateContext) ComponentState
}

StatefulHelper is a helper to implement concrete state component.

func (*StatefulHelper) CreateElement

func (w *StatefulHelper) CreateElement(ctx *Context, parent Element) (Element, error)

func (*StatefulHelper) CreateState

func (w *StatefulHelper) CreateState(ctx *StateContext) ComponentState

func (*StatefulHelper) ExclusiveKind

func (*StatefulHelper) ExclusiveKind(marker.KindStateful)

func (*StatefulHelper) WidgetID

func (w *StatefulHelper) WidgetID() ID

type StatefulWidget

type StatefulWidget interface {
	StatefulComponent
	ExclusiveType(marker.TypeWidget)
}

StatefulWidgets is a Widget that has mutable state.

Example
package main

import (
	"fmt"

	"github.com/mkch/goui"
	"github.com/mkch/goui/widgets"
)

// CountState is a [goui.WidgetState] that holds the click count.
type CountState struct {
	goui.StateUpdater // Implements Update method.
	goui.NopDestroyer // No cleanup needed.

	count int // The actual state.
}

// NewCountState creates a new [CountState].
func NewCountState(ctx *goui.StateContext) goui.WidgetState {
	return &CountState{
		StateUpdater: goui.NewStateUpdater(ctx),
	}
}

// Build implements [goui.WidgetState.Build] method.
func (state *CountState) Build() goui.Widget {
	return &widgets.Button{
		Label: fmt.Sprintf("Clicked %d times", state.count),
		OnClick: func(ctx *goui.Context) {
			state.Update(func() {
				state.count++
			})
		},
	}
}

// NewCounterButton creates a new counter button with the given ID.
// The returned counter button is a stateful widget that displays a button showing the click count.
// Each time the button is clicked, the click count increases by one.
func NewCounterButton(ID goui.ID) goui.StatefulWidget {
	return goui.NewStatefulWidget(
		ID,
		func(ctx *goui.StateContext) goui.WidgetState { return NewCountState(ctx) },
	)
}

func main() {
	var counterButton goui.StatefulWidget = NewCounterButton(goui.ValueID("id"))

	// If there is no need to set an id, StatefulWidgetFunc is very convenient.
	counterButton = goui.StatefulWidgetFunc(NewCountState)

	_ = counterButton
}

func NewStatefulWidget

func NewStatefulWidget(ID ID, stateCreator func(ctx *StateContext) WidgetState) StatefulWidget

NewStatefulWidget creates a new StatefulWidget with the given ID and state creator function.

type StatefulWidgetFunc

type StatefulWidgetFunc func(ctx *StateContext) WidgetState

StatefulWidgetFunc is a function type that implements StatefulWidget. Method WidgetID returns nil and CreateState calls f.

func (StatefulWidgetFunc) CreateElement

func (f StatefulWidgetFunc) CreateElement(ctx *Context, parent Element) (Element, error)

func (StatefulWidgetFunc) CreateState

func (f StatefulWidgetFunc) CreateState(ctx *StateContext) ComponentState

func (StatefulWidgetFunc) ExclusiveKind

func (StatefulWidgetFunc) ExclusiveKind(marker.KindStateful)

func (StatefulWidgetFunc) ExclusiveType

func (StatefulWidgetFunc) ExclusiveType(marker.TypeWidget)

func (StatefulWidgetFunc) WidgetID

func (f StatefulWidgetFunc) WidgetID() ID

type StatelessComponent

type StatelessComponent interface {
	Component
	// Build builds and returns the wrapped widget.
	Build(ctx *Context) Component
	ExclusiveKind(marker.KindStateless)
}

StatelessComponent is a Component that builds its UI using a Build method. Stateless widget is a wrapper around other widgets and do not hold any state.

type StatelessHelper

type StatelessHelper struct {
	ID
	// Builder is a function that builds and returns the wrapped widget. Can't be nil.
	Builder func(ctx *Context) Component
}

StatelessHelper is a helper to implement concrete StatelessComponent and StatelessWidget. The WidgetID method returns ID and the Build method calls Builder.

func (*StatelessHelper) Build

func (w *StatelessHelper) Build(ctx *Context) Component

Build implements [StatelessComponent.Build]. It calls the Builder function. Panics if Builder is nil.

func (*StatelessHelper) CreateElement

func (w *StatelessHelper) CreateElement(ctx *Context, parent Element) (Element, error)

CreateElement implements [Component.CreateElement].

func (*StatelessHelper) ExclusiveKind

func (*StatelessHelper) ExclusiveKind(marker.KindStateless)

func (*StatelessHelper) WidgetID

func (w *StatelessHelper) WidgetID() ID

WidgetID implements [Component.WidgetID].

type StatelessWidget

type StatelessWidget interface {
	StatelessComponent
	ExclusiveType(marker.TypeWidget)
}

StatelessWidget is a Widget that builds its UI using a Build method.

func NewStatelessWidget

func NewStatelessWidget(ID ID, builder func(ctx *Context) Widget) StatelessWidget

NewStatelessWidget creates a new StatelessWidget with the given ID and builder function.

type StatelessWidgetFunc

type StatelessWidgetFunc func(ctx *Context) Widget

StatelessWidgetFunc is a function type that implements StatelessWidget. Method WidgetID returns nil and Build calls f.

func (StatelessWidgetFunc) Build

func (f StatelessWidgetFunc) Build(ctx *Context) Component

Build implements [StatelessWidget.Build]. It calls f.

func (StatelessWidgetFunc) CreateElement

func (f StatelessWidgetFunc) CreateElement(ctx *Context, parent Element) (Element, error)

CreateElement implements [StatelessWidget.CreateElement].

func (StatelessWidgetFunc) ExclusiveKind

func (StatelessWidgetFunc) ExclusiveKind(marker.KindStateless)

func (StatelessWidgetFunc) ExclusiveType

func (StatelessWidgetFunc) ExclusiveType(marker.TypeWidget)

func (StatelessWidgetFunc) WidgetID

func (f StatelessWidgetFunc) WidgetID() ID

WidgetID implements [StatelessWidget.WidgetID].

type Widget

type Widget interface {
	Component
	ExclusiveType(marker.TypeWidget)
}

Widget represents a GUI widget laid out in a window.

type WidgetState

type WidgetState interface {
	// Destroy is called when the state is destroyed.
	// It can be used to clean up any resources associated with the state.
	Destroy()

	// Update calls updater and then updates the state.
	// Use [StateUpdater] to implement this method.
	Update(updater func()) error
	// Build builds the widget tree for this state.
	// It is called during the initial creation of the state
	// and whenever the state is updated via [State.Update].
	Build() Widget
}

WidgetState is the state associated with a StatefulWidget.

func NewWidgetState

func NewWidgetState(ctx *StateContext, build func() Widget, destroy func()) WidgetState

NewWidgetState creates a new State with the given context, a build function, and a destroy function. The returned State uses the build function to build its widget tree, and the destroy function to clean up resources. The destroy func can be nil. This function is convenient to create simple states without defining a new struct type.

Example
package main

import (
	"fmt"

	"github.com/mkch/goui"
	"github.com/mkch/goui/widgets"
)

func main() {
	// counterButton is a stateful widget that displays a button showing the click count.
	// Each time the button is clicked, the click count increases by one.
	var counterButton goui.Widget = goui.NewStatefulWidget(
		goui.ValueID(123),
		func(ctx *goui.StateContext) (state goui.WidgetState) {
			var count int // Click count, the actual state.
			return goui.NewWidgetState(ctx, func() goui.Widget {
				return &widgets.Button{
					Label: fmt.Sprintf("Clicked %d times", count),
					OnClick: func(ctx *goui.Context) {
						state.Update(func() { count++ })
					},
				}
			}, nil)
		},
	)

	_ = counterButton
}

type Window

type Window struct {
	ID     ID
	Title  string
	Width  metrics.DP
	Height metrics.DP
	// The root widget to display in the window.
	// If Root is nil, an empty window is created.
	Root Widget
	// The menu widget for the window.
	// If nil, no menu is created.
	// Only widgets representing menus should be assigned; others will not display correctly.
	Menu Menu
	// OnClose is called when the window is requested to close, if not nil.
	// If OnClose is not nil and returns false, the window will not close.
	OnClose   func(ctx *Context) bool
	OnDestroy func(ctx *Context)
}

Directories

Path Synopsis
Package gouitest provides utilities for testing goui applications.
Package gouitest provides utilities for testing goui applications.
internal
debug
Package debug provides debugging utilities.
Package debug provides debugging utilities.
tricks
Package tricks includes internal tricks used by goui for debugging purposes.
Package tricks includes internal tricks used by goui for debugging purposes.
Package marker defines marker type used by ExclusiveType and ExclusiveKind methods.
Package marker defines marker type used by ExclusiveType and ExclusiveKind methods.
Package menu implements menu widgets.
Package menu implements menu widgets.
Package metrics provides types and functions for device-independent pixel (DP) measurements.
Package metrics provides types and functions for device-independent pixel (DP) measurements.
samples
basic command
dpi command
idmatch command
listener command
login command
menu command
multiwindows command
panel command
stateful command
visibility command
internal/rowcol
Package rowcol provides utilities to implement Row and Column widgets.
Package rowcol provides utilities to implement Row and Column widgets.
row

Jump to

Keyboard shortcuts

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