ratatui_kit/hooks/
use_size.rs

1use crossterm::{event::Event, terminal};
2use ratatui::layout::Rect;
3
4use crate::{Hook, UseEvents, UseState};
5
6mod private {
7    pub trait Sealed {}
8    impl Sealed for crate::Hooks<'_, '_> {}
9}
10
11/// 获取终端当前尺寸,并在终端尺寸变化时更新,适合响应式布局。
12pub trait UseTerminalSize: private::Sealed {
13    fn use_terminal_size(&mut self) -> (u16, u16);
14}
15
16impl UseTerminalSize for crate::Hooks<'_, '_> {
17    fn use_terminal_size(&mut self) -> (u16, u16) {
18        let mut size = self.use_state(|| terminal::size().unwrap_or((0, 0)));
19
20        self.use_events(move |event| {
21            if let Event::Resize(width, height) = event {
22                size.set((width, height));
23            }
24        });
25
26        size.get()
27    }
28}
29
30/// 获取组件当前尺寸,但是是上一帧的尺寸
31pub trait UsePreviousSize: private::Sealed {
32    fn use_previous_size(&mut self) -> Rect;
33}
34
35pub struct UsePreviousSizeImpl {
36    size: Rect,
37}
38
39impl UsePreviousSizeImpl {
40    pub fn new() -> Self {
41        UsePreviousSizeImpl {
42            size: Rect::default(),
43        }
44    }
45}
46
47impl Hook for UsePreviousSizeImpl {
48    fn pre_component_draw(&mut self, drawer: &mut crate::ComponentDrawer) {
49        self.size = drawer.area;
50    }
51}
52
53impl UsePreviousSize for crate::Hooks<'_, '_> {
54    fn use_previous_size(&mut self) -> Rect {
55        let hook = self.use_hook(UsePreviousSizeImpl::new);
56        hook.size
57    }
58}