checkpointing, heavy dev
This commit is contained in:
280
internal/framebufferdisplay/README.md
Normal file
280
internal/framebufferdisplay/README.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user