From 0f7d9f060efc7cc14df6057e3aeef95a1c34a224 Mon Sep 17 00:00:00 2001 From: Piyush Mishra Date: Wed, 26 Jan 2022 01:46:32 +0530 Subject: [PATCH] Backward compatibility --- src/crop_window.rs | 2 +- src/draw_thread.rs | 195 +++++++++++++++++---------------------------- src/main_window.rs | 16 ++-- src/utils.rs | 115 +++++++++++++++++++++++--- 4 files changed, 185 insertions(+), 143 deletions(-) diff --git a/src/crop_window.rs b/src/crop_window.rs index 7c27941..f48d9b3 100644 --- a/src/crop_window.rs +++ b/src/crop_window.rs @@ -107,7 +107,7 @@ impl CropWindow { crop_pos: Option<(f64, f64)>, ) -> Option<(f64, f64)> { let mut container = - ImageContainer::new(path, Arc::new(RwLock::new(ImageProperties::new()))); + ImageContainer::new(path, Arc::new(RwLock::new(ImageProperties::default()))); { let prop = &mut container.properties.write().unwrap(); prop.dimension = prop.original_dimension; diff --git a/src/draw_thread.rs b/src/draw_thread.rs index 2132624..b40bfc0 100644 --- a/src/draw_thread.rs +++ b/src/draw_thread.rs @@ -15,9 +15,9 @@ //! Thread to manage drawing in background use crate::{ - globals, main_window::{MainWindow, Page}, - utils, AppMessage, + utils::{self, ImagePropertiesFile}, + AppMessage, }; use fltk::{ app, @@ -119,7 +119,7 @@ pub(crate) fn spawn_image_thread( &mut count, &mut dimension, &app_sender, - &properties, + Arc::clone(&properties), &mut _container, ); status.set_label(""); @@ -152,7 +152,7 @@ pub(crate) fn spawn_image_thread( &mut count, &mut dimension, &app_sender, - &properties, + Arc::clone(&properties), &mut _container, ); status.set_label(""); @@ -242,7 +242,7 @@ fn load_image( count: &mut Frame, dimension: &mut Frame, app_sender: &app::Sender, - properties: &Arc>, + properties: Arc>, container: &mut Option, ) { let imgs = images_path.read().unwrap(); @@ -254,136 +254,85 @@ fn load_image( count.set_label(&format!("[{}/{}]", file_choice.value() + 1, imgs.len())); let file = imgs.get(file_choice.value() as usize).unwrap(); - *container = Some(ImageContainer::new(&file, Arc::clone(properties))); + *container = Some(ImageContainer::new(&file, Arc::clone(&properties))); if let Some(cont) = container { let file = Path::new(&file); let conf = file.with_extension("conf"); - let properties = Arc::clone(&cont.properties); - let mut use_defaults = true; - if conf.exists() { - let mut prop = properties.write().unwrap(); - match fs::read_to_string(&conf) { - Ok(read) => { - if let Ok(saved_prop) = serde_json::from_str::(&read) { - utils::set_color_btn_rgba(saved_prop.rgba, layer_rgb); - layer_alpha.set_value(saved_prop.rgba[3] as f64); - quote.set_value(&saved_prop.quote); - subquote.set_value(&saved_prop.subquote); - subquote2.set_value(&saved_prop.subquote2); - tag.set_value(&saved_prop.tag); - tag2.set_value(&saved_prop.tag2); - quote_position.set_range(0.0, prop.original_dimension.1); - quote_position.set_value(saved_prop.quote_position); - subquote_position.set_range(0.0, prop.original_dimension.1); - subquote_position.set_value(saved_prop.subquote_position); - subquote2_position.set_range(0.0, prop.original_dimension.1); - subquote2_position.set_value(saved_prop.subquote2_position); - tag_position.set_range(0.0, prop.original_dimension.1); - tag_position.set_value(saved_prop.tag_position); - tag2_position.set_range(0.0, prop.original_dimension.1); - tag2_position.set_value(saved_prop.tag2_position); - quote_position_slider.set_range(0.0, prop.original_dimension.1); - subquote_position_slider.set_range(0.0, prop.original_dimension.1); - subquote2_position_slider.set_range(0.0, prop.original_dimension.1); - quote_position_slider.set_value(saved_prop.quote_position); - subquote_position_slider.set_value(saved_prop.subquote_position); - subquote2_position_slider.set_value(saved_prop.subquote2_position); - tag_position_slider.set_range(0.0, prop.original_dimension.1); - tag_position_slider.set_value(saved_prop.tag_position); - tag2_position_slider.set_range(0.0, prop.original_dimension.1); - tag2_position_slider.set_value(saved_prop.tag2_position); - dimension.set_label(&format!( - "[{}x{}]", - prop.original_dimension.0, prop.original_dimension.1 - )); - - prop.quote = saved_prop.quote; - prop.subquote = saved_prop.subquote; - prop.subquote2 = saved_prop.subquote2; - prop.tag = saved_prop.tag; - prop.tag2 = saved_prop.tag2; - prop.quote_position = saved_prop.quote_position; - prop.subquote_position = saved_prop.subquote_position; - prop.subquote2_position = saved_prop.subquote2_position; - prop.tag_position = saved_prop.tag_position; - prop.tag2_position = saved_prop.tag2_position; - prop.rgba = saved_prop.rgba; - prop.is_saved = true; - use_defaults = false; - drop(prop); - - match crop { - Some((x, y)) => cont.apply_crop_position(x, y), - None => match saved_prop.crop_position { - Some((x, y)) => cont.apply_crop_position(x, y), - None => cont.apply_crop(), - }, + let read = fs::read_to_string(&conf).unwrap_or("{}".to_owned()); + let read = match serde_json::from_str::(&read) { + Ok(r) => r, + Err(e) => { + warn!("Config is corrupt\n{:?}", e); + match dialog::choice_default("Config is corrupt, fix??", "yes", "no", "") { + 1 => { + if let Err(e) = fs::remove_file(&conf) { + dialog::alert_default("Failed to delete image properties file!"); + warn!("Failed to delete image properties file!\n{:?}", e); } + ImagePropertiesFile::default() } - } - Err(e) => { - dialog::alert_default("Failed to open config file!"); - warn!("Failed to open config file!\n{:?}", e); - } - }; - } - - if use_defaults { - let mut prop = properties.write().unwrap(); - if crop.is_none() { - quote.set_value(""); - prop.quote = "".to_owned(); - subquote.set_value(""); - prop.subquote = "".to_owned(); - subquote2.set_value(""); - prop.subquote2 = "".to_owned(); - } - quote_position.set_range(0.0, prop.original_dimension.1); - quote_position.set_value(prop.quote_position); - subquote_position.set_range(0.0, prop.original_dimension.1); - subquote_position.set_value(prop.subquote_position); - subquote2_position.set_range(0.0, prop.original_dimension.1); - subquote2_position.set_value(prop.subquote2_position); - tag_position.set_range(0.0, prop.original_dimension.1); - tag_position.set_value(prop.tag_position); - tag2_position.set_range(0.0, prop.original_dimension.1); - tag2_position.set_value(prop.tag2_position); - quote_position_slider.set_range(0.0, prop.original_dimension.1); - quote_position_slider.set_value(prop.quote_position); - subquote_position_slider.set_range(0.0, prop.original_dimension.1); - subquote_position_slider.set_value(prop.subquote_position); - subquote2_position_slider.set_range(0.0, prop.original_dimension.1); - subquote2_position_slider.set_value(prop.subquote2_position); - tag_position_slider.set_range(0.0, prop.original_dimension.1); - tag_position_slider.set_value(prop.tag_position); - tag2_position_slider.set_range(0.0, prop.original_dimension.1); - tag2_position_slider.set_value(prop.tag2_position); - - let glob = &globals::CONFIG.read().unwrap(); - utils::set_color_btn_rgba(glob.color_layer, layer_rgb); - layer_alpha.set_value(glob.color_layer[3] as f64); - prop.rgba = glob.color_layer; - drop(glob); - - match crop { - Some((x, y)) => { - prop.is_saved = false; - drop(prop); - cont.apply_crop_position(x, y); - } - None => { - prop.is_saved = true; - drop(prop); - cont.apply_crop(); + _ => return, } } + }; + + let mut properties = cont.properties.write().unwrap(); + properties.merge(read, &tag.value(), &tag2.value()); + properties.is_saved = true; + + quote.set_value(&properties.quote); + subquote.set_value(&properties.subquote); + subquote2.set_value(&properties.subquote2); + tag.set_value(&properties.tag); + tag2.set_value(&properties.tag2); + + quote_position.set_range(0.0, properties.original_dimension.1); + quote_position.set_value(properties.quote_position); + quote_position_slider.set_range(0.0, properties.original_dimension.1); + quote_position_slider.set_value(properties.quote_position); + + subquote_position.set_range(0.0, properties.original_dimension.1); + subquote_position.set_value(properties.subquote_position); + subquote_position_slider.set_range(0.0, properties.original_dimension.1); + subquote_position_slider.set_value(properties.subquote_position); + + subquote2_position.set_range(0.0, properties.original_dimension.1); + subquote2_position.set_value(properties.subquote2_position); + subquote2_position_slider.set_range(0.0, properties.original_dimension.1); + subquote2_position_slider.set_value(properties.subquote2_position); + + tag_position.set_range(0.0, properties.original_dimension.1); + tag_position.set_value(properties.tag_position); + tag_position_slider.set_range(0.0, properties.original_dimension.1); + tag_position_slider.set_value(properties.tag_position); + + tag2_position.set_range(0.0, properties.original_dimension.1); + tag2_position.set_value(properties.tag2_position); + tag2_position_slider.set_range(0.0, properties.original_dimension.1); + tag2_position_slider.set_value(properties.tag2_position); + + utils::set_color_btn_rgba(properties.color_layer, layer_rgb); + layer_alpha.set_value(properties.color_layer[3] as f64); + + dimension.set_label(&format!( + "[{}x{}]", + properties.original_dimension.0, properties.original_dimension.1 + )); + + let crop_position = properties.crop_position; + drop(properties); + match crop { + Some((x, y)) => cont.apply_crop_position(x, y), + None => match crop_position { + Some((x, y)) => cont.apply_crop_position(x, y), + None => cont.apply_crop(), + }, } cont.apply_scale(); - let prop = properties.read().unwrap(); - let (width, height) = prop.dimension; + let (width, height) = cont.properties.read().unwrap().dimension; page.col_flex.set_size(&page.image, height as i32); page.row_flex.set_size(&page.col_flex, width as i32); page.col_flex.recalc(); diff --git a/src/main_window.rs b/src/main_window.rs index 64b2e1e..2f25fdf 100644 --- a/src/main_window.rs +++ b/src/main_window.rs @@ -335,7 +335,7 @@ impl MainWindow { win.make_resizable(true); win.show(); - let properties = Arc::new(RwLock::new(ImageProperties::new())); + let properties = Arc::new(RwLock::new(ImageProperties::default())); let (rx, tx) = std::sync::mpsc::channel(); let mut main_win = Self { win, @@ -500,7 +500,7 @@ impl MainWindow { self.reset_darklayer_btn.set_callback(move |_| { let mut prop = properties.write().unwrap(); let color = globals::CONFIG.read().unwrap().color_layer; - prop.rgba = color; + prop.color_layer = color; prop.is_saved = false; utils::set_color_btn_rgba(color, &mut layer_rgb); layer_alpha.set_value(color[3] as f64); @@ -932,10 +932,14 @@ impl MainWindow { let (r, g, b) = dialog::color_chooser_with_default( "Pick a colour", dialog::ColorMode::Byte, - (prop.rgba[0], prop.rgba[1], prop.rgba[2]), + ( + prop.color_layer[0], + prop.color_layer[1], + prop.color_layer[2], + ), ); - prop.rgba = [r, g, b, prop.rgba[3]]; - utils::set_color_btn_rgba(prop.rgba, &mut f); + prop.color_layer = [r, g, b, prop.color_layer[3]]; + utils::set_color_btn_rgba(prop.color_layer, &mut f); f.redraw(); prop.is_saved = false; sender.send(DrawMessage::RedrawToBuffer).unwrap(); @@ -948,7 +952,7 @@ impl MainWindow { let sender = self.sender.clone(); self.layer_alpha.set_callback(move |f| { let mut prop = properties.write().unwrap(); - prop.rgba[3] = f.value() as u8; + prop.color_layer[3] = f.value() as u8; prop.is_saved = false; sender.send(DrawMessage::RedrawToBuffer).unwrap(); sender.send(DrawMessage::Flush).unwrap(); diff --git a/src/utils.rs b/src/utils.rs index 87a0894..de55898 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -84,7 +84,6 @@ impl ImageContainer { let img = DynamicImage::ImageRgb8(img.into_rgb8()); let (width, height): (f64, f64) = Coord::from(img.dimensions()).into(); - let (width, height) = (width, height); let config = globals::CONFIG.read().unwrap(); let mut prop = properties.write().unwrap(); @@ -162,7 +161,7 @@ impl ImageContainer { draw_layer_and_text( &mut tmp, - &prop.rgba, + &prop.color_layer, &prop.quote, &prop.subquote, &prop.subquote2, @@ -198,7 +197,10 @@ impl ImageContainer { let mut prop = prop.clone(); prop.path = None; - if let Err(e) = fs::write(&path_conf, serde_json::to_string(&prop).unwrap()) { + if let Err(e) = fs::write( + &path_conf, + serde_json::to_string(&ImagePropertiesFile::from(&prop)).unwrap(), + ) { dialog::alert_default("Failed to save conf!"); warn!("Failed to save conf!\n{:?}", e); } @@ -216,7 +218,7 @@ impl ImageContainer { draw_layer_and_text( &mut img, - &prop.rgba, + &prop.color_layer, &prop.quote, &prop.subquote, &prop.subquote2, @@ -281,7 +283,7 @@ impl ImageContainer { Some(p) => Path::new(p), None => return, }; - let path_conf = path_original.with_extension("conf"); + let path_properties = path_original.with_extension("conf"); let export = path_original.parent().unwrap().join("export").join( path_original .with_extension("png") @@ -298,10 +300,10 @@ impl ImageContainer { } } - if path_conf.exists() { - if let Err(e) = fs::remove_file(path_conf) { - dialog::alert_default("Failed to delete image conf!"); - warn!("Failed to delete image conf!\n{:?}", e); + if path_properties.exists() { + if let Err(e) = fs::remove_file(path_properties) { + dialog::alert_default("Failed to delete image properties file!"); + warn!("Failed to delete image properties file!\n{:?}", e); } } @@ -314,6 +316,66 @@ impl ImageContainer { } } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub(crate) struct ImagePropertiesFile { + // pub(crate) dimension: Option<(f64, f64)>, + // pub(crate) original_dimension: Option<(f64, f64)>, + pub(crate) crop_position: Option<(f64, f64)>, + pub(crate) quote: Option, + pub(crate) subquote: Option, + pub(crate) subquote2: Option, + pub(crate) tag: Option, + pub(crate) tag2: Option, + pub(crate) quote_position: Option, // as per original + pub(crate) subquote_position: Option, // as per original + pub(crate) subquote2_position: Option, // as per original + pub(crate) tag_position: Option, // as per original + pub(crate) tag2_position: Option, // as per original + pub(crate) color_layer: Option<[u8; 4]>, +} + +impl Default for ImagePropertiesFile { + fn default() -> Self { + Self { + // dimension: None, + // original_dimension: None, + crop_position: None, + quote: None, + subquote: None, + subquote2: None, + tag: None, + tag2: None, + quote_position: None, + subquote_position: None, + subquote2_position: None, + tag_position: None, + tag2_position: None, + color_layer: None, + } + } +} + +impl From<&ImageProperties> for ImagePropertiesFile { + fn from(props: &ImageProperties) -> Self { + Self { + // dimension: Some(props.dimension), + // original_dimension: Some(props.original_dimension), + crop_position: props.crop_position, + quote: Some(props.quote.clone()), + subquote: Some(props.subquote.clone()), + subquote2: Some(props.subquote2.clone()), + tag: Some(props.tag.clone()), + tag2: Some(props.tag2.clone()), + quote_position: Some(props.quote_position), + subquote_position: Some(props.subquote_position), + subquote2_position: Some(props.subquote2_position), + tag_position: Some(props.tag_position), + tag2_position: Some(props.tag2_position), + color_layer: Some(props.color_layer), + } + } +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub(crate) struct ImageProperties { pub(crate) path: Option, @@ -330,12 +392,12 @@ pub(crate) struct ImageProperties { pub(crate) subquote2_position: f64, // as per original pub(crate) tag_position: f64, // as per original pub(crate) tag2_position: f64, // as per original - pub(crate) rgba: [u8; 4], + pub(crate) color_layer: [u8; 4], pub(crate) is_saved: bool, } -impl ImageProperties { - pub(crate) fn new() -> Self { +impl Default for ImageProperties { + fn default() -> Self { Self { path: None, dimension: (0.0, 0.0), @@ -351,12 +413,39 @@ impl ImageProperties { subquote2_position: 0.0, tag_position: 0.0, tag2_position: 0.0, - rgba: [0; 4], + color_layer: [0; 4], is_saved: true, } } } +impl ImageProperties { + pub(crate) fn merge( + &mut self, + props: ImagePropertiesFile, + tag_default: &str, + tag2_default: &str, + ) { + if let Some(v) = props.crop_position { + self.crop_position = Some(v); + } + + self.quote = props.quote.unwrap_or("".to_owned()); + self.subquote = props.subquote.unwrap_or("".to_owned()); + self.subquote2 = props.subquote2.unwrap_or("".to_owned()); + self.tag = props.tag.unwrap_or(tag_default.to_owned()); + self.tag2 = props.tag2.unwrap_or(tag2_default.to_owned()); + self.quote_position = props.quote_position.unwrap_or(self.quote_position); + self.subquote_position = props.subquote_position.unwrap_or(self.subquote_position); + self.subquote2_position = props.subquote2_position.unwrap_or(self.subquote2_position); + self.tag_position = props.tag_position.unwrap_or(self.tag_position); + self.tag2_position = props.tag2_position.unwrap_or(self.tag2_position); + self.color_layer = props + .color_layer + .unwrap_or(globals::CONFIG.read().unwrap().color_layer); + } +} + fn draw_layer_and_text( tmp: &mut DynamicImage, rgba: &[u8; 4],