md_tui/nodes/
image.rs

1use std::cmp;
2
3use image::DynamicImage;
4use ratatui_image::{picker::Picker, protocol::StatefulProtocol};
5
6use super::{root::ComponentProps, textcomponent::TextNode};
7
8pub struct ImageComponent {
9    _alt_text: String,
10    y_offset: u16,
11    height: u16,
12    scroll_offset: u16,
13    image: StatefulProtocol,
14}
15
16impl ImageComponent {
17    pub fn new<T: ToString>(image: DynamicImage, height: u32, alt_text: T) -> Option<Self> {
18        let picker = Picker::from_query_stdio().ok()?;
19
20        let image = picker.new_resize_protocol(image);
21
22        let (_, f_height) = picker.font_size();
23
24        let height = cmp::min(height / u32::from(f_height), 20) as u16;
25
26        Some(Self {
27            height,
28            image,
29            _alt_text: alt_text.to_string(),
30            scroll_offset: 0,
31            y_offset: 0,
32        })
33    }
34
35    pub fn image_mut(&mut self) -> &mut StatefulProtocol {
36        &mut self.image
37    }
38
39    pub fn set_scroll_offset(&mut self, offset: u16) {
40        self.scroll_offset = offset;
41    }
42
43    #[must_use]
44    pub fn scroll_offset(&self) -> u16 {
45        self.scroll_offset
46    }
47
48    #[must_use]
49    pub fn y_offset(&self) -> u16 {
50        self.y_offset
51    }
52
53    #[must_use]
54    pub fn height(&self) -> u16 {
55        self.height
56    }
57}
58
59impl ComponentProps for ImageComponent {
60    fn height(&self) -> u16 {
61        self.height
62    }
63
64    fn set_y_offset(&mut self, y_offset: u16) {
65        self.y_offset = y_offset;
66    }
67
68    fn set_scroll_offset(&mut self, scroll: u16) {
69        self.scroll_offset = scroll;
70    }
71
72    fn kind(&self) -> TextNode {
73        TextNode::Image
74    }
75}