Skip to main content

ratatui_kit/components/
positioned.rs

1use crate::{AnyElement, Component, layout_style::LayoutStyle};
2use ratatui::{
3    layout::{Constraint, Rect},
4    widgets::Clear,
5};
6use ratatui_kit_macros::Props;
7
8#[derive(Default)]
9pub struct Positioned {
10    area: Rect,
11    clear: bool,
12}
13
14#[derive(Default, Props)]
15pub struct PositionedProps<'a> {
16    // 是否在渲染前清除该区域内容,默认为 false。
17    pub clear: bool,
18    pub x: u16,
19    pub y: u16,
20    pub width: u16,
21    pub height: u16,
22    pub children: Vec<AnyElement<'a>>,
23}
24
25impl Positioned {
26    // 从 props 派生自身状态的单一构造源(区域/清除标志只写一处,避免 new/update 漂移)。
27    fn from_props(props: &PositionedProps<'_>) -> Self {
28        Self {
29            area: Rect::new(props.x, props.y, props.width, props.height),
30            clear: props.clear,
31        }
32    }
33}
34
35impl Component for Positioned {
36    type Props<'a> = PositionedProps<'a>;
37
38    fn new(props: &Self::Props<'_>) -> Self {
39        Self::from_props(props)
40    }
41
42    fn update(
43        &mut self,
44        props: &mut Self::Props<'_>,
45        _hooks: crate::Hooks,
46        updater: &mut crate::ComponentUpdater,
47    ) {
48        *self = Self::from_props(props);
49        // 子节点与布局收尾保持显式。
50        updater.update_children(&mut props.children, None);
51        updater.set_layout_style(LayoutStyle {
52            width: Constraint::Length(0),
53            height: Constraint::Length(0),
54            ..Default::default()
55        });
56    }
57
58    fn draw(&mut self, drawer: &mut crate::ComponentDrawer<'_, '_>) {
59        if self.clear {
60            drawer.render_widget(Clear, self.area);
61        }
62        drawer.area = self.area;
63    }
64}