use super::{image::*, sizing::*, state::*, vec2f::*};
use {
crossterm::terminal::*,
cursive::{align::*, *},
std::{cell::*, sync::*},
};
pub struct ImageView {
pub(crate) image: Option<Image>,
pub(crate) sizing: Sizing,
pub(crate) align: Align,
pub(crate) size: Option<Vec2>,
pub(crate) content_offset: Mutex<RefCell<Option<Vec2>>>,
pub(crate) state: Mutex<RefCell<State>>,
pub(crate) cell_size: XY<f64>,
pub(crate) cell_aspect_ratio: f64,
}
impl ImageView {
pub fn image(&self) -> Option<&Image> {
self.image.as_ref()
}
pub fn set_image(&mut self, image: Image) {
self.image = Some(image);
self.reset_layout();
}
pub fn take_image(&mut self) -> Option<Image> {
self.reset_layout();
self.image.take()
}
pub fn with_image(self, image: Image) -> Self {
self.with(|self_| self_.set_image(image))
}
pub fn sizing(&self) -> Sizing {
self.sizing
}
pub fn set_sizing(&mut self, sizing: Sizing) {
if self.sizing != sizing {
self.sizing = sizing;
self.reset_layout();
}
}
pub fn with_sizing(self, sizing: Sizing) -> Self {
self.with(|self_| self_.set_sizing(sizing))
}
pub fn align(&self) -> Align {
self.align
}
pub fn set_align(&mut self, align: Align) {
if self.align != align {
self.align = align;
self.reset_layout();
}
}
pub fn with_align(self, align: Align) -> Self {
self.with(|self_| self_.set_align(align))
}
pub fn hide(&self) {
if let Some(image) = &self.image {
_ = image.hide();
}
}
fn reset_layout(&mut self) {
self.size = None;
self.set_content_offset(None);
}
pub(crate) fn get_state(&self) -> State {
*self.state.lock().unwrap().borrow()
}
pub(crate) fn set_state(&self, state: State) {
*self.state.lock().unwrap().borrow_mut() = state;
}
pub(crate) fn get_content_offset(&self) -> Option<Vec2> {
*self.content_offset.lock().unwrap().borrow()
}
pub(crate) fn set_content_offset(&self, content_offset: Option<Vec2>) {
*self.content_offset.lock().unwrap().borrow_mut() = content_offset;
}
}
impl Default for ImageView {
fn default() -> Self {
let cell_size = cell_size();
Self {
image: None,
sizing: Default::default(),
align: Align::center(),
size: None,
content_offset: Default::default(),
state: Default::default(),
cell_size,
cell_aspect_ratio: cell_size.aspect_ratio(),
}
}
}
fn cell_size() -> Vec2f {
match window_size() {
Ok(size) if size.width != 0 && size.height != 0 && size.columns != 0 && size.rows != 0 => {
(size.width as f64 / size.columns as f64, size.height as f64 / size.rows as f64)
}
_ => (8., 8.),
}
.into()
}