use std::sync::{atomic::AtomicBool, mpsc, Arc};
use ratatui::widgets::{Block, Widget};
use super::{
app::{pages::Page, SharedState},
events::Event,
};
pub trait BorderedWidget {
fn render_with_block(
self,
area: ratatui::prelude::Rect,
buf: &mut ratatui::prelude::Buffer,
block: Block<'_>,
) where
Self: Sized;
}
pub trait WidgetHeight {
fn height_used(&self, area: ratatui::prelude::Rect) -> u16;
}
pub trait CustomRender<Args = ()> {
#[allow(dead_code)]
fn render(
&self,
area: ratatui::prelude::Rect,
buf: &mut ratatui::prelude::Buffer,
args: Args,
) -> ratatui::prelude::Rect;
}
pub trait RectUtil {
fn consume_height(self, height: u16) -> crate::Result<ratatui::prelude::Rect>;
fn change_height(self, height: u16) -> ratatui::prelude::Rect;
fn margin_h(self, m: u16) -> ratatui::prelude::Rect;
fn margin_top(self, m: u16) -> ratatui::prelude::Rect;
fn margin_down(self, m: u16) -> ratatui::prelude::Rect;
fn expand_vertical(self, m: u16) -> ratatui::prelude::Rect;
fn block_inner(self) -> ratatui::prelude::Rect;
}
#[derive(Default)]
pub struct HandleResult {
pub page_pops: usize,
pub page_inserts: Vec<Page>,
pub esc_ignores: usize,
pub reload: bool,
pub refresh_assets: bool,
}
impl HandleResult {
pub fn merge(&mut self, other: HandleResult) {
self.page_pops += other.page_pops;
self.page_inserts.extend(other.page_inserts);
self.esc_ignores += other.esc_ignores;
self.reload |= other.reload;
self.refresh_assets |= other.refresh_assets;
}
}
pub trait Component {
fn reload(&mut self, _shared_state: &SharedState) -> crate::Result<()> {
Ok(())
}
fn text_input_mut(&mut self) -> Option<&mut String> {
None
}
async fn exit_threads(&mut self) {}
fn set_focus(&mut self, _focus: bool) {}
fn handle_event(
&mut self,
event: &Event,
area: ratatui::prelude::Rect,
transmitter: &mpsc::Sender<Event>,
shutdown_signal: &Arc<AtomicBool>,
shared_state: &SharedState,
) -> crate::Result<HandleResult>;
fn render_component(
&self,
area: ratatui::prelude::Rect,
buf: &mut ratatui::prelude::Buffer,
shared_state: &SharedState,
) -> ratatui::prelude::Rect
where
Self: Sized;
fn render_component_with_block(
&self,
area: ratatui::prelude::Rect,
buf: &mut ratatui::prelude::Buffer,
block: Block<'_>,
shared_state: &SharedState,
) -> ratatui::prelude::Rect
where
Self: Sized,
{
let inner_area = block.inner(area);
block
.style(&shared_state.theme)
.border_type((&shared_state.theme).into())
.render(area, buf);
self.render_component(inner_area, buf, shared_state);
area
}
}