diff --git a/app/src/cli.rs b/app/src/cli.rs index e07614d..3ed4998 100644 --- a/app/src/cli.rs +++ b/app/src/cli.rs @@ -6,8 +6,8 @@ use strum::IntoEnumIterator; use thiserror::Error; use crate::{ - effects::{self, custom_effect::CustomEffect, ManagerCreationError}, enums::{Brightness, Direction, Effects}, + manager::{self, custom_effect::CustomEffect, ManagerCreationError}, profile::{self, Profile}, }; @@ -152,7 +152,7 @@ pub fn try_cli() -> Result { } fn handle_cli_output(output_type: OutputType) -> Result { - let manager_result = effects::EffectManager::new(effects::OperationMode::Cli); + let manager_result = manager::EffectManager::new(manager::OperationMode::Cli); let instance_not_unique = manager_result .as_ref() .err() @@ -205,8 +205,8 @@ fn parse_cli() -> Result { [0; 12] }; - let profile = Profile { - name: "Profile".to_string(), + let mut profile = Profile { + name: None, rgb_zones: profile::arr_to_zones(rgb_array), effect, direction, diff --git a/app/src/enums.rs b/app/src/enums.rs index 7d8054d..6b6b86c 100644 --- a/app/src/enums.rs +++ b/app/src/enums.rs @@ -1,4 +1,4 @@ -use crate::{effects::custom_effect::CustomEffect, profile::Profile}; +use crate::{manager::custom_effect::CustomEffect, profile::Profile}; use serde::{Deserialize, Serialize}; use strum_macros::{Display, EnumIter, EnumString, IntoStaticStr}; diff --git a/app/src/gui/effect_options.rs b/app/src/gui/effect_options.rs deleted file mode 100644 index 4ca2cb7..0000000 --- a/app/src/gui/effect_options.rs +++ /dev/null @@ -1,69 +0,0 @@ -use eframe::egui::{ComboBox, Slider, Ui}; -use legion_rgb_driver::SPEED_RANGE; -use strum::IntoEnumIterator; - -use crate::{ - enums::{Brightness, Direction, Effects}, - profile::Profile, -}; - -use super::style::SpacingStyle; - -#[derive(Default)] -pub struct EffectOptions; - -const COMBOBOX_WIDTH: f32 = 20.0; - -impl EffectOptions { - pub fn show(&mut self, ui: &mut Ui, profile: &mut Profile, update_lights: &mut bool, spacing: &SpacingStyle) { - ui.scope(|ui| { - ui.style_mut().spacing.item_spacing = spacing.default; - - ComboBox::from_label("Brightness") - .width(COMBOBOX_WIDTH) - .selected_text({ - let text: &'static str = profile.brightness.into(); - text - }) - .show_ui(ui, |ui| { - for val in Brightness::iter() { - let text: &'static str = val.into(); - *update_lights |= ui.selectable_value(&mut profile.brightness, val, text).changed(); - } - }); - - ui.add_enabled_ui(profile.effect.takes_direction(), |ui| { - ComboBox::from_label("Direction") - .width(COMBOBOX_WIDTH) - .selected_text({ - let text: &'static str = profile.direction.into(); - text - }) - .show_ui(ui, |ui| { - for val in Direction::iter() { - let text: &'static str = val.into(); - *update_lights |= ui.selectable_value(&mut profile.direction, val, text).changed(); - } - }); - }); - - if let Effects::AmbientLight { fps, saturation_boost: saturation } = &mut profile.effect { - ui.horizontal(|ui| { - *update_lights |= ui.add(Slider::new(fps, 1..=60)).changed(); - ui.label("FPS"); - }); - ui.horizontal(|ui| { - *update_lights |= ui.add(Slider::new(saturation, 0.0..=1.0)).changed(); - ui.label("Saturation Boost"); - }); - } else { - let range = if profile.effect.is_built_in() { SPEED_RANGE } else { 1..=10 }; - - ui.horizontal(|ui| { - *update_lights |= ui.add_enabled(profile.effect.takes_speed(), Slider::new(&mut profile.speed, range)).changed(); - ui.label("Speed"); - }); - } - }); - } -} diff --git a/app/src/gui/menu_bar.rs b/app/src/gui/menu_bar.rs index 4565498..7f7fa9d 100644 --- a/app/src/gui/menu_bar.rs +++ b/app/src/gui/menu_bar.rs @@ -7,7 +7,7 @@ use egui_file::FileDialog; use egui_notify::Toasts; use std::{path::PathBuf, time::Duration}; -use crate::{effects::custom_effect::CustomEffect, gui::modals, profile::Profile}; +use crate::{gui::modals, manager::custom_effect::CustomEffect, profile::Profile}; use super::{CustomEffectState, GuiMessage}; diff --git a/app/src/gui/mod.rs b/app/src/gui/mod.rs index d6e78a6..9f521f2 100644 --- a/app/src/gui/mod.rs +++ b/app/src/gui/mod.rs @@ -21,19 +21,18 @@ use tray_icon::menu::MenuEvent; use crate::{ cli::OutputType, - effects::{self, custom_effect::CustomEffect, EffectManager, ManagerCreationError}, enums::Effects, + manager::{self, custom_effect::CustomEffect, EffectManager, ManagerCreationError}, persist::Settings, tray::{QUIT_ID, SHOW_ID}, }; -use self::{effect_options::EffectOptions, menu_bar::MenuBarState, profile_list::ProfileList, style::Theme}; +use self::{menu_bar::MenuBarState, profile_list::ProfileList, style::Theme}; -mod effect_options; mod menu_bar; mod modals; mod profile_list; -mod style; +pub mod style; pub struct App { settings: Settings, @@ -51,7 +50,6 @@ pub struct App { menu_bar: MenuBarState, profile_list: ProfileList, - effect_options: EffectOptions, global_rgb: [u8; 3], theme: Theme, toasts: Toasts, @@ -74,7 +72,7 @@ impl App { pub fn new(output: OutputType, has_tray: Arc, visible: Arc) -> Self { let (gui_tx, gui_rx) = crossbeam_channel::unbounded::(); - let manager_result = EffectManager::new(effects::OperationMode::Gui); + let manager_result = EffectManager::new(manager::OperationMode::Gui); let instance_not_unique = if let Err(err) = &manager_result { &ManagerCreationError::InstanceAlreadyRunning == err.current_context() @@ -106,7 +104,6 @@ impl App { menu_bar: MenuBarState::new(gui_tx_c), profile_list: ProfileList::new(profiles), - effect_options: EffectOptions::default(), global_rgb: [0; 3], theme: Theme::default(), toasts: Toasts::default(), @@ -247,7 +244,8 @@ impl eframe::App for App { ui.set_width(res.inner.rect.width()); ui.add_enabled_ui(matches!(self.custom_effect, CustomEffectState::None), |ui| { - self.effect_options.show(ui, &mut self.settings.current_profile, &mut self.profile_changed, &self.theme.spacing); + let mut effect = self.settings.current_profile.effect; + effect.show_ui(ui, &mut self.settings.current_profile, &mut self.profile_changed, &self.theme); }); self.profile_list diff --git a/app/src/gui/profile_list.rs b/app/src/gui/profile_list.rs index 1116a9c..63a3a28 100644 --- a/app/src/gui/profile_list.rs +++ b/app/src/gui/profile_list.rs @@ -35,13 +35,13 @@ impl ProfileList { modal.buttons(ui, |ui| { let is_empty = self.new_profile_name.is_empty(); - let name_not_unique = self.profiles.iter().any(|prof| prof.name == self.new_profile_name); + let name_not_unique = self.profiles.iter().any(|prof| prof.name.as_ref() == Some(&self.new_profile_name)); modal.button(ui, "Cancel"); ui.add_enabled_ui(!is_empty && !name_not_unique, |ui| { if modal.button(ui, "Save").clicked() { - current_profile.name = self.new_profile_name.clone(); + current_profile.name = Some(self.new_profile_name.clone()); self.profiles.push(current_profile.clone()); }; }); @@ -99,7 +99,8 @@ impl ProfileList { ScrollArea::vertical().auto_shrink([false; 2]).show(ui, |ui| { ui.horizontal_wrapped(|ui| { for prof in &self.profiles { - if ui.selectable_value(current_profile, prof.clone(), &prof.name).clicked() { + let name = prof.name.as_ref().map(|s| s.as_str()).unwrap_or("Unnamed"); + if ui.selectable_value(current_profile, prof.clone(), name).clicked() { *changed = true; *custom_effect_state = CustomEffectState::None; }; diff --git a/app/src/main.rs b/app/src/main.rs index 4ad0ffc..31281a9 100644 --- a/app/src/main.rs +++ b/app/src/main.rs @@ -4,9 +4,9 @@ mod cli; #[cfg(target_os = "windows")] mod console; -mod effects; mod enums; mod gui; +mod manager; mod persist; mod profile; mod tray; diff --git a/app/src/effects/custom_effect.rs b/app/src/manager/custom_effect.rs similarity index 100% rename from app/src/effects/custom_effect.rs rename to app/src/manager/custom_effect.rs diff --git a/app/src/effects/ambient.rs b/app/src/manager/effects/ambient.rs similarity index 97% rename from app/src/effects/ambient.rs rename to app/src/manager/effects/ambient.rs index 17df960..8a65fb6 100644 --- a/app/src/effects/ambient.rs +++ b/app/src/manager/effects/ambient.rs @@ -9,13 +9,15 @@ use fast_image_resize as fr; use fr::Resizer; use scrap::{Capturer, Display, Frame, TraitCapturer, TraitPixelBuffer}; +use crate::manager::Inner; + #[derive(Clone, Copy)] struct ScreenDimensions { src: (u32, u32), dest: (u32, u32), } -pub fn play(manager: &mut super::Inner, fps: u8, saturation_boost: f32) { +pub fn play(manager: &mut Inner, fps: u8, saturation_boost: f32) { while !manager.stop_signals.manager_stop_signal.load(Ordering::SeqCst) { //Display setup let display = Display::all().unwrap().remove(0); diff --git a/app/src/effects/christmas.rs b/app/src/manager/effects/christmas.rs similarity index 97% rename from app/src/effects/christmas.rs rename to app/src/manager/effects/christmas.rs index 9543fb7..cd24273 100644 --- a/app/src/effects/christmas.rs +++ b/app/src/manager/effects/christmas.rs @@ -2,7 +2,9 @@ use std::{sync::atomic::Ordering, thread, time::Duration}; use rand::Rng; -pub fn play(manager: &mut super::Inner, thread_rng: &mut rand::rngs::ThreadRng) { +use crate::manager::Inner; + +pub fn play(manager: &mut Inner, thread_rng: &mut rand::rngs::ThreadRng) { let xmas_color_array = [[255, 10, 10], [255, 255, 20], [30, 255, 30], [70, 70, 255]]; let subeffect_count = 4; let mut last_subeffect = -1; diff --git a/app/src/manager/effects/default_ui.rs b/app/src/manager/effects/default_ui.rs new file mode 100644 index 0000000..657e9e8 --- /dev/null +++ b/app/src/manager/effects/default_ui.rs @@ -0,0 +1,62 @@ +use eframe::egui::{ComboBox, Slider, Ui}; +use legion_rgb_driver::SPEED_RANGE; +use strum::IntoEnumIterator; + +use crate::{ + enums::{Brightness, Direction}, + gui::style::SpacingStyle, + profile::Profile, +}; + +const COMBOBOX_WIDTH: f32 = 20.0; + +pub fn show(ui: &mut Ui, profile: &mut Profile, update_lights: &mut bool, spacing: &SpacingStyle) { + ui.scope(|ui| { + ui.style_mut().spacing.item_spacing = spacing.default; + + show_brightness(ui, profile, update_lights); + show_direction(ui, profile, update_lights); + show_effect_settings(ui, profile, update_lights); + }); +} + +pub fn show_brightness(ui: &mut Ui, profile: &mut Profile, update_lights: &mut bool) { + ComboBox::from_label("Brightness") + .width(COMBOBOX_WIDTH) + .selected_text({ + let text: &'static str = profile.brightness.into(); + text + }) + .show_ui(ui, |ui| { + for val in Brightness::iter() { + let text: &'static str = val.into(); + *update_lights |= ui.selectable_value(&mut profile.brightness, val, text).changed(); + } + }); +} + +pub fn show_direction(ui: &mut Ui, profile: &mut Profile, update_lights: &mut bool) { + ui.add_enabled_ui(profile.effect.takes_direction(), |ui| { + ComboBox::from_label("Direction") + .width(COMBOBOX_WIDTH) + .selected_text({ + let text: &'static str = profile.direction.into(); + text + }) + .show_ui(ui, |ui| { + for val in Direction::iter() { + let text: &'static str = val.into(); + *update_lights |= ui.selectable_value(&mut profile.direction, val, text).changed(); + } + }); + }); +} + +pub fn show_effect_settings(ui: &mut Ui, profile: &mut Profile, update_lights: &mut bool) { + let range = if profile.effect.is_built_in() { SPEED_RANGE } else { 1..=10 }; + + ui.horizontal(|ui| { + *update_lights |= ui.add_enabled(profile.effect.takes_speed(), Slider::new(&mut profile.speed, range)).changed(); + ui.label("Speed"); + }); +} diff --git a/app/src/effects/disco.rs b/app/src/manager/effects/disco.rs similarity index 81% rename from app/src/effects/disco.rs rename to app/src/manager/effects/disco.rs index ff6d152..7a28484 100644 --- a/app/src/effects/disco.rs +++ b/app/src/manager/effects/disco.rs @@ -2,9 +2,9 @@ use std::{sync::atomic::Ordering, thread, time::Duration}; use rand::Rng; -use crate::profile::Profile; +use crate::{manager::Inner, profile::Profile}; -pub fn play(manager: &mut super::Inner, p: &Profile, thread_rng: &mut rand::rngs::ThreadRng) { +pub fn play(manager: &mut Inner, p: &Profile, thread_rng: &mut rand::rngs::ThreadRng) { while !manager.stop_signals.manager_stop_signal.load(Ordering::SeqCst) { let colors = [[255, 0, 0], [255, 255, 0], [0, 255, 0], [0, 255, 255], [0, 0, 255], [255, 0, 255]]; let colors_index = thread_rng.gen_range(0..6); diff --git a/app/src/effects/fade.rs b/app/src/manager/effects/fade.rs similarity index 93% rename from app/src/effects/fade.rs rename to app/src/manager/effects/fade.rs index a0c9d1a..3c7cc90 100644 --- a/app/src/effects/fade.rs +++ b/app/src/manager/effects/fade.rs @@ -9,9 +9,9 @@ use std::{ use device_query::DeviceQuery; -use crate::profile::Profile; +use crate::{manager::Inner, profile::Profile}; -pub fn play(manager: &mut super::Inner, p: &Profile) { +pub fn play(manager: &mut Inner, p: &Profile) { let stop_signals = manager.stop_signals.clone(); let kill_thread = Arc::new(AtomicBool::new(false)); diff --git a/app/src/effects/lightning.rs b/app/src/manager/effects/lightning.rs similarity index 88% rename from app/src/effects/lightning.rs rename to app/src/manager/effects/lightning.rs index e94ffc8..6b6d02d 100644 --- a/app/src/effects/lightning.rs +++ b/app/src/manager/effects/lightning.rs @@ -2,9 +2,9 @@ use std::{sync::atomic::Ordering, thread, time::Duration}; use rand::{rngs::ThreadRng, Rng}; -use crate::profile::Profile; +use crate::{manager::Inner, profile::Profile}; -pub fn play(manager: &mut super::Inner, p: &Profile, thread_rng: &mut ThreadRng) { +pub fn play(manager: &mut Inner, p: &Profile, thread_rng: &mut ThreadRng) { while !manager.stop_signals.manager_stop_signal.load(Ordering::SeqCst) { let profile_array = p.rgb_array(); diff --git a/app/src/manager/effects/mod.rs b/app/src/manager/effects/mod.rs new file mode 100644 index 0000000..300c131 --- /dev/null +++ b/app/src/manager/effects/mod.rs @@ -0,0 +1,42 @@ +use default_ui::{show_brightness, show_direction}; +use eframe::egui::{self, Slider}; + +use crate::{enums::Effects, profile::Profile}; + +pub mod ambient; +pub mod christmas; +pub mod default_ui; +pub mod disco; +pub mod fade; +pub mod lightning; +pub mod ripple; +pub mod swipe; +pub mod temperature; +pub mod zones; + +impl Effects { + pub fn show_ui(&mut self, ui: &mut egui::Ui, profile: &mut Profile, update_lights: &mut bool, theme: &crate::gui::style::Theme) { + match self { + Effects::AmbientLight { fps, saturation_boost } => { + ui.scope(|ui| { + ui.style_mut().spacing.item_spacing = theme.spacing.default; + + show_brightness(ui, profile, update_lights); + show_direction(ui, profile, update_lights); + + ui.horizontal(|ui| { + *update_lights |= ui.add(Slider::new(fps, 1..=60)).changed(); + ui.label("FPS"); + }); + ui.horizontal(|ui| { + *update_lights |= ui.add(Slider::new(saturation_boost, 0.0..=1.0)).changed(); + ui.label("Saturation Boost"); + }); + }); + } + _ => { + default_ui::show(ui, profile, update_lights, &theme.spacing); + } + } + } +} diff --git a/app/src/effects/ripple.rs b/app/src/manager/effects/ripple.rs similarity index 97% rename from app/src/effects/ripple.rs rename to app/src/manager/effects/ripple.rs index 80df69a..cd32ad9 100644 --- a/app/src/effects/ripple.rs +++ b/app/src/manager/effects/ripple.rs @@ -10,7 +10,10 @@ use std::{ use device_query::{DeviceEvents, Keycode}; -use crate::{effects::zones::KEY_ZONES, profile::Profile}; +use crate::{ + manager::{effects::zones::KEY_ZONES, Inner}, + profile::Profile, +}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] enum RippleMove { @@ -20,7 +23,7 @@ enum RippleMove { Off, } -pub fn play(manager: &mut super::Inner, p: &Profile) { +pub fn play(manager: &mut Inner, p: &Profile) { // Welcome to the definition of i-don't-know-what-im-doing let stop_signals = manager.stop_signals.clone(); diff --git a/app/src/effects/swipe.rs b/app/src/manager/effects/swipe.rs similarity index 85% rename from app/src/effects/swipe.rs rename to app/src/manager/effects/swipe.rs index 048a7ac..bf064e2 100644 --- a/app/src/effects/swipe.rs +++ b/app/src/manager/effects/swipe.rs @@ -1,8 +1,8 @@ use std::{sync::atomic::Ordering, thread, time::Duration}; -use crate::{enums::Direction, profile::Profile}; +use crate::{enums::Direction, manager::Inner, profile::Profile}; -pub fn play(manager: &mut super::Inner, p: &Profile) { +pub fn play(manager: &mut Inner, p: &Profile) { let mut rgb_array = p.rgb_array(); while !manager.stop_signals.manager_stop_signal.load(Ordering::SeqCst) { diff --git a/app/src/effects/temperature.rs b/app/src/manager/effects/temperature.rs similarity index 95% rename from app/src/effects/temperature.rs rename to app/src/manager/effects/temperature.rs index 974f2e0..a1b4426 100644 --- a/app/src/effects/temperature.rs +++ b/app/src/manager/effects/temperature.rs @@ -2,7 +2,9 @@ use std::{sync::atomic::Ordering, thread, time::Duration}; use sysinfo::{Components, System}; -pub fn play(manager: &mut super::Inner) { +use crate::manager::Inner; + +pub fn play(manager: &mut Inner) { let safe_temp = 20.0; let ramp_boost = 1.6; let temp_cool: [f32; 12] = [0.0, 255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 255.0, 0.0, 0.0, 255.0, 0.0]; diff --git a/app/src/effects/zones.rs b/app/src/manager/effects/zones.rs similarity index 100% rename from app/src/effects/zones.rs rename to app/src/manager/effects/zones.rs diff --git a/app/src/effects/mod.rs b/app/src/manager/mod.rs similarity index 98% rename from app/src/effects/mod.rs rename to app/src/manager/mod.rs index 8992840..844f6d5 100644 --- a/app/src/effects/mod.rs +++ b/app/src/manager/mod.rs @@ -4,6 +4,7 @@ use crate::{ }; use crossbeam_channel::{Receiver, Sender}; +use effects::{ambient, christmas, disco, fade, lightning, ripple, swipe, temperature}; use error_stack::{Result, ResultExt}; use legion_rgb_driver::{BaseEffects, Keyboard, SPEED_RANGE}; use rand::thread_rng; @@ -18,16 +19,8 @@ use thiserror::Error; use self::custom_effect::{CustomEffect, EffectType}; -mod ambient; -mod christmas; pub mod custom_effect; -mod disco; -mod fade; -mod lightning; -mod ripple; -mod swipe; -mod temperature; -mod zones; +mod effects; #[derive(Debug, Error, PartialEq)] #[error("Could not create keyboard manager")] diff --git a/app/src/profile.rs b/app/src/profile.rs index 7508baf..a2c52aa 100644 --- a/app/src/profile.rs +++ b/app/src/profile.rs @@ -28,7 +28,7 @@ type Zones = [KeyboardZone; 4]; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] pub struct Profile { - pub name: String, + pub name: Option, pub rgb_zones: Zones, pub effect: Effects, pub direction: Direction, @@ -39,7 +39,7 @@ pub struct Profile { impl Default for Profile { fn default() -> Self { Self { - name: "Profile".to_string(), + name: None, rgb_zones: Zones::default(), effect: Effects::default(), direction: Direction::default(), @@ -62,7 +62,10 @@ impl Profile { Self::load(path).change_context(LoadProfileError) } - pub fn save_profile(&self, path: &Path) -> Result<(), SaveProfileError> { + pub fn save_profile(&mut self, path: &Path) -> Result<(), SaveProfileError> { + if self.name.is_none() { + self.name = Some("Untitled".to_string()); + } self.save(path).change_context(SaveProfileError) }