Skip to main content

ratatui_kit/components/adapter/
stateful_widget.rs

1use crate::{Component, Props, State};
2use ratatui::widgets::StatefulWidget;
3
4// `T::State` 仍要求 Send + Sync,因 `State<T::State>` 需可存储于框架的
5// SyncStorage 状态体系中;0.30 起 `StatefulWidget::State`
6// 去掉了隐式 `Sized`,故显式补 `Sized`。
7
8pub struct StatefulWidgetAdapterProps<T>
9where
10    T: StatefulWidget + 'static,
11    T::State: Sized + Sync + Send + 'static,
12{
13    pub inner: T,
14    pub state: State<T::State>,
15}
16
17impl<T> Props for StatefulWidgetAdapterProps<T>
18where
19    T: StatefulWidget + 'static,
20    T::State: Sized + Sync + Send + 'static,
21{
22}
23
24pub struct StatefulWidgetAdapter<T>
25where
26    T: StatefulWidget + 'static,
27    T::State: Sized + Sync + Send + 'static,
28{
29    inner: T,
30    state: State<T::State>,
31}
32
33impl<T> Component for StatefulWidgetAdapter<T>
34where
35    T: StatefulWidget + 'static + Unpin + Clone,
36    T::State: Sized + Sync + Send + 'static + Unpin,
37    // 0.30 起 `List`/`Table` 等实现了 `StatefulWidget for &T` 且 State 类型一致,
38    // 借此约束即可在 draw 里按引用渲染。
39    for<'a> &'a T: StatefulWidget<State = T::State>,
40{
41    type Props<'a> = StatefulWidgetAdapterProps<T>;
42
43    fn new(props: &Self::Props<'_>) -> Self {
44        Self {
45            inner: props.inner.clone(),
46            state: props.state,
47        }
48    }
49
50    fn update(
51        &mut self,
52        props: &mut Self::Props<'_>,
53        _hooks: crate::Hooks,
54        _updater: &mut crate::ComponentUpdater,
55    ) {
56        self.inner = props.inner.clone();
57        self.state = props.state;
58    }
59
60    fn draw(&mut self, drawer: &mut crate::ComponentDrawer<'_, '_>) {
61        // 按引用渲染,免去每帧一次 clone。render_stateful_widget 泛型固定 W: StatefulWidget,
62        // 故 `&List` 不会触发 Widget/StatefulWidget 的 render 方法歧义(E0034)。
63        drawer.render_stateful_widget(&self.inner, drawer.area, &mut self.state.write_no_update());
64    }
65}