Skip to content

Latest commit

 

History

History
191 lines (135 loc) · 4.86 KB

File metadata and controls

191 lines (135 loc) · 4.86 KB

bgraph Quickstart

Get btop-style Braille graphs in your terminal app in under 5 minutes.

1. Add Dependencies (30 seconds)

[dependencies]
bgraph = "0.1"
ratatui = "0.29"
crossterm = "0.28"

2. Static Graph (2 minutes)

Display a sine wave with one data source:

use bgraph::{DataSource, Graph};
use ratatui::style::{Color, Style};

// Define your data source
struct SineWave;
impl DataSource for SineWave {
    fn sample(&self, x: f32) -> f32 {
        (x * 6.28).sin()
    }
}

// In your ratatui draw loop:
let graph = Graph::new(&SineWave)
    .x_range(0.0, 2.0)
    .y_range(-1.2, 1.2)
    .style(Style::default().fg(Color::Cyan));

frame.render_widget(graph, area);

Or use a closure:

use bgraph::{FnDataSource, Graph};

let data = vec![10.0, 45.0, 80.0, 60.0, 30.0];
let source = FnDataSource::new(move |x| {
    let i = (x * (data.len() - 1) as f32) as usize;
    data.get(i).copied().unwrap_or(0.0)
});

frame.render_widget(Graph::new(&source).x_range(0.0, 1.0), area);

3. Scrolling Time Series (1 minute)

Real-time scrolling graph with O(1) updates:

use bgraph::{TimeSeries, TimeSeriesState};

// Create state once (keeps last 100 points, Y: 0-100)
let mut state = TimeSeriesState::with_range(100, 0.0, 100.0);

// In your update loop:
state.push(new_value);  // O(1) - oldest point auto-removed

// In your draw loop:
let graph = TimeSeries::new();
frame.render_stateful_widget(graph, area, &mut state);

4. Heat-Map Colors (30 seconds)

Add value-based coloring with smooth RGB interpolation:

use bgraph::ColorGradient;
use ratatui::style::Color;

let gradient = ColorGradient::new()
    .add_stop(0.0, Color::Rgb(0, 150, 0))    // Green (low)
    .add_stop(0.5, Color::Rgb(255, 255, 0))  // Yellow (mid)
    .add_stop(1.0, Color::Rgb(255, 0, 0));   // Red (high)

let graph = TimeSeries::new().gradient(gradient);

5. Multi-Series with Legend (1 minute)

Overlay multiple data series (e.g., CPU cores):

use bgraph::{MultiTimeSeries, MultiTimeSeriesState, LegendPosition};

// 4 series, 100 points each, Y: 0-100
let mut state = MultiTimeSeriesState::with_range(4, 100, 0.0, 100.0);
state.set_label(0, "Core 0".to_string());
state.set_label(1, "Core 1".to_string());
// ...

// Update each series
state.push(0, core0_value);
state.push(1, core1_value);

// Render with legend
let graph = MultiTimeSeries::new()
    .show_legend(true)
    .legend_position(LegendPosition::TopRight);

frame.render_stateful_widget(graph, area, &mut state);

6. Dual Graphs (30 seconds)

Two independent graphs in one widget - horizontal or vertical split:

use bgraph::{DualTimeSeries, DualTimeSeriesState, SplitDirection};

let mut state = DualTimeSeriesState::with_ranges(
    100,                    // capacity
    (0.0, 100.0),          // first Y-range
    (0.0, 100.0),          // second Y-range
);

state.push(val1, val2);

// Horizontal: left | right (default)
let graph = DualTimeSeries::new().split_ratio(0.5);

// Vertical: top / bottom
let graph = DualTimeSeries::new()
    .split_direction(SplitDirection::Vertical)
    .split_ratio(0.5);

frame.render_stateful_widget(graph, area, &mut state);

7. Clean Scale Divisions (optional)

Snap graph height for mathematically clean scale markers:

use bgraph::snap_graph_area;

// Snap area to nice height (10, 20, etc.) and center vertically
let graph_area = snap_graph_area(inner_area);
frame.render_stateful_widget(graph, graph_area, &mut state);

Result: If your layout gives 12 rows, snap_graph_area returns 10 rows centered. Each row = exactly 10% of range, each braille sub-level = 2%. The 50% mark lands exactly on a row boundary.

Override: Don't call snap functions if you want full resolution.


Run the Demo

See all features in action:

cargo run --example demo

Common Patterns

Use Case Widget State
Static function plot Graph None (Widget)
Real-time scrolling TimeSeries TimeSeriesState
Compare two metrics DualTimeSeries DualTimeSeriesState
Multiple overlays MultiTimeSeries MultiTimeSeriesState

API at a Glance

// All time-series state has the same pattern:
let mut state = TimeSeriesState::with_range(capacity, y_min, y_max);
state.push(value);     // Add new point
state.clear();         // Reset

// All widgets support:
.style(Style::default().fg(Color::Cyan))  // Base color
.gradient(ColorGradient::new()...)        // Heat-map
.render_mode(RenderMode::Block)           // Fallback mode

Next Steps

  • See BGRAPH_CHEATSHEET.md for complete API reference
  • See CHANGELOG.md for release notes
  • Run cargo doc --open for full documentation