cursive-image 0.0.6

Image view for the Cursive TUI library
Documentation
use {
    cursive::{view::*, views::*, *},
    cursive_image::*,
};

// (note that rendering PDF is slow for dev builds)
const FILE: &str = "assets/media/example.pdf";
const NAME: &str = "Image";

fn main() {
    let mut cursive = default();

    // The constructor returns a vector of images, one for each page in the PDF
    // PDF pages can be either PNG or RGBA (PNG is usually more efficient)
    // Note that we can apply scaling during rendering
    let images = Image::new_owned_from_pdf_file(FILE, ImageFormat::PNG, 1.5, false).expect("new_owned_from_pdf_file");

    cursive.set_user_data(Pages::new(images));

    cursive.add_layer(
        Dialog::around(
            Panel::new(
                ImageView::default().with_sizing(Sizing::original()).with_name(NAME).scrollable().scroll_x(true),
            )
            .fixed_size((50, 30)),
        )
        .button("Previous", |cursive| flip_page(cursive, -1))
        .button("Next", |cursive| flip_page(cursive, 1)),
    );

    select_page(&mut cursive, 0);

    cursive.add_global_callback('q', |cursive| cursive.quit());

    cursive.run();
}

struct Pages {
    images: Vec<Option<Image>>,
    index: usize,
}

impl Pages {
    pub fn new(images: Vec<Image>) -> Self {
        Self { images: images.into_iter().map(|image| Some(image)).collect(), index: 0 }
    }
}

fn flip_page(cursive: &mut Cursive, delta: isize) {
    let new_index = {
        let pages: &mut Pages = cursive.user_data().unwrap();
        if let Some(index) = pages.index.checked_add_signed(delta)
            && index < pages.images.len()
        {
            Some(index)
        } else {
            None
        }
    };

    if let Some(new_index) = new_index {
        select_page(cursive, new_index);
    }
}

fn select_page(cursive: &mut Cursive, index: usize) {
    unset_page(cursive);
    set_page(cursive, index);
}

fn set_page(cursive: &mut Cursive, index: usize) {
    let image = {
        let pages: &mut Pages = cursive.user_data().unwrap();
        pages.index = index;
        pages.images[index].take().unwrap()
    };
    cursive.call_on_name(NAME, |image_view: &mut ImageView| image_view.set_image(image));
}

fn unset_page(cursive: &mut Cursive) {
    let image = cursive.call_on_name(NAME, |image_view: &mut ImageView| image_view.take_image()).unwrap();
    if let Some(image) = image {
        _ = image.hide();
        let pages: &mut Pages = cursive.user_data().unwrap();
        pages.images[pages.index] = Some(image);
    }
}