Skip to main content

rpi_tui/
container.rs

1//! Container component that holds multiple child components.
2
3use std::any::Any;
4use std::sync::{Arc, Mutex};
5
6use super::component::Component;
7
8/// Container - a component that contains other components.
9///
10/// Children are rendered in order, vertically stacked.
11#[derive(Clone)]
12pub struct Container {
13    children: Arc<Mutex<Vec<Arc<dyn Component>>>>,
14}
15
16impl Container {
17    /// Create a new empty container.
18    pub fn new() -> Self {
19        Self {
20            children: Arc::new(Mutex::new(Vec::new())),
21        }
22    }
23
24    /// Add a child component.
25    pub fn add_child(&self, component: Arc<dyn Component>) {
26        if let Ok(mut children) = self.children.lock() {
27            children.push(component);
28        }
29    }
30
31    /// Remove a child component.
32    pub fn remove_child(&self, component: &Arc<dyn Component>) {
33        if let Ok(mut children) = self.children.lock() {
34            children.retain(|c| !Arc::ptr_eq(c, component));
35        }
36    }
37
38    /// Clear all children.
39    pub fn clear(&self) {
40        if let Ok(mut children) = self.children.lock() {
41            children.clear();
42        }
43    }
44
45    /// Get the number of children.
46    pub fn child_count(&self) -> usize {
47        self.children.lock().map(|c| c.len()).unwrap_or(0)
48    }
49
50    /// Get a clone of the children list.
51    pub fn get_children(&self) -> Vec<Arc<dyn Component>> {
52        self.children.lock().map(|c| c.clone()).unwrap_or_default()
53    }
54}
55
56impl Default for Container {
57    fn default() -> Self {
58        Self::new()
59    }
60}
61
62impl Component for Container {
63    fn render(&self, width: usize) -> Vec<String> {
64        let mut lines = Vec::new();
65
66        if let Ok(children) = self.children.lock() {
67            for child in children.iter() {
68                let child_lines = child.render(width);
69                lines.extend(child_lines);
70            }
71        }
72
73        lines
74    }
75
76    fn invalidate(&self) {
77        if let Ok(children) = self.children.lock() {
78            for child in children.iter() {
79                child.invalidate();
80            }
81        }
82    }
83
84    fn as_any(&self) -> &dyn Any {
85        self
86    }
87}