rosaline

package module
v0.0.0-...-5ef44b2 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: LGPL-3.0 Imports: 27 Imported by: 0

README

Rosaline

Rosaline is a small, beginner-friendly graphics and GUI library for Go. It is designed for people who know a little Go and want to make a real graphical program without first learning a large framework.

Rosaline is currently at v0.15.0. The public API is small on purpose and grows through well-documented, tested features.

Goals

  • Beginner-friendly Go API
  • Builds with CGO_ENABLED=0
  • Linux is a first-class platform
  • The same application code runs on Linux, Windows, and macOS
  • Serious 2D drawing alongside normal GUI widgets
  • Small, memorable public API
  • Complete examples and feature-by-feature documentation

Install

Rosaline uses GitHub's normal Go module support:

go get github.com/SeraphinaDX/Rosaline

Rosaline requires Go 1.25 or newer. No C compiler or separately installed GUI toolkit is required. On Linux, a graphical desktop with X11 or XWayland is currently required; native Wayland support is on the roadmap.

The first build can take a while because the CGo-free window and AVIF backends must be compiled. Go caches them, so later builds are normally much faster.

Hello, Rosaline

package main

import "github.com/SeraphinaDX/Rosaline"

func main() {
	rosaline.Run(
		rosaline.Column(
			rosaline.Label("Hello, world!"),
			rosaline.Button("Click me", func() {
				rosaline.Message("Rosaline", "It works!")
			}).Primary(),
		),
	)
}

Save that as main.go, then run:

CGO_ENABLED=0 go run .

See docs/QUICK_START.md for a guided first application.

A small form

Form controls update normal Go variables through pointers:

var name string
var subscribed bool

rosaline.Run(
	rosaline.Column(
		rosaline.Label("Your name"),
		rosaline.TextBox(&name).Placeholder("Type your name").Focus(),
		rosaline.CheckBox("Send me updates", &subscribed),
		rosaline.Button("Continue", func() {
			rosaline.Message("Hello", "Welcome, "+name+"!")
		}).Primary(),
	),
)

See docs/TEXT_INPUT.md, docs/CHECKBOX.md, and docs/FORMS.md.

Layouts that stay readable

Build equal-cell grids, layered interfaces, centered cards, and adaptive rows from ordinary widgets:

panel := rosaline.Card(
	rosaline.Column(
		rosaline.Label("Quick actions").FontSize(24).Bold(),
		rosaline.Separator(),
		rosaline.Grid(2,
			rosaline.Button("Open", open),
			rosaline.Button("Save", save).Primary(),
		).Gap(8),
		rosaline.Row(
			rosaline.Label("Ready"),
			rosaline.Spring(),
			rosaline.Label("2 actions"),
		),
	).Gap(12),
)

rosaline.Run(
	rosaline.Stack(background, rosaline.Center(panel)).Expand(),
)

Align, Size, and MinSize cover positioning and sizing without manual coordinates. See Layout and Presentation and the complete Calculator application.

An interactive canvas

Canvas callbacks use the same coordinates as drawing commands:

var x, y float64

canvas := rosaline.Canvas(func(c *rosaline.DrawingCanvas) {
	c.Clear(rosaline.White)
	c.FillCircle(x, y, 12, rosaline.Rose)
})

canvas.OnMouseDown(func(event rosaline.MouseEvent) {
	if event.Button == rosaline.MouseLeft {
		x, y = event.X, event.Y
	}
})

Rosaline redraws automatically after mouse callbacks. See docs/CANVAS_INPUT.md for clicking, dragging, modifier keys, manual redraws, and a complete paint program.

Advanced drawing and image export

Paths can be reused, transformed, clipped, filled, and outlined:

heart := rosaline.NewPath().
	MoveTo(160, 80).
	CubicTo(80, 20, 30, 130, 160, 240).
	CubicTo(290, 130, 240, 20, 160, 80).
	Close()

canvas := rosaline.Canvas(func(c *rosaline.DrawingCanvas) {
	c.Clear(rosaline.White)
	c.FillPath(heart, rosaline.SoftRose)
	c.StrokePath(heart, 4, rosaline.Rose)
})

The same drawing engine produces off-screen images:

picture := canvas.Picture()
err := picture.SavePNG("heart.png")
err = picture.SaveAVIF("heart.avif")

See docs/DRAWING_PATHS.md, docs/TRANSFORMS_AND_CLIPPING.md, and docs/IMAGE_EXPORT.md.

A real image-viewer application

Rosaline v0.4 combines menus, dialogs, images, and scrolling:

viewer := rosaline.Image(nil)

openImage := func() {
	path, ok := rosaline.OpenFileDialog(rosaline.FileDialogOptions{
		Title: "Open Image",
	})
	if !ok {
		return
	}
	picture, err := rosaline.LoadImage(path)
	if err != nil {
		rosaline.Error("Could not open image", err.Error())
		return
	}
	viewer.SetImage(picture)
}

See docs/IMAGE_VIEWER.md for the complete application.

Timers and animation

Timers belong to the application and automatically stop with its event loop:

seconds := 0

clock := rosaline.Every(time.Second, func() {
	seconds++
})

rosaline.RunApp(rosaline.App{
	Timers: []*rosaline.Timer{clock},
	Content: rosaline.LabelFunc(func() string {
		return fmt.Sprintf("Running for %d seconds", seconds)
	}),
})

Use After for one delayed callback and Animate for a frame-rate-based canvas loop. See docs/TIMERS.md and docs/ANIMATION.md.

A complete canvas game

Rosaline's normal canvas, timer, keyboard, path, and transform APIs are enough for a real-time vector game:

canvas.OnKeyDown(func(event rosaline.KeyEvent) {
	if event.Is(rosaline.KeySpace) {
		controls.fire = true
	}
})
canvas.OnKeyUp(func(event rosaline.KeyEvent) {
	if event.Is(rosaline.KeySpace) {
		controls.fire = false
	}
})

animation := rosaline.Animate(60, func() {
	game.Update()
	canvas.Redraw()
})

The complete Starshower application adds a fixed-step model, held-key movement, vector spacecraft and asteroids, screen wrapping, collision detection, splitting rocks, waves, scoring, lives, pause, and restart. Its game rules have fast tests that do not open a window. See Building Starshower.

Slow work without a frozen window

Background tasks do ordinary Go work in a goroutine while Rosaline safely delivers progress and results to the GUI thread:

progress := 0.0

task := rosaline.Background(func(ctx context.Context, report *rosaline.TaskReporter) error {
	for step := 1; step <= 100; step++ {
		if !report.Report(float64(step), "Working...") {
			return ctx.Err()
		}
	}
	return nil
}).OnProgress(func(update rosaline.TaskProgress) {
	progress = update.Percent
}).AutoStart()

rosaline.RunApp(rosaline.App{
	Tasks:   []*rosaline.Task{task},
	Content: rosaline.ProgressBar(&progress),
})

Tasks support cancellation, reusable starts, posted result callbacks, normal Go errors, and automatic window-lifetime cleanup. See Background Tasks and the complete Background Bloom application.

Tabs and selectable lists

Larger applications can group related pages and present scrollable choices without leaving Rosaline's small composable API:

themes := rosaline.List("Rosaline", "Lavender", "Ocean").
	OnSelect(func(index int, value string) {
		fmt.Println("selected", value)
	})

preferences := rosaline.Tabs(
	rosaline.Tab("Appearance", themes),
	rosaline.Tab("About", rosaline.Label("Built with Rosaline")),
).Expand()

See docs/LISTS.md, docs/TABS.md, and the complete Preferences application.

Tables made from ordinary Go data

Tables use normal strings and slices rather than a framework-specific model:

files := rosaline.Table("Name", "Type", "Size").
	SetRows(
		[]string{"README.md", "Markdown", "8 KB"},
		[]string{"picture.png", "Image", "2.4 MB"},
	).
	OnActivate(func(row int, values []string) {
		fmt.Println("opened", values[0])
	})

Selection, keyboard activation, column sizing, dynamic replacement, and both scrollbars are built in. See docs/TABLES.md and the complete File Browser application.

Nested data with simple trees

Trees use ordinary node pointers, labels, and optional application values:

documents := rosaline.Node("Documents",
	rosaline.Node("Notes.txt"),
	rosaline.Node("Ideas.txt"),
).Expanded()

folders := rosaline.Tree(documents).
	OnActivate(func(node *rosaline.TreeNode) {
		fmt.Println("open", node.Value())
	})

Selection, activation, expansion callbacks, dynamic children, native keyboard navigation, and both scrollbars are built in. See docs/TREES.md and the upgraded File Browser application.

Multiple windows without another event loop

Secondary windows are reusable Go handles:

var about *rosaline.Window
about = rosaline.NewWindow(rosaline.WindowOptions{
	Title:  "About",
	Parent: rosaline.MainWindow(),
	Content: rosaline.Button("Close", func() {
		about.Close()
	}),
})

openAbout := rosaline.Button("About", func() {
	about.Show()
})

Calling Show twice focuses the existing window. Windows can close and reopen, share normal Go state, own menus and timers, and form safe parent-child relationships. See docs/MULTIPLE_WINDOWS.md and the complete Project Desk example.

Everyday controls with ordinary Go values

Radio groups, combo boxes, sliders, and progress bars bind directly to normal Go variables:

priority := "normal"
category := "Documentation"
completion := 35.0

rosaline.Run(
	rosaline.Column(
		rosaline.ComboBox(&category, "Documentation", "Development"),
		rosaline.RadioGroup(&priority,
			rosaline.Choice("Low", "low"),
			rosaline.Choice("Normal", "normal"),
			rosaline.Choice("High", "high"),
		).Horizontal(),
		rosaline.Slider(&completion, 0, 100).Step(5),
		rosaline.ProgressBar(&completion),
	)
)

The slider and progress bar share one pointer, so they stay synchronized after Rosaline events without a binding language. Options and choices can be replaced while the application is running. Progress bars also support an indeterminate busy mode. See Radio Groups, Combo Boxes, Sliders, Progress Bars, and the complete Task Settings application.

Keyboard input without platform code

Windows and canvases receive the same small KeyEvent, and applications can define shortcuts without building a menu:

canvas := rosaline.Canvas(draw).
	Focus().
	OnKeyDown(func(event rosaline.KeyEvent) {
		if event.Is(rosaline.KeyRight) {
			x += 10
		}
	})

rosaline.RunApp(rosaline.App{
	Shortcuts: rosaline.Shortcuts(
		rosaline.Shortcut("Primary+S", save),
		rosaline.Shortcut("F1", showHelp),
	),
	Content: canvas,
})

Primary follows the platform convention: Control on Linux and Windows, Command on macOS. Canvas key callbacks redraw automatically, and window key handlers observe input without breaking normal text editing. See Keyboard Input and Shortcuts and the complete Keyboard Garden application.

Edit real documents

An expanding text area includes the editing operations needed by a document application:

text := ""
editor := rosaline.TextArea(&text).Expand().Focus()

rosaline.RunApp(rosaline.App{
	OnCloseRequest: func() bool {
		if !editor.Modified() {
			return true
		}
		switch rosaline.AskSaveChanges("Unsaved changes", "Save before closing?") {
		case rosaline.SaveChanges:
			return save()
		case rosaline.DiscardChanges:
			return true
		default:
			return false
		}
	},
	Content: editor,
})

Text, SetText, Append, Clear, MarkSaved, undo/redo, clipboard commands, selection, find/replace, and cursor position remain methods on the same small widget. The close prompt offers Save, Discard, and Cancel without risking a document when saving is cancelled or fails. See Text Editing and the complete Notepad application.

Included in v0.15.0

  • Application windows
  • Labels and dynamic labels with font size, bold, and text alignment
  • Buttons and message dialogs
  • Rows, columns, spacing, padding, and expansion
  • Equal-column grids with automatic rows, gaps, padding, and expansion
  • Layered stacks with metadata-driven alignment and centered overlays
  • Adaptive springs, themed separators and cards, and preferred or minimum sizing wrappers
  • Simple state values
  • Single-line input and expanding multiline document editing with a native scrollbar
  • Password display, placeholders, change events, and Enter submission
  • Text-area content methods, saved-state tracking, undo/redo, clipboard commands, selection, exact find/replace, and cursor position
  • Checkboxes bound to Go Boolean variables
  • Radio groups with separate labels and values, vertical or horizontal layout, callbacks, programmatic selection, and dynamic choices
  • Read-only combo boxes with callbacks, programmatic selection, width control, and dynamic options
  • Numeric sliders with safe ranges, optional steps, horizontal or vertical direction, focus, callbacks, and programmatic control
  • Determinate and indeterminate progress bars with custom maximums, size, direction, and start/stop controls
  • Tab and Shift+Tab keyboard navigation
  • Backend-neutral window and canvas key-down and key-up events
  • Friendly named key constants, printable text, and modifier fields
  • Menu-free application shortcuts with cross-platform Primary modifiers
  • Keyboard-enabled canvases with initial or callback-requested focus, click-to-focus, a visible focus ring, and automatic redraw
  • A first-class canvas with lines, rectangles, circles, and text
  • Reusable paths with straight, quadratic, and cubic Bézier sections
  • Translate, rotate, scale, Push/Pop, and transformed clipping
  • Canvas clicks, pointer movement, dragging, and button-release events
  • Automatic and manually requested canvas redraws
  • CGo-free loading and display of PNG, JPEG, GIF, BMP, TIFF, WebP, and AVIF
  • Off-screen drawing with the same API as visible canvases
  • PNG and CGo-free AVIF image export
  • Horizontal and vertical scroll areas
  • Native open, save, message, error, and confirmation dialogs
  • Menu bars with working keyboard shortcuts
  • Repeating and one-shot application timers
  • Start, stop, restart, and running-state timer controls
  • Frame-rate-based canvas animation
  • Window-owned background tasks with standard Go context cancellation
  • GUI-thread progress, completion, and posted result callbacks
  • Safe task restart, auto-start, panic conversion, and late-callback cleanup
  • Native tabbed interfaces with selection callbacks and programmatic selection
  • Scrollable single-selection lists with selection and activation callbacks
  • Dynamic list replacement and safe programmatic selection
  • Focus traversal that automatically skips controls on hidden tab pages
  • Native multi-column tables built from ordinary [][]string data
  • Table selection, activation, column sizing, dynamic rows, and two-axis scrolling
  • Native trees with nested nodes, labels, and application-defined values
  • Tree selection, activation, expansion callbacks, dynamic roots and children, and two-axis scrolling
  • Reusable secondary windows with simple show, close, focus, title, and state controls
  • Window-specific content, menus, shortcuts, themes, focus traversal, and timers
  • Parent-child window lifecycles, automatic parent opening, cascading closure, and duplicate prevention
  • Cancellable close requests for protecting unsaved window content
  • Automatic dynamic-widget refresh across every open window
  • Semantic colors and themes
  • A saveable Paint application with menus, shortcuts, and PNG/AVIF output
  • A complete Preferences application combining tabs, lists, form controls, and a live canvas preview
  • A complete File Browser using lazy folder trees, tables, and Go's standard filesystem APIs
  • A complete Project Desk application combining an editor, live child preview, About window, shared state, menus, and dynamic titles
  • A complete Task Settings application combining everyday controls, shared Go state, validation, dynamic choices, and both progress modes
  • A complete Keyboard Garden combining canvas input, modifiers, releases, standalone shortcuts, drawing, dialogs, and PNG export
  • A complete Background Bloom combining responsive image generation, progress, cancellation, result posting, shortcuts, dialogs, and PNG export
  • A complete Calculator combining grids, stacks, cards, alignment, dynamic typography, adaptive spacing, keyboard input, shortcuts, and tested logic
  • A complete Notepad combining document editing, files, menus, shortcuts, find/replace, saved-state tracking, status information, and safe closing
  • A complete Starshower vector game combining fixed-step simulation, held-key controls, transforms, wrapping, collisions, score, lives, waves, and pause
  • Runnable hello, counter, canvas, forms, drawing, paint, image-viewer, and animation examples, plus the Preferences, File Browser, and Project Desk applications, Task Settings, Keyboard Garden, Background Bloom, and the Calculator, Notepad, and Starshower
  • Unit tests for non-visual core behavior

Run the examples

From the extracted project root:

CGO_ENABLED=0 go run ./examples/hello
CGO_ENABLED=0 go run ./examples/counter
CGO_ENABLED=0 go run ./examples/canvas
CGO_ENABLED=0 go run ./examples/drawing
CGO_ENABLED=0 go run ./examples/forms
CGO_ENABLED=0 go run ./examples/paint
CGO_ENABLED=0 go run ./examples/imageviewer
CGO_ENABLED=0 go run ./examples/animation
CGO_ENABLED=0 go run ./examples/preferences
CGO_ENABLED=0 go run ./examples/filebrowser
CGO_ENABLED=0 go run ./examples/windows
CGO_ENABLED=0 go run ./examples/tasksettings
CGO_ENABLED=0 go run ./examples/keyboard
CGO_ENABLED=0 go run ./examples/background
CGO_ENABLED=0 go run ./examples/calculator
CGO_ENABLED=0 go run ./examples/notepad
CGO_ENABLED=0 go run ./examples/starshower

Project status

The API is experimental until v1.0. With the documentation-application set now complete, development is shifting toward custom widgets, accessibility groundwork, API stabilization, and deeper Linux display testing.

Rosaline's backend is intentionally private. Application code only imports the rosaline package, so the backend can improve without forcing beginners to rewrite their programs.

License

Rosaline is free software licensed under the GNU Lesser General Public License v3.0 or later.

Applications may use and link to Rosaline without being required to adopt the LGPL. Modifications to Rosaline itself must remain available under the LGPL, and distribution must follow the license's relinking and source-availability requirements. The incorporated GNU GPL v3 text is included in LICENSE.GPL.

Dependencies keep their own licenses; see THIRD_PARTY_NOTICES.md.

Copyright (C) 2026 Britney Lozza and Rosaline contributors.

Documentation

Overview

Package rosaline makes small graphical Go applications easy to build.

The package deliberately keeps window setup, the event loop, layout, and the platform backend out of beginner programs. A complete application can be as small as:

rosaline.Run(rosaline.Label("Hello, world!"))

Use RunApp when you want to set the title, initial window size, or theme. TextBox, TextArea, and CheckBox bind directly to ordinary Go variables. Canvas mouse callbacks make drawing programs interactive without exposing platform event types. Images, scroll areas, menus, and file dialogs provide the groundwork for complete desktop applications while ordinary file I/O remains normal Go. App-owned timers support delayed work, repeating updates, and canvas animation without exposing the private event loop. Paths, transforms, clipping, off-screen rendering, and PNG or AVIF export support complete graphical applications with one consistent drawing API. Tabs organize larger interfaces into composable pages. Lists provide native scrolling, keyboard selection, activation, and programmatic item updates. Tables display ordinary slices of strings under named columns with native scrolling, keyboard behavior, selection, and activation. Trees display nested nodes with native expansion, selection, activation, dynamic child replacement, and optional application-defined values. NewWindow creates reusable secondary windows with independent content, menus, focus, themes, timers, and safe parent-child lifecycles. RadioGroup and ComboBox provide compact pointer-bound choices. Slider and ProgressBar share ordinary float64 values for numeric input and progress, including indeterminate busy feedback. KeyEvent supports window-wide and focused-canvas keyboard input. Standalone shortcuts use familiar names and a cross-platform Primary modifier without requiring a menu or exposing backend key values. Background creates window-owned tasks with standard context cancellation, progress reports, completion callbacks, and safe GUI-thread result posting. Grid, Stack, Align, Center, Spring, Separator, Card, Size, and MinSize build polished adaptive layouts while remaining ordinary composable widgets. TextArea supports expanding document editors with saved-state tracking, undo and redo, clipboard commands, selection, find and replace, and cursor positions. Window close requests can be cancelled to protect unsaved work. Canvas keyboard events, animation timers, paths, and transforms also support small real-time games while application logic remains ordinary testable Go.

Index

Constants

This section is empty.

Variables

View Source
var (
	Black       = RGB(0, 0, 0)
	White       = RGB(255, 255, 255)
	Rose        = Hex("#d64f8c")
	SoftRose    = Hex("#f4a6c8")
	Transparent = RGBA(0, 0, 0, 0)
)
View Source
var DefaultTheme = Theme{
	Background: Hex("#fff8fc"),
	Surface:    Hex("#ffffff"),
	Primary:    Hex("#c43f7a"),
	Text:       Hex("#2a1722"),
	Muted:      Hex("#7d6874"),
	Border:     Hex("#d9b8ca"),
	Danger:     Hex("#b4234d"),
	Success:    Hex("#267a50"),
}

DefaultTheme is Rosaline's light rose theme.

Functions

func Confirm

func Confirm(title, text string) bool

Confirm asks a yes-or-no question and reports whether the user chose Yes.

func Error

func Error(title, text string)

Error displays an error dialog.

func Message

func Message(title, text string)

Message displays a simple informational dialog.

func OpenFileDialog

func OpenFileDialog(options FileDialogOptions) (path string, ok bool)

OpenFileDialog asks the user to choose one existing file. ok is false when the user cancels the dialog.

func Quit

func Quit()

Quit closes the Rosaline application.

func Run

func Run(content Widget)

Run opens a window containing content using beginner-friendly defaults.

func RunApp

func RunApp(app App)

RunApp opens the primary application window and runs its event loop.

func SaveFileDialog

func SaveFileDialog(options FileDialogOptions) (path string, ok bool)

SaveFileDialog asks the user where to save a file. ok is false when the user cancels. Existing files require confirmation before they are returned.

Types

type AVIFOptions

type AVIFOptions struct {
	Quality  int
	Speed    int
	Lossless bool
}

AVIFOptions controls AVIF image export. Zero values use Rosaline's high-quality beginner-friendly defaults.

type Alignment

type Alignment uint8

Alignment controls where Align places content on one axis.

const (
	// AlignStart places content at the left or top edge.
	AlignStart Alignment = iota
	// AlignCenter places content in the center of an axis.
	AlignCenter
	// AlignEnd places content at the right or bottom edge.
	AlignEnd
	// AlignStretch stretches content across an axis.
	AlignStretch
)

type AlignmentBox

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

AlignmentBox positions content within all the space its parent gives it.

func Align

func Align(content Widget, horizontal, vertical Alignment) *AlignmentBox

Align positions content independently on the horizontal and vertical axes.

func Center

func Center(content Widget) *AlignmentBox

Center centers content horizontally and vertically.

type App

type App struct {
	Title     string
	Width     int
	Height    int
	Padding   int
	Theme     Theme
	Menu      *AppMenuBar
	Timers    []*Timer
	Tasks     []*Task
	Shortcuts []KeyShortcut
	OnKeyDown func(KeyEvent)
	OnKeyUp   func(KeyEvent)
	// OnCloseRequest runs before the window closes. Return false to keep the
	// application open, for example while a document has unsaved changes.
	OnCloseRequest func() bool
	Content        Widget
}

App describes Rosaline's primary application window.

type AppMenu

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

AppMenu is one named drop-down menu in a menu bar.

func Menu(text string, entries ...MenuEntry) *AppMenu

Menu creates one named drop-down menu.

type AppMenuBar

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

AppMenuBar is a window's top-level menu bar.

func MenuBar(menus ...*AppMenu) *AppMenuBar

MenuBar creates a top-level menu bar.

type Box

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

Box arranges child widgets in a row or column.

func Column

func Column(children ...Widget) *Box

Column arranges widgets from top to bottom.

func Row

func Row(children ...Widget) *Box

Row arranges widgets from left to right.

func (*Box) Expand

func (b *Box) Expand() *Box

Expand asks the layout to use available window space.

func (*Box) Gap

func (b *Box) Gap(pixels int) *Box

Gap sets the space between children in pixels.

func (*Box) Padding

func (b *Box) Padding(pixels int) *Box

Padding sets the space inside the layout in pixels.

type ButtonWidget

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

ButtonWidget is a clickable button.

func Button

func Button(text string, onClick func()) *ButtonWidget

Button creates a button. onClick runs when the user activates it.

func (*ButtonWidget) Primary

func (b *ButtonWidget) Primary() *ButtonWidget

Primary gives a button the theme's primary color.

type CanvasWidget

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

CanvasWidget is a custom 2D drawing surface.

func Canvas

func Canvas(draw func(*DrawingCanvas)) *CanvasWidget

Canvas creates a 2D drawing surface.

func (*CanvasWidget) Background

func (c *CanvasWidget) Background(color Color) *CanvasWidget

Background sets the canvas background.

func (*CanvasWidget) Expand

func (c *CanvasWidget) Expand() *CanvasWidget

Expand asks the canvas to use available layout space.

func (*CanvasWidget) Focus

func (c *CanvasWidget) Focus() *CanvasWidget

Focus gives this canvas keyboard focus. Before the window opens, it asks Rosaline to focus the canvas initially. A canvas with a key handler also participates in Tab focus order.

func (*CanvasWidget) OnKeyDown

func (c *CanvasWidget) OnKeyDown(handler func(KeyEvent)) *CanvasWidget

OnKeyDown runs when a key is pressed while the canvas has focus. Clicking a keyboard-enabled canvas gives it focus.

func (*CanvasWidget) OnKeyUp

func (c *CanvasWidget) OnKeyUp(handler func(KeyEvent)) *CanvasWidget

OnKeyUp runs when a key is released while the canvas has focus.

func (*CanvasWidget) OnMouseDown

func (c *CanvasWidget) OnMouseDown(handler func(MouseEvent)) *CanvasWidget

OnMouseDown runs when a mouse button is pressed over the canvas.

func (*CanvasWidget) OnMouseMove

func (c *CanvasWidget) OnMouseMove(handler func(MouseEvent)) *CanvasWidget

OnMouseMove runs when the pointer moves over the canvas. Event Button is MouseNone for normal movement and identifies the held button while dragging.

func (*CanvasWidget) OnMouseUp

func (c *CanvasWidget) OnMouseUp(handler func(MouseEvent)) *CanvasWidget

OnMouseUp runs when a mouse button is released over the canvas.

func (*CanvasWidget) Picture

func (c *CanvasWidget) Picture() *Picture

Picture renders the canvas into an off-screen Picture. The result can be saved as PNG or AVIF and is available even before the widget is mounted.

func (*CanvasWidget) Redraw

func (c *CanvasWidget) Redraw()

Redraw clears the canvas and runs its drawing function again. Call Redraw from Rosaline callbacks after changing drawing state. Mouse callbacks redraw automatically, so they normally do not need to call it themselves.

func (*CanvasWidget) Size

func (c *CanvasWidget) Size(width, height int) *CanvasWidget

Size sets the canvas's initial size in pixels.

type CardWidget

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

CardWidget presents one widget on the theme's surface color with a border and comfortable padding.

func Card

func Card(content Widget) *CardWidget

Card wraps content in a themed surface and border.

func (*CardWidget) Expand

func (c *CardWidget) Expand() *CardWidget

Expand asks the card to use available space.

func (*CardWidget) Padding

func (c *CardWidget) Padding(pixels int) *CardWidget

Padding changes the space inside the card in pixels.

type CheckBoxWidget

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

CheckBoxWidget is a labeled checkbox bound to a Go bool.

func CheckBox

func CheckBox(text string, value *bool) *CheckBoxWidget

CheckBox creates a checkbox. It updates value when the user toggles it. Pass a pointer with &, as in CheckBox("Updates", &updates).

func (*CheckBoxWidget) Focus

func (c *CheckBoxWidget) Focus() *CheckBoxWidget

Focus asks Rosaline to give this checkbox focus when the window opens. If several widgets request focus, the first one wins.

func (*CheckBoxWidget) OnChange

func (c *CheckBoxWidget) OnChange(handler func(bool)) *CheckBoxWidget

OnChange runs after the user toggles the checkbox.

type Color

type Color struct {
	R, G, B, A uint8
}

Color stores a red, green, blue, and alpha component.

func Hex

func Hex(value string) Color

Hex parses #RGB, #RRGGBB, or #RRGGBBAA. Invalid values return black. Use ParseHex when an invalid value should be reported as an error.

func ParseHex

func ParseHex(value string) (Color, error)

ParseHex parses #RGB, #RRGGBB, or #RRGGBBAA.

func RGB

func RGB(r, g, b uint8) Color

RGB creates an opaque color.

func RGBA

func RGBA(r, g, b, a uint8) Color

RGBA creates a color with an alpha component.

func (Color) String

func (c Color) String() string

type ComboBoxWidget

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

ComboBoxWidget displays a compact drop-down selection bound to a Go string.

func ComboBox

func ComboBox(value *string, options ...string) *ComboBoxWidget

ComboBox creates a read-only drop-down. It updates value when the user picks an option. An unavailable value safely selects the first option.

func (*ComboBoxWidget) Focus

func (c *ComboBoxWidget) Focus() *ComboBoxWidget

Focus asks Rosaline to focus this combo box when the window opens.

func (*ComboBoxWidget) OnChange

func (c *ComboBoxWidget) OnChange(handler func(string)) *ComboBoxWidget

OnChange runs after the selected value changes through the UI or Select.

func (*ComboBoxWidget) Options

func (c *ComboBoxWidget) Options() []string

Options returns a copy of the current drop-down options.

func (*ComboBoxWidget) Select

func (c *ComboBoxWidget) Select(value string)

Select changes the selection. Values not present in the options are ignored.

func (*ComboBoxWidget) Selected

func (c *ComboBoxWidget) Selected() string

Selected returns the currently bound option.

func (*ComboBoxWidget) SetOptions

func (c *ComboBoxWidget) SetOptions(options ...string)

SetOptions replaces every option. Duplicate strings are ignored. If the old value is unavailable, the first replacement is selected.

func (*ComboBoxWidget) Width

func (c *ComboBoxWidget) Width(columns int) *ComboBoxWidget

Width sets the preferred width in text columns.

type DrawingCanvas

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

DrawingCanvas provides Rosaline's beginner-friendly 2D drawing operations. The same API draws both visible widgets and off-screen images.

func (*DrawingCanvas) Circle

func (c *DrawingCanvas) Circle(x, y, radius, stroke float64, value Color)

Circle draws the outline of a circle.

func (*DrawingCanvas) Clear

func (c *DrawingCanvas) Clear(value Color)

Clear removes existing drawing and fills the entire canvas with color. Clear is unaffected by the current transform or clipping region.

func (*DrawingCanvas) Clip

func (c *DrawingCanvas) Clip(rect Rect)

Clip restricts subsequent drawing to rect. The rectangle follows the current transform and intersects any existing clipping region.

func (*DrawingCanvas) ClipRect

func (c *DrawingCanvas) ClipRect(x, y, width, height float64)

ClipRect is a convenient form of Clip using separate coordinates.

func (*DrawingCanvas) FillCircle

func (c *DrawingCanvas) FillCircle(x, y, radius float64, value Color)

FillCircle draws a filled circle.

func (*DrawingCanvas) FillPath

func (c *DrawingCanvas) FillPath(path *Path, value Color)

FillPath fills a reusable Path.

func (*DrawingCanvas) FillRect

func (c *DrawingCanvas) FillRect(x, y, width, height float64, value Color)

FillRect draws a filled rectangle.

func (*DrawingCanvas) Line

func (c *DrawingCanvas) Line(x1, y1, x2, y2, stroke float64, value Color)

Line draws a line.

func (*DrawingCanvas) Pop

func (c *DrawingCanvas) Pop()

Pop restores the most recently saved transform and clipping region. Calling Pop without a matching Push has no effect.

func (*DrawingCanvas) Push

func (c *DrawingCanvas) Push()

Push saves the current transform and clipping region. Push calls may be nested and paired with Pop.

func (*DrawingCanvas) Rect

func (c *DrawingCanvas) Rect(x, y, width, height, stroke float64, value Color)

Rect draws the outline of a rectangle.

func (*DrawingCanvas) ResetClip

func (c *DrawingCanvas) ResetClip()

ResetClip removes every active clipping region.

func (*DrawingCanvas) ResetTransform

func (c *DrawingCanvas) ResetTransform()

ResetTransform restores the normal untransformed coordinate system.

func (*DrawingCanvas) Rotate

func (c *DrawingCanvas) Rotate(degrees float64)

Rotate rotates subsequent drawing clockwise by degrees around the current origin.

func (*DrawingCanvas) Scale

func (c *DrawingCanvas) Scale(x, y float64)

Scale scales subsequent drawing around the current origin.

func (*DrawingCanvas) StrokePath

func (c *DrawingCanvas) StrokePath(path *Path, stroke float64, value Color)

StrokePath draws the outline of a reusable Path.

func (*DrawingCanvas) Text

func (c *DrawingCanvas) Text(text string, x, y float64, style TextStyle)

Text draws text from its top-left corner.

func (*DrawingCanvas) Translate

func (c *DrawingCanvas) Translate(x, y float64)

Translate moves subsequent drawing by x and y pixels.

type FileDialogOptions

type FileDialogOptions struct {
	Title            string
	InitialDirectory string
	InitialFile      string
	DefaultExtension string
	Filters          []FileFilter
}

FileDialogOptions customizes an open or save dialog. Every field is optional; Rosaline supplies beginner-friendly defaults.

type FileFilter

type FileFilter struct {
	Name       string
	Extensions []string
}

FileFilter describes one group of files in an open or save dialog.

type GridLayout

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

GridLayout arranges widgets in automatically filled rows and columns.

func Grid

func Grid(columns int, children ...Widget) *GridLayout

Grid creates a layout with the requested number of columns. Children fill each row from left to right. Invalid column counts safely use one column.

func (*GridLayout) Expand

func (g *GridLayout) Expand() *GridLayout

Expand asks the grid and its equal-sized cells to use available space.

func (*GridLayout) Gap

func (g *GridLayout) Gap(pixels int) *GridLayout

Gap sets the space between grid cells in pixels.

func (*GridLayout) Padding

func (g *GridLayout) Padding(pixels int) *GridLayout

Padding sets the space around the inside of the grid in pixels.

type ImageWidget

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

ImageWidget displays a Picture.

func Image

func Image(picture *Picture) *ImageWidget

Image creates a widget that displays picture. A nil picture is allowed and shows a friendly placeholder until SetImage is called.

func (*ImageWidget) Expand

func (i *ImageWidget) Expand() *ImageWidget

Expand asks the image widget to use available layout space.

func (*ImageWidget) Picture

func (i *ImageWidget) Picture() *Picture

Picture returns the picture currently displayed by the widget.

func (*ImageWidget) Placeholder

func (i *ImageWidget) Placeholder(text string) *ImageWidget

Placeholder changes the text shown when no picture is loaded.

func (*ImageWidget) SetImage

func (i *ImageWidget) SetImage(picture *Picture)

SetImage changes the displayed picture. It can be called from Rosaline callbacks after the widget has been mounted.

type Key

type Key string

Key identifies a keyboard key without exposing backend-specific names. Printable keys use a lowercase value; Text preserves the text actually produced by the event.

const (
	KeyUnknown   Key = ""
	KeyBackspace Key = "Backspace"
	KeyTab       Key = "Tab"
	KeyEnter     Key = "Enter"
	KeyEscape    Key = "Escape"
	KeySpace     Key = "Space"
	KeyDelete    Key = "Delete"
	KeyInsert    Key = "Insert"
	KeyHome      Key = "Home"
	KeyEnd       Key = "End"
	KeyPageUp    Key = "PageUp"
	KeyPageDown  Key = "PageDown"
	KeyLeft      Key = "Left"
	KeyUp        Key = "Up"
	KeyRight     Key = "Right"
	KeyDown      Key = "Down"
	KeyShift     Key = "Shift"
	KeyControl   Key = "Control"
	KeyAlt       Key = "Alt"
	KeySuper     Key = "Super"
	KeyCapsLock  Key = "CapsLock"
	KeyF1        Key = "F1"
	KeyF2        Key = "F2"
	KeyF3        Key = "F3"
	KeyF4        Key = "F4"
	KeyF5        Key = "F5"
	KeyF6        Key = "F6"
	KeyF7        Key = "F7"
	KeyF8        Key = "F8"
	KeyF9        Key = "F9"
	KeyF10       Key = "F10"
	KeyF11       Key = "F11"
	KeyF12       Key = "F12"
)

func (Key) String

func (k Key) String() string

String returns the friendly name of a key.

type KeyEvent

type KeyEvent struct {
	Key     Key
	Text    string
	Shift   bool
	Control bool
	Alt     bool
	Primary bool
}

KeyEvent describes a key press or release. Text contains produced text such as "a" or "A" and is empty for keys such as Left and Escape.

func (KeyEvent) Is

func (e KeyEvent) Is(key Key) bool

Is reports whether this event belongs to key.

type KeyShortcut

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

KeyShortcut connects a key combination to an ordinary func(). Create one with Shortcut and place it in App.Shortcuts or WindowOptions.Shortcuts.

func Shortcut

func Shortcut(keys string, onPress func()) KeyShortcut

Shortcut creates a window shortcut such as "Primary+S", "Ctrl+Shift+S", or "Escape". Primary means Control on Linux and Windows and Command on macOS.

func Shortcuts

func Shortcuts(shortcuts ...KeyShortcut) []KeyShortcut

Shortcuts collects shortcut values without requiring a slice literal.

func (KeyShortcut) Keys

func (s KeyShortcut) Keys() string

Keys returns the human-readable key combination supplied to Shortcut.

type LabelWidget

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

LabelWidget displays text.

func Label

func Label(text string) *LabelWidget

Label creates a label with fixed text.

func LabelFunc

func LabelFunc(text func() string) *LabelWidget

LabelFunc creates a label whose text is recalculated after Rosaline events. It is useful for counters and other small pieces of changing text.

func (*LabelWidget) Bold

func (l *LabelWidget) Bold() *LabelWidget

Bold gives the label bold text.

func (*LabelWidget) Color

func (l *LabelWidget) Color(color Color) *LabelWidget

Color sets this label's text color.

func (*LabelWidget) FontSize

func (l *LabelWidget) FontSize(pixels int) *LabelWidget

FontSize sets the label text size in pixels. Non-positive values use the platform's normal interface size.

func (*LabelWidget) TextAlign

func (l *LabelWidget) TextAlign(alignment Alignment) *LabelWidget

TextAlign aligns text inside the label horizontally.

type ListWidget

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

ListWidget displays a scrollable list with one selected item.

func List

func List(items ...string) *ListWidget

List creates a single-selection list. The first item is selected by default.

func (*ListWidget) Expand

func (l *ListWidget) Expand() *ListWidget

Expand asks the list to use available layout space.

func (*ListWidget) Items

func (l *ListWidget) Items() []string

Items returns a copy of the list's current items.

func (*ListWidget) OnActivate

func (l *ListWidget) OnActivate(handler func(index int, value string)) *ListWidget

OnActivate runs when an item is double-clicked or activated with Enter.

func (*ListWidget) OnSelect

func (l *ListWidget) OnSelect(handler func(index int, value string)) *ListWidget

OnSelect runs when the selected item changes.

func (*ListWidget) Select

func (l *ListWidget) Select(index int)

Select changes the selected item. Invalid indices clear the selection. When the list is mounted, changing selection also runs OnSelect.

func (*ListWidget) Selected

func (l *ListWidget) Selected() (index int, value string, ok bool)

Selected returns the selected index and value. ok is false when the list is empty or has no selection.

func (*ListWidget) SetItems

func (l *ListWidget) SetItems(items ...string)

SetItems replaces every item. Selection remains at the same index when possible, moves to the last available item when necessary, and selects the first item when changing an empty list into a non-empty list.

func (*ListWidget) Size

func (l *ListWidget) Size(columns, rows int) *ListWidget

Size sets the list's approximate width in characters and height in rows.

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

MenuAction is a clickable command inside a menu.

func MenuItem(text string, onClick func()) *MenuAction

MenuItem creates a clickable menu command.

func (m *MenuAction) Shortcut(shortcut string) *MenuAction

Shortcut displays and binds a keyboard shortcut such as "Primary+O" or "Primary+Shift+S".

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

MenuEntry is an item or separator accepted by Menu.

func MenuSeparator() MenuEntry

MenuSeparator inserts a dividing line between menu commands.

type MouseButton

type MouseButton uint8

MouseButton identifies a mouse button without exposing platform details.

const (
	// MouseNone means that no mouse button is pressed.
	MouseNone MouseButton = iota
	// MouseLeft is the primary mouse button.
	MouseLeft
	// MouseMiddle is the middle mouse button.
	MouseMiddle
	// MouseRight is the secondary mouse button.
	MouseRight
)

type MouseEvent

type MouseEvent struct {
	X        float64
	Y        float64
	Button   MouseButton
	Dragging bool
	Shift    bool
	Control  bool
	Alt      bool
}

MouseEvent describes mouse input on a Canvas. X and Y are measured from the canvas's top-left corner.

type Path

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

Path describes a reusable shape made from straight lines and Bézier curves.

func NewPath

func NewPath() *Path

NewPath creates an empty path.

func (*Path) Close

func (p *Path) Close() *Path

Close connects the current point to the beginning of its path section.

func (*Path) CubicTo

func (p *Path) CubicTo(control1X, control1Y, control2X, control2Y, x, y float64) *Path

CubicTo adds a cubic Bézier curve with two control points.

func (*Path) LineTo

func (p *Path) LineTo(x, y float64) *Path

LineTo adds a straight line from the current point to x, y.

func (*Path) MoveTo

func (p *Path) MoveTo(x, y float64) *Path

MoveTo begins a new part of the path at x, y.

func (*Path) QuadraticTo

func (p *Path) QuadraticTo(controlX, controlY, x, y float64) *Path

QuadraticTo adds a quadratic Bézier curve with one control point.

type Picture

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

Picture contains a decoded image that Rosaline can display.

func LoadImage

func LoadImage(path string) (*Picture, error)

LoadImage reads and decodes an image file. PNG, JPEG, GIF, BMP, TIFF, WebP, and AVIF are supported.

func NewPicture

func NewPicture(pixels image.Image) *Picture

NewPicture creates a Rosaline picture from Go's standard image.Image type.

func Render

func Render(width, height int, draw func(*DrawingCanvas)) *Picture

Render draws an off-screen picture. It uses the same DrawingCanvas API as a visible Canvas widget and defaults to a white background.

func (*Picture) Format

func (p *Picture) Format() string

Format returns the decoded format name, such as "png" or "jpeg".

func (*Picture) Height

func (p *Picture) Height() int

Height returns the picture height in pixels.

func (*Picture) Image

func (p *Picture) Image() image.Image

Image returns the underlying standard-library image.Image value.

func (*Picture) Path

func (p *Picture) Path() string

Path returns the filename used by LoadImage. Pictures made with NewPicture have an empty path.

func (*Picture) SaveAVIF

func (p *Picture) SaveAVIF(path string, options ...AVIFOptions) error

SaveAVIF writes the picture as an AVIF image. Without options, Rosaline uses quality 90 and speed 8. AVIF encoding is CGo-free and needs no external tool.

func (*Picture) SavePNG

func (p *Picture) SavePNG(path string) error

SavePNG writes the picture as a PNG image.

func (*Picture) Width

func (p *Picture) Width() int

Width returns the picture width in pixels.

type ProgressBarWidget

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

ProgressBarWidget displays determinate progress or a busy animation.

func ProgressBar

func ProgressBar(value *float64) *ProgressBarWidget

ProgressBar creates a horizontal determinate progress bar bound to a Go float64. Values are clamped between zero and 100 by default.

func (*ProgressBarWidget) Busy

Busy switches to an indeterminate animation and starts it. Use this when work is happening but its completion percentage is unknown.

func (*ProgressBarWidget) Determinate

func (p *ProgressBarWidget) Determinate() *ProgressBarWidget

Determinate returns to percentage-style progress and stops any busy animation.

func (*ProgressBarWidget) Horizontal

func (p *ProgressBarWidget) Horizontal() *ProgressBarWidget

Horizontal arranges progress from left to right. This is the default.

func (*ProgressBarWidget) IsBusy

func (p *ProgressBarWidget) IsBusy() bool

IsBusy reports whether the bar is in indeterminate mode.

func (*ProgressBarWidget) Length

func (p *ProgressBarWidget) Length(pixels int) *ProgressBarWidget

Length sets the preferred progress bar length in pixels.

func (*ProgressBarWidget) Max

func (p *ProgressBarWidget) Max() float64

Max returns the current upper bound.

func (*ProgressBarWidget) Maximum

func (p *ProgressBarWidget) Maximum(maximum float64) *ProgressBarWidget

Maximum changes the upper bound. Invalid or non-positive values use 100.

func (*ProgressBarWidget) Running

func (p *ProgressBarWidget) Running() bool

Running reports whether the busy animation is currently running.

func (*ProgressBarWidget) SetValue

func (p *ProgressBarWidget) SetValue(value float64)

SetValue changes determinate progress and clamps it to the current maximum.

func (*ProgressBarWidget) Start

Start resumes a busy progress bar. It has no effect in determinate mode.

func (*ProgressBarWidget) Stop

Stop pauses a busy progress bar. It keeps the bar in busy mode so Start can resume it later.

func (*ProgressBarWidget) Value

func (p *ProgressBarWidget) Value() float64

Value returns the currently bound determinate value.

func (*ProgressBarWidget) Vertical

func (p *ProgressBarWidget) Vertical() *ProgressBarWidget

Vertical arranges progress from bottom to top.

type RadioChoice

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

RadioChoice is one labeled value accepted by RadioGroup. Create choices with Choice rather than filling this type manually.

func Choice

func Choice(label, value string) RadioChoice

Choice creates one radio-group choice. Empty labels use the value, or the friendly label "Choice" when both strings are empty.

func (RadioChoice) Label

func (c RadioChoice) Label() string

Label returns the text displayed beside this choice.

func (RadioChoice) Value

func (c RadioChoice) Value() string

Value returns the value stored in the RadioGroup's bound Go string.

type RadioGroupWidget

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

RadioGroupWidget displays mutually exclusive choices bound to a Go string.

func RadioGroup

func RadioGroup(value *string, choices ...RadioChoice) *RadioGroupWidget

RadioGroup creates a vertical group of choices. It updates value whenever the user selects one. An unavailable value safely selects the first choice.

func (*RadioGroupWidget) Choices

func (r *RadioGroupWidget) Choices() []RadioChoice

Choices returns a copy of the configured choices.

func (*RadioGroupWidget) Focus

func (r *RadioGroupWidget) Focus() *RadioGroupWidget

Focus asks Rosaline to focus the selected choice when the window opens.

func (*RadioGroupWidget) Horizontal

func (r *RadioGroupWidget) Horizontal() *RadioGroupWidget

Horizontal arranges the choices from left to right.

func (*RadioGroupWidget) OnChange

func (r *RadioGroupWidget) OnChange(handler func(string)) *RadioGroupWidget

OnChange runs after the selected value changes through the UI or Select.

func (*RadioGroupWidget) Select

func (r *RadioGroupWidget) Select(value string)

Select changes the selection. Values not present in the group are ignored.

func (*RadioGroupWidget) Selected

func (r *RadioGroupWidget) Selected() string

Selected returns the currently bound choice value.

func (*RadioGroupWidget) SetChoices

func (r *RadioGroupWidget) SetChoices(choices ...RadioChoice)

SetChoices replaces every choice. Duplicate values are ignored. If the old value is unavailable, the first replacement is selected.

func (*RadioGroupWidget) Vertical

func (r *RadioGroupWidget) Vertical() *RadioGroupWidget

Vertical arranges the choices from top to bottom. This is the default.

type Rect

type Rect struct {
	X      float64
	Y      float64
	Width  float64
	Height float64
}

Rect describes a rectangle used for clipping and other drawing operations.

type SaveDecision

type SaveDecision uint8

SaveDecision describes what the user wants to do with unsaved changes.

const (
	// CancelChanges keeps the document open and cancels the pending action.
	CancelChanges SaveDecision = iota
	// SaveChanges asks the application to save before continuing.
	SaveChanges
	// DiscardChanges continues without saving.
	DiscardChanges
)

func AskSaveChanges

func AskSaveChanges(title, text string) SaveDecision

AskSaveChanges asks whether unsaved work should be saved, discarded, or kept open. The dialog uses the platform's standard Yes, No, and Cancel buttons: Yes returns SaveChanges, No returns DiscardChanges, and Cancel or closing the dialog returns CancelChanges.

type ScrollWidget

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

ScrollWidget displays content inside a viewport with horizontal and vertical scrollbars.

func Scroll

func Scroll(content Widget) *ScrollWidget

Scroll creates a scrollable viewport around content.

func (*ScrollWidget) Expand

func (s *ScrollWidget) Expand() *ScrollWidget

Expand asks the scroll area to use available layout space.

func (*ScrollWidget) Size

func (s *ScrollWidget) Size(width, height int) *ScrollWidget

Size sets the viewport's preferred size in pixels.

type SeparatorWidget

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

SeparatorWidget is a thin themed dividing line.

func Separator

func Separator() *SeparatorWidget

Separator creates a one-pixel horizontal dividing line.

func (*SeparatorWidget) Horizontal

func (s *SeparatorWidget) Horizontal() *SeparatorWidget

Horizontal changes the separator to a horizontal line. This is the default.

func (*SeparatorWidget) Thickness

func (s *SeparatorWidget) Thickness(pixels int) *SeparatorWidget

Thickness changes the line thickness in pixels. Invalid values use one.

func (*SeparatorWidget) Vertical

func (s *SeparatorWidget) Vertical() *SeparatorWidget

Vertical changes the separator to a vertical line.

type SizeBox

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

SizeBox gives one widget a preferred or minimum pixel size.

func MinSize

func MinSize(content Widget, width, height int) *SizeBox

MinSize preserves the content's natural size while requiring at least the supplied width and height in pixels.

func Size

func Size(content Widget, width, height int) *SizeBox

Size gives content a preferred pixel size. The content fills that area.

func (*SizeBox) Expand

func (s *SizeBox) Expand() *SizeBox

Expand asks the sized area to grow when more space is available.

type SliderWidget

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

SliderWidget displays a numeric slider bound to a Go float64.

func Slider

func Slider(value *float64, minimum, maximum float64) *SliderWidget

Slider creates a horizontal numeric slider. Reversed bounds are swapped, equal bounds receive a safe one-unit range, and value is clamped.

func (*SliderWidget) Bounds

func (s *SliderWidget) Bounds() (minimum, maximum float64)

Bounds returns the normalized minimum and maximum.

func (*SliderWidget) Focus

func (s *SliderWidget) Focus() *SliderWidget

Focus asks Rosaline to focus this slider when the window opens.

func (*SliderWidget) Horizontal

func (s *SliderWidget) Horizontal() *SliderWidget

Horizontal arranges the slider from left to right. This is the default.

func (*SliderWidget) Length

func (s *SliderWidget) Length(pixels int) *SliderWidget

Length sets the preferred slider length in pixels.

func (*SliderWidget) OnChange

func (s *SliderWidget) OnChange(handler func(float64)) *SliderWidget

OnChange runs after the value changes through the UI or SetValue.

func (*SliderWidget) SetRange

func (s *SliderWidget) SetRange(minimum, maximum float64) *SliderWidget

SetRange changes the numeric bounds and clamps the current value.

func (*SliderWidget) SetValue

func (s *SliderWidget) SetValue(value float64)

SetValue clamps and optionally rounds a new value.

func (*SliderWidget) Step

func (s *SliderWidget) Step(step float64) *SliderWidget

Step rounds values to a positive interval measured from the minimum. Zero or invalid steps leave the slider continuous.

func (*SliderWidget) Value

func (s *SliderWidget) Value() float64

Value returns the currently bound numeric value.

func (*SliderWidget) Vertical

func (s *SliderWidget) Vertical() *SliderWidget

Vertical arranges the slider from bottom to top.

type SpringWidget

type SpringWidget struct{}

SpringWidget is flexible empty space that absorbs extra room in a Row or Column. Use Spacer when the empty space should have a fixed size.

func Spring

func Spring() *SpringWidget

Spring creates flexible empty space.

type StackLayout

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

StackLayout layers widgets in the same space. Later children appear above earlier children. Align or Center can position an overlay without stretching its visible content.

func Stack

func Stack(children ...Widget) *StackLayout

Stack layers ordinary widgets in one shared area.

func (*StackLayout) Expand

func (s *StackLayout) Expand() *StackLayout

Expand asks the stack to use available space.

type State

type State[T any] struct {
	// contains filtered or unexported fields
}

State stores a value that can be safely read and changed. LabelFunc and button callbacks are enough for basic reactive interfaces.

func NewState

func NewState[T any](initial T) *State[T]

NewState creates state with an initial value.

func (*State[T]) Get

func (s *State[T]) Get() T

Get returns the current value.

func (*State[T]) Set

func (s *State[T]) Set(value T)

Set replaces the current value.

func (*State[T]) Update

func (s *State[T]) Update(change func(T) T)

Update calculates and stores a new value from the current value.

type TabPage

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

TabPage is one named page inside Tabs.

func Tab

func Tab(title string, content Widget) *TabPage

Tab creates one named tab page.

func (*TabPage) Title

func (t *TabPage) Title() string

Title returns the text displayed on the tab.

type TableWidget

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

TableWidget displays rows of text under named columns.

func Table

func Table(columns ...string) *TableWidget

Table creates an empty table with the supplied column headings. Add data with SetRows. Empty headings receive friendly names, and a table created without headings gets one column named "Value".

func (*TableWidget) ColumnWidth

func (t *TableWidget) ColumnWidth(column, pixels int) *TableWidget

ColumnWidth sets one column's preferred width in pixels. Invalid column indices and non-positive widths are ignored.

func (*TableWidget) Columns

func (t *TableWidget) Columns() []string

Columns returns a copy of the table's column headings.

func (*TableWidget) Expand

func (t *TableWidget) Expand() *TableWidget

Expand asks the table to use available layout space.

func (*TableWidget) Height

func (t *TableWidget) Height(rows int) *TableWidget

Height sets the preferred number of visible rows.

func (*TableWidget) OnActivate

func (t *TableWidget) OnActivate(handler func(row int, values []string)) *TableWidget

OnActivate runs when a row is double-clicked or activated with Enter. The values slice is a copy and is safe for the application to keep or modify.

func (*TableWidget) OnSelect

func (t *TableWidget) OnSelect(handler func(row int, values []string)) *TableWidget

OnSelect runs when the selected row changes. The values slice is a copy and is safe for the application to keep or modify.

func (*TableWidget) Rows

func (t *TableWidget) Rows() [][]string

Rows returns a deep copy of the table data.

func (*TableWidget) Select

func (t *TableWidget) Select(row int)

Select changes the selected row. Invalid indices clear the selection. When the table is mounted, a changed selection also runs OnSelect.

func (*TableWidget) Selected

func (t *TableWidget) Selected() (row int, values []string, ok bool)

Selected returns the selected row index and a copy of its values. ok is false when the table is empty or has no selection.

func (*TableWidget) SetRows

func (t *TableWidget) SetRows(rows ...[]string) *TableWidget

SetRows replaces every row and returns the table so setup calls can be chained. Each row is copied, padded with empty cells when short, and trimmed when it contains more values than the table has columns.

type TabsWidget

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

TabsWidget displays one of several named pages at a time.

func Tabs

func Tabs(pages ...*TabPage) *TabsWidget

Tabs creates a tabbed interface. The first non-nil page is selected by default.

func (*TabsWidget) Expand

func (t *TabsWidget) Expand() *TabsWidget

Expand asks the tabs to use available layout space.

func (*TabsWidget) OnChange

func (t *TabsWidget) OnChange(handler func(index int, title string)) *TabsWidget

OnChange runs after the user or application changes the selected tab.

func (*TabsWidget) Pages

func (t *TabsWidget) Pages() []*TabPage

Pages returns a copy of the configured tab pages.

func (*TabsWidget) Select

func (t *TabsWidget) Select(index int)

Select displays the page at index. Invalid indices have no effect. When the tabs are mounted, a changed selection runs OnChange.

func (*TabsWidget) Selected

func (t *TabsWidget) Selected() (index int, title string, ok bool)

Selected returns the selected page index and title. ok is false when there are no pages.

type Task

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

Task represents reusable background work owned by an App or WindowOptions. Create one with Background.

func Background

func Background(work func(context.Context, *TaskReporter) error) *Task

Background creates stopped background work. The work function runs in a Go goroutine after Start. Include the Task in App.Tasks or WindowOptions.Tasks.

func (*Task) AutoStart

func (t *Task) AutoStart() *Task

AutoStart starts the task when its window opens. A reusable secondary window starts the task again each time it is opened.

func (*Task) Cancel

func (t *Task) Cancel()

Cancel asks running work to stop through its context. Work should observe ctx.Done or return when Report or Post returns false.

func (*Task) OnDone

func (t *Task) OnDone(callback func(error)) *Task

OnDone sets the GUI-thread callback invoked when work finishes. Cancellation is reported with context.Canceled and can be checked with errors.Is.

func (*Task) OnProgress

func (t *Task) OnProgress(callback func(TaskProgress)) *Task

OnProgress sets the GUI-thread callback for Report updates.

func (*Task) Progress

func (t *Task) Progress() TaskProgress

Progress returns the most recently delivered progress update.

func (*Task) Running

func (t *Task) Running() bool

Running reports whether work is running or queued to start with its window.

func (*Task) Start

func (t *Task) Start()

Start begins stopped work. Calling Start while the task is running has no effect. Before RunApp, it queues the task to begin when its window opens. Call task controls from Rosaline callbacks, not background goroutines.

type TaskProgress

type TaskProgress struct {
	Percent float64
	Message string
}

TaskProgress is a progress update from background work. Percent is always between zero and 100. Message is optional application-defined status text.

type TaskReporter

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

TaskReporter safely sends information from a background Task to Rosaline's GUI thread. Applications receive one from Background rather than creating it.

func (*TaskReporter) Post

func (r *TaskReporter) Post(callback func()) bool

Post schedules callback on Rosaline's GUI thread. Use it when background work has produced a result that should change application state or a widget. It returns false after the task is cancelled or its window closes.

func (*TaskReporter) Report

func (r *TaskReporter) Report(percent float64, message ...string) bool

Report sends percentage progress and optional status text to OnProgress. It returns false after the task is cancelled or its window closes.

type TextAreaWidget

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

TextAreaWidget is a multiline text input bound to a Go string.

func TextArea

func TextArea(value *string) *TextAreaWidget

TextArea creates a multiline input. The area updates value as the user types. Pass a pointer with &, as in TextArea(&notes).

func (*TextAreaWidget) Append

func (t *TextAreaWidget) Append(text string)

Append adds text at the end of the document.

func (*TextAreaWidget) Clear

func (t *TextAreaWidget) Clear()

Clear removes all text. When mounted, the change can be undone.

func (*TextAreaWidget) Copy

func (t *TextAreaWidget) Copy()

Copy copies the selected text to the platform clipboard.

func (*TextAreaWidget) Cursor

func (t *TextAreaWidget) Cursor() TextPosition

Cursor returns the current insertion position. Before the text area is mounted, the cursor is at line 1, column 0.

func (*TextAreaWidget) Cut

func (t *TextAreaWidget) Cut()

Cut copies the selected text to the platform clipboard and removes it.

func (*TextAreaWidget) Expand

func (t *TextAreaWidget) Expand() *TextAreaWidget

Expand asks the text area to use all available horizontal and vertical space. This is useful for editors and other document-style applications.

func (*TextAreaWidget) FindNext

func (t *TextAreaWidget) FindNext(query string) bool

FindNext selects the next exact occurrence of query, wrapping to the start when necessary. It returns false when query is empty or absent.

func (*TextAreaWidget) Focus

func (t *TextAreaWidget) Focus() *TextAreaWidget

Focus asks Rosaline to give this text area focus when the window opens. If several widgets request focus, the first one wins.

func (*TextAreaWidget) MarkSaved

func (t *TextAreaWidget) MarkSaved()

MarkSaved records the current text as the clean saved version. Subsequent edits make Modified return true until the text matches this version again.

func (*TextAreaWidget) Modified

func (t *TextAreaWidget) Modified() bool

Modified reports whether the current text differs from the last value recorded by MarkSaved. A newly created text area begins unmodified.

func (*TextAreaWidget) OnChange

func (t *TextAreaWidget) OnChange(handler func(string)) *TextAreaWidget

OnChange runs after the user or a mounted editing method changes the text.

func (*TextAreaWidget) OnCursorMove

func (t *TextAreaWidget) OnCursorMove(handler func(TextPosition)) *TextAreaWidget

OnCursorMove runs after keyboard or mouse input moves the insertion cursor.

func (*TextAreaWidget) Paste

func (t *TextAreaWidget) Paste()

Paste inserts text from the platform clipboard at the cursor.

func (*TextAreaWidget) Redo

func (t *TextAreaWidget) Redo()

Redo reapplies the newest available undone edit. It safely does nothing when the text area is not mounted or no redo operation is available.

func (*TextAreaWidget) ReplaceAll

func (t *TextAreaWidget) ReplaceAll(old, replacement string) int

ReplaceAll replaces every exact occurrence of old with replacement and returns the number of replacements. An empty old value changes nothing.

func (*TextAreaWidget) ReplaceSelection

func (t *TextAreaWidget) ReplaceSelection(replacement string) bool

ReplaceSelection replaces the selected text and reports whether a selection existed. The replacement becomes one normal undoable edit.

func (*TextAreaWidget) SelectAll

func (t *TextAreaWidget) SelectAll()

SelectAll selects all text in the area.

func (*TextAreaWidget) SetText

func (t *TextAreaWidget) SetText(text string)

SetText replaces all text and begins a fresh undo history. Call MarkSaved afterward when the replacement came from opening or creating a document.

func (*TextAreaWidget) Size

func (t *TextAreaWidget) Size(columns, lines int) *TextAreaWidget

Size sets the preferred width in text columns and height in text lines.

func (*TextAreaWidget) Text

func (t *TextAreaWidget) Text() string

Text returns the current text. It is also available through the pointer originally passed to TextArea.

func (*TextAreaWidget) Undo

func (t *TextAreaWidget) Undo()

Undo reverses the newest available edit. It safely does nothing when the text area is not mounted or no undo operation is available.

type TextBoxWidget

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

TextBoxWidget is a single-line text input bound to a Go string.

func TextBox

func TextBox(value *string) *TextBoxWidget

TextBox creates a single-line input. The box updates value as the user types. Pass a pointer with &, as in TextBox(&name).

func (*TextBoxWidget) Focus

func (t *TextBoxWidget) Focus() *TextBoxWidget

Focus asks Rosaline to give this text box focus when the window opens. If several widgets request focus, the first one wins.

func (*TextBoxWidget) OnChange

func (t *TextBoxWidget) OnChange(handler func(string)) *TextBoxWidget

OnChange runs after the user changes the value.

func (*TextBoxWidget) OnSubmit

func (t *TextBoxWidget) OnSubmit(handler func(string)) *TextBoxWidget

OnSubmit runs when the user presses Enter while the text box has focus.

func (*TextBoxWidget) Password

func (t *TextBoxWidget) Password() *TextBoxWidget

Password hides typed characters. The bound Go string still contains the real value so the application can validate or submit it.

func (*TextBoxWidget) Placeholder

func (t *TextBoxWidget) Placeholder(text string) *TextBoxWidget

Placeholder shows a hint while the text box is empty.

func (*TextBoxWidget) Width

func (t *TextBoxWidget) Width(columns int) *TextBoxWidget

Width sets the preferred width in text columns.

type TextPosition

type TextPosition struct {
	Line   int
	Column int
}

TextPosition identifies a place in a text area. Lines begin at 1 and columns begin at 0, matching the way most editors display cursor positions.

type TextStyle

type TextStyle struct {
	Color Color
	Size  int
}

TextStyle controls text drawn on a Canvas.

type Theme

type Theme struct {
	Background Color
	Surface    Color
	Primary    Color
	Text       Color
	Muted      Color
	Border     Color
	Danger     Color
	Success    Color
}

Theme contains semantic colors used by Rosaline widgets.

type Timer

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

Timer runs a callback later or at a regular interval while its window is open. Create timers with Every, After, or Animate, then include them in App.Timers or WindowOptions.Timers.

func After

func After(delay time.Duration, callback func()) *Timer

After creates a running one-shot timer. It calls callback once after delay, then stops. It begins when its App starts.

func Animate

func Animate(framesPerSecond int, frame func()) *Timer

Animate creates a repeating timer measured in frames per second. Use it to update drawing state, then call CanvasWidget.Redraw from the frame callback. Invalid frame rates use 60 FPS; rates above 1000 FPS are limited to 1000.

func Every

func Every(interval time.Duration, callback func()) *Timer

Every creates a running timer that calls callback repeatedly. It begins when its App starts. Durations shorter than one millisecond use one millisecond.

func (*Timer) Restart

func (t *Timer) Restart()

Restart resets the wait and starts the timer again from the beginning.

func (*Timer) Running

func (t *Timer) Running() bool

Running reports whether the timer is started. Before RunApp, true means the timer is ready to begin as soon as its App opens.

func (*Timer) Start

func (t *Timer) Start()

Start starts a stopped timer. Calling Start on a running timer has no effect. Call timer methods from Rosaline callbacks, not background goroutines.

func (*Timer) Stop

func (t *Timer) Stop()

Stop pauses a timer. A stopped repeating timer can be continued with Start.

type TreeNode

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

TreeNode is one item in a Tree. Create nodes with Node rather than filling this type manually.

func Node

func Node(label string, children ...*TreeNode) *TreeNode

Node creates one tree item. Child nodes appear beneath it. Empty labels use the friendly text "Item".

func (*TreeNode) Children

func (n *TreeNode) Children() []*TreeNode

Children returns a copy of the node's immediate child list.

func (*TreeNode) Expanded

func (n *TreeNode) Expanded() *TreeNode

Expanded asks the node to start open when the tree appears.

func (*TreeNode) IsExpanded

func (n *TreeNode) IsExpanded() bool

IsExpanded reports whether the node is currently open.

func (*TreeNode) Label

func (n *TreeNode) Label() string

Label returns the text displayed for this node.

func (*TreeNode) Value

func (n *TreeNode) Value() string

Value returns the application-defined value. It defaults to the node label.

func (*TreeNode) WithValue

func (n *TreeNode) WithValue(value string) *TreeNode

WithValue attaches an application-defined string to the node. File paths, record IDs, and other identifiers can then be read with Value in callbacks.

type TreeWidget

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

TreeWidget displays nested nodes with native expansion and selection.

func Tree

func Tree(nodes ...*TreeNode) *TreeWidget

Tree creates a native tree. The first non-nil root node is selected by default.

func (*TreeWidget) Expand

func (t *TreeWidget) Expand() *TreeWidget

Expand asks the tree to use available layout space.

func (*TreeWidget) Height

func (t *TreeWidget) Height(rows int) *TreeWidget

Height sets the preferred number of visible rows.

func (*TreeWidget) Nodes

func (t *TreeWidget) Nodes() []*TreeNode

Nodes returns a copy of the root-node list.

func (*TreeWidget) OnActivate

func (t *TreeWidget) OnActivate(handler func(node *TreeNode)) *TreeWidget

OnActivate runs when a node is double-clicked or activated with Enter.

func (*TreeWidget) OnExpand

func (t *TreeWidget) OnExpand(handler func(node *TreeNode, expanded bool)) *TreeWidget

OnExpand runs after a node is opened or closed. It is especially useful for loading children only when the user opens a node.

func (*TreeWidget) OnSelect

func (t *TreeWidget) OnSelect(handler func(node *TreeNode)) *TreeWidget

OnSelect runs when the selected node changes.

func (*TreeWidget) Select

func (t *TreeWidget) Select(node *TreeNode)

Select changes the selected node. nil or a node outside this tree clears the selection. When mounted, a changed selection also runs OnSelect.

func (*TreeWidget) Selected

func (t *TreeWidget) Selected() (node *TreeNode, ok bool)

Selected returns the selected node and whether a selection exists.

func (*TreeWidget) SetChildren

func (t *TreeWidget) SetChildren(parent *TreeNode, children ...*TreeNode)

SetChildren replaces one node's immediate children. Cycles, nil children, and repeated pointers are ignored. If a removed descendant was selected, the parent becomes selected.

func (*TreeWidget) SetExpanded

func (t *TreeWidget) SetExpanded(node *TreeNode, expanded bool)

SetExpanded opens or closes a node. Invalid nodes have no effect. A changed state runs OnExpand after the tree has been mounted.

func (*TreeWidget) SetNodes

func (t *TreeWidget) SetNodes(nodes ...*TreeNode) *TreeWidget

SetNodes replaces every root node and returns the tree so setup calls can be chained. Existing selection is kept when its node remains in the new tree.

func (*TreeWidget) Width

func (t *TreeWidget) Width(pixels int) *TreeWidget

Width sets the preferred tree-column width in pixels.

type Widget

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

Widget is anything Rosaline can place in a window or layout. Applications normally use constructor functions such as Label, Button, Column, Row, and Canvas rather than implementing Widget themselves.

func Spacer

func Spacer(width, height int) Widget

Spacer inserts a fixed amount of empty space.

type Window

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

Window is a reusable secondary-window handle. Create one with NewWindow.

func MainWindow

func MainWindow() *Window

MainWindow returns the primary application-window handle. It can be used as WindowOptions.Parent when a secondary window should belong to the main one.

func NewWindow

func NewWindow(options WindowOptions) *Window

NewWindow creates a reusable secondary window. Creation does not display it; call Show from a Rosaline callback while the application is running.

func (*Window) Close

func (w *Window) Close()

Close closes the window and its open child windows. The same Window can be shown again later. Closing MainWindow closes the entire application.

func (*Window) Focus

func (w *Window) Focus() *Window

Focus raises and focuses an open window. Closed windows are unchanged.

func (*Window) IsOpen

func (w *Window) IsOpen() bool

IsOpen reports whether the window is currently displayed.

func (*Window) SetTitle

func (w *Window) SetTitle(title string) *Window

SetTitle changes the title now and keeps it when the window is reopened. Empty titles use "Rosaline".

func (*Window) Show

func (w *Window) Show() *Window

Show opens the window. If it is already open, Show raises and focuses the existing window rather than creating a duplicate.

type WindowOptions

type WindowOptions struct {
	Title     string
	Width     int
	Height    int
	Padding   int
	Theme     Theme
	Menu      *AppMenuBar
	Timers    []*Timer
	Tasks     []*Task
	Shortcuts []KeyShortcut
	OnKeyDown func(KeyEvent)
	OnKeyUp   func(KeyEvent)
	// OnCloseRequest runs before a direct close request. Return false to keep
	// the window open. OnClose runs after the window has closed.
	OnCloseRequest func() bool
	Content        Widget
	Parent         *Window
	OnClose        func()
}

WindowOptions describes a secondary application window. Every field is optional; Rosaline supplies the same friendly defaults used by RunApp.

Directories

Path Synopsis
examples
animation command
background command
The background example renders a picture without freezing the window.
The background example renders a picture without freezing the window.
calculator command
The calculator example combines Rosaline's layout and presentation tools.
The calculator example combines Rosaline's layout and presentation tools.
canvas command
counter command
drawing command
filebrowser command
forms command
hello command
imageviewer command
keyboard command
The keyboard example combines canvas key events with window shortcuts.
The keyboard example combines canvas key events with window shortcuts.
notepad command
The Notepad example combines Rosaline's text-editing and application APIs.
The Notepad example combines Rosaline's text-editing and application APIs.
paint command
preferences command
starshower command
Starshower is a complete little vector arcade game built with Rosaline.
Starshower is a complete little vector arcade game built with Rosaline.
tasksettings command
The tasksettings example combines Rosaline's everyday controls in one small application.
The tasksettings example combines Rosaline's everyday controls in one small application.
windows command

Jump to

Keyboard shortcuts

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