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