ratatui_kit/render/
updater.rs

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