use std::collections::VecDeque;
use web_time::Instant;
use crate::system::SYSTEM_COLUMNS;
use crate::viz::bars::bars_row;
use crate::viz::flame::flame_chart;
use crate::viz::metric::{LABEL_COL_W, Metric, RowView, STAT_COL_W, metric_row};
use crate::viz::state::PanelState;
pub fn show<R>(
ui: &mut egui::Ui,
state: &mut PanelState,
history: &VecDeque<R>,
metrics: &[Metric<R>],
) {
let started = Instant::now();
header_row(ui, state);
bars_row(ui, state);
ui.separator();
let frame_view = state.view.lock();
flame_chart::<R>(
ui,
&frame_view,
state.system.len(),
state.pinned,
state.selection,
&mut state.flame_view,
);
drop(frame_view);
ui.separator();
let plot_w = (ui.available_width() - LABEL_COL_W - STAT_COL_W - 16.0).max(120.0);
let view = RowView {
pinned: state.pinned,
selection: state.selection,
plot_w,
history_capacity: state.config.history_capacity,
};
let load_ms = state.profiler_load_ns / 1e6;
for c in SYSTEM_COLUMNS {
let m = Metric::new(c.name, c.get, c.unit).describe(c.description);
let show_load = state.show_profiler_load && c.name == "frame_ms";
metric_row(ui, &m, &state.system, view, show_load.then_some(load_ms));
}
for m in metrics {
metric_row(ui, m, history, view, None);
}
state.record_render_ns(started.elapsed().as_nanos() as u64);
}
fn header_row(ui: &mut egui::Ui, state: &mut PanelState) {
ui.horizontal(|ui| {
let paused = state.is_paused();
let label = if paused { "▶ resume" } else { "⏸ pause" };
if ui.small_button(label).clicked() {
state.toggle_pause();
}
ui.label(if paused {
"paused · click a bar to inspect · shift-drag to zoom a range · resume to follow"
} else {
"live · click a bar to pause & inspect · shift-drag to zoom a range"
});
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
if ui
.selectable_label(state.show_profiler_load, "⚙ profiler")
.on_hover_text("annotate frame_ms with vor's own per-frame cost (tick + render)")
.clicked()
{
state.toggle_profiler_load();
}
});
});
}