#![allow( clippy::upper_case_acronyms, clippy::vec_init_then_push, clippy::unsound_collection_transmute, clippy::new_without_default )] mod app; mod bitmap; mod brush; mod cache; mod cli; mod command; mod consts; mod dither; mod error; mod grid; mod guide; mod lisp; mod message; mod render; mod symmetry; mod undo; mod utils; mod widget; use { app::AppState, cli::Config, error::{AppError, SdlTTFError}, render::Signal, }; use std::{sync::mpsc, thread}; use log::{error, info}; use sdl2::event::Event; pub fn error_sink() -> Result<(), AppError> { let (render_tx, app_rx) = mpsc::channel(); let (app_tx, render_rx) = mpsc::channel(); let render_handle = thread::spawn(move || -> Result<(), AppError> { let sdl_context = sdl2::init().map_err(AppError::Sdl)?; info!("Initialized SDL context"); let ttf_context = sdl2::ttf::init() .map_err(SdlTTFError::Init) .map_err(AppError::SdlTTF)?; info!("Initialized SDL_ttf context"); while let Ok(signal) = render_rx.recv() { match signal { Signal::Quit => { let ev = sdl_context.event().unwrap(); ev.push_event(Event::Quit { timestamp: 0u32 }) .expect("unable to quit ohno"); } _ => {} } } Ok(()) }); match cli::parse_args().map_err(AppError::Cli)? { Config::Help => { println!("{}", cli::HELP_TEXT); } Config::NewProject { file_name, dimensions: (width, height), } => { AppState::init(width, height, app_tx, app_rx, None, file_name)?.run(); } Config::ExistingProject { file_name } => { let image = utils::load_file(&file_name).map_err(AppError::File)?; AppState::init( image.width(), image.height(), app_tx, app_rx, Some(image.data), Some(file_name), )? .run(); } } Ok(()) } pub fn main() { env_logger::init(); if let Err(e) = error_sink() { error!("{}", e); } }