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