pub trait OverlayView<R> {
fn update(&mut self, _config: &mut crate::config::ClinConfig) {}
fn render(
&mut self,
frame: &mut ratatui::Frame,
area: ratatui::layout::Rect,
theme: &crate::app_theme::AppThemeColors,
config: &crate::config::ClinConfig,
);
fn handle_event(
&mut self,
event: crossterm::event::Event,
terminal: &ratatui::Terminal<ratatui::backend::CrosstermBackend<std::io::Stdout>>,
config: &mut crate::config::ClinConfig,
) -> anyhow::Result<Option<R>>;
fn title(&self) -> String;
fn render_title(
&self,
frame: &mut ratatui::Frame,
area: ratatui::layout::Rect,
theme: &crate::app_theme::AppThemeColors,
) {
crate::ui::draw_view_title_bar(frame, area, &self.title(), theme);
}
}
pub fn run_overlay<V, R>(
terminal: &mut ratatui::Terminal<ratatui::backend::CrosstermBackend<std::io::Stdout>>,
view: &mut V,
config: &mut crate::config::ClinConfig,
theme: &crate::app_theme::AppThemeColors,
poll_rate: std::time::Duration,
) -> anyhow::Result<R>
where
V: OverlayView<R>,
{
loop {
view.update(config);
terminal.draw(|f| {
let outer = ratatui::layout::Layout::default()
.direction(ratatui::layout::Direction::Vertical)
.constraints([
ratatui::layout::Constraint::Length(1),
ratatui::layout::Constraint::Min(0),
])
.split(f.area());
view.render_title(f, outer[0], theme);
view.render(f, outer[1], theme, config);
})?;
if crossterm::event::poll(poll_rate)? {
match crossterm::event::read()? {
crossterm::event::Event::Resize(_, _) => {
terminal.autoresize()?;
let _ = terminal.clear();
}
ev => {
if let Some(result) = view.handle_event(ev, terminal, config)? {
return Ok(result);
}
}
}
}
}
}