ratatui_kit/hooks/
use_size.rs1use std::{cell::Cell, rc::Rc};
2
3use crossterm::{event::Event, terminal};
4use ratatui::layout::Rect;
5
6use crate::{
7 Hook, State, SystemContext, UseState,
8 input::{EventOptions, EventPriority, EventResult},
9};
10
11mod private {
12 pub trait Sealed {}
13 impl Sealed for crate::Hooks<'_, '_> {}
14}
15
16pub trait UseTerminalSize: private::Sealed {
18 fn use_terminal_size(&mut self) -> (u16, u16);
19}
20
21impl UseTerminalSize for crate::Hooks<'_, '_> {
22 fn use_terminal_size(&mut self) -> (u16, u16) {
23 let mut size = self.use_state(|| terminal::size().unwrap_or((0, 0)));
24
25 let hook = self.use_hook(UseTerminalSizeImpl::new);
26 hook.size = Some(size);
27
28 size.get()
29 }
30}
31
32struct UseTerminalSizeImpl {
37 size: Option<State<(u16, u16)>>,
38}
39
40impl UseTerminalSizeImpl {
41 fn new() -> Self {
42 Self { size: None }
43 }
44}
45
46impl Hook for UseTerminalSizeImpl {
47 fn post_component_update(&mut self, updater: &mut crate::ComponentUpdater) {
48 let Some(mut size) = self.size else {
49 return;
50 };
51 let mut system = updater
52 .get_context_mut::<SystemContext>()
53 .expect("SystemContext 缺失(根 context 必有)");
54
55 system.input.register_handler(
58 None,
59 EventPriority::Normal,
60 EventOptions::default(),
61 Rc::new(Cell::new(Rect::default())),
62 Box::new(move |event| {
63 if let Event::Resize(width, height) = event {
64 size.set((width, height));
65 }
66 EventResult::Ignored
67 }),
68 );
69 }
70}
71
72pub trait UsePreviousSize: private::Sealed {
74 fn use_previous_size(&mut self) -> Rect;
75}
76
77pub struct UsePreviousSizeImpl {
78 size: Rect,
79}
80
81impl Default for UsePreviousSizeImpl {
82 fn default() -> Self {
83 Self::new()
84 }
85}
86
87impl UsePreviousSizeImpl {
88 pub fn new() -> Self {
89 UsePreviousSizeImpl {
90 size: Rect::default(),
91 }
92 }
93}
94
95impl Hook for UsePreviousSizeImpl {
96 fn pre_component_draw(&mut self, drawer: &mut crate::ComponentDrawer) {
97 self.size = drawer.area;
98 }
99}
100
101impl UsePreviousSize for crate::Hooks<'_, '_> {
102 fn use_previous_size(&mut self) -> Rect {
103 let hook = self.use_hook(UsePreviousSizeImpl::new);
104 hook.size
105 }
106}