Skip to main content

ratatui_kit/components/adapter/
widget.rs

1use crate::{Component, Props};
2use ratatui::widgets::Widget;
3
4// 0.30 起 `List`/`Paragraph`/`Table`/`Gauge` 等 widget 内含 `Option<Block>`,而 `Block`
5// 因新增阴影效果(`Arc<dyn CellEffect>`)不再 Send + Sync。但 ratatui-kit 的 `Props`/
6// `Component` 要求 Send + Sync(组件 `wait()` 经 `BoxFuture` 轮询)。
7//
8// 适配器在此放宽:不再要求被适配 widget 自身 Send + Sync,改为对适配器及其 props 以
9// `unsafe impl` 断言 Send + Sync。这与框架对 `AnyProps` 的既有处理(`unsafe impl Send/Sync`)
10// 一致——组件树只在单线程渲染路径中访问,widget 不跨线程并发使用,断言成立。
11// 好处:任意 ratatui widget 仍可经 `$expr` 直接嵌入元素树,保持 0.29 的使用体验。
12
13pub struct WidgetAdapterProps<T>
14where
15    T: Widget + 'static,
16{
17    pub inner: T,
18}
19
20// Safety: 见本文件顶部说明。
21unsafe impl<T: Widget + 'static> Send for WidgetAdapterProps<T> {}
22unsafe impl<T: Widget + 'static> Sync for WidgetAdapterProps<T> {}
23unsafe impl<T: Widget + 'static> Props for WidgetAdapterProps<T> {}
24
25pub struct WidgetAdapter<T>
26where
27    T: Widget + 'static,
28{
29    inner: T,
30}
31
32// Safety: 见本文件顶部说明。
33unsafe impl<T: Widget + 'static> Send for WidgetAdapter<T> {}
34unsafe impl<T: Widget + 'static> Sync for WidgetAdapter<T> {}
35
36impl<T> Component for WidgetAdapter<T>
37where
38    T: Widget + 'static + Unpin + Clone,
39{
40    type Props<'a> = WidgetAdapterProps<T>;
41
42    fn new(props: &Self::Props<'_>) -> Self {
43        Self {
44            inner: props.inner.clone(),
45        }
46    }
47
48    fn update(
49        &mut self,
50        props: &mut Self::Props<'_>,
51        _hooks: crate::Hooks,
52        _updater: &mut crate::ComponentUpdater,
53    ) {
54        self.inner = props.inner.clone();
55    }
56
57    fn draw(&mut self, drawer: &mut crate::ComponentDrawer<'_, '_>) {
58        drawer.render_widget(self.inner.clone(), drawer.area);
59    }
60}