diff --git a/src/config.rs b/src/config.rs index 5b596ad..5c14816 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,10 +1,14 @@ //! load, save configuration and parse cli args +use std::collections::HashMap; + use clap::{ArgEnum, Parser}; use fltk::dialog; use fltk_theme::ThemeType; use serde::{Deserialize, Serialize}; +use crate::globals; + /// Simple program calculate size of stuff in quote image #[derive(Parser, Debug)] #[clap(about, version, author)] @@ -60,12 +64,15 @@ impl Into for Themes { } /// Configuation file -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ConfigFile { pub quote_font_ttf: String, pub tag_font_ttf: String, pub quote_font_ratio: f64, pub tag_font_ratio: f64, + pub quote_position_ratio: f64, + pub tag_position_ratio: f64, + pub image_ratio: (f64, f64), pub color_layer: [u8; 4], } @@ -74,8 +81,11 @@ impl Default for ConfigFile { Self { quote_font_ttf: String::new(), tag_font_ttf: String::new(), - quote_font_ratio: 215.0, + quote_font_ratio: 230.0, tag_font_ratio: 150.0, + quote_position_ratio: 0.7, + tag_position_ratio: 0.5, + image_ratio: (4.0, 4.0), color_layer: [20, 22, 25, 197], } } @@ -93,22 +103,28 @@ impl ConfigFile { }; if conf.exists() { - if let Ok(text) = std::fs::read_to_string(&conf) { - if let Ok(config) = serde_json::from_str::(&text) { - return config; - } + let map = match std::fs::read_to_string(&conf) { + Ok(r) => serde_json::from_str::>(&r).ok(), + Err(_) => None, + }; + + let map = match map { + Some(m) => m, + None => HashMap::new(), + }; + + if let Some(config) = map.get(&*globals::CONFIG_NAME.read().unwrap()) { + return config.to_owned(); } } let config = Self::default(); - if let Err(_) = std::fs::write(&conf, serde_json::to_string(&config).unwrap()) { - dialog::message_default("Can't write config!"); - eprintln!("Can't write config!"); - } + config.save(); config } pub(crate) fn save(&self) { + let config_name = &*globals::CONFIG_NAME.read().unwrap(); let conf = match dirs::config_dir() { Some(path) => path.join("post_maker.config"), None => std::env::current_exe() @@ -118,7 +134,19 @@ impl ConfigFile { .join("post_maker.config"), }; - if let Err(_) = std::fs::write(&conf, serde_json::to_string(self).unwrap()) { + let map = match std::fs::read_to_string(&conf) { + Ok(r) => serde_json::from_str::>(&r).ok(), + Err(_) => None, + }; + + let mut map = match map { + Some(m) => m, + None => HashMap::new(), + }; + + map.insert(config_name.to_owned(), (*self).clone()); + + if let Err(_) = std::fs::write(&conf, serde_json::to_string(&map).unwrap()) { dialog::message_default("Can't write config!"); eprintln!("Can't write config!"); } diff --git a/src/config_window.rs b/src/config_window.rs index b6918a9..ee2e021 100644 --- a/src/config_window.rs +++ b/src/config_window.rs @@ -262,6 +262,9 @@ impl ConfigWindow { tag_font_ttf: tag_font_ttf.value(), quote_font_ratio: quote_font_ratio.value(), tag_font_ratio: tag_font_ratio.value(), + quote_position_ratio: *globals::QUOTE_POSITION_RATIO.read().unwrap(), + tag_position_ratio: *globals::TAG_POSITION_RATIO.read().unwrap(), + image_ratio: *globals::IMAGE_RATIO.read().unwrap(), color_layer: [ layer_red.value() as u8, layer_green.value() as u8, diff --git a/src/crop_window.rs b/src/crop_window.rs index 502f945..d289650 100644 --- a/src/crop_window.rs +++ b/src/crop_window.rs @@ -153,7 +153,8 @@ impl CropWindow { let (original_width, original_height) = prop.original_dimension; let (original_x, original_y) = prop.crop_position.unwrap(); let (resized_width, resized_height) = (image.width() as f64, image.height() as f64); - let (bound_width, bound_height) = utils::get_4_5(resized_width, resized_height); + let (bound_width, bound_height) = + utils::croped_ratio(resized_width, resized_height); let (bound_x, bound_y) = ( (original_x * resized_width as f64) / original_width, @@ -183,7 +184,7 @@ impl CropWindow { let (original_x, original_y) = prop.crop_position.unwrap(); let (original_width, original_heigth) = prop.original_dimension; let (original_bound_width, original_bound_height) = - utils::get_4_5(original_width, original_heigth); + utils::croped_ratio(original_width, original_heigth); let point = original_width / image.width() as f64; let (event_x, event_y) = ( (app::event_x() - f.x()) as f64 * point, diff --git a/src/globals.rs b/src/globals.rs index 37284fd..ad8ee2b 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -5,7 +5,14 @@ use std::{ffi::OsString, io::Read, sync::RwLock}; lazy_static! { pub static ref THEME: config::Themes = config::config().theme.unwrap_or(config::Themes::System); + pub static ref CONFIG_NAME: RwLock = RwLock::new("default".to_owned()); pub static ref CONFIG: RwLock = RwLock::new(config::ConfigFile::load()); + pub static ref IMAGE_RATIO: RwLock<(f64, f64)> = + RwLock::new(CONFIG.read().unwrap().image_ratio); + pub static ref QUOTE_POSITION_RATIO: RwLock = + RwLock::new(CONFIG.read().unwrap().quote_position_ratio); + pub static ref TAG_POSITION_RATIO: RwLock = + RwLock::new(CONFIG.read().unwrap().tag_position_ratio); pub static ref FONT_QUOTE: Font<'static> = { let mut buffer = Vec::new(); if let Ok(mut file) = std::fs::File::open(CONFIG.read().unwrap().quote_font_ttf.as_str()) { diff --git a/src/utils.rs b/src/utils.rs index 55efde4..34d08ca 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -72,8 +72,8 @@ impl ImageContainer { let mut prop = properties.write().unwrap(); prop.path = Some(path.to_owned()); prop.original_dimension = (width, height); - prop.quote_position = (height * 2.0) / 3.0; - prop.tag_position = height / 2.0; + prop.quote_position = height * &*globals::QUOTE_POSITION_RATIO.read().unwrap(); + prop.tag_position = height * &*globals::TAG_POSITION_RATIO.read().unwrap(); Self { image: img.clone(), @@ -96,14 +96,15 @@ impl ImageContainer { pub(crate) fn apply_crop(&mut self) { let mut prop = self.properties.write().unwrap(); let (original_width, original_height) = prop.original_dimension; - let (origina_crop_width, origina_crop_height) = get_4_5(original_width, original_height); + let (origina_crop_width, origina_crop_height) = + croped_ratio(original_width, original_height); prop.crop_position = Some(( original_width / 2.0 - origina_crop_width / 2.0, original_height / 2.0 - origina_crop_height / 2.0, )); let (s_width, s_height): (f64, f64) = Coord::from(self.image.dimensions()).into(); - let (c_width, c_height) = get_4_5(s_width, s_height); + let (c_width, c_height) = croped_ratio(s_width, s_height); let (cx, cy) = ((s_width - c_width) / 2.0, (s_height - c_height) / 2.0); prop.dimension = (c_width, c_height); @@ -120,7 +121,7 @@ impl ImageContainer { prop.crop_position = Some((original_x, original_y)); let (s_width, s_height): (f64, f64) = Coord::from(self.image.dimensions()).into(); - let (c_width, c_height) = get_4_5(s_width, s_height); + let (c_width, c_height) = croped_ratio(s_width, s_height); let (cx, cy) = ( (original_x * s_width) / original_width, (original_y * s_height) / original_height, @@ -177,7 +178,7 @@ impl ImageContainer { let mut img = image::open(&path_original).unwrap(); let (width, height): (f64, f64) = Coord::from(img.dimensions()).into(); let (crop_x, crop_y) = prop.crop_position.unwrap(); - let (crop_width, crop_height) = get_4_5(width, height); + let (crop_width, crop_height) = croped_ratio(width, height); let mut img = img.crop( crop_x as u32, crop_y as u32, @@ -354,7 +355,7 @@ fn draw_layer_and_text( } } -pub(crate) fn get_4_5(width: f64, height: f64) -> (f64, f64) { +pub(crate) fn croped_ratio(width: f64, height: f64) -> (f64, f64) { if width > width_from_height(height) { (width_from_height(height), height) } else { @@ -363,11 +364,13 @@ pub(crate) fn get_4_5(width: f64, height: f64) -> (f64, f64) { } pub(crate) fn width_from_height(height: f64) -> f64 { - (4.0 * height) / 5.0 + let (w, h) = &*globals::IMAGE_RATIO.read().unwrap(); + (w * height) / h } pub(crate) fn height_from_width(width: f64) -> f64 { - (5.0 * width) / 4.0 + let (w, h) = &*globals::IMAGE_RATIO.read().unwrap(); + (h * width) / w } pub(crate) fn quote_from_height(height: f64) -> f64 {