# Framebuffer Display API A high-level Go package for easily creating text-based status displays on Linux framebuffers. Perfect for system monitors, embedded displays, IoT dashboards, and more. ## API Design Concepts Below are four different API design approaches for creating framebuffer displays. Each example shows how you might implement a system status display. ### Concept 1: Builder Pattern ```go package main import ( "time" fb "github.com/example/framebufferdisplay" ) func main() { // Create and configure display with fluent interface display := fb.New(). AutoDetect(). // Find first available framebuffer WithFont("IBM Plex Mono", 14). // Default font WithUpdateInterval(time.Second). // Auto-refresh rate Build() defer display.Close() // Define the layout display.Layout(func(canvas *fb.Canvas) { // Header section canvas.Section("header", fb.TopCenter). Font("IBM Plex Mono", 24). Color(fb.White). Text("System Status") // System info section canvas.Section("info", fb.TopLeft). Margin(20). Rows( fb.Row().Label("Hostname:").Value(getHostname()), fb.Row().Label("Uptime:").Value(getUptime()), fb.Row().Label("Load:").Value(getLoad()).Color(fb.Red), ) // CPU meters canvas.Section("cpu", fb.CenterLeft). Title("CPU Usage"). Meters(getCPUMeters()...) // Memory bar canvas.Section("memory", fb.BottomLeft). Title("Memory"). ProgressBar(getMemoryPercent(), fb.Green) }) // Start the display loop display.Run() } ``` ### Concept 2: Declarative/React-like ```go package main import ( fb "github.com/example/framebufferdisplay" ) type SystemStatus struct { fb.Component hostname string uptime time.Duration } func (s *SystemStatus) Render() fb.Element { return fb.Screen( fb.Header( fb.Text("System Status"). Font("IBM Plex Mono", 48). Color(fb.RGB(100, 200, 255)), ), fb.Grid(fb.GridOptions{Columns: 2, Gap: 20}, // Left column fb.Column( fb.Card( fb.Title("System Info"), fb.List( fb.ListItem("Hostname", s.hostname), fb.ListItem("Uptime", formatDuration(s.uptime)), fb.ListItem("OS", getOS()), ), ), fb.Card( fb.Title("Network"), fb.List(getNetworkInfo()...), ), ), // Right column fb.Column( fb.Card( fb.Title("CPU Usage"), fb.BarChart(getCPUData(), fb.ChartOptions{ Height: 200, Color: fb.Gradient(fb.Green, fb.Red), }), ), fb.Card( fb.Title("Memory"), fb.CircularProgress(getMemoryPercent(), fb.Blue), fb.Text(getMemoryDetails()).Size(12), ), ), ), ) } func main() { fb.Run(&SystemStatus{}) } ``` ### Concept 3: Immediate Mode ```go package main import ( fb "github.com/example/framebufferdisplay" ) func main() { // Auto-detect and initialize ctx := fb.Init() defer ctx.Close() // Main render loop ctx.Loop(func(d *fb.Draw) { // Clear with background d.Clear(fb.Black) // Draw header d.SetFont("IBM Plex Mono Bold", 36) d.SetColor(fb.White) d.TextCenter(d.Width/2, 50, "System Monitor") // System info box d.SetFont("IBM Plex Mono", 14) d.Box(20, 100, 400, 200, fb.Gray) d.SetColor(fb.Green) d.Text(30, 120, "Hostname: %s", getHostname()) d.Text(30, 140, "Uptime: %s", getUptime()) d.Text(30, 160, "Load: %.2f %.2f %.2f", getLoad()) // CPU visualization cpus := getCPUPercents() for i, cpu := range cpus { y := 320 + i*30 d.Text(30, y, "CPU%d", i) d.ProgressBar(80, y-10, 300, 20, cpu, fb.Heat(cpu)) } // Memory meter mem := getMemoryPercent() d.SetFont("IBM Plex Mono", 18) d.Text(30, 500, "Memory: %.1f%%", mem) d.Gauge(30, 520, 350, 40, mem, fb.Blue) // Update display d.Present() }) } ``` ### Concept 4: Template/Widget-based ```go package main import ( fb "github.com/example/framebufferdisplay" ) func main() { // Create display with auto-detection display := fb.NewDisplay() // Create a dashboard with predefined widgets dashboard := fb.Dashboard{ Title: "System Status", Theme: fb.Themes.Dark, Layout: fb.GridLayout(3, 3), // 3x3 grid Widgets: []fb.Widget{ // Row 1 fb.BigNumber{ GridPos: fb.Pos(0, 0), Label: "CPU Temp", Value: getCPUTemp, Unit: "°C", Color: fb.TempColor, // Auto-colors based on value }, fb.LineGraph{ GridPos: fb.Pos(1, 0).Span(2, 1), // Spans 2 columns Title: "CPU History", Duration: 5 * time.Minute, Source: streamCPUData, }, // Row 2 fb.InfoTable{ GridPos: fb.Pos(0, 1), Rows: []fb.TableRow{ {"Host", getHostname}, {"Kernel", getKernel}, {"Uptime", getUptime}, }, }, fb.MultiMeter{ GridPos: fb.Pos(1, 1), Title: "CPU Cores", Meters: getCPUCoreMeters, Compact: true, }, fb.PieChart{ GridPos: fb.Pos(2, 1), Title: "Disk Usage", Data: getDiskUsage, }, // Row 3 fb.MemoryWidget{ GridPos: fb.Pos(0, 2).Span(2, 1), ShowDetails: true, }, fb.NetworkTraffic{ GridPos: fb.Pos(2, 2), Interface: "eth0", }, }, // Optional: Add alerts Alerts: []fb.Alert{ fb.Alert{ Condition: func() bool { return getCPUTemp() > 80 }, Message: "High CPU Temperature!", Color: fb.Red, }, }, } // Run the dashboard display.RunDashboard(dashboard) } ``` ## Key Features Across All Concepts - **Auto-detection**: Automatically finds and configures the first available framebuffer - **Resolution independence**: Layouts adapt to the detected resolution - **Font management**: Easy font loading and sizing - **Color utilities**: Named colors, RGB, gradients, and conditional coloring - **Common widgets**: Progress bars, meters, graphs, tables, etc. - **Refresh control**: Configurable update intervals or manual control - **Error handling**: Graceful fallbacks for missing fonts, permissions, etc. ## Design Considerations Each approach offers different benefits: 1. **Builder Pattern**: Familiar to Go developers, good for static layouts 2. **Declarative**: Clean separation of data and presentation, easy to test 3. **Immediate Mode**: Simple and direct, good for dynamic content 4. **Widget-based**: Highest level abstraction, fastest to build common dashboards The final API could combine elements from multiple approaches, such as using the widget system from Concept 4 with the immediate mode drawing primitives from Concept 3 for custom widgets.