Help us shape the future of Go! Take the 2026 Go Developer Survey

fluo

package module
v0.17.0 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2026 License: MIT Imports: 0 Imported by: 0

README

fluo

A retained-mode GUI toolkit for Go with its own OpenGL renderer and a classic Windows-2000 look. fluo gives a Go program a themed widget tree — layout, input routing, and data binding — over a thin OpenGL 3.3 backend. No browser engine, no native OS toolkit underneath.

Controls draw themselves from swappable design tokens, so restyling an app is a data change. Each package stands on its own, so you can pull in just the renderer or the whole stack.

Features

  • A complete control set: buttons, checkboxes, radio groups, toggle switches, text boxes, sliders, progress bars, combo boxes, tooltips, list/tree/tab views, expanders, menus, modal dialogs, toasts, and a virtualized data grid. Layout panels (stack, grid, dock, wrap, canvas), a draggable split panel, and a custom title bar for undecorated windows come with it.
  • A text box that scales from a one-line field to a small code editor: word wrap, a line-number gutter, Tab-to-indent with block indent/outdent, word-wise motion, double-click-word and triple-click-line selection, and IME input.
  • Classic Windows-2000 chrome: four-tone raised and sunken bevels, square corners, gradient title bars. The classic themes don't reach for soft effects, but the primitives are there — DrawShadow, DrawBackdropBlur, and an AcrylicSurface control built on them.
  • Light and dark themes, both driven entirely by design tokens. Roll your own by copying one and changing a few colors.
  • One- and two-way data binding between typed properties and controls, plus observable-list collection binding.
  • Virtualized list and data-grid views for large data sets.

Requirements

  • Go 1.23
  • A C compiler — the go-gl/glfw and go-gl/gl bindings use cgo
  • An OpenGL 3.3 core-profile driver

Install

go get github.com/0xdreadnaught/fluo

Quickstart

package main

import (
	"log"

	"github.com/0xdreadnaught/fluo/app"
	"github.com/0xdreadnaught/fluo/controls"
	"github.com/0xdreadnaught/fluo/core"
	"github.com/0xdreadnaught/fluo/render"
	"github.com/0xdreadnaught/fluo/text"

	"golang.org/x/image/font/gofont/goregular"
)

func main() {
	font, _ := text.Load(goregular.TTF)
	root := controls.NewTextBlock(text.NewFace(font, 16), "Hello, fluo!")

	log.Fatal(app.Run(app.Config{Title: "hello", Width: 320, Height: 200}, func(c *app.Ctx) {
		c.Input.SetRoot(root)
		core.MeasureWidget(root, c.Size)
		core.ArrangeWidget(root, render.Rect{W: c.Size.W, H: c.Size.H})
		core.RenderWidget(root, c.R)
	}))
}

examples/counter shows the same thing with a proper one-time root guard and a data-bound label.

Architecture

fluo is layered bottom to top; each layer depends only on the ones below it.

Package Role
render, render/gl Renderer interface and geometry, implemented on OpenGL 3.3
text Font loading and glyph rasterization
core Widget/Element layout engine (Measure/Arrange/Render) and Property[T]
input Hit-testing, event bubbling, capture, focus
theme Color, metric, and typography tokens (Light(), Dark())
controls The built-in widget set
bind One- and two-way binding
anim, timers Tween animation and the frame-tick timer service
app glfw window host and embeddable surface

Examples

Run any of them with go run, e.g. go run ./cmd/fluo-gallery.

Documentation

go doc ./<package> covers each package. Longer guides — controls, data binding, theming, and the renderer — live in docs/wiki.

Status

v0.15.1. Every layer is implemented, tested (headless layout and binding tests plus GL golden images that auto-skip without a GPU), and exercised together by the gallery. Known gaps:

  • The custom title bar covers Windows and Linux. There's no native macOS integration.
  • No accessibility (screen-reader) hooks yet.

See CHANGELOG.md and ROADMAP.md for the full history.

License

MIT

Documentation

Overview

Package fluo is the module root for github.com/0xdreadnaught/fluo, a retained-mode, classic Windows-styled GUI toolkit for OpenGL apps in Go. It declares no exported symbols of its own — every usable package lives in a subdirectory (render, text, core, input, theme, controls, bind, anim, timers, app) — this file exists solely to give `go doc .`/pkg.go.dev a landing-page overview, quickstart, and architecture map for the module as a whole.

Quickstart

A minimal program: load a font, build one widget, and drive it from app.Run's per-frame callback.

font, _ := text.Load(goregular.TTF)
root := controls.NewTextBlock(text.NewFace(font, 16), "Hello, fluo!")

log.Fatal(app.Run(app.Config{Title: "hello", Width: 320, Height: 200}, func(c *app.Ctx) {
	c.Input.SetRoot(root)
	core.MeasureWidget(root, c.Size)
	core.ArrangeWidget(root, render.Rect{W: c.Size.W, H: c.Size.H})
	core.RenderWidget(root, c.R)
}))

See examples/counter, examples/form, and examples/todo for complete, runnable programs, and cmd/fluo-gallery for every control composed together.

Architecture

fluo is layered bottom to top; each layer only depends on the ones below it:

render    — the Renderer interface and geometry primitives (Color/
            Point/Size/Rect); render/gl implements it on OpenGL 3.3.
text      — font loading, grayscale glyph rasterization into a
            coverage atlas, and single-line layout, on top of render.
core      — the Widget/Element layout engine (Measure/Arrange/Render)
            and the reactive Property[T].
input     — hit-testing, event bubbling, capture, and focus over a
            core.Widget tree.
theme     — the color/metric/typography token model (Light/Dark).
controls  — the built-in widget set, styled from theme and wired to
            input.
bind      — one-way/two-way binding between core.Property[T]/
            bind.List[T] and controls.
anim/     — easing/Tween animation and the frame-tick timer service
timers      controls use for caret blink, tooltip dwell, and
            cross-fades.
app       — Run/Surface, the glfw window host (or embeddable surface)
            that ties every layer above together into a running
            program.

go doc on any of the above (e.g. `go doc ./controls`) gives a one-paragraph summary of its role and key types.

Directories

Path Synopsis
Package anim provides easing functions and a frame-driven Tween that interpolates a normalized progress value 0→1 over a duration, using a timers.Queue as its clock.
Package anim provides easing functions and a frame-driven Tween that interpolates a normalized progress value 0→1 over a duration, using a timers.Queue as its clock.
Package app provides fluo's desktop window host: Run opens a GLFW window with an OpenGL 3.3 core context, wires up render/gl's Renderer, and drives a frame(*Ctx) callback every vsync until the window closes.
Package app provides fluo's desktop window host: Run opens a GLFW window with an OpenGL 3.3 core context, wires up render/gl's Renderer, and drives a frame(*Ctx) callback every vsync until the window closes.
Package bind connects core.Property[T] values to controls: one-way binding pushes a property's value into a control on every change, and two-way binding additionally OWNS a control's OnChanged slot so user edits flow back into the property.
Package bind connects core.Property[T] values to controls: one-way binding pushes a property's value into a control on every change, and two-way binding additionally OWNS a control's OnChanged slot so user edits flow back into the property.
cmd
fluo-demo command
Command fluo-demo is a minimal demo host exercising every fluo primitive: rounded rects, stroke, shadow, SDF text, and a manually hand-rolled hover/press-reactive button (this becomes controls.Button in Phase 5).
Command fluo-demo is a minimal demo host exercising every fluo primitive: rounded rects, stroke, shadow, SDF text, and a manually hand-rolled hover/press-reactive button (this becomes controls.Button in Phase 5).
fluo-editor command
Command fluo-editor is a standalone code-editor demo built on fluo's multi-line TextBox: a monospace editor with a line-number gutter, word-wrap OFF (long lines scroll horizontally), tab-to-indent, mouse-wheel scrolling, and a live Ln/Col status.
Command fluo-editor is a standalone code-editor demo built on fluo's multi-line TextBox: a monospace editor with a line-number gutter, word-wrap OFF (long lines scroll horizontally), tab-to-indent, mouse-wheel scrolling, and a live Ln/Col status.
fluo-gallery command
Command fluo-gallery is the widget gallery: it grows a page per control as phases land.
Command fluo-gallery is the widget gallery: it grows a page per control as phases land.
Package controls provides fluo's built-in widget set, all styled from theme.Active() rather than hard-coded values.
Package controls provides fluo's built-in widget set, all styled from theme.Active() rather than hard-coded values.
Package core is fluo's layout engine and widget foundation.
Package core is fluo's layout engine and widget foundation.
examples
counter command
Command counter is fluo's smallest example: a Button increments a core.Property[int], and a TextBlock shows the current count via bind.OneWay.
Command counter is fluo's smallest example: a Button increments a core.Property[int], and a TextBlock shows the current count via bind.OneWay.
form command
Command form demonstrates binding several controls to one small model: a TextBox, CheckBox, and Slider each two-way bound to a field of model, and a TextBlock one-way bound to all three, echoing the combined state on every change.
Command form demonstrates binding several controls to one small model: a TextBox, CheckBox, and Slider each two-way bound to a field of model, and a TextBlock one-way bound to all three, echoing the combined state on every change.
todo command
Command todo demonstrates list binding: a TextBox + "Add" Button append to a bind.List[string], a ListView renders it, and a TextBlock tracks the item count — all driven off the same List, with no manual widget rebuilding.
Command todo demonstrates list binding: a TextBox + "Add" Button append to a bind.List[string], a ListView renders it, and a TextBlock tracks the item count — all driven off the same List, with no manual widget rebuilding.
Package input turns raw pointer/keyboard/wheel events into dispatch against a core.Widget tree.
Package input turns raw pointer/keyboard/wheel events into dispatch against a core.Widget tree.
Package render defines fluo's abstract 2D drawing surface: the Renderer interface (FillRect/FillRoundedRect/StrokeRoundedRect/DrawShadow/ DrawBackdropBlur/DrawQuad/DrawGlyphs plus texture management and clip push/pop) and the plain-data geometry types every other package builds on — Point, Size, Rect (with Thickness-based Inset), and Color (0..1 float components, with RGB/RGBA byte-based constructors).
Package render defines fluo's abstract 2D drawing surface: the Renderer interface (FillRect/FillRoundedRect/StrokeRoundedRect/DrawShadow/ DrawBackdropBlur/DrawQuad/DrawGlyphs plus texture management and clip push/pop) and the plain-data geometry types every other package builds on — Point, Size, Rect (with Thickness-based Inset), and Color (0..1 float components, with RGB/RGBA byte-based constructors).
gl
Package gl implements render.Renderer on top of OpenGL 3.3 core.
Package gl implements render.Renderer on top of OpenGL 3.3 core.
gl/gltest
Package gltest is a golden-image test harness for OpenGL rendering code.
Package gltest is a golden-image test harness for OpenGL rendering code.
Package text provides pure-Go font loading, glyph rasterization, and single-line text layout, built on golang.org/x/image/font/sfnt.
Package text provides pure-Go font loading, glyph rasterization, and single-line text layout, built on golang.org/x/image/font/sfnt.
Package theme holds fluo's classic Windows-2000-inspired design tokens.
Package theme holds fluo's classic Windows-2000-inspired design tokens.
Package timers provides a frame-driven timer service: Queue holds a set of pending Timer callbacks, and the host calls Advance(now) once per frame to fire whichever are due, in due-time order.
Package timers provides a frame-driven timer service: Queue holds a set of pending Timer callbacks, and the host calls Advance(now) once per frame to fire whichever are due, in due-time order.

Jump to

Keyboard shortcuts

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