1use super::{sizing::*, state::*, vec2f::*};
2
3use {
4 crossterm::terminal::*,
5 cursive::{align::*, *},
6 image::*,
7 std::{cell::*, path::*, sync::*},
8};
9
10pub struct ImageView {
26 pub(crate) image: Option<DynamicImage>,
27 pub(crate) sizing: Sizing,
28 pub(crate) align: Align,
29
30 pub(crate) size: Option<Vec2>,
31 pub(crate) content_offset: Mutex<RefCell<Option<Vec2>>>,
32 pub(crate) state: Mutex<RefCell<State>>,
33
34 pub(crate) cell_size: XY<f64>,
35 pub(crate) cell_aspect_ratio: f64,
36}
37
38impl ImageView {
39 pub fn image(&self) -> Option<&DynamicImage> {
41 self.image.as_ref()
42 }
43
44 pub fn image_mut(&mut self) -> Option<&mut DynamicImage> {
46 self.image.as_mut()
47 }
48
49 pub fn set_image(&mut self, image: DynamicImage) {
51 self.image = Some(image);
52 self.size = None;
53 }
54
55 pub fn with_image(self, image: DynamicImage) -> Self {
59 self.with(|self_| self_.set_image(image))
60 }
61
62 pub fn set_image_file<PathT>(&mut self, path: PathT)
64 where
65 PathT: AsRef<Path>,
66 {
67 let image = ImageReader::open(path).unwrap().decode().unwrap();
68 self.set_image(image);
69 }
70
71 pub fn with_image_file<PathT>(self, path: PathT) -> Self
75 where
76 PathT: AsRef<Path>,
77 {
78 self.with(|self_| self_.set_image_file(path))
79 }
80
81 pub fn sizing(&self) -> Sizing {
83 self.sizing
84 }
85
86 pub fn set_sizing(&mut self, sizing: Sizing) {
88 if self.sizing != sizing {
89 self.sizing = sizing;
90 self.size = None;
91 }
92 }
93
94 pub fn with_sizing(self, sizing: Sizing) -> Self {
98 self.with(|self_| self_.set_sizing(sizing))
99 }
100
101 pub fn align(&self) -> Align {
103 self.align
104 }
105
106 pub fn set_align(&mut self, align: Align) {
108 if self.align != align {
109 self.align = align;
110 self.size = None;
111 }
112 }
113
114 pub fn with_align(self, align: Align) -> Self {
118 self.with(|self_| self_.set_align(align))
119 }
120}
121
122impl Default for ImageView {
123 fn default() -> Self {
124 let cell_size = cell_size();
125 Self {
126 image: None,
127 sizing: Default::default(),
128 align: Align::center(),
129 size: None,
130 content_offset: Default::default(),
131 state: Default::default(),
132 cell_size,
133 cell_aspect_ratio: cell_size.aspect_ratio(),
134 }
135 }
136}
137
138fn cell_size() -> Vec2f {
142 match window_size() {
143 Ok(size) if size.width != 0 && size.height != 0 && size.columns != 0 && size.rows != 0 => {
144 (size.width as f64 / size.columns as f64, size.height as f64 / size.rows as f64)
145 }
146
147 _ => (8., 8.),
148 }
149 .into()
150}