A Go-based UI library for building graphical interfaces on retro gaming handhelds that support SDL2.
🇮🇹 (Chase, Grey, & HBO Home Entertainment, 1999–2007) 🇮🇹
- Type-safe FSM navigation - Context-based finite state machine for multiscreen flows
- Rich UI components - Lists, keyboards, dialogs, detail screens, and more
- Advanced input handling - Chord/sequence detection, configurable button mapping
- Thread-safe updates - Atomic operations for progress bars, status text, visibility
- Responsive design - Automatic scaling based on screen resolution
- Image support - PNG, JPEG, and SVG rendering with scaling
brew install sdl2 sdl2_image sdl2_ttfgo get github.com/BrandonKowalski/gabagool/v2package main
import "github.com/BrandonKowalski/gabagool/v2"
func main() {
gabagool.Init(gabagool.Options{
WindowTitle: "My App",
ShowBackground: true,
IsNextUI: true,
})
defer gabagool.Close()
// Create a simple list
list := gabagool.NewList(gabagool.ListOptions{
Title: "Main Menu",
Items: []gabagool.ListItem{
{Label: "Option 1"},
{Label: "Option 2"},
{Label: "Option 3"},
},
})
// Run the FSM
fsm := gabagool.NewFSM()
fsm.AddNode("main", list)
fsm.Run("main")
}Scrollable list with multi-select, reordering, and customizable appearance.
Rich content display with slideshows, metadata sections, descriptions, and images.
Text input with multiple layouts (QWERTY, URL-optimized, numeric) and symbol modes.
Settings menu with toggles, text input, color pickers, and clickable items.
Dialog with customizable confirm/cancel buttons and optional imagery.
Multiple choice dialog with descriptions for each option.
Loading screen for async operations with optional progress bar.
Hexagonal grid color selector with 25 distinguishable colors.
Multi-threaded downloads with progress tracking and speed calculation.
Top-right display for clock, battery, WiFi, and custom icons.
Gabagool abstracts physical controller inputs into virtual buttons.
This can be controlled by mapping files.
// Chord: buttons pressed simultaneously
processor.AddChord([]constants.VirtualButton{constants.L1, constants.R1}, func () {
// triggered when L1+R1 pressed together
})
// Sequence: buttons pressed in order
processor.AddSequence([]constants.VirtualButton{constants.A, constants.B, constants.A}, func () {
// triggered after A -> B -> A sequence
})