diff --git a/rog-control-center/src/lib.rs b/rog-control-center/src/lib.rs index b7fed048..0d1aa896 100644 --- a/rog-control-center/src/lib.rs +++ b/rog-control-center/src/lib.rs @@ -15,6 +15,7 @@ pub mod error; pub mod mocking; pub mod notify; pub mod page_states; +pub mod pages; pub mod widgets; #[cfg(feature = "mocking")] diff --git a/rog-control-center/src/main.rs b/rog-control-center/src/main.rs index 5516507e..a8765c5f 100644 --- a/rog-control-center/src/main.rs +++ b/rog-control-center/src/main.rs @@ -72,7 +72,9 @@ fn main() -> Result<(), Box> { }; let native_options = eframe::NativeOptions { - decorated: true, + decorated: false, + transparent: false, + max_window_size: Some(egui::vec2(800.0, 600.0)), ..Default::default() }; diff --git a/rog-control-center/src/pages/anime_page.rs b/rog-control-center/src/pages/anime_page.rs new file mode 100644 index 00000000..fe082407 --- /dev/null +++ b/rog-control-center/src/pages/anime_page.rs @@ -0,0 +1,9 @@ +use crate::RogApp; + +impl<'a> RogApp<'a> { + pub fn anime_page(&mut self, ctx: &egui::Context) { + egui::CentralPanel::default().show(ctx, |ui| { + ui.label("In progress"); + }); + } +} diff --git a/rog-control-center/src/pages/aura_page.rs b/rog-control-center/src/pages/aura_page.rs new file mode 100644 index 00000000..aab1ff93 --- /dev/null +++ b/rog-control-center/src/pages/aura_page.rs @@ -0,0 +1,190 @@ +use egui::{RichText, Ui}; +use rog_aura::{AuraModeNum, AuraZone, Colour, Speed}; +use rog_supported::SupportedFunctions; + +use crate::{ + page_states::{AuraState, PageDataStates}, + RogApp, RogDbusClientBlocking, +}; + +impl<'a> RogApp<'a> { + pub fn aura_page(&mut self, ctx: &egui::Context) { + let Self { + supported, + states, + asus_dbus: dbus, + .. + } = self; + + egui::CentralPanel::default().show(ctx, |ui| { + Self::aura_modes(supported, states, dbus, ui); + }); + } + + fn aura_modes( + supported: &SupportedFunctions, + states: &mut PageDataStates, + dbus: &mut RogDbusClientBlocking, + ui: &mut Ui, + ) { + let mut changed = false; + let mut selected = states.aura.current_mode; + + let has_keyzones = supported + .keyboard_led + .multizone_led_mode + .contains(&AuraZone::Key2); + let has_logo = supported + .keyboard_led + .multizone_led_mode + .contains(&AuraZone::Logo); + let has_lightbar = supported + .keyboard_led + .multizone_led_mode + .contains(&AuraZone::BarLeft) + || supported + .keyboard_led + .multizone_led_mode + .contains(&AuraZone::BarRight); + + ui.heading("Aura modes"); + let mut item = |a: AuraModeNum, ui: &mut Ui| { + if ui + .selectable_value(&mut selected, a, format!("{:?}", a)) + .clicked() + { + changed = true; + } + }; + + ui.horizontal_wrapped(|ui| { + for a in states.aura.modes.keys() { + item(*a, ui); + } + }); + + // TODO: Need some sort of mapping to enable options only if + // they actually work. + if let Some(effect) = states.aura.modes.get_mut(&selected) { + let mut zone_button = |a: AuraZone, ui: &mut Ui| { + ui.selectable_value(&mut effect.zone, a, format!("{:?}", a)); + }; + let mut speed_button = |a: Speed, ui: &mut Ui| { + ui.selectable_value(&mut effect.speed, a, format!("{:?}", a)); + }; + let mut dir_button = |a: rog_aura::Direction, ui: &mut Ui| { + ui.selectable_value(&mut effect.direction, a, format!("{:?}", a)); + }; + + let mut c1: [f32; 3] = effect.colour1.into(); + let mut c2: [f32; 3] = effect.colour2.into(); + + ui.separator(); + ui.horizontal_wrapped(|ui| { + ui.vertical(|ui| { + let h = 16.0; + ui.set_row_height(22.0); + if has_keyzones || has_lightbar || has_logo { + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Zone").size(h)); + }); + } + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Colour 1").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Colour 2").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Speed").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Direction").size(h)); + }); + }); + ui.vertical(|ui| { + ui.set_row_height(22.0); + if has_keyzones || has_lightbar || has_logo { + ui.horizontal_wrapped(|ui| { + zone_button(AuraZone::None, ui); + if has_keyzones { + zone_button(AuraZone::Key1, ui); + zone_button(AuraZone::Key2, ui); + zone_button(AuraZone::Key3, ui); + zone_button(AuraZone::Key4, ui); + } + if has_logo { + zone_button(AuraZone::Logo, ui); + } + if has_lightbar { + zone_button(AuraZone::BarLeft, ui); + zone_button(AuraZone::BarRight, ui); + } + }); + } + + egui::color_picker::color_edit_button_rgb(ui, &mut c1); + egui::color_picker::color_edit_button_rgb(ui, &mut c2); + + ui.horizontal_wrapped(|ui| { + speed_button(Speed::Low, ui); + speed_button(Speed::Med, ui); + speed_button(Speed::High, ui); + }); + + ui.horizontal_wrapped(|ui| { + dir_button(rog_aura::Direction::Left, ui); + dir_button(rog_aura::Direction::Down, ui); + dir_button(rog_aura::Direction::Right, ui); + dir_button(rog_aura::Direction::Up, ui); + }); + }); + }); + + effect.colour1 = Colour::from(&c1); + effect.colour2 = Colour::from(&c2); + } + + ui.separator(); + ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { + if ui.add(egui::Button::new("Cancel")).clicked() { + let notif = states.aura.was_notified.clone(); + match AuraState::new(notif, supported, dbus) { + Ok(a) => states.aura.modes = a.modes, + Err(e) => states.error = Some(e.to_string()), + } + } + + if ui.add(egui::Button::new("Apply")).clicked() { + changed = true; + } + }); + + // egui::TopBottomPanel::bottom("error_bar") + // .default_height(26.0) + // .show(ctx, |ui| { + // ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { + // if ui.add(egui::Button::new("Cancel")).clicked() { + // let notif = states.aura.was_notified.clone(); + // states.aura.modes = AuraState::new(notif, supported, dbus).modes; + // } + + // if ui.add(egui::Button::new("Apply")).clicked() { + // changed = true; + // } + // }); + // }); + + if changed { + states.aura.current_mode = selected; + + dbus.proxies() + .led() + .set_led_mode(states.aura.modes.get(&selected).unwrap()) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + } + } +} diff --git a/rog-control-center/src/pages/fan_curve_page.rs b/rog-control-center/src/pages/fan_curve_page.rs new file mode 100644 index 00000000..b14ec90b --- /dev/null +++ b/rog-control-center/src/pages/fan_curve_page.rs @@ -0,0 +1,82 @@ +use crate::{ + page_states::{FanCurvesState, ProfilesState}, + widgets::fan_graphs, + RogApp, RogDbusClientBlocking, +}; +use egui::Ui; +use rog_profiles::Profile; +use rog_supported::SupportedFunctions; + +impl<'a> RogApp<'a> { + pub fn fan_curve_page(&mut self, ctx: &egui::Context) { + let Self { + supported, + states, + asus_dbus: dbus, + .. + } = self; + + egui::CentralPanel::default().show(ctx, |ui| { + ui.heading("Custom fan curves"); + ui.label("A fan curve is only active when the related profile is active and the curve is enabled"); + Self::fan_curve( + supported, + &mut states.profiles, + &mut states.fan_curves, + dbus, &mut states.error, + ui, + ); + + fan_graphs(&mut states.profiles, &mut states.fan_curves, dbus, &mut states.error, ui); + }); + } + + fn fan_curve( + supported: &SupportedFunctions, + profiles: &mut ProfilesState, + curves: &mut FanCurvesState, + dbus: &RogDbusClientBlocking, + do_error: &mut Option, + ui: &mut Ui, + ) { + ui.separator(); + ui.label("Enabled fan-curves"); + + let mut changed = false; + ui.horizontal(|ui| { + let mut item = |p: Profile, curves: &mut FanCurvesState, mut checked: bool| { + if ui + .add(egui::Checkbox::new(&mut checked, format!("{:?}", p))) + .changed() + { + dbus.proxies() + .profile() + .set_fan_curve_enabled(p, checked) + .map_err(|err| { + *do_error = Some(err.to_string()); + }) + .ok(); + + if !checked { + curves.enabled.remove(&p); + } else { + curves.enabled.insert(p); + } + changed = true; + } + }; + + for f in profiles.list.iter() { + item(*f, curves, curves.enabled.contains(f)); + } + }); + + if changed { + let notif = curves.was_notified.clone(); + match FanCurvesState::new(notif, supported, dbus) { + Ok(f) => *curves = f, + Err(e) => *do_error = Some(e.to_string()), + } + } + } +} diff --git a/rog-control-center/src/pages/mod.rs b/rog-control-center/src/pages/mod.rs new file mode 100644 index 00000000..985fce73 --- /dev/null +++ b/rog-control-center/src/pages/mod.rs @@ -0,0 +1,9 @@ +mod anime_page; +mod aura_page; +mod fan_curve_page; +mod system_page; + +pub use anime_page::*; +pub use aura_page::*; +pub use fan_curve_page::*; +pub use system_page::*; diff --git a/rog-control-center/src/pages/system_page.rs b/rog-control-center/src/pages/system_page.rs new file mode 100644 index 00000000..860bb73c --- /dev/null +++ b/rog-control-center/src/pages/system_page.rs @@ -0,0 +1,39 @@ +use crate::{ + widgets::{anime_power_group, aura_power_group, platform_profile, rog_bios_group}, + RogApp, +}; + +impl<'a> RogApp<'a> { + pub fn system_page(&mut self, ctx: &egui::Context) { + let Self { + supported, + states, + asus_dbus: dbus, + .. + } = self; + + egui::CentralPanel::default().show(ctx, |ui| { + // The central panel the region left after adding TopPanel's and SidePanel's + + ui.heading("Experimental application for asusd"); + ui.separator(); + + egui::ScrollArea::vertical().show(ui, |ui| { + if supported.platform_profile.platform_profile { + ui.group(|ui| platform_profile(states, dbus, ui)); + } + + ui.separator(); + ui.group(|ui| rog_bios_group(supported, states, dbus, ui)); + + ui.separator(); + ui.group(|ui| aura_power_group(supported, states, dbus, ui)); + + if supported.anime_ctrl.0 { + ui.separator(); + ui.group(|ui| anime_power_group(supported, states, dbus, ui)); + } + }); + }); + } +} diff --git a/rog-control-center/src/widgets/anime_page.rs b/rog-control-center/src/widgets/anime_page.rs deleted file mode 100644 index 9ae20ab8..00000000 --- a/rog-control-center/src/widgets/anime_page.rs +++ /dev/null @@ -1,77 +0,0 @@ -use egui::RichText; - -use crate::RogApp; - -impl<'a> RogApp<'a> { - pub fn anime_page(&mut self, ctx: &egui::Context) { - egui::CentralPanel::default().show(ctx, |ui| { - ui.heading("AniMe Matrix Settings"); - ui.label("Options are incomplete. Awake + Boot should work"); - - let Self { - states, - asus_dbus: dbus, - .. - } = self; - - let mut changed = false; - - ui.horizontal_wrapped(|ui| { - ui.vertical(|ui| { - let h = 16.0; - ui.set_row_height(22.0); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Brightness").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Boot").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Awake").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Sleep").size(h)); - }); - }); - ui.vertical(|ui| { - ui.set_row_height(22.0); - ui.horizontal_wrapped(|ui| { - if ui - .add(egui::Slider::new(&mut states.anime.bright, 0..=254)) - .changed() - { - changed = true; - } - }); - ui.horizontal_wrapped(|ui| { - if ui.checkbox(&mut states.anime.boot, "Enable").changed() { - dbus.proxies() - .anime() - .set_boot_on_off(states.anime.boot) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - } - }); - ui.horizontal_wrapped(|ui| { - if ui.checkbox(&mut states.anime.awake, "Enable").changed() { - dbus.proxies() - .anime() - .set_on_off(states.anime.awake) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - } - }); - ui.horizontal_wrapped(|ui| { - if ui.checkbox(&mut states.anime.sleep, "Enable").changed() { - changed = true; - } - }); - }); - }); - }); - } -} diff --git a/rog-control-center/src/widgets/anime_power.rs b/rog-control-center/src/widgets/anime_power.rs new file mode 100644 index 00000000..e3b03623 --- /dev/null +++ b/rog-control-center/src/widgets/anime_power.rs @@ -0,0 +1,73 @@ +use egui::{RichText, Ui}; +use rog_supported::SupportedFunctions; + +use crate::{page_states::PageDataStates, RogDbusClientBlocking}; + +pub fn anime_power_group( + _supported: &SupportedFunctions, + states: &mut PageDataStates, + dbus: &mut RogDbusClientBlocking, + ui: &mut Ui, +) { + ui.heading("AniMe Matrix Settings"); + ui.label("Options are incomplete. Awake + Boot should work"); + + let mut changed = false; + + ui.horizontal_wrapped(|ui| { + ui.vertical(|ui| { + let h = 16.0; + ui.set_row_height(22.0); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Brightness").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Boot").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Awake").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Sleep").size(h)); + }); + }); + ui.vertical(|ui| { + ui.set_row_height(22.0); + ui.horizontal_wrapped(|ui| { + if ui + .add(egui::Slider::new(&mut states.anime.bright, 0..=254)) + .changed() + { + changed = true; + } + }); + ui.horizontal_wrapped(|ui| { + if ui.checkbox(&mut states.anime.boot, "Enable").changed() { + dbus.proxies() + .anime() + .set_boot_on_off(states.anime.boot) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + } + }); + ui.horizontal_wrapped(|ui| { + if ui.checkbox(&mut states.anime.awake, "Enable").changed() { + dbus.proxies() + .anime() + .set_on_off(states.anime.awake) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + } + }); + ui.horizontal_wrapped(|ui| { + if ui.checkbox(&mut states.anime.sleep, "Enable").changed() { + changed = true; + } + }); + }); + }); +} diff --git a/rog-control-center/src/widgets/aura_page.rs b/rog-control-center/src/widgets/aura_page.rs deleted file mode 100644 index b28a95b5..00000000 --- a/rog-control-center/src/widgets/aura_page.rs +++ /dev/null @@ -1,482 +0,0 @@ -use egui::{RichText, Ui}; -use rog_aura::{ - usb::{AuraDev1866, AuraDev19b6, AuraDevice, AuraPowerDev}, - AuraModeNum, AuraZone, Colour, Speed, -}; -use rog_supported::SupportedFunctions; - -use crate::{ - page_states::{AuraState, PageDataStates}, - RogApp, RogDbusClientBlocking, -}; - -impl<'a> RogApp<'a> { - pub fn aura_page(&mut self, ctx: &egui::Context) { - let Self { - supported, - states, - asus_dbus: dbus, - .. - } = self; - - egui::CentralPanel::default().show(ctx, |ui| { - Self::aura_power(supported, states, dbus, ui); - ui.separator(); - Self::aura_modes(supported, states, dbus, ui); - }); - } - - fn aura_power( - supported: &SupportedFunctions, - states: &mut PageDataStates, - dbus: &mut RogDbusClientBlocking, - ui: &mut Ui, - ) { - match supported.keyboard_led.prod_id { - AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866 => { - Self::aura_power1(supported, states, dbus, ui) - } - AuraDevice::X19B6 => Self::aura_power2(supported, states, dbus, ui), - AuraDevice::Unknown => {} - } - } - - fn aura_power1( - supported: &SupportedFunctions, - states: &mut PageDataStates, - dbus: &mut RogDbusClientBlocking, - ui: &mut Ui, - ) { - let enabled_states = &mut states.aura.enabled; - - ui.heading("Aura go brrrrr! (incomplete)"); - ui.separator(); - - let boot = &mut enabled_states.x1866.contains(&AuraDev1866::Boot); - let sleep = &mut enabled_states.x1866.contains(&AuraDev1866::Sleep); - let keyboard = &mut enabled_states.x1866.contains(&AuraDev1866::Keyboard); - let lightbar = &mut enabled_states.x1866.contains(&AuraDev1866::Lightbar); - let mut changed = false; - - ui.horizontal_wrapped(|ui| { - ui.vertical(|ui| { - let h = 16.0; - ui.set_row_height(22.0); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Boot").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Awake").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Sleep").size(h)); - }); - // if supported.keyboard_led.brightness_set { - // ui.horizontal_wrapped(|ui| { - // ui.label(RichText::new("Brightness").size(h)); - // }); - // } - }); - ui.vertical(|ui| { - ui.set_row_height(22.0); - ui.horizontal_wrapped(|ui| { - if ui.checkbox(boot, "Enable").changed() { - changed = true; - } - }); - ui.horizontal_wrapped(|ui| { - if ui.toggle_value(keyboard, "Keyboard").changed() { - changed = true; - } - if !supported.keyboard_led.multizone_led_mode.is_empty() { - if ui.toggle_value(lightbar, "Lightbar").changed() { - changed = true; - } - } - }); - ui.horizontal_wrapped(|ui| { - if ui.checkbox(sleep, "Enable").changed() { - changed = true; - } - }); - - // We currently don't have a watch for system changes here - // if supported.keyboard_led.brightness_set { - // if ui - // .add(egui::Slider::new( - // &mut states.aura.bright, - // 0..=3, - // )) - // .changed() - // { - // let bright = LedBrightness::from(states.aura.bright as u32); - // dbus.proxies() - // .led() - // .set_brightness(bright) - // .map_err(|err| { - // states.error = Some(err.to_string()); - // }) - // .ok(); - // } - // } - }); - }); - - if changed { - let mut enabled = Vec::new(); - let mut disabled = Vec::new(); - - let mut modify = |b: bool, a: AuraDev1866| { - if b { - enabled.push(a); - if !enabled_states.x1866.contains(&a) { - enabled_states.x1866.push(a); - } - } else { - disabled.push(a); - // This would be so much better as a hashset - if enabled_states.x1866.contains(&a) { - let mut idx = 0; - for (i, n) in enabled_states.x1866.iter().enumerate() { - if *n == a { - idx = i; - break; - } - } - enabled_states.x1866.remove(idx); - } - } - }; - modify(*boot, AuraDev1866::Boot); - modify(*sleep, AuraDev1866::Sleep); - modify(*keyboard, AuraDev1866::Keyboard); - if !supported.keyboard_led.multizone_led_mode.is_empty() { - modify(*lightbar, AuraDev1866::Lightbar); - } - - let mut send = |enable: bool, data: Vec| { - let options = AuraPowerDev { - x1866: data, - x19b6: vec![], - }; - // build data to send - dbus.proxies() - .led() - .set_leds_power(options, enable) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - }; - send(true, enabled); - send(false, disabled); - } - } - - fn aura_power2( - supported: &SupportedFunctions, - states: &mut PageDataStates, - dbus: &mut RogDbusClientBlocking, - ui: &mut Ui, - ) { - let enabled_states = &mut states.aura.enabled; - - ui.heading("Lights go brrrrr! (incomplete)"); - ui.separator(); - - let has_logo = supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::Logo); - let has_lightbar = supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::BarLeft) - || supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::BarRight); - - let boot_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootBar); - let boot_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootLogo); - let boot_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootKeyb); - - let awake_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeBar); - let awake_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeLogo); - let awake_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeKeyb); - - let sleep_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepBar); - let sleep_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepLogo); - let sleep_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepKeyb); - - let mut changed = false; - - let mut item = |keyboard: &mut bool, logo: &mut bool, lightbar: &mut bool, ui: &mut Ui| { - ui.horizontal_wrapped(|ui| { - if ui.checkbox(keyboard, "Keyboard").changed() { - changed = true; - } - if has_logo && ui.checkbox(logo, "Logo").changed() { - changed = true; - } - if has_lightbar && ui.checkbox(lightbar, "Lightbar").changed() { - changed = true; - } - }); - }; - - ui.horizontal_wrapped(|ui| { - ui.vertical(|ui| { - let h = 16.0; - ui.set_row_height(22.0); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Boot").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Awake").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Sleep").size(h)); - }); - }); - ui.vertical(|ui| { - ui.set_row_height(22.0); - item(boot_keyb, boot_logo, boot_bar, ui); - item(awake_keyb, awake_logo, awake_bar, ui); - item(sleep_keyb, sleep_logo, sleep_bar, ui); - }); - }); - - if changed { - let mut enabled = Vec::new(); - let mut disabled = Vec::new(); - - let mut modify = |b: bool, a: AuraDev19b6| { - if b { - enabled.push(a); - if !enabled_states.x19b6.contains(&a) { - enabled_states.x19b6.push(a); - } - } else { - disabled.push(a); - // This would be so much better as a hashset - if enabled_states.x19b6.contains(&a) { - let mut idx = 0; - for (i, n) in enabled_states.x19b6.iter().enumerate() { - if *n == a { - idx = i; - break; - } - } - enabled_states.x1866.remove(idx); - } - } - }; - modify(*boot_keyb, AuraDev19b6::BootKeyb); - modify(*sleep_keyb, AuraDev19b6::SleepKeyb); - modify(*awake_keyb, AuraDev19b6::AwakeKeyb); - if supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::Logo) - { - modify(*boot_logo, AuraDev19b6::BootLogo); - modify(*sleep_logo, AuraDev19b6::SleepLogo); - modify(*awake_logo, AuraDev19b6::AwakeLogo); - } - if supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::BarLeft) - { - modify(*boot_bar, AuraDev19b6::BootBar); - modify(*sleep_bar, AuraDev19b6::SleepBar); - modify(*awake_bar, AuraDev19b6::AwakeBar); - } - - let mut send = |enable: bool, data: Vec| { - let options = AuraPowerDev { - x1866: vec![], - x19b6: data, - }; - // build data to send - dbus.proxies() - .led() - .set_leds_power(options, enable) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - }; - send(true, enabled); - send(false, disabled); - } - } - - fn aura_modes( - supported: &SupportedFunctions, - states: &mut PageDataStates, - dbus: &mut RogDbusClientBlocking, - ui: &mut Ui, - ) { - let mut changed = false; - let mut selected = states.aura.current_mode; - - let has_keyzones = supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::Key2); - let has_logo = supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::Logo); - let has_lightbar = supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::BarLeft) - || supported - .keyboard_led - .multizone_led_mode - .contains(&AuraZone::BarRight); - - ui.heading("Aura modes"); - let mut item = |a: AuraModeNum, ui: &mut Ui| { - if ui - .selectable_value(&mut selected, a, format!("{:?}", a)) - .clicked() - { - changed = true; - } - }; - - ui.horizontal_wrapped(|ui| { - for a in states.aura.modes.keys() { - item(*a, ui); - } - }); - - // TODO: Need some sort of mapping to enable options only if - // they actually work. - if let Some(effect) = states.aura.modes.get_mut(&selected) { - let mut zone_button = |a: AuraZone, ui: &mut Ui| { - ui.selectable_value(&mut effect.zone, a, format!("{:?}", a)); - }; - let mut speed_button = |a: Speed, ui: &mut Ui| { - ui.selectable_value(&mut effect.speed, a, format!("{:?}", a)); - }; - let mut dir_button = |a: rog_aura::Direction, ui: &mut Ui| { - ui.selectable_value(&mut effect.direction, a, format!("{:?}", a)); - }; - - let mut c1: [f32; 3] = effect.colour1.into(); - let mut c2: [f32; 3] = effect.colour2.into(); - - ui.separator(); - ui.horizontal_wrapped(|ui| { - ui.vertical(|ui| { - let h = 16.0; - ui.set_row_height(22.0); - if has_keyzones || has_lightbar || has_logo { - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Zone").size(h)); - }); - } - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Colour 1").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Colour 2").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Speed").size(h)); - }); - ui.horizontal_wrapped(|ui| { - ui.label(RichText::new("Direction").size(h)); - }); - }); - ui.vertical(|ui| { - ui.set_row_height(22.0); - if has_keyzones || has_lightbar || has_logo { - ui.horizontal_wrapped(|ui| { - zone_button(AuraZone::None, ui); - if has_keyzones { - zone_button(AuraZone::Key1, ui); - zone_button(AuraZone::Key2, ui); - zone_button(AuraZone::Key3, ui); - zone_button(AuraZone::Key4, ui); - } - if has_logo { - zone_button(AuraZone::Logo, ui); - } - if has_lightbar { - zone_button(AuraZone::BarLeft, ui); - zone_button(AuraZone::BarRight, ui); - } - }); - } - - egui::color_picker::color_edit_button_rgb(ui, &mut c1); - egui::color_picker::color_edit_button_rgb(ui, &mut c2); - - ui.horizontal_wrapped(|ui| { - speed_button(Speed::Low, ui); - speed_button(Speed::Med, ui); - speed_button(Speed::High, ui); - }); - - ui.horizontal_wrapped(|ui| { - dir_button(rog_aura::Direction::Left, ui); - dir_button(rog_aura::Direction::Down, ui); - dir_button(rog_aura::Direction::Right, ui); - dir_button(rog_aura::Direction::Up, ui); - }); - }); - }); - - effect.colour1 = Colour::from(&c1); - effect.colour2 = Colour::from(&c2); - } - - ui.separator(); - ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { - if ui.add(egui::Button::new("Cancel")).clicked() { - let notif = states.aura.was_notified.clone(); - match AuraState::new(notif, supported, dbus) { - Ok(a) => states.aura.modes = a.modes, - Err(e) => states.error = Some(e.to_string()), - } - } - - if ui.add(egui::Button::new("Apply")).clicked() { - changed = true; - } - }); - - // egui::TopBottomPanel::bottom("error_bar") - // .default_height(26.0) - // .show(ctx, |ui| { - // ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { - // if ui.add(egui::Button::new("Cancel")).clicked() { - // let notif = states.aura.was_notified.clone(); - // states.aura.modes = AuraState::new(notif, supported, dbus).modes; - // } - - // if ui.add(egui::Button::new("Apply")).clicked() { - // changed = true; - // } - // }); - // }); - - if changed { - states.aura.current_mode = selected; - - dbus.proxies() - .led() - .set_led_mode(states.aura.modes.get(&selected).unwrap()) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - } - } -} diff --git a/rog-control-center/src/widgets/aura_power.rs b/rog-control-center/src/widgets/aura_power.rs new file mode 100644 index 00000000..2c8a41fe --- /dev/null +++ b/rog-control-center/src/widgets/aura_power.rs @@ -0,0 +1,289 @@ +use egui::{RichText, Ui}; +use rog_aura::{ + usb::{AuraDev1866, AuraDev19b6, AuraDevice, AuraPowerDev}, + AuraZone, +}; +use rog_supported::SupportedFunctions; + +use crate::{page_states::PageDataStates, RogDbusClientBlocking}; + +pub fn aura_power_group( + supported: &SupportedFunctions, + states: &mut PageDataStates, + dbus: &mut RogDbusClientBlocking, + ui: &mut Ui, +) { + ui.heading("LED settings"); + + match supported.keyboard_led.prod_id { + AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866 => { + aura_power1(supported, states, dbus, ui) + } + AuraDevice::X19B6 => aura_power2(supported, states, dbus, ui), + AuraDevice::Unknown => {} + } +} + +fn aura_power1( + supported: &SupportedFunctions, + states: &mut PageDataStates, + dbus: &mut RogDbusClientBlocking, + ui: &mut Ui, +) { + let enabled_states = &mut states.aura.enabled; + let boot = &mut enabled_states.x1866.contains(&AuraDev1866::Boot); + let sleep = &mut enabled_states.x1866.contains(&AuraDev1866::Sleep); + let keyboard = &mut enabled_states.x1866.contains(&AuraDev1866::Keyboard); + let lightbar = &mut enabled_states.x1866.contains(&AuraDev1866::Lightbar); + let mut changed = false; + + ui.horizontal_wrapped(|ui| { + ui.vertical(|ui| { + let h = 16.0; + ui.set_row_height(22.0); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Boot").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Awake").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Sleep").size(h)); + }); + // if supported.keyboard_led.brightness_set { + // ui.horizontal_wrapped(|ui| { + // ui.label(RichText::new("Brightness").size(h)); + // }); + // } + }); + ui.vertical(|ui| { + ui.set_row_height(22.0); + ui.horizontal_wrapped(|ui| { + if ui.checkbox(boot, "Enable").changed() { + changed = true; + } + }); + ui.horizontal_wrapped(|ui| { + if ui.toggle_value(keyboard, "Keyboard").changed() { + changed = true; + } + if !supported.keyboard_led.multizone_led_mode.is_empty() { + if ui.toggle_value(lightbar, "Lightbar").changed() { + changed = true; + } + } + }); + ui.horizontal_wrapped(|ui| { + if ui.checkbox(sleep, "Enable").changed() { + changed = true; + } + }); + + // We currently don't have a watch for system changes here + // if supported.keyboard_led.brightness_set { + // if ui + // .add(egui::Slider::new( + // &mut states.aura.bright, + // 0..=3, + // )) + // .changed() + // { + // let bright = LedBrightness::from(states.aura.bright as u32); + // dbus.proxies() + // .led() + // .set_brightness(bright) + // .map_err(|err| { + // states.error = Some(err.to_string()); + // }) + // .ok(); + // } + // } + }); + }); + + if changed { + let mut enabled = Vec::new(); + let mut disabled = Vec::new(); + + let mut modify = |b: bool, a: AuraDev1866| { + if b { + enabled.push(a); + if !enabled_states.x1866.contains(&a) { + enabled_states.x1866.push(a); + } + } else { + disabled.push(a); + // This would be so much better as a hashset + if enabled_states.x1866.contains(&a) { + let mut idx = 0; + for (i, n) in enabled_states.x1866.iter().enumerate() { + if *n == a { + idx = i; + break; + } + } + enabled_states.x1866.remove(idx); + } + } + }; + modify(*boot, AuraDev1866::Boot); + modify(*sleep, AuraDev1866::Sleep); + modify(*keyboard, AuraDev1866::Keyboard); + if !supported.keyboard_led.multizone_led_mode.is_empty() { + modify(*lightbar, AuraDev1866::Lightbar); + } + + let mut send = |enable: bool, data: Vec| { + let options = AuraPowerDev { + x1866: data, + x19b6: vec![], + }; + // build data to send + dbus.proxies() + .led() + .set_leds_power(options, enable) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + }; + send(true, enabled); + send(false, disabled); + } +} + +fn aura_power2( + supported: &SupportedFunctions, + states: &mut PageDataStates, + dbus: &mut RogDbusClientBlocking, + ui: &mut Ui, +) { + let enabled_states = &mut states.aura.enabled; + let has_logo = supported + .keyboard_led + .multizone_led_mode + .contains(&AuraZone::Logo); + let has_lightbar = supported + .keyboard_led + .multizone_led_mode + .contains(&AuraZone::BarLeft) + || supported + .keyboard_led + .multizone_led_mode + .contains(&AuraZone::BarRight); + + let boot_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootBar); + let boot_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootLogo); + let boot_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::BootKeyb); + + let awake_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeBar); + let awake_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeLogo); + let awake_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::AwakeKeyb); + + let sleep_bar = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepBar); + let sleep_logo = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepLogo); + let sleep_keyb = &mut enabled_states.x19b6.contains(&AuraDev19b6::SleepKeyb); + + let mut changed = false; + + let mut item = |keyboard: &mut bool, logo: &mut bool, lightbar: &mut bool, ui: &mut Ui| { + ui.horizontal_wrapped(|ui| { + if ui.checkbox(keyboard, "Keyboard").changed() { + changed = true; + } + if has_logo && ui.checkbox(logo, "Logo").changed() { + changed = true; + } + if has_lightbar && ui.checkbox(lightbar, "Lightbar").changed() { + changed = true; + } + }); + }; + + ui.horizontal_wrapped(|ui| { + ui.vertical(|ui| { + let h = 16.0; + ui.set_row_height(22.0); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Boot").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Awake").size(h)); + }); + ui.horizontal_wrapped(|ui| { + ui.label(RichText::new("Sleep").size(h)); + }); + }); + ui.vertical(|ui| { + ui.set_row_height(22.0); + item(boot_keyb, boot_logo, boot_bar, ui); + item(awake_keyb, awake_logo, awake_bar, ui); + item(sleep_keyb, sleep_logo, sleep_bar, ui); + }); + }); + + if changed { + let mut enabled = Vec::new(); + let mut disabled = Vec::new(); + + let mut modify = |b: bool, a: AuraDev19b6| { + if b { + enabled.push(a); + if !enabled_states.x19b6.contains(&a) { + enabled_states.x19b6.push(a); + } + } else { + disabled.push(a); + // This would be so much better as a hashset + if enabled_states.x19b6.contains(&a) { + let mut idx = 0; + for (i, n) in enabled_states.x19b6.iter().enumerate() { + if *n == a { + idx = i; + break; + } + } + enabled_states.x1866.remove(idx); + } + } + }; + modify(*boot_keyb, AuraDev19b6::BootKeyb); + modify(*sleep_keyb, AuraDev19b6::SleepKeyb); + modify(*awake_keyb, AuraDev19b6::AwakeKeyb); + if supported + .keyboard_led + .multizone_led_mode + .contains(&AuraZone::Logo) + { + modify(*boot_logo, AuraDev19b6::BootLogo); + modify(*sleep_logo, AuraDev19b6::SleepLogo); + modify(*awake_logo, AuraDev19b6::AwakeLogo); + } + if supported + .keyboard_led + .multizone_led_mode + .contains(&AuraZone::BarLeft) + { + modify(*boot_bar, AuraDev19b6::BootBar); + modify(*sleep_bar, AuraDev19b6::SleepBar); + modify(*awake_bar, AuraDev19b6::AwakeBar); + } + + let mut send = |enable: bool, data: Vec| { + let options = AuraPowerDev { + x1866: vec![], + x19b6: data, + }; + // build data to send + dbus.proxies() + .led() + .set_leds_power(options, enable) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + }; + send(true, enabled); + send(false, disabled); + } +} diff --git a/rog-control-center/src/widgets/fan_curve_page.rs b/rog-control-center/src/widgets/fan_curve_page.rs deleted file mode 100644 index 65085e29..00000000 --- a/rog-control-center/src/widgets/fan_curve_page.rs +++ /dev/null @@ -1,193 +0,0 @@ -use crate::{ - page_states::{FanCurvesState, ProfilesState}, - RogApp, RogDbusClientBlocking, -}; -use egui::{plot::Points, Ui}; -use rog_profiles::{FanCurvePU, Profile}; -use rog_supported::SupportedFunctions; - -impl<'a> RogApp<'a> { - pub fn fan_curve_page(&mut self, ctx: &egui::Context) { - let Self { - supported, - states, - asus_dbus: dbus, - .. - } = self; - - egui::CentralPanel::default().show(ctx, |ui| { - ui.heading("Custom fan curves"); - ui.label("A fan curve is only active when the related profile is active and the curve is enabled"); - Self::fan_curve( - supported, - &mut states.profiles, - &mut states.fan_curves, - dbus, &mut states.error, - ui, - ); - - Self::fan_graphs(&mut states.profiles, &mut states.fan_curves, dbus, &mut states.error, ui); - }); - } - - fn fan_curve( - supported: &SupportedFunctions, - profiles: &mut ProfilesState, - curves: &mut FanCurvesState, - dbus: &RogDbusClientBlocking, - do_error: &mut Option, - ui: &mut Ui, - ) { - ui.separator(); - ui.label("Enabled fan-curves"); - - let mut changed = false; - ui.horizontal(|ui| { - let mut item = |p: Profile, curves: &mut FanCurvesState, mut checked: bool| { - if ui - .add(egui::Checkbox::new(&mut checked, format!("{:?}", p))) - .changed() - { - dbus.proxies() - .profile() - .set_fan_curve_enabled(p, checked) - .map_err(|err| { - *do_error = Some(err.to_string()); - }) - .ok(); - - if !checked { - curves.enabled.remove(&p); - } else { - curves.enabled.insert(p); - } - changed = true; - } - }; - - for f in profiles.list.iter() { - item(*f, curves, curves.enabled.contains(f)); - } - }); - - if changed { - let notif = curves.was_notified.clone(); - match FanCurvesState::new(notif, supported, dbus) { - Ok(f) => *curves = f, - Err(e) => *do_error = Some(e.to_string()), - } - } - } - - fn fan_graphs( - profiles: &mut ProfilesState, - curves: &mut FanCurvesState, - dbus: &RogDbusClientBlocking, - do_error: &mut Option, - ui: &mut Ui, - ) { - ui.separator(); - - let mut item = |p: Profile, ui: &mut Ui| { - ui.selectable_value(&mut curves.show_curve, p, format!("{p:?}")); - }; - - ui.horizontal_wrapped(|ui| { - for a in curves.curves.iter() { - item(*a.0, ui); - } - - ui.selectable_value( - &mut curves.show_graph, - FanCurvePU::CPU, - format!("{:?}", FanCurvePU::CPU), - ); - ui.selectable_value( - &mut curves.show_graph, - FanCurvePU::GPU, - format!("{:?}", FanCurvePU::GPU), - ); - }); - - let curve = curves.curves.get_mut(&curves.show_curve).unwrap(); - - use egui::plot::{Line, Plot, PlotPoints}; - - let data = if curves.show_graph == FanCurvePU::CPU { - &mut curve.cpu - } else { - &mut curve.gpu - }; - - let points = data.temp.iter().enumerate().map(|(idx, x)| { - let x = *x as f64; - let y = ((data.pwm[idx] as u32) * 100 / 255) as f64; - [x, y] - }); - - let line = Line::new(PlotPoints::from_iter(points.clone())).width(2.0); - let points = Points::new(PlotPoints::from_iter(points)).radius(3.0); - - Plot::new("my_plot") - .view_aspect(1.666) - // .center_x_axis(true) - // .center_y_axis(true) - .include_x(0.0) - .include_x(104.0) - .include_y(0.0) - .include_y(106.0) - .allow_scroll(false) - .allow_drag(false) - .allow_boxed_zoom(false) - .x_axis_formatter(|d, _r| format!("{}", d)) - .y_axis_formatter(|d, _r| format!("{:.*}%", 1, d)) - .label_formatter(|name, value| { - if !name.is_empty() { - format!("{}: {:.*}%", name, 1, value.y) - } else { - format!("Temp {}c\nFan {:.*}%", value.x as u8, 1, value.y) - } - }) - .show(ui, |plot_ui| { - if plot_ui.plot_hovered() { - let mut idx = 0; - - if let Some(point) = plot_ui.pointer_coordinate() { - let mut x: i32 = 255; - for (i, n) in data.temp.iter().enumerate() { - let tmp = x.min((point.x as i32 - *n as i32).abs()); - if tmp < x { - x = tmp; - idx = i; - } - } - - if plot_ui.plot_clicked() { - data.temp[idx] = point.x as u8; - data.pwm[idx] = (point.y * 255.0 / 100.0) as u8; - } else { - let drag = plot_ui.pointer_coordinate_drag_delta(); - if drag.length_sq() != 0.0 { - data.temp[idx] = (point.x as f32 + drag.x) as u8; - data.pwm[idx] = ((point.y as f32 + drag.y) * 255.0 / 100.0) as u8; - } - } - } - } - plot_ui.line(line); - plot_ui.points(points) - }); - - ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { - if ui.add(egui::Button::new("Apply Fan-curve")).clicked() { - dbus.proxies() - .profile() - .set_fan_curve(profiles.current, data.clone()) - .map_err(|err| { - *do_error = Some(err.to_string()); - }) - .ok(); - } - }); - } -} diff --git a/rog-control-center/src/widgets/fan_graph.rs b/rog-control-center/src/widgets/fan_graph.rs new file mode 100644 index 00000000..1fb9a9f8 --- /dev/null +++ b/rog-control-center/src/widgets/fan_graph.rs @@ -0,0 +1,119 @@ +use egui::{plot::Points, Ui}; +use rog_profiles::{FanCurvePU, Profile}; + +use crate::{ + page_states::{FanCurvesState, ProfilesState}, + RogDbusClientBlocking, +}; + +pub fn fan_graphs( + profiles: &mut ProfilesState, + curves: &mut FanCurvesState, + dbus: &RogDbusClientBlocking, + do_error: &mut Option, + ui: &mut Ui, +) { + ui.separator(); + + let mut item = |p: Profile, ui: &mut Ui| { + ui.selectable_value(&mut curves.show_curve, p, format!("{p:?}")); + }; + + ui.horizontal_wrapped(|ui| { + for a in curves.curves.iter() { + item(*a.0, ui); + } + + ui.selectable_value( + &mut curves.show_graph, + FanCurvePU::CPU, + format!("{:?}", FanCurvePU::CPU), + ); + ui.selectable_value( + &mut curves.show_graph, + FanCurvePU::GPU, + format!("{:?}", FanCurvePU::GPU), + ); + }); + + let curve = curves.curves.get_mut(&curves.show_curve).unwrap(); + + use egui::plot::{Line, Plot, PlotPoints}; + + let data = if curves.show_graph == FanCurvePU::CPU { + &mut curve.cpu + } else { + &mut curve.gpu + }; + + let points = data.temp.iter().enumerate().map(|(idx, x)| { + let x = *x as f64; + let y = ((data.pwm[idx] as u32) * 100 / 255) as f64; + [x, y] + }); + + let line = Line::new(PlotPoints::from_iter(points.clone())).width(2.0); + let points = Points::new(PlotPoints::from_iter(points)).radius(3.0); + + Plot::new("my_plot") + .view_aspect(1.666) + // .center_x_axis(true) + // .center_y_axis(true) + .include_x(0.0) + .include_x(104.0) + .include_y(0.0) + .include_y(106.0) + .allow_scroll(false) + .allow_drag(false) + .allow_boxed_zoom(false) + .x_axis_formatter(|d, _r| format!("{}", d)) + .y_axis_formatter(|d, _r| format!("{:.*}%", 1, d)) + .label_formatter(|name, value| { + if !name.is_empty() { + format!("{}: {:.*}%", name, 1, value.y) + } else { + format!("Temp {}c\nFan {:.*}%", value.x as u8, 1, value.y) + } + }) + .show(ui, |plot_ui| { + if plot_ui.plot_hovered() { + let mut idx = 0; + + if let Some(point) = plot_ui.pointer_coordinate() { + let mut x: i32 = 255; + for (i, n) in data.temp.iter().enumerate() { + let tmp = x.min((point.x as i32 - *n as i32).abs()); + if tmp < x { + x = tmp; + idx = i; + } + } + + if plot_ui.plot_clicked() { + data.temp[idx] = point.x as u8; + data.pwm[idx] = (point.y * 255.0 / 100.0) as u8; + } else { + let drag = plot_ui.pointer_coordinate_drag_delta(); + if drag.length_sq() != 0.0 { + data.temp[idx] = (point.x as f32 + drag.x) as u8; + data.pwm[idx] = ((point.y as f32 + drag.y) * 255.0 / 100.0) as u8; + } + } + } + } + plot_ui.line(line); + plot_ui.points(points) + }); + + ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { + if ui.add(egui::Button::new("Apply Fan-curve")).clicked() { + dbus.proxies() + .profile() + .set_fan_curve(profiles.current, data.clone()) + .map_err(|err| { + *do_error = Some(err.to_string()); + }) + .ok(); + } + }); +} diff --git a/rog-control-center/src/widgets/mod.rs b/rog-control-center/src/widgets/mod.rs index 403e5a33..1132c541 100644 --- a/rog-control-center/src/widgets/mod.rs +++ b/rog-control-center/src/widgets/mod.rs @@ -1,13 +1,13 @@ -mod anime_page; -mod aura_page; -mod fan_curve_page; +mod anime_power; +mod aura_power; +mod fan_graph; +mod rog_bios; mod side_panel; -mod system_page; mod top_bar; -pub use anime_page::*; -pub use aura_page::*; -pub use fan_curve_page::*; +pub use anime_power::*; +pub use aura_power::*; +pub use fan_graph::*; +pub use rog_bios::*; pub use side_panel::*; -pub use system_page::*; pub use top_bar::*; diff --git a/rog-control-center/src/widgets/rog_bios.rs b/rog-control-center/src/widgets/rog_bios.rs new file mode 100644 index 00000000..a5f474e4 --- /dev/null +++ b/rog-control-center/src/widgets/rog_bios.rs @@ -0,0 +1,110 @@ +use crate::{page_states::PageDataStates, RogDbusClientBlocking}; +use egui::Ui; +use rog_profiles::Profile; +use rog_supported::SupportedFunctions; + +pub fn platform_profile(states: &mut PageDataStates, dbus: &RogDbusClientBlocking, ui: &mut Ui) { + ui.heading("Platform profile"); + + let mut changed = false; + let mut item = |p: Profile, ui: &mut Ui| { + if ui + .selectable_value(&mut states.profiles.current, p, format!("{p:?}")) + .clicked() + { + changed = true; + } + }; + + ui.horizontal_wrapped(|ui| { + for a in states.profiles.list.iter() { + item(*a, ui); + } + }); + + if changed { + dbus.proxies() + .profile() + .set_active_profile(states.profiles.current) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + }; +} + +pub fn rog_bios_group( + supported: &SupportedFunctions, + states: &mut PageDataStates, + dbus: &mut RogDbusClientBlocking, + ui: &mut Ui, +) { + ui.heading("Bios options"); + + let slider = egui::Slider::new(&mut states.charge_limit, 20..=100) + .text("Charging limit") + .step_by(1.0); + if ui.add(slider).drag_released() { + dbus.proxies() + .charge() + .set_limit(states.charge_limit as u8) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + } + + if supported.rog_bios_ctrl.post_sound { + if ui + .add(egui::Checkbox::new( + &mut states.bios.post_sound, + "POST sound", + )) + .changed() + { + dbus.proxies() + .rog_bios() + .set_post_boot_sound(states.bios.post_sound) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + } + } + + if supported.rog_bios_ctrl.post_sound { + if ui + .add(egui::Checkbox::new( + &mut states.bios.panel_overdrive, + "Panel overdrive", + )) + .changed() + { + dbus.proxies() + .rog_bios() + .set_panel_overdrive(states.bios.panel_overdrive) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + } + } + + if supported.rog_bios_ctrl.dedicated_gfx { + if ui + .add(egui::Checkbox::new( + &mut states.bios.dedicated_gfx, + "G-Sync Dedicated GPU mode", + )) + .changed() + { + dbus.proxies() + .rog_bios() + .set_dedicated_graphic_mode(states.bios.dedicated_gfx) + .map_err(|err| { + states.error = Some(err.to_string()); + }) + .ok(); + } + } +} diff --git a/rog-control-center/src/widgets/system_page.rs b/rog-control-center/src/widgets/system_page.rs deleted file mode 100644 index 1332e9a6..00000000 --- a/rog-control-center/src/widgets/system_page.rs +++ /dev/null @@ -1,134 +0,0 @@ -use crate::{page_states::PageDataStates, RogApp, RogDbusClientBlocking}; -use egui::Ui; -use rog_profiles::Profile; - -impl<'a> RogApp<'a> { - pub fn system_page(&mut self, ctx: &egui::Context) { - let Self { - supported, - states, - asus_dbus: dbus, - .. - } = self; - - egui::CentralPanel::default().show(ctx, |ui| { - // The central panel the region left after adding TopPanel's and SidePanel's - - ui.heading("Experimental application for asusd"); - ui.horizontal(|ui| { - egui::global_dark_light_mode_buttons(ui); - egui::warn_if_debug_build(ui); - }); - - ui.separator(); - - egui::ScrollArea::vertical().show(ui, |ui| { - ui.heading("Charge control"); - let slider = egui::Slider::new(&mut states.charge_limit, 20..=100) - .text("Limit") - .step_by(1.0); - if ui.add(slider).drag_released() { - dbus.proxies() - .charge() - .set_limit(states.charge_limit as u8) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - } - - ui.separator(); - ui.heading("Bios options"); - - if supported.rog_bios_ctrl.post_sound { - if ui - .add(egui::Checkbox::new( - &mut states.bios.post_sound, - "POST sound", - )) - .changed() - { - dbus.proxies() - .rog_bios() - .set_post_boot_sound(states.bios.post_sound) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - } - } - - if supported.rog_bios_ctrl.post_sound { - if ui - .add(egui::Checkbox::new( - &mut states.bios.panel_overdrive, - "Panel overdrive", - )) - .changed() - { - dbus.proxies() - .rog_bios() - .set_panel_overdrive(states.bios.panel_overdrive) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - } - } - - if supported.rog_bios_ctrl.dedicated_gfx { - if ui - .add(egui::Checkbox::new( - &mut states.bios.dedicated_gfx, - "G-Sync Dedicated GPU mode", - )) - .changed() - { - dbus.proxies() - .rog_bios() - .set_dedicated_graphic_mode(states.bios.dedicated_gfx) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - } - } - - if supported.platform_profile.platform_profile { - Self::platform_profile(states, dbus, ui); - } - }); - }); - } - - fn platform_profile(states: &mut PageDataStates, dbus: &RogDbusClientBlocking, ui: &mut Ui) { - ui.separator(); - ui.heading("Platform profile"); - - let mut changed = false; - let mut item = |p: Profile, ui: &mut Ui| { - if ui - .selectable_value(&mut states.profiles.current, p, format!("{p:?}")) - .clicked() - { - changed = true; - } - }; - - ui.horizontal_wrapped(|ui| { - for a in states.profiles.list.iter() { - item(*a, ui); - } - }); - - if changed { - dbus.proxies() - .profile() - .set_active_profile(states.profiles.current) - .map_err(|err| { - states.error = Some(err.to_string()); - }) - .ok(); - }; - } -} diff --git a/rog-control-center/src/widgets/top_bar.rs b/rog-control-center/src/widgets/top_bar.rs index bedff1c5..132a1387 100644 --- a/rog-control-center/src/widgets/top_bar.rs +++ b/rog-control-center/src/widgets/top_bar.rs @@ -1,5 +1,7 @@ use std::sync::atomic::Ordering; +use egui::{vec2, Align2, Button, FontId, Id, Rect, RichText, Sense, Vec2}; + use crate::RogApp; impl<'a> RogApp<'a> { @@ -36,6 +38,41 @@ impl<'a> RogApp<'a> { .ok(); } }); + + ui.horizontal(|ui| { + egui::global_dark_light_mode_switch(ui); + egui::warn_if_debug_build(ui); + }); + + /***********************************************************/ + // Drag area + let text_color = ctx.style().visuals.text_color(); + let mut titlebar_rect = ui.available_rect_before_wrap(); + titlebar_rect.max.x -= titlebar_rect.height(); + if ui + .interact(titlebar_rect, Id::new("title_bar"), Sense::drag()) + .drag_started() + { + frame.drag_window(); + } + /***********************************************************/ + let height = titlebar_rect.height(); + // Paint the title: + ui.painter().text( + titlebar_rect.center_top() + vec2(0.0, height / 2.0), + Align2::CENTER_CENTER, + "ROG Control Center", + FontId::proportional(height - 2.0), + text_color, + ); + // Add the close button: + let close_response = ui.put( + Rect::from_min_size(titlebar_rect.right_top(), Vec2::splat(height)), + Button::new(RichText::new("❌").size(height - 4.0)).frame(false), + ); + if close_response.clicked() { + frame.quit(); + } }); }); }