use std::collections::HashMap;
use ratatui::{Frame, layout::Rect};
use crate::core::model::component_context::ComponentContext;
pub trait TuiComponent: Send + Sync + 'static {
fn name(&self) -> &'static str;
fn render(
&self,
ctx: &ComponentContext,
area: Rect,
frame: &mut Frame,
render_child: &mut dyn FnMut(&str, Rect, &mut Frame, &str),
measure_child: &mut dyn FnMut(&str, &str, u16) -> Option<u16>,
);
fn natural_height(
&self,
_ctx: &ComponentContext,
_available_width: u16,
_measure_child: &mut dyn FnMut(&str, &str, u16) -> Option<u16>,
) -> Option<u16> {
None
}
fn handle_event(
&self,
_ctx: &ComponentContext,
_event: &crate::core::event::InputEvent,
) -> Option<crate::core::event::EventResult> {
None
}
}
impl<T: TuiComponent> crate::core::catalog::component_api::ComponentApi for T {
fn name(&self) -> &'static str {
<Self as TuiComponent>::name(self)
}
}
pub type ComponentRegistry = HashMap<String, Box<dyn TuiComponent>>;
pub fn build_registry(components: Vec<Box<dyn TuiComponent>>) -> ComponentRegistry {
components
.into_iter()
.map(|c| {
let name = c.name().to_string();
(name, c)
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
struct FakeComponent;
impl TuiComponent for FakeComponent {
fn name(&self) -> &'static str {
"Fake"
}
fn render(
&self,
_ctx: &ComponentContext,
_area: Rect,
_frame: &mut Frame,
_render_child: &mut dyn FnMut(&str, Rect, &mut Frame, &str),
_measure_child: &mut dyn FnMut(&str, &str, u16) -> Option<u16>,
) {
}
}
#[test]
fn build_registry_keys_by_name() {
let registry = build_registry(vec![Box::new(FakeComponent)]);
assert!(registry.contains_key("Fake"));
}
}