mod support;
use gpui::{
App, Bounds, Context, Render, Window, WindowBounds, WindowOptions, div, prelude::*, px, size,
};
use ruviz::{data::StreamingXY, prelude::*};
use ruviz_gpui::{PerformancePreset, RuvizPlot, plot_builder};
use std::{env, time::Duration};
use support::{application, exit_on_window_open_failure, sleep};
struct StreamingEmbedDemo {
plot: gpui::Entity<RuvizPlot>,
}
impl StreamingEmbedDemo {
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let producer_interval_ms = env::args()
.skip(1)
.find_map(parse_interval_arg)
.unwrap_or(16);
let stream = StreamingXY::new(2_048);
stream.push_many((0..240).map(|i| {
let x = i as f64 * 0.02;
(x, x.sin())
}));
let plot: Plot = Plot::new()
.line_streaming(&stream)
.title("Streaming GPUI Embed")
.xlabel("t")
.ylabel("signal")
.into();
let plot = plot_builder(plot)
.interactive()
.performance_preset(PerformancePreset::Interactive)
.build(cx);
window
.spawn(cx, {
let stream = stream.clone();
async move |_| {
let mut t = 240.0 * 0.02;
loop {
sleep(Duration::from_millis(producer_interval_ms)).await;
stream.push(t, (t * 1.5).sin());
t += 0.02;
}
}
})
.detach();
window
.spawn(cx, {
let plot = plot.clone();
async move |cx| loop {
sleep(Duration::from_secs(1)).await;
let plot = plot.clone();
cx.on_next_frame(move |_, cx| {
let plot = plot.read(cx);
let stats = plot.stats();
println!(
"producer_ms={} backend={:?} render_fps={:.1} display_hz_est={:.1} render_avg_ms={:.2} present_avg_ms={:.2}",
producer_interval_ms,
stats.active_backend,
stats.render.current_fps,
stats.presentation.current_fps,
stats.render.average_frame_time.as_secs_f64() * 1000.0,
stats.presentation.average_present_interval.as_secs_f64() * 1000.0,
);
});
}
})
.detach();
Self { plot }
}
}
fn parse_interval_arg(arg: String) -> Option<u64> {
if let Some(value) = arg.strip_prefix("--interval-ms=") {
value.parse().ok()
} else {
arg.parse().ok()
}
}
impl Render for StreamingEmbedDemo {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div().size_full().p_4().child(self.plot.clone())
}
}
fn main() {
application().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(960.0), px(640.0)), cx);
exit_on_window_open_failure(
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|window, cx| cx.new(|cx| StreamingEmbedDemo::new(window, cx)),
),
"streaming embed",
);
cx.activate(true);
});
}