From 75d093e5df7c75745467fde1410478616ebb1256 Mon Sep 17 00:00:00 2001 From: Piyush Mishra Date: Sun, 23 Jan 2022 13:26:03 +0530 Subject: [PATCH] Support for multiple congifs --- .vscode/launch.json | 45 ++++++ src/config.rs | 93 +++++------ src/config_picker.rs | 84 ++++++++++ src/config_window.rs | 371 +++++++++++++++++++++++++++++++++++++++---- src/globals.rs | 12 +- src/main.rs | 3 +- src/main_window.rs | 4 +- src/utils.rs | 25 +-- 8 files changed, 535 insertions(+), 102 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 src/config_picker.rs diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..6e65dd8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,45 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'post_maker'", + "cargo": { + "args": [ + "build", + "--bin=post_maker", + "--package=post_maker" + ], + "filter": { + "name": "post_maker", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'post_maker'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=post_maker", + "--package=post_maker" + ], + "filter": { + "name": "post_maker", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index 5c14816..7d5fb74 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,13 +1,25 @@ //! load, save configuration and parse cli args -use std::collections::HashMap; - +use crate::{config_picker::ConfigPicker, globals}; use clap::{ArgEnum, Parser}; use fltk::dialog; use fltk_theme::ThemeType; +use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, path::PathBuf}; -use crate::globals; +lazy_static! { + pub static ref CONFIG_PATH: PathBuf = { + match dirs::config_dir() { + Some(path) => path.join("post_maker.config"), + None => std::env::current_exe() + .unwrap() + .parent() + .unwrap() + .join("post_maker.config"), + } + }; +} /// Simple program calculate size of stuff in quote image #[derive(Parser, Debug)] @@ -85,7 +97,7 @@ impl Default for ConfigFile { tag_font_ratio: 150.0, quote_position_ratio: 0.7, tag_position_ratio: 0.5, - image_ratio: (4.0, 4.0), + image_ratio: (4.0, 5.0), color_layer: [20, 22, 25, 197], } } @@ -93,63 +105,52 @@ impl Default for ConfigFile { impl ConfigFile { pub(crate) fn load() -> Self { - let conf = match dirs::config_dir() { - Some(path) => path.join("post_maker.config"), - None => std::env::current_exe() - .unwrap() - .parent() - .unwrap() - .join("post_maker.config"), - }; - - if conf.exists() { - let map = match std::fs::read_to_string(&conf) { - Ok(r) => serde_json::from_str::>(&r).ok(), - Err(_) => None, - }; + // config_picker::ConfigPicker::new(); + if CONFIG_PATH.exists() { + let map = get_configs(); let map = match map { Some(m) => m, None => HashMap::new(), }; - if let Some(config) = map.get(&*globals::CONFIG_NAME.read().unwrap()) { + let default_config = (&*globals::CONFIG_NAME.read().unwrap()).to_string(); + let config_name = if map.len() > 1 || !map.contains_key(&default_config) { + ConfigPicker::new(map.keys().map(|a| a.to_owned()).collect()) + .selected() + .unwrap_or(default_config) + } else { + default_config + }; + + if let Some(config) = map.get(&config_name) { + *globals::CONFIG_NAME.write().unwrap() = config_name; return config.to_owned(); } } let config = Self::default(); - config.save(); + let mut configs = HashMap::new(); + configs.insert( + (&*globals::CONFIG_NAME.read().unwrap()).to_owned(), + config.clone(), + ); + save_configs(configs); 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() - .unwrap() - .parent() - .unwrap() - .join("post_maker.config"), - }; +pub(crate) fn get_configs() -> Option> { + match std::fs::read_to_string(&*CONFIG_PATH) { + Ok(r) => serde_json::from_str::>(&r).ok(), + Err(_) => None, + } +} - 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!"); - } +pub(crate) fn save_configs(configs: HashMap) { + if let Err(_) = std::fs::write(&*CONFIG_PATH, serde_json::to_string(&configs).unwrap()) { + dialog::alert_default("Can't write config!"); + eprintln!("Can't write config!"); } } diff --git a/src/config_picker.rs b/src/config_picker.rs new file mode 100644 index 0000000..ad0a354 --- /dev/null +++ b/src/config_picker.rs @@ -0,0 +1,84 @@ +use crate::globals; +use fltk::{ + app, + browser::{Browser, BrowserType}, + button::Button, + frame::Frame, + group::Flex, + image::SvgImage, + prelude::*, + window::Window, +}; + +pub(crate) struct ConfigPicker { + pub(crate) win: Window, + pub(crate) browse: Browser, + pub(crate) apply_btn: Button, + pub(crate) configs: Vec, +} + +impl ConfigPicker { + pub(crate) fn new(configs: Vec) -> Self { + let mut win = Window::new(0, 0, 500, 400, "Configurations").center_screen(); + win.set_icon(Some( + SvgImage::from_data(globals::ICON.to_str().unwrap()).unwrap(), + )); + + let mut main_flex = Flex::default().size_of_parent().column(); + + // Work area + let mut browse = Browser::default().with_type(BrowserType::Hold); + for name in &configs { + browse.add(&name); + } + browse.select(1); + + // Panel + let top_padding_btn = Frame::default(); + let mut panel_flex = Flex::default().row(); + Frame::default(); + let apply_btn = Button::default().with_label("apply"); + Frame::default(); + panel_flex.set_size(&apply_btn, 100); + panel_flex.end(); + let bottom_padding_btn = Frame::default(); + + main_flex.set_size(&top_padding_btn, 5); + main_flex.set_size(&panel_flex, 30); + main_flex.set_size(&bottom_padding_btn, 5); + main_flex.end(); + + win.end(); + win.make_resizable(true); + + let mut config_picker = Self { + win, + browse, + apply_btn, + configs, + }; + config_picker.event(); + + config_picker.win.show(); + while config_picker.win.shown() { + app::wait(); + } + config_picker + } + + fn event(&mut self) { + let mut win = self.win.clone(); + self.apply_btn.set_callback(move |_| { + win.hide(); + }); + } + + pub(crate) fn selected(&self) -> Option { + let idx = self.browse.value(); + if idx == 0 { + None + } else { + self.configs.get(idx as usize - 1).map(|a| a.to_owned()) + } + } +} diff --git a/src/config_window.rs b/src/config_window.rs index ee2e021..43c0455 100644 --- a/src/config_window.rs +++ b/src/config_window.rs @@ -1,9 +1,10 @@ //! Window to edit configuration -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; use fltk::{ app, + browser::{Browser, BrowserType}, button::Button, dialog::{self, FileDialogOptions, NativeFileChooser}, enums::{Align, Font}, @@ -17,16 +18,27 @@ use fltk::{ window::Window, }; -use crate::{config::ConfigFile, globals}; +use crate::{ + config::{self, ConfigFile}, + globals, +}; pub(crate) struct ConfigWindow { pub(crate) win: Window, + pub(crate) browse: Browser, + pub(crate) selected_browse_line: Rc>, + pub(crate) add_config_btn: Button, + pub(crate) del_config_btn: Button, pub(crate) quote_font_ttf: Output, pub(crate) quote_font_ttf_browse: Button, pub(crate) tag_font_ttf: Output, pub(crate) tag_font_ttf_browse: Button, pub(crate) quote_font_ratio: ValueInput, pub(crate) tag_font_ratio: ValueInput, + pub(crate) quote_position_ratio: ValueInput, + pub(crate) tag_position_ratio: ValueInput, + pub(crate) image_ratio_width: ValueInput, + pub(crate) image_ratio_height: ValueInput, pub(crate) layer_red: Spinner, pub(crate) layer_green: Spinner, pub(crate) layer_blue: Spinner, @@ -34,24 +46,48 @@ pub(crate) struct ConfigWindow { pub(crate) defaults_btn: Button, pub(crate) save_btn: Button, pub(crate) cancel_btn: Button, + pub(crate) configs: Rc>>, did_save: Rc>, } impl ConfigWindow { pub(crate) fn new() -> Self { - let mut win = Window::new(0, 0, 500, 300, "Config").center_screen(); + let configs = config::get_configs().unwrap_or(HashMap::new()); + let mut win = Window::new(0, 0, 700, 450, "Config").center_screen(); win.set_icon(Some( SvgImage::from_data(globals::ICON.to_str().unwrap()).unwrap(), )); + let mut row = Flex::default().with_size(690, 440).with_pos(5, 5).row(); + let mut config_picker_flex = Flex::default().column(); + // Picker + let browse = Browser::default().with_type(BrowserType::Hold); - let mut col = Flex::default().with_size(490, 290).with_pos(5, 5).column(); + // Panel + let top_padding_btn = Frame::default(); + let mut panel_flex = Flex::default().row(); + Frame::default(); + let add_config_btn = Button::default().with_label("add"); + let del_config_btn = Button::default().with_label("delete"); + Frame::default(); + panel_flex.set_size(&add_config_btn, 50); + panel_flex.set_size(&del_config_btn, 50); + panel_flex.end(); + let bottom_padding_btn = Frame::default(); + + config_picker_flex.set_size(&top_padding_btn, 5); + config_picker_flex.set_size(&panel_flex, 30); + config_picker_flex.set_size(&bottom_padding_btn, 5); + config_picker_flex.end(); + row.set_size(&config_picker_flex, 200); + + let mut col = Flex::default().column(); let mut quote_font_ttf_grp = Flex::default().row(); quote_font_ttf_grp.set_size( &Frame::default() .with_label("Font for quote (ttf)") .with_align(Align::Right | Align::Inside), - 160, + 170, ); let quote_font_ttf = Output::default(); let quote_font_ttf_browse = Button::default().with_label("Pick"); @@ -64,7 +100,7 @@ impl ConfigWindow { &Frame::default() .with_label("Font for tag (ttf)") .with_align(Align::Right | Align::Inside), - 160, + 170, ); let tag_font_ttf = Output::default(); let tag_font_ttf_browse = Button::default().with_label("Pick"); @@ -77,14 +113,14 @@ impl ConfigWindow { &Frame::default() .with_label("Quote text size ratio") .with_align(Align::Right | Align::Inside), - 160, + 170, ); let quote_font_ratio = ValueInput::default(); quote_font_ratio_grp.end(); col.set_size("e_font_ratio_grp, 30); let mut grp = Flex::default().row(); - grp.set_size(&Frame::default(), 160); + grp.set_size(&Frame::default(), 170); let mut hint = Frame::default() .with_label("Font size in image of resolution 4000x5000") .with_align(Align::Left | Align::Inside); @@ -98,14 +134,14 @@ impl ConfigWindow { &Frame::default() .with_label("Tag text size ratio") .with_align(Align::Right | Align::Inside), - 160, + 170, ); let tag_font_ratio = ValueInput::default(); tag_font_ratio_grp.end(); col.set_size(&tag_font_ratio_grp, 30); let mut grp = Flex::default().row(); - grp.set_size(&Frame::default(), 160); + grp.set_size(&Frame::default(), 170); let mut hint = Frame::default() .with_label("Font size in image of resolution 4000x5000") .with_align(Align::Left | Align::Inside); @@ -114,6 +150,41 @@ impl ConfigWindow { grp.end(); col.set_size(&grp, 13); + let mut quote_position_ratio_grp = Flex::default().row(); + quote_position_ratio_grp.set_size( + &Frame::default() + .with_label("Quote text position ratio") + .with_align(Align::Right | Align::Inside), + 170, + ); + let quote_position_ratio = ValueInput::default(); + quote_position_ratio_grp.end(); + col.set_size("e_position_ratio_grp, 30); + + let mut tag_position_ratio_grp = Flex::default().row(); + tag_position_ratio_grp.set_size( + &Frame::default() + .with_label("Tag text position ratio") + .with_align(Align::Right | Align::Inside), + 170, + ); + let tag_position_ratio = ValueInput::default(); + tag_position_ratio_grp.end(); + col.set_size(&tag_position_ratio_grp, 30); + + let mut image_ratio_grp = Flex::default().row(); + image_ratio_grp.set_size( + &Frame::default() + .with_label("Image size ratio") + .with_align(Align::Right | Align::Inside), + 170, + ); + let image_ratio_width = ValueInput::default(); + image_ratio_grp.set_size(&Frame::default().with_label("x"), 30); + let image_ratio_height = ValueInput::default(); + image_ratio_grp.end(); + col.set_size(&image_ratio_grp, 30); + col.set_size( &Frame::default().with_label("Default colour shader to use with new images:"), 30, @@ -155,18 +226,27 @@ impl ConfigWindow { col.set_size(&panel_grp, 30); col.end(); + row.end(); win.end(); win.make_modal(true); win.make_resizable(true); let mut config_window = Self { win, + browse, + selected_browse_line: Rc::new(RefCell::new(0)), + add_config_btn, + del_config_btn, quote_font_ttf, quote_font_ttf_browse, tag_font_ttf, tag_font_ttf_browse, quote_font_ratio, tag_font_ratio, + quote_position_ratio, + tag_position_ratio, + image_ratio_width, + image_ratio_height, layer_red, layer_green, layer_blue, @@ -174,6 +254,7 @@ impl ConfigWindow { defaults_btn, save_btn, cancel_btn, + configs: Rc::new(RefCell::new(configs)), did_save: Rc::new(RefCell::new(false)), }; config_window.event(); @@ -182,17 +263,32 @@ impl ConfigWindow { } pub(crate) fn show(&mut self) -> bool { - let glob = globals::CONFIG.read().unwrap(); - self.quote_font_ttf.set_value(glob.quote_font_ttf.as_str()); - self.tag_font_ttf.set_value(glob.tag_font_ttf.as_str()); - self.quote_font_ratio.set_value(glob.quote_font_ratio); - self.tag_font_ratio.set_value(glob.tag_font_ratio); - self.layer_red.set_value(glob.color_layer[0] as f64); - self.layer_green.set_value(glob.color_layer[1] as f64); - self.layer_blue.set_value(glob.color_layer[2] as f64); - self.layer_alpha.set_value(glob.color_layer[3] as f64); + let config_name = &*globals::CONFIG_NAME.read().unwrap(); + self.browse.clear(); + for (idx, name) in self.configs.borrow().keys().enumerate() { + self.browse.add(name); + if name == config_name { + self.browse.select(idx as i32 + 1); + } + } + *self.selected_browse_line.borrow_mut() = self.browse.value(); + let config = globals::CONFIG.read().unwrap(); + self.quote_font_ttf + .set_value(config.quote_font_ttf.as_str()); + self.tag_font_ttf.set_value(config.tag_font_ttf.as_str()); + self.quote_font_ratio.set_value(config.quote_font_ratio); + self.tag_font_ratio.set_value(config.tag_font_ratio); + self.quote_position_ratio + .set_value(config.quote_position_ratio); + self.tag_position_ratio.set_value(config.tag_position_ratio); + self.image_ratio_width.set_value(config.image_ratio.0); + self.image_ratio_height.set_value(config.image_ratio.1); + self.layer_red.set_value(config.color_layer[0] as f64); + self.layer_green.set_value(config.color_layer[1] as f64); + self.layer_blue.set_value(config.color_layer[2] as f64); + self.layer_alpha.set_value(config.color_layer[3] as f64); *self.did_save.borrow_mut() = false; - drop(glob); + drop(config); self.win.show(); while self.win.shown() { app::wait(); @@ -201,6 +297,190 @@ impl ConfigWindow { } fn event(&mut self) { + let mut quote_font_ttf = self.quote_font_ttf.clone(); + let mut tag_font_ttf = self.tag_font_ttf.clone(); + let mut quote_font_ratio = self.quote_font_ratio.clone(); + let mut tag_font_ratio = self.tag_font_ratio.clone(); + let mut quote_position_ratio = self.quote_position_ratio.clone(); + let mut tag_position_ratio = self.tag_position_ratio.clone(); + let mut image_ratio_width = self.image_ratio_width.clone(); + let mut image_ratio_height = self.image_ratio_height.clone(); + let mut layer_red = self.layer_red.clone(); + let mut layer_green = self.layer_green.clone(); + let mut layer_blue = self.layer_blue.clone(); + let mut layer_alpha = self.layer_alpha.clone(); + let mut browse = self.browse.clone(); + let configs = Rc::clone(&self.configs); + let selected_browse_line = Rc::clone(&self.selected_browse_line); + self.add_config_btn.set_callback(move |_| { + let name = loop { + let name = dialog::input_default("Enter new config's name", ""); + match name { + Some(name) => { + let name = name.trim(); + if name == "" { + dialog::alert_default("Name is empty!"); + } else if !configs.borrow().contains_key(name) { + break name.to_owned(); + } else { + dialog::alert_default("Name is already used!"); + } + } + None => { + return; + } + } + }; + + if let Some(conf) = configs + .borrow_mut() + .get_mut(&browse.selected_text().unwrap()) + { + conf.quote_font_ttf = quote_font_ttf.value(); + conf.tag_font_ttf = tag_font_ttf.value(); + conf.quote_font_ratio = quote_font_ratio.value(); + conf.tag_font_ratio = tag_font_ratio.value(); + conf.quote_position_ratio = quote_position_ratio.value(); + conf.tag_position_ratio = tag_position_ratio.value(); + conf.image_ratio = (image_ratio_width.value(), image_ratio_height.value()); + conf.color_layer = [ + layer_red.value() as u8, + layer_green.value() as u8, + layer_blue.value() as u8, + layer_alpha.value() as u8, + ]; + } + + let conf = ConfigFile::default(); + quote_font_ttf.set_value(&conf.quote_font_ttf); + tag_font_ttf.set_value(&conf.tag_font_ttf); + quote_font_ratio.set_value(conf.quote_font_ratio); + tag_font_ratio.set_value(conf.tag_font_ratio); + quote_position_ratio.set_value(conf.quote_position_ratio); + tag_position_ratio.set_value(conf.tag_position_ratio); + image_ratio_width.set_value(conf.image_ratio.0); + image_ratio_height.set_value(conf.image_ratio.1); + layer_red.set_value(conf.color_layer[0] as f64); + layer_green.set_value(conf.color_layer[1] as f64); + layer_blue.set_value(conf.color_layer[2] as f64); + layer_alpha.set_value(conf.color_layer[3] as f64); + browse.add(&name); + configs.borrow_mut().insert(name.clone(), conf); + browse.select(browse.size()); + *selected_browse_line.borrow_mut() = browse.value(); + }); + + let mut quote_font_ttf = self.quote_font_ttf.clone(); + let mut tag_font_ttf = self.tag_font_ttf.clone(); + let mut quote_font_ratio = self.quote_font_ratio.clone(); + let mut tag_font_ratio = self.tag_font_ratio.clone(); + let mut quote_position_ratio = self.quote_position_ratio.clone(); + let mut tag_position_ratio = self.tag_position_ratio.clone(); + let mut image_ratio_width = self.image_ratio_width.clone(); + let mut image_ratio_height = self.image_ratio_height.clone(); + let mut layer_red = self.layer_red.clone(); + let mut layer_green = self.layer_green.clone(); + let mut layer_blue = self.layer_blue.clone(); + let mut layer_alpha = self.layer_alpha.clone(); + let mut browse = self.browse.clone(); + let configs = Rc::clone(&self.configs); + let selected_browse_line = Rc::clone(&self.selected_browse_line); + self.del_config_btn.set_callback(move |_| { + let ch = dialog::choice_default("Do you want to delete??", "Yes", "No", ""); + if ch == 1 { + return; + } + if browse.size() == 1 { + dialog::alert_default("Atleast one config should exist!"); + return; + } + let line = browse.value(); + configs + .borrow_mut() + .remove(&browse.selected_text().unwrap()); + browse.remove(browse.value()); + + let line = if browse.size() < line { line - 1 } else { line }; + browse.select(line); + *selected_browse_line.borrow_mut() = browse.value(); + + if let Some(conf) = configs.borrow().get(&browse.selected_text().unwrap()) { + quote_font_ttf.set_value(&conf.quote_font_ttf); + tag_font_ttf.set_value(&conf.tag_font_ttf); + quote_font_ratio.set_value(conf.quote_font_ratio); + tag_font_ratio.set_value(conf.tag_font_ratio); + quote_position_ratio.set_value(conf.quote_position_ratio); + tag_position_ratio.set_value(conf.tag_position_ratio); + image_ratio_width.set_value(conf.image_ratio.0); + image_ratio_height.set_value(conf.image_ratio.1); + layer_red.set_value(conf.color_layer[0] as f64); + layer_green.set_value(conf.color_layer[1] as f64); + layer_blue.set_value(conf.color_layer[2] as f64); + layer_alpha.set_value(conf.color_layer[3] as f64); + } + }); + + let mut quote_font_ttf = self.quote_font_ttf.clone(); + let mut tag_font_ttf = self.tag_font_ttf.clone(); + let mut quote_font_ratio = self.quote_font_ratio.clone(); + let mut tag_font_ratio = self.tag_font_ratio.clone(); + let mut quote_position_ratio = self.quote_position_ratio.clone(); + let mut tag_position_ratio = self.tag_position_ratio.clone(); + let mut image_ratio_width = self.image_ratio_width.clone(); + let mut image_ratio_height = self.image_ratio_height.clone(); + let mut layer_red = self.layer_red.clone(); + let mut layer_green = self.layer_green.clone(); + let mut layer_blue = self.layer_blue.clone(); + let mut layer_alpha = self.layer_alpha.clone(); + let configs = Rc::clone(&self.configs); + let selected_browse_line = Rc::clone(&self.selected_browse_line); + self.browse.set_callback(move |f| { + if f.value() == 0 { + f.select(*selected_browse_line.borrow()); + return; + } + + if *selected_browse_line.borrow() == f.value() { + return; + } + + if let Some(conf) = configs + .borrow_mut() + .get_mut(&f.text(*selected_browse_line.borrow()).unwrap()) + { + conf.quote_font_ttf = quote_font_ttf.value(); + conf.tag_font_ttf = tag_font_ttf.value(); + conf.quote_font_ratio = quote_font_ratio.value(); + conf.tag_font_ratio = tag_font_ratio.value(); + conf.quote_position_ratio = quote_position_ratio.value(); + conf.tag_position_ratio = tag_position_ratio.value(); + conf.image_ratio = (image_ratio_width.value(), image_ratio_height.value()); + conf.color_layer = [ + layer_red.value() as u8, + layer_green.value() as u8, + layer_blue.value() as u8, + layer_alpha.value() as u8, + ]; + } + + if let Some(conf) = configs.borrow().get(&f.selected_text().unwrap()) { + quote_font_ttf.set_value(&conf.quote_font_ttf); + tag_font_ttf.set_value(&conf.tag_font_ttf); + quote_font_ratio.set_value(conf.quote_font_ratio); + tag_font_ratio.set_value(conf.tag_font_ratio); + quote_position_ratio.set_value(conf.quote_position_ratio); + tag_position_ratio.set_value(conf.tag_position_ratio); + image_ratio_width.set_value(conf.image_ratio.0); + image_ratio_height.set_value(conf.image_ratio.1); + layer_red.set_value(conf.color_layer[0] as f64); + layer_green.set_value(conf.color_layer[1] as f64); + layer_blue.set_value(conf.color_layer[2] as f64); + layer_alpha.set_value(conf.color_layer[3] as f64); + } + *selected_browse_line.borrow_mut() = f.value(); + // println!("browse {:?}", selected_config_name); + }); + let mut quote_font_ttf = self.quote_font_ttf.clone(); self.quote_font_ttf_browse.set_callback(move |_| { let mut chooser = NativeFileChooser::new(fltk::dialog::FileDialogType::BrowseFile); @@ -208,6 +488,7 @@ impl ConfigWindow { chooser.set_filter("*.ttf"); chooser.show(); let path = chooser.filename(); + let path = std::fs::canonicalize(&path).unwrap_or(path); quote_font_ttf.set_value(path.to_str().unwrap()); }); @@ -230,6 +511,10 @@ impl ConfigWindow { let mut tag_font_ttf = self.tag_font_ttf.clone(); let mut quote_font_ratio = self.quote_font_ratio.clone(); let mut tag_font_ratio = self.tag_font_ratio.clone(); + let mut quote_position_ratio = self.quote_position_ratio.clone(); + let mut tag_position_ratio = self.tag_position_ratio.clone(); + let mut image_ratio_width = self.image_ratio_width.clone(); + let mut image_ratio_height = self.image_ratio_height.clone(); let mut layer_red = self.layer_red.clone(); let mut layer_green = self.layer_green.clone(); let mut layer_blue = self.layer_blue.clone(); @@ -240,44 +525,60 @@ impl ConfigWindow { tag_font_ttf.set_value(&conf.tag_font_ttf); quote_font_ratio.set_value(conf.quote_font_ratio); tag_font_ratio.set_value(conf.tag_font_ratio); + quote_position_ratio.set_value(conf.quote_position_ratio); + tag_position_ratio.set_value(conf.tag_position_ratio); + image_ratio_width.set_value(conf.image_ratio.0); + image_ratio_height.set_value(conf.image_ratio.1); layer_red.set_value(conf.color_layer[0] as f64); layer_green.set_value(conf.color_layer[1] as f64); layer_blue.set_value(conf.color_layer[2] as f64); layer_alpha.set_value(conf.color_layer[3] as f64); }); - let mut win = self.win.clone(); let quote_font_ttf = self.quote_font_ttf.clone(); let tag_font_ttf = self.tag_font_ttf.clone(); let quote_font_ratio = self.quote_font_ratio.clone(); let tag_font_ratio = self.tag_font_ratio.clone(); + let quote_position_ratio = self.quote_position_ratio.clone(); + let tag_position_ratio = self.tag_position_ratio.clone(); + let image_ratio_width = self.image_ratio_width.clone(); + let image_ratio_height = self.image_ratio_height.clone(); let layer_red = self.layer_red.clone(); let layer_green = self.layer_green.clone(); let layer_blue = self.layer_blue.clone(); let layer_alpha = self.layer_alpha.clone(); + let browse = self.browse.clone(); + let configs = Rc::clone(&self.configs); let did_save = Rc::clone(&self.did_save); + let mut win = self.win.clone(); self.save_btn.set_callback(move |_| { - let conf = ConfigFile { - quote_font_ttf: quote_font_ttf.value(), - 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: [ + if let Some(conf) = configs + .borrow_mut() + .get_mut(&browse.selected_text().unwrap()) + { + conf.quote_font_ttf = quote_font_ttf.value(); + conf.tag_font_ttf = tag_font_ttf.value(); + conf.quote_font_ratio = quote_font_ratio.value(); + conf.tag_font_ratio = tag_font_ratio.value(); + conf.quote_position_ratio = quote_position_ratio.value(); + conf.tag_position_ratio = tag_position_ratio.value(); + conf.image_ratio = (image_ratio_width.value(), image_ratio_height.value()); + conf.color_layer = [ layer_red.value() as u8, layer_green.value() as u8, layer_blue.value() as u8, layer_alpha.value() as u8, - ], - }; + ]; + } - conf.save(); - *globals::CONFIG.write().unwrap() = conf; + config::save_configs((*configs.borrow()).clone()); + + if let Some(c) = configs.borrow().get(&*globals::CONFIG_NAME.read().unwrap()) { + *globals::CONFIG.write().unwrap() = c.to_owned(); + } *did_save.borrow_mut() = true; win.hide(); - dialog::message_default("Re-open Post Maker to see changes!") + dialog::message_default("Re-open Post Maker to see changes properly!") }); } } diff --git a/src/globals.rs b/src/globals.rs index ad8ee2b..8cdc2ab 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -7,12 +7,12 @@ 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 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/main.rs b/src/main.rs index e322a1b..a66e927 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ #![windows_subsystem = "windows"] mod config; +mod config_picker; mod config_window; mod crop_window; mod draw_thread; @@ -25,8 +26,8 @@ pub(crate) enum AppMessage { fn main() { let app = App::default(); - WidgetTheme::new(globals::THEME.clone().into()).apply(); + lazy_static::initialize(&globals::CONFIG); let draw_buff: Arc>>> = Arc::new(RwLock::new(None)); let (main_sender, main_receiver) = channel::(); diff --git a/src/main_window.rs b/src/main_window.rs index 9a86367..d41c4e2 100644 --- a/src/main_window.rs +++ b/src/main_window.rs @@ -287,7 +287,7 @@ impl MainWindow { let expost_dir = path.join("export"); if !expost_dir.exists() { if let Err(_) = fs::create_dir(expost_dir) { - fltk::dialog::message_default("Failed: Readonly folder!"); + fltk::dialog::alert_default("Failed: create export folder!"); return; } } @@ -329,7 +329,7 @@ impl MainWindow { Shortcut::None, menu::MenuFlag::Normal, move |_| { - dialog::message_default( + dialog::alert_default( "Created with <3 by PiyushXCoder\nhttps://github.com/PiyushXCoder", ); }, diff --git a/src/utils.rs b/src/utils.rs index 34d08ca..eeea3d0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -60,7 +60,7 @@ impl ImageContainer { let img = match image::open(path) { Ok(i) => i, Err(_) => { - dialog::message_default("Failed to open image"); + dialog::alert_default("Failed to open image!"); panic!("Failed to open image"); } }; @@ -69,11 +69,12 @@ impl ImageContainer { 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(); prop.path = Some(path.to_owned()); prop.original_dimension = (width, height); - prop.quote_position = height * &*globals::QUOTE_POSITION_RATIO.read().unwrap(); - prop.tag_position = height * &*globals::TAG_POSITION_RATIO.read().unwrap(); + prop.quote_position = height * config.quote_position_ratio; + prop.tag_position = height * config.tag_position_ratio; Self { image: img.clone(), @@ -172,7 +173,7 @@ impl ImageContainer { let mut prop = prop.clone(); prop.path = None; if fs::write(&path_conf, serde_json::to_string(&prop).unwrap()).is_err() { - dialog::message_default("Failed to save conf!"); + dialog::alert_default("Failed to save conf!"); } let mut img = image::open(&path_original).unwrap(); @@ -200,7 +201,7 @@ impl ImageContainer { .save_with_format(&export, image::ImageFormat::Png) .is_err() { - dialog::message_default("Failed to export png!"); + dialog::alert_default("Failed to export png!"); } } @@ -223,12 +224,12 @@ impl ImageContainer { let path_conf_new = new_path.with_extension("conf"); if path.exists() && fs::copy(path, &new_path).is_err() { - dialog::message_default("Failed to clone image!"); + dialog::alert_default("Failed to clone image!"); return None; } if path_conf.exists() && fs::copy(path_conf, &path_conf_new).is_err() { - dialog::message_default("Failed to clone image!"); + dialog::alert_default("Failed to clone image!"); return None; } Some(new_path) @@ -255,15 +256,15 @@ impl ImageContainer { ); if path_original.exists() && fs::remove_file(path_original).is_err() { - dialog::message_default("Failed to delete image!"); + dialog::alert_default("Failed to delete image!"); } if path_conf.exists() && fs::remove_file(path_conf).is_err() { - dialog::message_default("Failed to delete image conf!"); + dialog::alert_default("Failed to delete image conf!"); } if export.exists() && fs::remove_file(export).is_err() { - dialog::message_default("Failed to delete exported image!"); + dialog::alert_default("Failed to delete exported image!"); } } } @@ -364,12 +365,12 @@ pub(crate) fn croped_ratio(width: f64, height: f64) -> (f64, f64) { } pub(crate) fn width_from_height(height: f64) -> f64 { - let (w, h) = &*globals::IMAGE_RATIO.read().unwrap(); + let (w, h) = globals::CONFIG.read().unwrap().image_ratio; (w * height) / h } pub(crate) fn height_from_width(width: f64) -> f64 { - let (w, h) = &*globals::IMAGE_RATIO.read().unwrap(); + let (w, h) = globals::CONFIG.read().unwrap().image_ratio; (h * width) / w }