a2ui_tui/components/
column.rs1use ratatui::{Frame, layout::{Direction, Rect}};
4
5use a2ui_base::model::component_context::ComponentContext;
6use a2ui_base::protocol::common_types::{Align, ChildList, Justify};
7use crate::component_impl::TuiComponent;
8use crate::components::row::{render_static_children, render_template_children};
9
10pub struct ColumnComponent;
16
17impl TuiComponent for ColumnComponent {
18 fn name(&self) -> &'static str {
19 "Column"
20 }
21
22 fn render(
23 &self,
24 ctx: &ComponentContext,
25 area: Rect,
26 frame: &mut Frame,
27 render_child: &mut dyn FnMut(&str, Rect, &mut Frame, &str),
28 measure_child: &mut dyn FnMut(&str, &str, u16) -> Option<u16>,
29 ) {
30 let comp_model = match ctx.components.get(&ctx.component_id) {
31 Some(m) => m,
32 None => return,
33 };
34
35 let children = match comp_model.children() {
36 Some(c) => c,
37 None => return,
38 };
39
40 let justify = comp_model.get_property::<Justify>("justify").unwrap_or(Justify::Start);
41 let align = comp_model.get_property::<Align>("align").unwrap_or(Align::Stretch);
42
43 match children {
44 ChildList::Static(ids) => {
45 render_static_children(
46 ctx, area, frame, render_child, measure_child,
47 &ids, justify, align, Direction::Vertical,
48 );
49 }
50 ChildList::Template { component_id, path } => {
51 render_template_children(
52 ctx, area, frame, render_child, measure_child,
53 &component_id, &path, justify, align, Direction::Vertical,
54 );
55 }
56 }
57 }
58
59 fn natural_height(
63 &self,
64 ctx: &ComponentContext,
65 available_width: u16,
66 measure_child: &mut dyn FnMut(&str, &str, u16) -> Option<u16>,
67 ) -> Option<u16> {
68 let comp_model = ctx.components.get(&ctx.component_id)?;
69 let ids = match comp_model.children()? {
70 ChildList::Static(ids) => ids,
71 ChildList::Template { component_id, path } => {
72 let count = match ctx.data_context.get(&path) {
73 Some(serde_json::Value::Array(arr)) => arr.len(),
74 _ => return None,
75 };
76 if count == 0 {
77 return Some(0);
78 }
79 let item_path = format!("{}/{}", path, 0);
82 let one = measure_child(&component_id, &item_path, available_width)?;
83 return Some(one.saturating_mul(count as u16));
84 }
85 };
86 if ids.is_empty() {
87 return Some(0);
88 }
89 let base = ctx.data_context.base_path();
92 let mut sum: u16 = 0;
93 for id in &ids {
94 sum = sum.saturating_add(measure_child(id, base, available_width)?);
95 }
96 Some(sum)
97 }
98}