tui_popup/
known_size_wrapper.rs

1use std::fmt::Debug;
2
3use derive_setters::Setters;
4use ratatui_core::buffer::Buffer;
5use ratatui_core::layout::Rect;
6use ratatui_core::widgets::Widget;
7
8use crate::KnownSize;
9
10/// The `KnownSizeWrapper` struct wraps a widget and provides a fixed size for it.
11///
12/// This struct is used to wrap a widget and provide a fixed size for it. This is useful when you
13/// want to use a widget that does not implement [`KnownSize`] as the body of a popup.
14#[derive(Debug, Setters)]
15pub struct KnownSizeWrapper<W> {
16    #[setters(skip)]
17    pub inner: W,
18    pub width: usize,
19    pub height: usize,
20}
21
22impl<W: Widget> Widget for KnownSizeWrapper<W> {
23    fn render(self, area: Rect, buf: &mut Buffer) {
24        self.inner.render(area, buf);
25    }
26}
27
28impl<W> Widget for &KnownSizeWrapper<W>
29where
30    for<'a> &'a W: Widget,
31{
32    fn render(self, area: Rect, buf: &mut Buffer) {
33        self.inner.render(area, buf);
34    }
35}
36
37impl<W> KnownSize for KnownSizeWrapper<W> {
38    fn width(&self) -> usize {
39        self.width
40    }
41
42    fn height(&self) -> usize {
43        self.height
44    }
45}
46
47impl<W> KnownSize for &KnownSizeWrapper<W> {
48    fn width(&self) -> usize {
49        self.width
50    }
51
52    fn height(&self) -> usize {
53        self.height
54    }
55}
56
57impl<W> KnownSizeWrapper<W> {
58    /// Create a new `KnownSizeWrapper` with the given widget and size.
59    pub const fn new(inner: W, width: usize, height: usize) -> Self {
60        Self {
61            inner,
62            width,
63            height,
64        }
65    }
66}
67#[cfg(test)]
68mod tests {
69    use ratatui_core::buffer::Buffer;
70    use ratatui_core::layout::Rect;
71    use ratatui_core::widgets::Widget;
72
73    use super::*;
74
75    struct TestWidget;
76
77    impl Widget for TestWidget {
78        fn render(self, area: Rect, buf: &mut Buffer) {
79            "Hello".render(area, buf);
80        }
81    }
82
83    #[test]
84    fn test_sized_wrapper_new() {
85        let widget = TestWidget;
86        let wrapper = KnownSizeWrapper::new(widget, 10, 20);
87        assert_eq!(wrapper.width, 10);
88        assert_eq!(wrapper.height, 20);
89    }
90
91    #[test]
92    fn test_sized_wrapper_render() {
93        let widget = TestWidget;
94        let wrapper = KnownSizeWrapper::new(widget, 20, 5);
95        let mut buffer = Buffer::empty(Rect::new(0, 0, 20, 5));
96        wrapper.render(buffer.area, &mut buffer);
97        let expected = Buffer::with_lines([
98            "Hello               ",
99            "                    ",
100            "                    ",
101            "                    ",
102            "                    ",
103        ]);
104        assert_eq!(buffer, expected);
105    }
106}