ratatui_kit/hooks/
mod.rs

1#![allow(unused)]
2use crate::{
3    context::ContextStack,
4    render::{ComponentDrawer, ComponentUpdater},
5};
6use std::{
7    any::Any,
8    pin::Pin,
9    task::{Context, Poll},
10};
11mod use_context;
12pub use use_context::*;
13mod use_events;
14pub use use_events::*;
15mod use_future;
16pub use use_future::*;
17mod use_state;
18pub use use_state::*;
19mod use_memo;
20pub use use_memo::*;
21mod use_effect;
22pub use use_effect::*;
23
24pub trait Hook: Unpin + Send {
25    fn poll_change(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<()> {
26        Poll::Pending
27    }
28
29    fn pre_component_update(&mut self, _updater: &mut ComponentUpdater) {}
30    fn post_component_update(&mut self, _updater: &mut ComponentUpdater) {}
31
32    fn pre_component_draw(&mut self, _drawer: &mut ComponentDrawer) {}
33    fn post_component_draw(&mut self, _drawer: &mut ComponentDrawer) {}
34}
35
36pub(crate) trait AnyHook: Hook {
37    fn any_self_mut(&mut self) -> &mut dyn Any;
38}
39
40impl<T: Hook + 'static> AnyHook for T {
41    fn any_self_mut(&mut self) -> &mut dyn Any {
42        self
43    }
44}
45
46impl Hook for Vec<Box<dyn AnyHook>> {
47    fn poll_change(mut self: Pin<&mut Self>, _cx: &mut Context) -> Poll<()> {
48        let mut is_ready = false;
49        for hook in self.iter_mut() {
50            if Pin::new(&mut **hook).poll_change(_cx).is_ready() {
51                is_ready = true;
52            }
53        }
54
55        if is_ready {
56            Poll::Ready(())
57        } else {
58            Poll::Pending
59        }
60    }
61
62    fn pre_component_update(&mut self, _updater: &mut ComponentUpdater) {
63        for hook in self.iter_mut() {
64            hook.pre_component_update(_updater);
65        }
66    }
67
68    fn post_component_update(&mut self, _updater: &mut ComponentUpdater) {
69        for hook in self.iter_mut() {
70            hook.post_component_update(_updater);
71        }
72    }
73
74    fn pre_component_draw(&mut self, _updater: &mut ComponentDrawer) {
75        for hook in self.iter_mut() {
76            hook.pre_component_draw(_updater);
77        }
78    }
79
80    fn post_component_draw(&mut self, _updater: &mut ComponentDrawer) {
81        for hook in self.iter_mut() {
82            hook.post_component_draw(_updater);
83        }
84    }
85}
86
87pub struct Hooks<'a, 'b: 'a> {
88    hooks: &'a mut Vec<Box<dyn AnyHook>>,
89    first_update: bool,
90    hook_index: usize,
91    pub(crate) context: Option<&'a ContextStack<'b>>,
92}
93
94impl<'a> Hooks<'a, '_> {
95    pub(crate) fn new(hooks: &'a mut Vec<Box<dyn AnyHook>>, first_update: bool) -> Self {
96        Self {
97            hooks,
98            first_update,
99            hook_index: 0,
100            context: None,
101        }
102    }
103
104    pub fn with_context_stack<'c, 'd>(
105        &'c mut self,
106        context: &'c ContextStack<'d>,
107    ) -> Hooks<'c, 'd> {
108        Hooks {
109            hooks: self.hooks,
110            first_update: self.first_update,
111            hook_index: self.hook_index,
112            context: Some(context),
113        }
114    }
115
116    pub fn use_hook<F, H>(&mut self, f: F) -> &mut H
117    where
118        F: FnOnce() -> H,
119        H: Hook + Unpin + 'static,
120    {
121        if self.first_update {
122            self.hooks.push(Box::new(f()));
123        }
124        let idx = self.hook_index;
125        self.hook_index += 1;
126
127        self.hooks
128            .get_mut(idx)
129            .and_then(|hook| hook.any_self_mut().downcast_mut::<H>())
130            .expect("Hook type mismatch, ensure the hook is of the correct type")
131    }
132}