feat(example): debounce, top right corner performance info and update on resize
This commit is contained in:
+45
-1
@@ -1,6 +1,10 @@
|
|||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crossterm::event::{Event, KeyCode, MouseEventKind};
|
use crossterm::event::{Event, KeyCode, MouseEventKind};
|
||||||
use ratatui::backend::{Backend, CrosstermBackend};
|
use ratatui::backend::{Backend, CrosstermBackend};
|
||||||
|
use ratatui::layout::Rect;
|
||||||
use ratatui::style::{Color, Modifier, Style};
|
use ratatui::style::{Color, Modifier, Style};
|
||||||
|
use ratatui::text::Span;
|
||||||
use ratatui::widgets::{Block, Scrollbar, ScrollbarOrientation};
|
use ratatui::widgets::{Block, Scrollbar, ScrollbarOrientation};
|
||||||
use ratatui::{Frame, Terminal};
|
use ratatui::{Frame, Terminal};
|
||||||
use tui_tree_widget::{Tree, TreeItem, TreeState};
|
use tui_tree_widget::{Tree, TreeItem, TreeState};
|
||||||
@@ -133,8 +137,17 @@ fn main() -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> std::io::Result<()> {
|
fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> std::io::Result<()> {
|
||||||
|
const DEBOUNCE: Duration = Duration::from_millis(20); // 50 FPS
|
||||||
|
|
||||||
|
let before = Instant::now();
|
||||||
terminal.draw(|frame| app.draw(frame))?;
|
terminal.draw(|frame| app.draw(frame))?;
|
||||||
|
let mut last_render_took = before.elapsed();
|
||||||
|
|
||||||
|
let mut debounce: Option<Instant> = None;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
let timeout = debounce.map_or(DEBOUNCE, |start| DEBOUNCE.saturating_sub(start.elapsed()));
|
||||||
|
if crossterm::event::poll(timeout)? {
|
||||||
let update = match crossterm::event::read()? {
|
let update = match crossterm::event::read()? {
|
||||||
Event::Key(key) => match key.code {
|
Event::Key(key) => match key.code {
|
||||||
KeyCode::Char('q') => return Ok(()),
|
KeyCode::Char('q') => return Ok(()),
|
||||||
@@ -155,10 +168,41 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> std::io::Res
|
|||||||
MouseEventKind::ScrollUp => app.state.scroll_up(1),
|
MouseEventKind::ScrollUp => app.state.scroll_up(1),
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
|
Event::Resize(_, _) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if update {
|
if update {
|
||||||
terminal.draw(|frame| app.draw(frame))?;
|
debounce.get_or_insert_with(Instant::now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if debounce.is_some_and(|debounce| debounce.elapsed() > DEBOUNCE) {
|
||||||
|
let before = Instant::now();
|
||||||
|
terminal.draw(|frame| {
|
||||||
|
app.draw(frame);
|
||||||
|
|
||||||
|
// Performance info in top right corner
|
||||||
|
{
|
||||||
|
let text = format!(
|
||||||
|
" {} {last_render_took:?} {:.1} FPS",
|
||||||
|
frame.count(),
|
||||||
|
1.0 / last_render_took.as_secs_f64()
|
||||||
|
);
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
let area = Rect {
|
||||||
|
y: 0,
|
||||||
|
height: 1,
|
||||||
|
x: frame.size().width.saturating_sub(text.len() as u16),
|
||||||
|
width: text.len() as u16,
|
||||||
|
};
|
||||||
|
frame.render_widget(
|
||||||
|
Span::styled(text, Style::new().fg(Color::Black).bg(Color::Gray)),
|
||||||
|
area,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
last_render_took = before.elapsed();
|
||||||
|
|
||||||
|
debounce = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user