franklin 0.1.4

A utility for generating images through evolution.
Documentation
use std::sync::mpsc::{Receiver, TryRecvError};

use anyhow::Result;
use show_image::{
    create_window,
    event::{self, WindowEvent},
    ImageInfo, ImageView, WindowOptions, WindowProxy,
};

use crate::models::Image;

pub struct Window {
    window: WindowProxy,
    event_receiver: Receiver<WindowEvent>,
    should_exit: bool,
}

impl Window {
    fn new(window: WindowProxy) -> Result<Self> {
        let event_receiver = window.event_channel()?;

        Ok(Self {
            window,
            event_receiver,
            should_exit: false,
        })
    }

    pub fn run_with_context<F>(dimensions: (usize, usize), func: F)
    where
        F: FnOnce(Self) -> Result<()> + Send + 'static,
    {
        show_image::run_context(move || -> Result<()> {
            let window_options = WindowOptions::default()
                .set_resizable(false)
                .set_size([dimensions.0 as u32, dimensions.1 as u32]);
            let window = create_window("Franklin", window_options)?;

            let this = Self::new(window)?;
            func(this)?;

            Ok(())
        })
    }

    pub fn show_image(&mut self, title: &str, image: &Image) -> Result<()> {
        let image_info = ImageInfo::rgb8(image.width() as u32, image.height() as u32);

        let image_bytes = image.as_raw_bytes();
        let image_view = ImageView::new(image_info, image_bytes.as_slice());

        self.handle_events();

        if !self.should_exit {
            self.window.set_image(title, image_view)?;
        }

        Ok(())
    }

    fn handle_events(&mut self) {
        loop {
            match self.event_receiver.try_recv() {
                Ok(event) => {
                    if let event::WindowEvent::KeyboardInput(event) = event {
                        if event.input.key_code == Some(event::VirtualKeyCode::Escape)
                            && event.input.state.is_pressed()
                        {
                            self.should_exit = true;
                        }
                    }
                }
                Err(TryRecvError::Disconnected) => {
                    println!("Disconnected");
                    self.should_exit = true;
                    break;
                }
                Err(TryRecvError::Empty) => break,
            }
        }
    }

    pub fn should_exit(&self) -> bool {
        self.should_exit
    }
}