ratatui_kit/render/
updater.rs

1use std::{
2    any::Any,
3    cell::{Ref, RefMut},
4};
5
6use crate::{
7    ElementKey,
8    component::{Components, InstantiatedComponent},
9    context::{Context, ContextStack},
10    element::ElementExt,
11    layout_style::LayoutStyle,
12    multimap::AppendOnlyMultimap,
13    terminal::Terminal,
14};
15
16pub struct ComponentUpdater<'a, 'c: 'a> {
17    key: ElementKey,
18    component_context_stack: &'a mut ContextStack<'c>,
19    terminal: &'a mut Terminal,
20    components: &'a mut Components,
21    transparent_layout: bool,
22    layout_style: &'a mut LayoutStyle,
23}
24
25impl<'a, 'c: 'a> ComponentUpdater<'a, 'c> {
26    pub(crate) fn new(
27        key: ElementKey,
28        component_context_stack: &'a mut ContextStack<'c>,
29        terminal: &'a mut Terminal,
30        components: &'a mut Components,
31        layout_style: &'a mut LayoutStyle,
32    ) -> ComponentUpdater<'a, 'c> {
33        ComponentUpdater {
34            key,
35            component_context_stack,
36            terminal,
37            components,
38            transparent_layout: false,
39            layout_style,
40        }
41    }
42
43    pub fn component_context_stack(&self) -> &ContextStack<'c> {
44        self.component_context_stack
45    }
46
47    pub fn key(&self) -> &ElementKey {
48        &self.key
49    }
50
51    pub fn get_context<T: Any>(&self) -> Option<Ref<T>> {
52        self.component_context_stack.get_context()
53    }
54
55    pub fn get_context_mut<T: Any>(&self) -> Option<RefMut<T>> {
56        self.component_context_stack.get_context_mut()
57    }
58
59    pub fn terminal(&mut self) -> &mut Terminal {
60        self.terminal
61    }
62
63    pub fn set_transparent_layout(&mut self, transparent: bool) {
64        self.transparent_layout = transparent;
65    }
66
67    pub(crate) fn has_transparent_layout(&self) -> bool {
68        self.transparent_layout
69    }
70
71    pub fn set_layout_style(&mut self, layout_style: LayoutStyle) {
72        *self.layout_style = layout_style;
73    }
74
75    pub fn update_children<I, T>(&mut self, elements: I, context: Option<Context>)
76    where
77        I: IntoIterator<Item = T>,
78        T: ElementExt,
79    {
80        self.component_context_stack
81            .with_context(context, |context_stack| {
82                let mut used_components = AppendOnlyMultimap::default();
83
84                for mut child in elements {
85                    let mut component = match self.components.pop_front(child.key()) {
86                        Some(component)
87                            if component.component().type_id()
88                                == child.helper().component_type_id() =>
89                        {
90                            component
91                        }
92                        _ => {
93                            let h = child.helper();
94                            InstantiatedComponent::new(child.key().clone(), child.props_mut(), h)
95                        }
96                    };
97
98                    component.update(self.terminal, context_stack, child.props_mut());
99                    used_components.push_back(child.key().clone(), component);
100                }
101
102                self.components.components = used_components.into();
103            });
104    }
105}