From 08219a9c112bdbbec47a35383618efbd674e05a9 Mon Sep 17 00:00:00 2001 From: Marko19907 Date: Wed, 27 Dec 2023 14:09:32 +0100 Subject: [PATCH 1/8] Added serde, serde_json, and updated winresource --- Cargo.lock | 159 +++++++++++++++++++++++++++++++++-------------------- Cargo.toml | 8 ++- 2 files changed, 104 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2e8d6cd..62b7463 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,6 +10,8 @@ dependencies = [ "libloading", "native-windows-gui", "rand", + "serde", + "serde_json", "winapi", "winresource", ] @@ -28,9 +30,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "cfg-if" @@ -46,9 +48,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -57,25 +59,31 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "indexmap" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown", ] +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] @@ -88,15 +96,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libloading" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", "windows-sys", @@ -110,15 +118,15 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "muldiv" @@ -154,24 +162,24 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "plotters" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ "num-traits", "plotters-backend", @@ -181,9 +189,9 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "ppv-lite86" @@ -193,18 +201,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.28" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -239,17 +247,48 @@ dependencies = [ "getrandom", ] +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + [[package]] name = "serde" -version = "1.0.183" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +dependencies = [ + "itoa", + "ryu", + "serde", +] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -266,9 +305,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" dependencies = [ "proc-macro2", "quote", @@ -277,9 +316,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", @@ -289,18 +328,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap", "serde", @@ -311,9 +350,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-segmentation" @@ -335,9 +374,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -345,9 +384,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", @@ -360,9 +399,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -370,9 +409,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", @@ -383,15 +422,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" dependencies = [ "js-sys", "wasm-bindgen", @@ -493,18 +532,18 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.4" +version = "0.5.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acaaa1190073b2b101e15083c38ee8ec891b5e05cbee516521e94ec008f61e64" +checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" dependencies = [ "memchr", ] [[package]] name = "winresource" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba0f9a8c8deba5c08bb4ca5a03bdc3068e572d9b8ae46738fd3a78504249c23" +checksum = "77e2aaaf8cfa92078c0c0375423d631f82f2f57979c2884fdd5f604a11e45329" dependencies = [ "toml", "version_check", diff --git a/Cargo.toml b/Cargo.toml index 411ed94..522a7f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,11 +17,13 @@ ProductName = "OLEDShift" ProductVersion = "1.1.1" [build-dependencies] -winresource = "0.1.16" +winresource = "0.1.17" [dependencies] lazy_static = "1.4.0" libloading = "0.8" -native-windows-gui = { version = "1.0.13", features = ["notice", "high-dpi", "number-select"]} +native-windows-gui = { version = "1.0.13", features = ["notice", "high-dpi", "number-select"] } rand = "0.8" -winapi = { version = "0.3", features = ["winuser", "shellapi"] } +winapi = { version = "0.3", features = ["winuser", "shellapi", "windef", "minwindef", "basetsd"] } +serde = { version = "1.0.193", features = ["derive"] } +serde_json = "1.0.108" From 4b15c1678bcf990dd2ee5e6e823c2dab33ba3d09 Mon Sep 17 00:00:00 2001 From: Marko19907 Date: Wed, 27 Dec 2023 14:12:37 +0100 Subject: [PATCH 2/8] Created Settings and the SettingsManager --- src/main.rs | 1 + src/settings.rs | 158 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 src/settings.rs diff --git a/src/main.rs b/src/main.rs index 38d2a7f..fca0228 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ mod mover; mod controller; mod delay_dialog; mod distance_dialog; +mod settings; fn main() { diff --git a/src/settings.rs b/src/settings.rs new file mode 100644 index 0000000..ec07355 --- /dev/null +++ b/src/settings.rs @@ -0,0 +1,158 @@ +use std::fs::{File, write}; +use std::io::Read; +use std::sync::{Arc, Mutex}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub struct Settings { + running: bool, + delay: i32, + max_distance_x: i32, + max_distance_y: i32, +} + +impl Settings { + fn default() -> Self { + // The default settings + return Settings { + running: true, + delay: 30000, // 30 seconds // TODO: Use Delays::ThirtySeconds perhaps or move this to seconds instead of milliseconds + max_distance_x: 50, + max_distance_y: 50, + } + } + + pub fn get_running(&self) -> bool { + return self.running; + } + + pub fn set_running(&mut self, running: bool) { + self.running = running; + } + + /// Returns the delay in milliseconds + pub fn get_delay(&self) -> i32 { + return self.delay + } + + /// Sets the delay, in milliseconds + pub fn set_delay(&mut self, delay: i32) { + self.delay = delay; + } + + /// Returns the delay in seconds + pub fn get_delay_seconds(&self) -> i32 { + return self.delay / 1000; + } + + /// Sets the delay, in seconds + pub fn set_delay_seconds(&mut self, delay: i32) { + self.delay = delay * 1000; + } + + pub fn get_max_distance(&self) -> (i32, i32) { + return (self.max_distance_x, self.max_distance_y); + } + + pub fn set_max_distance(&mut self, max_distance_x: i32, max_distance_y: i32) { + self.max_distance_x = max_distance_x; + self.max_distance_y = max_distance_y; + } +} + + + +const PATH: &str = "settings.json"; + +pub struct SettingsManager { + settings: Arc>, +} + +impl SettingsManager { + pub fn new() -> Self { + println!("Loading settings..."); + + if !std::path::Path::new(PATH).exists() { + println!("No settings file found, creating default settings..."); + let settings = Settings::default(); + let serialized = serde_json::to_string_pretty(&settings).unwrap(); + write(PATH, serialized).unwrap(); + } + + let mut file = File::open(PATH).unwrap(); + let mut contents = String::new(); + file.read_to_string(&mut contents).unwrap(); + let settings: Settings = serde_json::from_str(&contents).unwrap(); + + println!("Done!"); + + return SettingsManager { + settings: Arc::new(Mutex::new(settings)), + } + } + + /// Serializes and saves the settings to the settings file + fn save_settings(settings: &Settings) { + let serialized = serde_json::to_string_pretty(settings).unwrap(); + write(PATH, serialized).unwrap(); + } + + // --------------------------------------------------------------------------------------------- + // Getters and setters + // --------------------------------------------------------------------------------------------- + + pub fn is_running(&self) -> bool { + let settings = self.settings.lock().unwrap(); + return settings.running; + } + + /// Sets the running state, and saves the settings to the settings file + pub fn set_running(&self, running: bool) { + let mut settings = self.settings.lock().unwrap(); + settings.running = running; + SettingsManager::save_settings(&*settings); + } + + /// Toggles the running state, and saves the settings to the settings file + pub fn toggle_running(&self) { + let mut settings = self.settings.lock().unwrap(); + settings.running = !settings.running; + SettingsManager::save_settings(&*settings); + } + + pub fn get_delay(&self) -> i32 { + let settings = self.settings.lock().unwrap(); + return settings.delay; + } + + /// Sets the delay, in milliseconds, and saves the settings to the settings file + pub fn set_delay(&self, delay: i32) { + let mut settings = self.settings.lock().unwrap(); + settings.delay = delay; + SettingsManager::save_settings(&*settings); + } + + pub fn get_delay_seconds(&self) -> i32 { + let settings = self.settings.lock().unwrap(); + return settings.get_delay_seconds(); + } + + /// Sets the delay, in seconds, and saves the settings to the settings file + pub fn set_delay_seconds(&self, delay: i32) { + let mut settings = self.settings.lock().unwrap(); + settings.set_delay_seconds(delay); + SettingsManager::save_settings(&*settings); + } + + pub fn get_max_distance(&self) -> (i32, i32) { + let settings = self.settings.lock().unwrap(); + return settings.get_max_distance(); + } + + /// Sets the max distance, in pixels, and saves the settings to the settings file + pub fn set_max_distance(&self, max_distance_x: i32, max_distance_y: i32) { + let mut settings = self.settings.lock().unwrap(); + settings.set_max_distance(max_distance_x, max_distance_y); + SettingsManager::save_settings(&*settings); + } +} From 51fb58a6a70882532adc27bb957b7fb7f8e7a735 Mon Sep 17 00:00:00 2001 From: Marko19907 Date: Wed, 27 Dec 2023 14:14:21 +0100 Subject: [PATCH 3/8] Updated the Controller to use the SettingsManager --- src/controller.rs | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/controller.rs b/src/controller.rs index c0ddb35..38d5859 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -3,6 +3,7 @@ use std::thread; use std::thread::sleep; use std::time::Duration; use lazy_static::lazy_static; +use crate::settings::SettingsManager; use crate::mover; /// The delays that can be selected from the tray menu, in milliseconds @@ -50,37 +51,39 @@ impl Distances { } lazy_static! { + // This is a global variable that can be accessed from anywhere in the program + // It wasn't possible to pass the max move to the mover function since it's used in a C style callback, so this is the next best thing pub static ref MAX_MOVE: Mutex<(i32, i32)> = Mutex::new((50, 50)); } pub(crate) struct Controller { - interval: i32, - running: bool, + settings_manager: SettingsManager, } impl Default for Controller { fn default() -> Self { - Self { - interval: Delays::ThirtySeconds as i32, - running: true, - } + return Self::new(); } } impl Controller { pub fn new() -> Self { - Self::default() + let controller = Controller { + settings_manager: SettingsManager::new(), + }; + controller.update_max_move(); + return controller; } pub fn run(controller: Arc>) { thread::Builder::new().name("mover_thread".to_string()).spawn(move || { - let interval = controller.lock().unwrap().interval as u64; + let interval = controller.lock().unwrap().get_interval() as u64; sleep(Duration::from_millis(interval)); // Wait for the first interval, don't move windows immediately loop { let controller = controller.lock().unwrap(); - let running = controller.running; - let interval = controller.interval as u64; + let running = controller.is_running(); + let interval = controller.get_interval() as u64; drop(controller); if running { @@ -93,26 +96,32 @@ impl Controller { } pub fn get_interval(&self) -> i32 { - self.interval + return self.settings_manager.get_delay(); } pub fn set_interval(&mut self, interval: i32) { - self.interval = interval; + self.settings_manager.set_delay(interval); } pub fn is_running(&self) -> bool { - self.running + return self.settings_manager.is_running(); } pub fn toggle_running(&mut self) { - self.running = !self.running; + self.settings_manager.toggle_running(); } pub fn get_max_move(&self) -> (i32, i32) { - return *MAX_MOVE.lock().unwrap(); + return self.settings_manager.get_max_distance(); } pub fn set_max_move(&mut self, max_move_x: i32, max_move_y: i32) { *MAX_MOVE.lock().unwrap() = (max_move_x, max_move_y); + self.settings_manager.set_max_distance(max_move_x, max_move_y); + } + + /// Updates the max move from the settings file, to be used on startup + fn update_max_move(&self) { + *MAX_MOVE.lock().unwrap() = self.settings_manager.get_max_distance(); } } From a53b4c3c47f1d69fdeb1824079cb8fddc46e9058 Mon Sep 17 00:00:00 2001 From: Marko19907 Date: Fri, 29 Dec 2023 14:52:13 +0100 Subject: [PATCH 4/8] Code cleanup --- src/controller.rs | 12 ++++++------ src/mover.rs | 2 +- src/settings.rs | 12 ++++++++++-- src/view.rs | 10 ---------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/controller.rs b/src/controller.rs index 38d5859..5897634 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -62,17 +62,17 @@ pub(crate) struct Controller { impl Default for Controller { fn default() -> Self { - return Self::new(); + let controller = Controller { + settings_manager: SettingsManager::default(), + }; + controller.update_max_move(); + return controller; } } impl Controller { pub fn new() -> Self { - let controller = Controller { - settings_manager: SettingsManager::new(), - }; - controller.update_max_move(); - return controller; + return Controller::default(); } pub fn run(controller: Arc>) { diff --git a/src/mover.rs b/src/mover.rs index c0d351b..e5c6e07 100644 --- a/src/mover.rs +++ b/src/mover.rs @@ -46,7 +46,7 @@ use winapi::{ WINDOWPLACEMENT }, }; -use winapi::um::winuser::{GetClassNameW, GetWindowTextW}; +use winapi::um::winuser::GetClassNameW; use crate::controller::{MAX_MOVE}; diff --git a/src/settings.rs b/src/settings.rs index ec07355..bdd52a6 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -19,7 +19,7 @@ impl Settings { delay: 30000, // 30 seconds // TODO: Use Delays::ThirtySeconds perhaps or move this to seconds instead of milliseconds max_distance_x: 50, max_distance_y: 50, - } + }; } pub fn get_running(&self) -> bool { @@ -32,7 +32,7 @@ impl Settings { /// Returns the delay in milliseconds pub fn get_delay(&self) -> i32 { - return self.delay + return self.delay; } /// Sets the delay, in milliseconds @@ -68,6 +68,14 @@ pub struct SettingsManager { settings: Arc>, } +impl Default for SettingsManager { + fn default() -> Self { + return SettingsManager { + settings: Arc::new(Mutex::new(Settings::default())), + }; + } +} + impl SettingsManager { pub fn new() -> Self { println!("Loading settings..."); diff --git a/src/view.rs b/src/view.rs index 087c1be..59bdb82 100644 --- a/src/view.rs +++ b/src/view.rs @@ -35,16 +35,6 @@ pub struct SystemTray { } impl SystemTray { - - fn new(&self) -> Self { - let controller = Arc::new(Mutex::new(Controller::new())); - - return SystemTray { - controller, - ..Default::default() - }; - } - fn show_menu(&self) { let (x, y) = nwg::GlobalCursor::position(); self.tray_menu.popup(x, y); From 88f329ddade09c8736e427977ae03ee3e429f2d9 Mon Sep 17 00:00:00 2001 From: Marko19907 Date: Fri, 29 Dec 2023 15:10:17 +0100 Subject: [PATCH 5/8] Added better error management to the settings manager --- src/settings.rs | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/settings.rs b/src/settings.rs index bdd52a6..f65e0f7 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -77,25 +77,39 @@ impl Default for SettingsManager { } impl SettingsManager { - pub fn new() -> Self { + pub fn new() -> Result { println!("Loading settings..."); if !std::path::Path::new(PATH).exists() { println!("No settings file found, creating default settings..."); let settings = Settings::default(); let serialized = serde_json::to_string_pretty(&settings).unwrap(); - write(PATH, serialized).unwrap(); + if let Err(err) = write(PATH, serialized) { + eprintln!("Failed to create the default settings file: {}", err); + } } - let mut file = File::open(PATH).unwrap(); - let mut contents = String::new(); - file.read_to_string(&mut contents).unwrap(); - let settings: Settings = serde_json::from_str(&contents).unwrap(); - - println!("Done!"); - - return SettingsManager { - settings: Arc::new(Mutex::new(settings)), + let result = File::open(PATH) + .and_then(|mut file| { + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + Ok(serde_json::from_str::(&contents)?) + }); + + match result { + Ok(settings) => { + println!("Settings loaded successfully!"); + Ok(SettingsManager { + settings: Arc::new(Mutex::new(settings)), + }) + } + Err(err) => { + // Send the error message back to the UI with the default settings + Err(( + err.to_string(), + SettingsManager::default(), + )) + } } } From 4043c7b4490eb06cb028743b62590b03aeb21892 Mon Sep 17 00:00:00 2001 From: Marko19907 Date: Fri, 29 Dec 2023 15:13:23 +0100 Subject: [PATCH 6/8] Introduced dialog notification for unsuccessful config file parsing --- src/controller.rs | 7 +++++++ src/view.rs | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/controller.rs b/src/controller.rs index 5897634..de634d8 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -75,6 +75,13 @@ impl Controller { return Controller::default(); } + /// Sets the settings manager for the controller + pub fn set_settings(controller: Arc>, settings: SettingsManager) { + let mut controller = controller.lock().unwrap(); + controller.settings_manager = settings; + controller.update_max_move(); + } + pub fn run(controller: Arc>) { thread::Builder::new().name("mover_thread".to_string()).spawn(move || { let interval = controller.lock().unwrap().get_interval() as u64; diff --git a/src/view.rs b/src/view.rs index 59bdb82..b809773 100644 --- a/src/view.rs +++ b/src/view.rs @@ -56,6 +56,12 @@ impl SystemTray { self.tray.show("OLEDShift", Some("OLEDShift is running in the system tray"), Some(flags), Some(&self.icon)); } + /// Shows the failed to parse the config file error message + fn show_config_parse_failed_message(&self, error_message: &str) { + let message = format!("Failed to parse the config file!\nThe default settings will be used instead.\n\nError: {}", error_message); + nwg::modal_error_message(&self.window, "Config parsing failed", &message); + } + fn do_delay(&self, delay: Delays) { match delay { Delays::ThirtySeconds => self.controller.lock().unwrap().set_interval(Delays::ThirtySeconds as i32), @@ -246,6 +252,7 @@ mod system_tray_ui { use std::cell::RefCell; use std::ops::Deref; use crate::controller::{Controller, Delays, Distances}; + use crate::settings::SettingsManager; use crate::view::{ICON, SystemTray}; pub struct SystemTrayUi { @@ -370,6 +377,12 @@ mod system_tray_ui { default_handler: Default::default(), }; + // Setup the controller + let settings_manager = SettingsManager::new().unwrap_or_else(|(err, manager)| { + ui.inner.show_config_parse_failed_message(&err); + return manager; + }); + Controller::set_settings(ui.inner.controller.clone(), settings_manager); // Start the controller Controller::run(ui.inner.controller.clone()); From a367af6b611d07ebb5bfefe725d276d9fd8f802b Mon Sep 17 00:00:00 2001 From: Marko19907 Date: Sat, 30 Dec 2023 01:52:05 +0100 Subject: [PATCH 7/8] Enhanced error handling, added checks for zero and negative values in the SettingsManager --- src/settings.rs | 74 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/src/settings.rs b/src/settings.rs index f65e0f7..556b647 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -2,21 +2,31 @@ use std::fs::{File, write}; use std::io::Read; use std::sync::{Arc, Mutex}; use serde::{Deserialize, Serialize}; +use crate::controller::Delays; #[derive(Serialize, Deserialize)] pub struct Settings { running: bool, - delay: i32, + delay_milliseconds: i32, max_distance_x: i32, max_distance_y: i32, } +/// Lowest delay allowed, in milliseconds (1 second) +pub const LOWEST_DELAY: i32 = 1000; + +/// Highest delay allowed, in milliseconds (30 minutes) +pub const MAX_DELAY: i32 = 1800000; + +/// Lowest max distance allowed, in pixels +pub const LOWEST_MAX_DISTANCE: i32 = 1; + impl Settings { fn default() -> Self { // The default settings return Settings { running: true, - delay: 30000, // 30 seconds // TODO: Use Delays::ThirtySeconds perhaps or move this to seconds instead of milliseconds + delay_milliseconds: Delays::ThirtySeconds as i32, max_distance_x: 50, max_distance_y: 50, }; @@ -32,22 +42,22 @@ impl Settings { /// Returns the delay in milliseconds pub fn get_delay(&self) -> i32 { - return self.delay; + return self.delay_milliseconds; } /// Sets the delay, in milliseconds pub fn set_delay(&mut self, delay: i32) { - self.delay = delay; + self.delay_milliseconds = delay; } /// Returns the delay in seconds pub fn get_delay_seconds(&self) -> i32 { - return self.delay / 1000; + return self.delay_milliseconds / 1000; } /// Sets the delay, in seconds pub fn set_delay_seconds(&mut self, delay: i32) { - self.delay = delay * 1000; + self.delay_milliseconds = delay * 1000; } pub fn get_max_distance(&self) -> (i32, i32) { @@ -96,8 +106,52 @@ impl SettingsManager { Ok(serde_json::from_str::(&contents)?) }); - match result { - Ok(settings) => { + return match result { + Ok(mut settings) => { + let mut errors: Vec = Vec::new(); + + // Validate the settings and update them if necessary since the user could have edited the settings file + if settings.delay_milliseconds < LOWEST_DELAY { + settings.delay_milliseconds = LOWEST_DELAY; + errors.push( + format!("The delay was too low, it has been set to the lowest possible value of {} second.", LOWEST_DELAY / 1000) + ); + } + if settings.delay_milliseconds > MAX_DELAY { + settings.delay_milliseconds = MAX_DELAY; + errors.push( + format!("The delay was too high, it has been set to the highest possible value of {} seconds.", MAX_DELAY / 1000) + ); + } + + if settings.max_distance_x < LOWEST_MAX_DISTANCE { + settings.max_distance_x = LOWEST_MAX_DISTANCE; + errors.push( + format!("The max distance X was too low, it has been set to the lowest possible value of {} pixel.", LOWEST_MAX_DISTANCE) + ); + } + if settings.max_distance_y < LOWEST_MAX_DISTANCE { + settings.max_distance_y = LOWEST_MAX_DISTANCE; + errors.push( + format!("The max distance Y was too low, it has been set to the lowest possible value of {} pixel.", LOWEST_MAX_DISTANCE) + ); + } + + if !errors.is_empty() { + println!("Found invalid values in the settings file!"); + + // Update the settings file with the valid settings + let serialized = serde_json::to_string_pretty(&settings).expect("Failed to serialize the settings"); + if let Err(err) = write(PATH, serialized) { + eprintln!("Failed to update the settings file: {}", err); + } + + return Err(( + errors.join("\n"), + SettingsManager::default(), + )); + } + println!("Settings loaded successfully!"); Ok(SettingsManager { settings: Arc::new(Mutex::new(settings)), @@ -144,13 +198,13 @@ impl SettingsManager { pub fn get_delay(&self) -> i32 { let settings = self.settings.lock().unwrap(); - return settings.delay; + return settings.delay_milliseconds; } /// Sets the delay, in milliseconds, and saves the settings to the settings file pub fn set_delay(&self, delay: i32) { let mut settings = self.settings.lock().unwrap(); - settings.delay = delay; + settings.delay_milliseconds = delay; SettingsManager::save_settings(&*settings); } From 7345a5ce0b208c6067948647cedfe67a67fac3e4 Mon Sep 17 00:00:00 2001 From: Marko19907 Date: Sat, 30 Dec 2023 01:53:22 +0100 Subject: [PATCH 8/8] Use the new constants from the Settings in the dialogs --- src/delay_dialog.rs | 7 ++++--- src/distance_dialog.rs | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/delay_dialog.rs b/src/delay_dialog.rs index 152bdf1..5294f7d 100644 --- a/src/delay_dialog.rs +++ b/src/delay_dialog.rs @@ -1,5 +1,6 @@ use std::{thread, cell::RefCell}; use nwg::{ControlHandle, NativeUi, NumberSelectData}; +use crate::settings::{LOWEST_DELAY, MAX_DELAY}; pub enum DelayDialogData { Cancel, @@ -28,9 +29,9 @@ impl DelayDialog { let number_select_data = NumberSelectData::Int { value: (current_value / 1000) as i64, - step: 1, // 1 second - max: 1800, // 30 minutes - min: 1, // 1 second + step: 1, // 1 second steps + max: MAX_DELAY as i64, // 30 minutes + min: LOWEST_DELAY as i64, // 1 second }; app.number_select.set_data(number_select_data); diff --git a/src/distance_dialog.rs b/src/distance_dialog.rs index 9e29b61..dde2ee5 100644 --- a/src/distance_dialog.rs +++ b/src/distance_dialog.rs @@ -1,6 +1,7 @@ use crate::mover; use std::{thread, cell::RefCell}; use nwg::{ControlHandle, NativeUi, NumberSelectData}; +use crate::settings::LOWEST_MAX_DISTANCE; pub enum DistanceDialogData { Cancel, @@ -35,7 +36,7 @@ impl DistanceDialog { value: current_value_x as i64, step: 1, max: smallest_x as i64 / 4, - min: 1, + min: LOWEST_MAX_DISTANCE as i64, }; app.number_select_x.set_data(number_select_data_x); @@ -43,7 +44,7 @@ impl DistanceDialog { value: current_value_y as i64, step: 1, max: smallest_y as i64 / 4, - min: 1, + min: LOWEST_MAX_DISTANCE as i64, }; app.number_select_y.set_data(number_select_data_y);