use std::collections::HashMap;
use ratatui::{
Frame,
layout::Rect,
widgets::{Block, Paragraph},
};
use crate::core::catalog::function_api::FunctionImplementation;
use crate::core::catalog::Catalog;
use crate::core::model::component_context::ComponentContext;
use crate::core::model::components_model::SurfaceComponentsModel;
use crate::core::model::data_model::DataModel;
use crate::core::model::surface_model::SurfaceModel;
use super::component_impl::ComponentRegistry;
pub struct SurfaceRenderer<'a> {
surface: &'a SurfaceModel,
registry: &'a ComponentRegistry,
catalog: &'a Catalog,
}
impl<'a> SurfaceRenderer<'a> {
pub fn new(
surface: &'a SurfaceModel,
registry: &'a ComponentRegistry,
catalog: &'a Catalog,
) -> Self {
Self {
surface,
registry,
catalog,
}
}
pub fn render(&self, frame: &mut Frame, area: Rect) {
let data_model = self.surface.data_model.borrow();
let components = self.surface.components.borrow();
if !components.contains("root") {
let widget = Paragraph::new("No root component").block(Block::bordered());
frame.render_widget(widget, area);
return;
}
render_node(
"root",
"",
area,
frame,
&data_model,
&components,
self.registry,
&self.catalog.functions,
);
}
pub fn render_child_by_id(
&self,
child_id: &str,
base_path: &str,
area: Rect,
frame: &mut Frame,
data_model: &DataModel,
components: &SurfaceComponentsModel,
) {
render_node(
child_id,
base_path,
area,
frame,
data_model,
components,
self.registry,
&self.catalog.functions,
);
}
}
fn render_node(
component_id: &str,
base_path: &str,
area: Rect,
frame: &mut Frame,
data_model: &DataModel,
components: &SurfaceComponentsModel,
registry: &ComponentRegistry,
functions: &HashMap<String, Box<dyn FunctionImplementation>>,
) {
let comp_model = match components.get(component_id) {
Some(m) => m,
None => {
let msg = format!("Component not found: {}", component_id);
let widget = Paragraph::new(msg).block(Block::bordered());
frame.render_widget(widget, area);
return;
}
};
let ctx = ComponentContext::new(
component_id.to_string(),
data_model,
components,
functions,
base_path,
);
let tui_comp = match registry.get(&comp_model.component_type) {
Some(c) => c,
None => {
let msg = format!("Unknown component type: {}", comp_model.component_type);
let widget = Paragraph::new(msg).block(Block::bordered());
frame.render_widget(widget, area);
return;
}
};
let mut render_child = |child_id: &str, child_area: Rect, child_frame: &mut Frame| {
render_node(
child_id,
base_path,
child_area,
child_frame,
data_model,
components,
registry,
functions,
);
};
tui_comp.render(&ctx, area, frame, &mut render_child);
}