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}