ratatui_kit/render/
updater.rs1use 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}