From a0dd0b36dd115883dd956f6ec5b31e9b1412789e Mon Sep 17 00:00:00 2001 From: mihai2mn Date: Sat, 24 Jan 2026 16:52:20 +0100 Subject: [PATCH] feat(ui): Major UI update to Slint components - Add real-time system status components - Add theme support - Improve layouts --- build_error.log | 252 ++++++++++++++ build_error_fans.log | 53 +++ build_error_fans_2.log | 49 +++ error.log | 66 ++++ rog-control-center/ui/main_window.slint | 312 +++++++++++------ rog-control-center/ui/pages/about.slint | 173 ++++++---- rog-control-center/ui/pages/anime.slint | 33 +- .../ui/pages/app_settings.slint | 161 ++++++--- rog-control-center/ui/pages/aura.slint | 73 +++- rog-control-center/ui/pages/fans.slint | 126 ++++++- rog-control-center/ui/pages/screenpad.slint | 102 ++++++ rog-control-center/ui/pages/slash.slint | 114 ++++++ rog-control-center/ui/pages/supergfx.slint | 73 ++++ rog-control-center/ui/pages/system.slint | 217 ++++-------- rog-control-center/ui/themes/rog_theme.slint | 13 + rog-control-center/ui/types/aura_types.slint | 21 ++ rog-control-center/ui/types/fan_types.slint | 326 ++---------------- .../ui/types/screenpad_types.slint | 13 + rog-control-center/ui/types/slash_types.slint | 49 +++ .../ui/types/supergfx_types.slint | 10 + .../ui/widgets/aura_power.slint | 33 +- rog-control-center/ui/widgets/common.slint | 83 +++-- rog-control-center/ui/widgets/graph.slint | 54 +-- rog-control-center/ui/widgets/sidebar.slint | 49 ++- .../ui/widgets/status_bar.slint | 58 ++++ .../ui/windows/tray_tooltip.slint | 76 ++++ 26 files changed, 1818 insertions(+), 771 deletions(-) create mode 100644 build_error.log create mode 100644 build_error_fans.log create mode 100644 build_error_fans_2.log create mode 100644 error.log create mode 100644 rog-control-center/ui/pages/screenpad.slint create mode 100644 rog-control-center/ui/pages/slash.slint create mode 100644 rog-control-center/ui/pages/supergfx.slint create mode 100644 rog-control-center/ui/themes/rog_theme.slint create mode 100644 rog-control-center/ui/types/screenpad_types.slint create mode 100644 rog-control-center/ui/types/slash_types.slint create mode 100644 rog-control-center/ui/types/supergfx_types.slint create mode 100644 rog-control-center/ui/widgets/status_bar.slint create mode 100644 rog-control-center/ui/windows/tray_tooltip.slint diff --git a/build_error.log b/build_error.log new file mode 100644 index 00000000..986cf0e5 --- /dev/null +++ b/build_error.log @@ -0,0 +1,252 @@ +warning: rog-control-center@6.3.0: warning: padding-bottom only has effect on layout elements +warning: rog-control-center@6.3.0: --> /mnt/Data/mihais/builds/ROGCC/rog-control-center/ui/widgets/sidebar.slint:122:29 +warning: rog-control-center@6.3.0: | +warning: rog-control-center@6.3.0: 122 | padding-bottom: 20px; +warning: rog-control-center@6.3.0: | ^^^^^ + Compiling rog-control-center v6.3.0 (/mnt/Data/mihais/builds/ROGCC/rog-control-center) +error[E0308]: mismatched types + --> rog-control-center/src/ui/mod.rs:46:36 + | +41 | concat_idents::concat_idents!(set = set_, $proxy_fn { + | ---- arguments to this method are incorrect +... +46 | proxy_copy.set(value $($conv2)*).await, + | ^^^^^ expected `u8`, found `f32` + | + ::: rog-control-center/src/ui/setup_slash.rs:51:17 + | +51 | / set_ui_callbacks!( +52 | | ui_handle, +53 | | SlashPageData(), +54 | | proxy.brightness(), +55 | | "Slash brightness set to {}", +56 | | "Failed to set slash brightness" +57 | | ); + | |_________________- in this macro invocation + | +note: method defined here + --> /mnt/Data/mihais/builds/ROGCC/rog-dbus/src/zbus_slash.rs:20:8 + | +20 | fn set_brightness(&self, value: u8) -> zbus::Result<()>; + | ^^^^^^^^^^^^^^ + = note: this error originates in the macro `set_ui_callbacks` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> rog-control-center/src/ui/mod.rs:63:54 + | + 58 | concat_idents::concat_idents!(set = set_, $proxy_fn { + | ---- arguments to this method are incorrect +... + 63 | handle.global::<$data>().set(out $($conv1)*); + | ^^^ expected `f32`, found `u8` + | + ::: rog-control-center/src/ui/setup_slash.rs:51:17 + | + 51 | / set_ui_callbacks!( + 52 | | ui_handle, + 53 | | SlashPageData(), + 54 | | proxy.brightness(), + 55 | | "Slash brightness set to {}", + 56 | | "Failed to set slash brightness" + 57 | | ); + | |_________________- in this macro invocation + | +note: method defined here + --> /mnt/Data/mihais/builds/ROGCC/target/debug/build/rog-control-center-f28a2c919698f43f/out/main_window.rs:1854:39 + | +1854 | # [allow (dead_code)] pub fn set_brightness (& self , value : f32) { + | ^^^^^^^^^^^^^^ ----------- + = note: this error originates in the macro `set_ui_callbacks` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer + | + 63 | handle.global::<$data>().set(out.into() $($conv1)*); + | +++++++ + +error[E0308]: mismatched types + --> rog-control-center/src/ui/mod.rs:46:36 + | +41 | concat_idents::concat_idents!(set = set_, $proxy_fn { + | ---- arguments to this method are incorrect +... +46 | proxy_copy.set(value $($conv2)*).await, + | ^^^^^ expected `u8`, found `f32` + | + ::: rog-control-center/src/ui/setup_slash.rs:58:17 + | +58 | / set_ui_callbacks!( +59 | | ui_handle, +60 | | SlashPageData(), +61 | | proxy.interval(), +62 | | "Slash interval set to {}", +63 | | "Failed to set slash interval" +64 | | ); + | |_________________- in this macro invocation + | +note: method defined here + --> /mnt/Data/mihais/builds/ROGCC/rog-dbus/src/zbus_slash.rs:26:8 + | +26 | fn set_interval(&self, value: u8) -> zbus::Result<()>; + | ^^^^^^^^^^^^ + = note: this error originates in the macro `set_ui_callbacks` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> rog-control-center/src/ui/mod.rs:63:54 + | + 58 | concat_idents::concat_idents!(set = set_, $proxy_fn { + | ---- arguments to this method are incorrect +... + 63 | handle.global::<$data>().set(out $($conv1)*); + | ^^^ expected `f32`, found `u8` + | + ::: rog-control-center/src/ui/setup_slash.rs:58:17 + | + 58 | / set_ui_callbacks!( + 59 | | ui_handle, + 60 | | SlashPageData(), + 61 | | proxy.interval(), + 62 | | "Slash interval set to {}", + 63 | | "Failed to set slash interval" + 64 | | ); + | |_________________- in this macro invocation + | +note: method defined here + --> /mnt/Data/mihais/builds/ROGCC/target/debug/build/rog-control-center-f28a2c919698f43f/out/main_window.rs:1974:39 + | +1974 | # [allow (dead_code)] pub fn set_interval (& self , value : f32) { + | ^^^^^^^^^^^^ ----------- + = note: this error originates in the macro `set_ui_callbacks` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer + | + 63 | handle.global::<$data>().set(out.into() $($conv1)*); + | +++++++ + +error[E0599]: no method named `on_set_mode_index` found for struct `SlashPageData<'a>` in the current scope + --> rog-control-center/src/ui/setup_slash.rs:119:22 + | + 119 | data.on_set_mode_index(move |idx| { + | -----^^^^^^^^^^^^^^^^^ + | + ::: /mnt/Data/mihais/builds/ROGCC/target/debug/build/rog-control-center-f28a2c919698f43f/out/main_window.rs:1847:25 + | +1847 | # [allow (unused)] pub struct r#SlashPageData < 'a > (& 'a :: core :: pin :: Pin < sp :: Rc < InnerSlashPageData >>) ; + | --------------------------------- method `on_set_mode_index` not found for this struct + | +help: there is a method `set_mode_index` with a similar name + | + 119 - data.on_set_mode_index(move |idx| { + 119 + data.set_mode_index(move |idx| { + | + +error[E0599]: no method named `row_count` found for struct `ModelRc` in the current scope + --> rog-control-center/src/ui/setup_slash.rs:127:60 + | +127 | if idx >= 0 && idx < d.get_modes().row_count() { + | ^^^^^^^^^ method not found in `ModelRc` + | + ::: /home/mihais/.cargo/git/checkouts/slint-774a37e469fae6bf/f181d5e/internal/core/model.rs:125:8 + | +125 | fn row_count(&self) -> usize; + | --------- the method is available for `ModelRc` here + | + = help: items from traits can only be used if the trait is in scope +help: trait `Model` which provides `row_count` is implemented but not in scope; perhaps you want to import it + | + 1 + use slint::Model; + | + +error[E0599]: no method named `row_data` found for struct `ModelRc` in the current scope + --> rog-control-center/src/ui/setup_slash.rs:128:48 + | +128 | ... Some(d.get_modes().row_data(idx as usize).unwrap_or_default()) + | ^^^^^^^^ + | + ::: /home/mihais/.cargo/git/checkouts/slint-774a37e469fae6bf/f181d5e/internal/core/model.rs:132:8 + | +132 | fn row_data(&self, row: usize) -> Option; + | -------- the method is available for `ModelRc` here + | + = help: items from traits can only be used if the trait is in scope +help: there is a method `set_row_data` with a similar name, but with different arguments + --> /home/mihais/.cargo/git/checkouts/slint-774a37e469fae6bf/f181d5e/internal/core/model.rs:142:5 + | +142 | fn set_row_data(&self, _row: usize, _data: Self::Data) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: trait `Model` which provides `row_data` is implemented but not in scope; perhaps you want to import it + | + 1 + use slint::Model; + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> rog-control-center/src/ui/setup_slash.rs:136:28 + | +136 | if let Some(mode_str) = mode_str_opt { + | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound in `std::prelude::v1::Some` + --> /home/mihais/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:599:17 + | +599 | pub enum Option { + | ^ required by this bound in `std::prelude::v1::Some` +... +607 | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ---- required by a bound in this tuple variant + +error[E0599]: no method named `iter` found for struct `ModelRc` in the current scope + --> rog-control-center/src/ui/setup_slash.rs:166:49 + | +166 | ... for (i, m) in model.iter().enumerate() { + | ^^^^ + | + ::: /home/mihais/.cargo/git/checkouts/slint-774a37e469fae6bf/f181d5e/internal/core/model.rs:157:8 + | +157 | fn iter(&self) -> ModelIterator<'_, Self::Data> + | ---- the method is available for `ModelRc` here + | + = help: items from traits can only be used if the trait is in scope +help: there is a method `filter` with a similar name, but with different arguments + --> /home/mihais/.cargo/git/checkouts/slint-774a37e469fae6bf/f181d5e/internal/core/model.rs:260:5 + | +260 | / fn filter(self, filter_function: F) -> FilterModel +261 | | where +262 | | Self: Sized + 'static, +263 | | F: Fn(&Self::Data) -> bool + 'static, + | |_____________________________________________^ +help: trait `Model` which provides `iter` is implemented but not in scope; perhaps you want to import it + | + 1 + use slint::Model; + | + +error[E0599]: no method named `iter` found for struct `ModelRc` in the current scope + --> rog-control-center/src/ui/setup_slash.rs:185:41 + | +185 | for (i, m) in model.iter().enumerate() { + | ^^^^ + | + ::: /home/mihais/.cargo/git/checkouts/slint-774a37e469fae6bf/f181d5e/internal/core/model.rs:157:8 + | +157 | fn iter(&self) -> ModelIterator<'_, Self::Data> + | ---- the method is available for `ModelRc` here + | + = help: items from traits can only be used if the trait is in scope +help: there is a method `filter` with a similar name, but with different arguments + --> /home/mihais/.cargo/git/checkouts/slint-774a37e469fae6bf/f181d5e/internal/core/model.rs:260:5 + | +260 | / fn filter(self, filter_function: F) -> FilterModel +261 | | where +262 | | Self: Sized + 'static, +263 | | F: Fn(&Self::Data) -> bool + 'static, + | |_____________________________________________^ +help: trait `Model` which provides `iter` is implemented but not in scope; perhaps you want to import it + | + 1 + use slint::Model; + | + +Some errors have detailed explanations: E0277, E0308, E0599. +For more information about an error, try `rustc --explain E0277`. +warning: rog-control-center@6.3.0: warning: padding-bottom only has effect on layout elements +warning: rog-control-center@6.3.0: --> /mnt/Data/mihais/builds/ROGCC/rog-control-center/ui/widgets/sidebar.slint:122:29 +warning: rog-control-center@6.3.0: | +warning: rog-control-center@6.3.0: 122 | padding-bottom: 20px; +warning: rog-control-center@6.3.0: | ^^^^^ +error: could not compile `rog-control-center` (lib) due to 10 previous errors diff --git a/build_error_fans.log b/build_error_fans.log new file mode 100644 index 00000000..664340c2 --- /dev/null +++ b/build_error_fans.log @@ -0,0 +1,53 @@ +warning: rog-control-center@6.3.0: warning: padding-bottom only has effect on layout elements +warning: rog-control-center@6.3.0: --> /mnt/Data/mihais/builds/ROGCC/rog-control-center/ui/widgets/sidebar.slint:122:29 +warning: rog-control-center@6.3.0: | +warning: rog-control-center@6.3.0: 122 | padding-bottom: 20px; +warning: rog-control-center@6.3.0: | ^^^^^ + Compiling rog-control-center v6.3.0 (/mnt/Data/mihais/builds/ROGCC/rog-control-center) +error[E0505]: cannot move out of `handle_copy` because it is borrowed + --> rog-control-center/src/ui/setup_fans.rs:174:59 + | +137 | let handle_copy = handle.clone(); + | ----------- binding `handle_copy` declared here +... +174 | if let Err(e) = handle_copy.upgrade_in_event_loop(move |handle| { + | ----------- --------------------- ^^^^^^^^^^^^^ move out of `handle_copy` occurs here + | | | + | | borrow later used by call + | borrow of `handle_copy` occurs here +... +216 | let handle_weak = handle_copy.clone(); + | ----------- move occurs due to use in closure + | +help: consider cloning the value before moving it into the closure + | +174 ~ if let Err(e) = handle_copy.upgrade_in_event_loop({ +175 + let value = handle_copy.clone(); +176 ~ move |handle| { +177 | let global = handle.global::(); +... +217 | }); +218 ~ let handle_weak = value.clone(); +219 | global.on_set_fan_data(move |fan, profile, enabled, data| { +... +232 | }); +233 ~ } +234 ~ }) { + | + +warning: unused variable: `ui_weak_copy` + --> rog-control-center/src/ui/setup_slash.rs:32:17 + | +32 | let ui_weak_copy = ui_weak.clone(); + | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_ui_weak_copy` + | + = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default + +For more information about this error, try `rustc --explain E0505`. +warning: `rog-control-center` (lib) generated 1 warning +warning: rog-control-center@6.3.0: warning: padding-bottom only has effect on layout elements +warning: rog-control-center@6.3.0: --> /mnt/Data/mihais/builds/ROGCC/rog-control-center/ui/widgets/sidebar.slint:122:29 +warning: rog-control-center@6.3.0: | +warning: rog-control-center@6.3.0: 122 | padding-bottom: 20px; +warning: rog-control-center@6.3.0: | ^^^^^ +error: could not compile `rog-control-center` (lib) due to 1 previous error; 1 warning emitted diff --git a/build_error_fans_2.log b/build_error_fans_2.log new file mode 100644 index 00000000..e02da263 --- /dev/null +++ b/build_error_fans_2.log @@ -0,0 +1,49 @@ +warning: rog-control-center@6.3.0: warning: padding-bottom only has effect on layout elements +warning: rog-control-center@6.3.0: --> /mnt/Data/mihais/builds/ROGCC/rog-control-center/ui/widgets/sidebar.slint:122:29 +warning: rog-control-center@6.3.0: | +warning: rog-control-center@6.3.0: 122 | padding-bottom: 20px; +warning: rog-control-center@6.3.0: | ^^^^^ + Compiling rog-control-center v6.3.0 (/mnt/Data/mihais/builds/ROGCC/rog-control-center) +error[E0505]: cannot move out of `handle` because it is borrowed + --> rog-control-center/src/ui/setup_fans.rs:216:36 + | + 174 | if let Err(e) = handle_copy.upgrade_in_event_loop(move |handle| { + | ------ binding `handle` declared here + 175 | let global = handle.global::(); + | ------ borrow of `handle` occurs here +... + 216 | global.on_set_fan_data(move |fan, profile, enabled, data| { + | --------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `handle` occurs here + | | + | borrow later used by call + 217 | let fans = fans.clone(); + 218 | let handle_weak = handle.as_weak(); + | ------ move occurs due to use in closure + | +note: if `MainWindow` implemented `Clone`, you could clone the value + --> /mnt/Data/mihais/builds/ROGCC/target/debug/build/rog-control-center-f28a2c919698f43f/out/main_window.rs:128899:6 + | +128899 | pub struct r#MainWindow (sp :: VRc < sp :: ItemTreeVTable , InnerMainWindow >) ; + | ^^^^^^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type + | + ::: rog-control-center/src/ui/setup_fans.rs:175:26 + | + 175 | let global = handle.global::(); + | ------ you could clone this value + +warning: unused variable: `ui_weak_copy` + --> rog-control-center/src/ui/setup_slash.rs:32:17 + | +32 | let ui_weak_copy = ui_weak.clone(); + | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_ui_weak_copy` + | + = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default + +For more information about this error, try `rustc --explain E0505`. +warning: `rog-control-center` (lib) generated 1 warning +warning: rog-control-center@6.3.0: warning: padding-bottom only has effect on layout elements +warning: rog-control-center@6.3.0: --> /mnt/Data/mihais/builds/ROGCC/rog-control-center/ui/widgets/sidebar.slint:122:29 +warning: rog-control-center@6.3.0: | +warning: rog-control-center@6.3.0: 122 | padding-bottom: 20px; +warning: rog-control-center@6.3.0: | ^^^^^ +error: could not compile `rog-control-center` (lib) due to 1 previous error; 1 warning emitted diff --git a/error.log b/error.log new file mode 100644 index 00000000..15799bc5 --- /dev/null +++ b/error.log @@ -0,0 +1,66 @@ +warning: rog-control-center@6.3.0: warning: padding-bottom only has effect on layout elements +warning: rog-control-center@6.3.0: --> /mnt/Data/mihais/builds/ROGCC/rog-control-center/ui/widgets/sidebar.slint:122:29 +warning: rog-control-center@6.3.0: | +warning: rog-control-center@6.3.0: 122 | padding-bottom: 20px; +warning: rog-control-center@6.3.0: | ^^^^^ + Checking rog-control-center v6.3.0 (/mnt/Data/mihais/builds/ROGCC/rog-control-center) +warning: unused import: `Weak` + --> rog-control-center/src/ui/setup_screenpad.rs:3:30 + | +3 | use slint::{ComponentHandle, Weak}; + | ^^^^ + | + = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + +warning: unused import: `set_ui_callbacks` + --> rog-control-center/src/ui/setup_screenpad.rs:8:13 + | +8 | use crate::{set_ui_callbacks, MainWindow, ScreenpadPageData}; + | ^^^^^^^^^^^^^^^^ + +warning: unused import: `ScreenpadPageData` + --> rog-control-center/src/ui/mod.rs:27:46 + | +27 | use crate::{AppSettingsPageData, MainWindow, ScreenpadPageData}; + | ^^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> rog-control-center/src/ui/setup_screenpad.rs:81:57 + | +81 | ... bl.set_screenpad_brightness(val as u32).await, + | ------------------------ ^^^^^^^^^^ expected `i32`, found `u32` + | | + | arguments to this method are incorrect + | +note: method defined here + --> /mnt/Data/mihais/builds/ROGCC/rog-dbus/src/zbus_backlight.rs:40:8 + | +40 | fn set_screenpad_brightness(&self, value: i32) -> zbus::Result<()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit + | +81 | bl.set_screenpad_brightness((val as u32).try_into().unwrap()).await, + | + +++++++++++++++++++++ + +warning: unused variable: `ui_weak_copy` + --> rog-control-center/src/ui/setup_slash.rs:32:17 + | +32 | let ui_weak_copy = ui_weak.clone(); + | ^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_ui_weak_copy` + | + = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default + +warning: unused variable: `backlight` + --> rog-control-center/src/ui/setup_system.rs:298:13 + | +298 | let backlight = BacklightProxy::builder(&conn) + | ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_backlight` + +For more information about this error, try `rustc --explain E0308`. +warning: `rog-control-center` (lib) generated 5 warnings +warning: rog-control-center@6.3.0: warning: padding-bottom only has effect on layout elements +warning: rog-control-center@6.3.0: --> /mnt/Data/mihais/builds/ROGCC/rog-control-center/ui/widgets/sidebar.slint:122:29 +warning: rog-control-center@6.3.0: | +warning: rog-control-center@6.3.0: 122 | padding-bottom: 20px; +warning: rog-control-center@6.3.0: | ^^^^^ +error: could not compile `rog-control-center` (lib) due to 1 previous error; 5 warnings emitted diff --git a/rog-control-center/ui/main_window.slint b/rog-control-center/ui/main_window.slint index 93fb9272..7b119e6b 100644 --- a/rog-control-center/ui/main_window.slint +++ b/rog-control-center/ui/main_window.slint @@ -1,13 +1,15 @@ -import { Palette, Button, VerticalBox } from "std-widgets.slint"; +import { Button, VerticalBox } from "std-widgets.slint"; import { AppSize } from "globals.slint"; import { PageSystem, SystemPageData, AttrMinMax } from "pages/system.slint"; import { SideBar } from "widgets/sidebar.slint"; import { PageAbout } from "pages/about.slint"; import { PageFans } from "pages/fans.slint"; +import { PageSlash, SlashPageData } from "pages/slash.slint"; +import { PageSupergfx, SupergfxPageData } from "pages/supergfx.slint"; +import { PageScreenpad, ScreenpadPageData } from "pages/screenpad.slint"; import { PageAnime, AnimePageData } from "pages/anime.slint"; import { RogItem } from "widgets/common.slint"; import { PageAura } from "pages/aura.slint"; -import { PageGPU } from "pages/gpu.slint"; import { Node } from "widgets/graph.slint"; export { Node } import { FanPageData, FanType, Profile } from "types/fan_types.slint"; @@ -15,8 +17,18 @@ export { FanPageData, FanType, Profile } import { AuraPageData, AuraDevType, LaptopAuraPower, AuraPowerState, PowerZones, AuraEffect } from "types/aura_types.slint"; export { AuraPageData, AuraDevType, LaptopAuraPower, AuraPowerState, PowerZones, AuraEffect } import { PageAppSettings, AppSettingsPageData } from "pages/app_settings.slint"; +import { StatusBar, SystemStatus } from "widgets/status_bar.slint"; +import { TrayTooltip } from "windows/tray_tooltip.slint"; +export { TrayTooltip } -export { AppSize, AttrMinMax, SystemPageData, AnimePageData, AppSettingsPageData } +import { RogPalette } from "themes/rog_theme.slint"; + +export { AppSize, AttrMinMax, SystemPageData, AnimePageData, AppSettingsPageData, SystemStatus, SlashPageData, SupergfxPageData, ScreenpadPageData } + +export global SomeError { + in property error_message: ""; + in property error_help: ""; +} export component MainWindow inherits Window { title: "ROG Control"; @@ -25,130 +37,133 @@ export component MainWindow inherits Window { default-font-size: 14px; default-font-weight: 400; icon: @image-url("../data/rog-control-center.png"); - in property <[bool]> sidebar_items_avilable: [ - true, - true, - true, - true, - true, // GPU Configuration - true, // App Settings - true, // About - ]; + in property <[bool]> sidebar_items_avilable: [true, true, true, true, true, true, true, true, true]; private property show_notif; private property fade_cover; private property toast: false; private property toast_text: "I show when something is waiting"; + callback show_toast(string); + callback start_toast_timer(); + callback hide_toast(); + + hide_toast() => { + toast = false; + } + show_toast(text) => { toast = text != ""; toast_text = text; + if (toast) { + start_toast_timer(); + } } + callback exit-app(); callback show_notification(bool); + show_notification(yes) => { show_notif = yes; fade_cover = yes; } + callback external_colour_change(); external_colour_change() => { aura.external_colour_change(); aura.external_colour_change(); } + min-height: AppSize.height; min-width: AppSize.width; - background: Palette.alternate-background; + background: RogPalette.background; - HorizontalLayout { - padding: 0px; - VerticalLayout { + VerticalLayout { + HorizontalLayout { padding: 0px; - side-bar := SideBar { - model: [ - @tr("Menu1" => "System Control"), - @tr("Menu2" => "Keyboard Aura"), - @tr("Menu3" => "AniMe Matrix"), - @tr("Menu4" => "Fan Curves"), - @tr("Menu5" => "GPU Configuration"), - @tr("Menu6" => "App Settings"), - @tr("Menu7" => "About"), - ]; - available: root.sidebar_items_avilable; - } - - Button { - height: 40px; - width: side-bar.width; - text: @tr("Quit App"); - clicked() => { - root.exit-app(); - } - } - } - - Rectangle { - background: Palette.background; - if(side-bar.current-item == 0): page := PageSystem { - width: root.width - side-bar.width; - height: root.height + 12px; - } - - /*if(side-bar.current-item == 1):*/ aura := PageAura { - width: root.width - side-bar.width; - visible: side-bar.current-item == 1; - } - - if(side-bar.current-item == 2): PageAnime { - width: root.width - side-bar.width; - visible: side-bar.current-item == 2; - } - - if(side-bar.current-item == 3): fans := PageFans { - width: root.width - side-bar.width; - visible: side-bar.current-item == 3; - } - - if(side-bar.current-item == 4): PageGPU { - width: root.width - side-bar.width; - visible: side-bar.current-item == 4; - } - - if(side-bar.current-item == 5): PageAppSettings { - width: root.width - side-bar.width; - visible: side-bar.current-item == 5; - } - - if(side-bar.current-item == 6): PageAbout { - width: root.width - side-bar.width; - visible: side-bar.current-item == 6; - } - - if toast: Rectangle { - x: 0px; - y: root.height - self.height; - width: root.width - side-bar.width; - height: 40px; - opacity: 1.0; - background: Palette.selection-background; - clip: true; - TouchArea { - height: 100%; - width: 100%; - clicked => { - toast = false; - } + + // Left Column: Sidebar + Quit Button + VerticalLayout { + side-bar := SideBar { + title: @tr("ROG"); + model: [ + @tr("Menu1" => "System Control"), + @tr("Menu2" => "Keyboard Aura"), + @tr("Menu3" => "AniMe Matrix"), + @tr("Menu7" => "Slash Lighting"), + @tr("Menu8" => "Graphics Control"), + @tr("Menu9" => "Screenpad Control"), + @tr("Menu4" => "Fan Curves"), + @tr("Menu5" => "App Settings"), + @tr("Menu6" => "About"), + ]; + available: root.sidebar_items_avilable; } Rectangle { - height: 100%; - width: 100%; - background: Palette.control-background; + max-height: 40px; + width: side-bar.width; + background: RogPalette.control-background; Text { - color: Palette.control-foreground; - text: root.toast_text; + vertical-alignment: center; + horizontal-alignment: center; + text: @tr("Quit App"); + color: RogPalette.text-primary; + } + + TouchArea { + clicked => { + root.exit-app(); + } } } } + + // Right Column: Content Pages + Rectangle { + background: RogPalette.background; + if(side-bar.current-item == 0): page := PageSystem { + width: root.width - side-bar.width; + height: root.height + 12px; + } + + aura := PageAura { + width: root.width - side-bar.width; + visible: side-bar.current-item == 1; + } + + if(side-bar.current-item == 2): PageAnime { + width: root.width - side-bar.width; + } + + if(side-bar.current-item == 3): PageSlash { + width: root.width - side-bar.width; + } + + if(side-bar.current-item == 4): PageSupergfx { + width: root.width - side-bar.width; + } + + if(side-bar.current-item == 5): PageScreenpad { + width: root.width - side-bar.width; + } + + fans := PageFans { + width: root.width - side-bar.width; + visible: side-bar.current-item == 6; + } + + if(side-bar.current-item == 7): PageAppSettings { + width: root.width - side-bar.width; + } + + if(side-bar.current-item == 8): PageAbout { + width: root.width - side-bar.width; + } + } } + + // Bottom: Status Bar + StatusBar {} } if fade_cover: Rectangle { @@ -156,7 +171,7 @@ export component MainWindow inherits Window { y: 0px; width: root.width; height: root.height; - background: Colors.rgba(25,33,23,20); + background: Colors.rgba(0,0,0,0.7); opacity: 0.7; TouchArea { height: 100%; @@ -171,6 +186,52 @@ export component MainWindow inherits Window { } } + // Modern floating toast/snackbar notification + // Shows at the bottom center, non-intrusive + Rectangle { + visible: self.opacity > 0; + opacity: root.toast ? 1 : 0; + animate opacity { duration: 300ms; } + + x: (root.width - 400px) / 2; // Center horizontally + y: root.height - 80px; // Bottom padding + width: 400px; + height: 48px; + border-radius: RogPalette.border-radius; + border-width: 1px; + border-color: RogPalette.accent; + background: RogPalette.control-background; + drop-shadow-blur: 10px; + drop-shadow-color: Colors.black; + + TouchArea { + height: 100%; + width: 100%; + clicked => { + toast = false; + } + } + + HorizontalLayout { + padding-left: 16px; + padding-right: 16px; + alignment: space-between; + + Text { + vertical-alignment: center; + color: RogPalette.text-primary; + text: root.toast_text; + overflow: elide; + } + + Text { + vertical-alignment: center; + text: "Dismiss"; + color: RogPalette.text-secondary; + font-size: 12px; + } + } + } // // TODO: or use Dialogue if show_notif: Rectangle { @@ -187,13 +248,20 @@ export component MainWindow inherits Window { } } - // TODO: add properties to display Rectangle { height: 100%; width: 100%; - background: Palette.background; - Text { - text: "Click here to exit"; + background: RogPalette.control-background; + border-radius: 8px; + + VerticalLayout { + alignment: center; + Text { + horizontal-alignment: center; + text: "Click here to exit"; + color: RogPalette.text-primary; + font-size: 16px; + } } } } @@ -203,31 +271,45 @@ export component MainWindow inherits Window { y: 0px; width: root.width; height: root.height; - background: Palette.background; - border-color: Palette.border; - border-width: 3px; - border-radius: 10px; + + background: RogPalette.background; + border-color: RogPalette.accent; + border-width: 2px; + border-radius: 8px; VerticalBox { - RogItem { - min-height: 50px; - max-height: 100px; + padding: 20px; + spacing: 15px; + alignment: center; + + Text { + text: "Error"; + font-size: 22px; + font-weight: 700; + color: RogPalette.accent; + horizontal-alignment: center; + } + + Rectangle { + background: RogPalette.control-background; + border-radius: 8px; + min-height: 60px; + Text { text <=> SomeError.error_message; - font-size: 18px; + font-size: 16px; + color: RogPalette.text-primary; + horizontal-alignment: center; + vertical-alignment: center; } } Text { text <=> SomeError.error_help; - horizontal-alignment: TextHorizontalAlignment.center; - vertical-alignment: TextVerticalAlignment.center; + color: RogPalette.text-secondary; + horizontal-alignment: center; + vertical-alignment: center; } } } } - -export global SomeError { - in property error_message: ""; - in property error_help: ""; -} diff --git a/rog-control-center/ui/pages/about.slint b/rog-control-center/ui/pages/about.slint index b4dd9676..d1e43ca6 100644 --- a/rog-control-center/ui/pages/about.slint +++ b/rog-control-center/ui/pages/about.slint @@ -1,75 +1,126 @@ -import { - AboutSlint, - VerticalBox, - HorizontalBox, - ScrollView, -} from "std-widgets.slint"; +import { VerticalBox, HorizontalBox, ScrollView } from "std-widgets.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; + +export component PageAbout inherits Rectangle { + background: RogPalette.background; -export component PageAbout inherits VerticalLayout { - padding: 10px; - spacing: 10px; ScrollView { + VerticalBox { + padding: 30px; + spacing: 20px; + alignment: center; - HorizontalBox { - alignment: LayoutAlignment.center; - VerticalBox { - alignment: LayoutAlignment.center; + // Title + Text { + horizontal-alignment: center; + text: "ROG Control Center"; + font-size: 28px; + font-weight: 800; + color: RogPalette.accent; + } - Text { - vertical-alignment: TextVerticalAlignment.center; - horizontal-alignment: TextHorizontalAlignment.center; - text: "ROG Control Center"; - font-size: 22px; + Text { + horizontal-alignment: center; + text: "A modern UI for asusctl built with Slint"; + font-size: 16px; + color: RogPalette.text-secondary; + } + + // Version info + Rectangle { + height: 60px; + background: RogPalette.control-background; + border-radius: 8px; + border-width: 1px; + border-color: RogPalette.control-border; + + HorizontalBox { + padding: 15px; + alignment: center; + Text { + text: "Version 6.3.0"; + font-size: 14px; + color: RogPalette.text-primary; + } + Text { + text: " | "; + color: RogPalette.text-secondary; + } + Text { + text: "Requires kernel 6.10+"; + font-size: 14px; + color: RogPalette.text-secondary; + } } + } - Text { - wrap: TextWrap.word-wrap; - text: "\nA powerful graphical interface for managing ASUS ROG, TUF, and ProArt laptops on Linux. It acts as the official GUI for the asusctl toolset, allowing for seamless hardware tuning without the command line."; + // Features section + Rectangle { + background: RogPalette.control-background; + border-radius: 8px; + border-width: 1px; + border-color: RogPalette.control-border; + + VerticalBox { + padding: 20px; + spacing: 12px; + + Text { + text: "Features"; + font-size: 18px; + font-weight: 700; + color: RogPalette.accent; + } + + // Completed features + Text { text: "[x] ROG-themed dark UI"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] System status bar (CPU/GPU temps & fan speeds)"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] Power profile management"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] Aura RGB keyboard lighting"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] AniMe Matrix display"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] Slash LED control"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] Supergfx graphics switching"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] Screenpad brightness & gamma"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] Custom fan curves"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] Desktop notifications (KDE OSD)"; color: RogPalette.text-primary; font-size: 13px; } + Text { text: "[x] System tray integration"; color: RogPalette.text-primary; font-size: 13px; } + + // Pending features + Rectangle { height: 10px; } + Text { text: "Planned:"; font-size: 14px; font-weight: 600; color: RogPalette.text-secondary; } + Text { text: "[ ] ROG Ally specific settings"; color: RogPalette.text-secondary; font-size: 13px; } + Text { text: "[ ] Advanced Aura zone editing"; color: RogPalette.text-secondary; font-size: 13px; } } + } - Text { - font-weight: 900; - text: "Key Features:"; - } + // Credits + Rectangle { + background: RogPalette.control-background; + border-radius: 8px; + border-width: 1px; + border-color: RogPalette.control-border; - Text { - text: " • Performance: Switch power profiles and customize fan curves.\n • Aura Sync: Control keyboard backlighting and LED effects.\n • Battery Health: Set charge limits to extend battery longevity.\n • Display: Toggle Panel Overdrive and refresh rates.\n • AniMe Matrix: Control AniMe Matrix displays."; - } + VerticalBox { + padding: 20px; + spacing: 8px; - Text { - font-weight: 900; - text: "Requirements:"; - } + Text { + text: "Credits"; + font-size: 18px; + font-weight: 700; + color: RogPalette.accent; + } - Text { - text: " • This software requires kernel version 6.19."; - } - - Text { - font-weight: 900; - text: "Work in progress:"; - } - - Text { - text: " • Theme the widgets\n • Add a cpu/gpu temp/fan speed info bar\n • Include fan speeds, temps in a bottom bar\n • Slash control\n • Screenpad controls\n • ROG Ally specific settings"; - } - - Text { - font-weight: 900; - text: "License:"; - } - - Text { - text: " This project is open-source software licensed under the Mozilla Public License 2.0 (MPL-2.0)."; - } - - Text { - font-weight: 900; - text: "Links:"; - } - - Text { - text: " Source Code: https://gitlab.com/asus-linux/asusctl\n Website: https://asus-linux.org/"; + Text { + text: "asusctl & asusd by Luke Jones"; + font-size: 13px; + color: RogPalette.text-primary; + } + Text { + text: "UI built with Slint"; + font-size: 13px; + color: RogPalette.text-secondary; + } } } } diff --git a/rog-control-center/ui/pages/anime.slint b/rog-control-center/ui/pages/anime.slint index 7eb28898..6536b339 100644 --- a/rog-control-center/ui/pages/anime.slint +++ b/rog-control-center/ui/pages/anime.slint @@ -1,5 +1,6 @@ import { SystemDropdown, SystemToggle } from "../widgets/common.slint"; import { Palette, GroupBox, VerticalBox, Button, HorizontalBox } from "std-widgets.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; export global AnimePageData { in-out property <[string]> brightness_names: [ @@ -36,8 +37,12 @@ export component PageAnime inherits Rectangle { property show_display_advanced: false; property show_builtin_advanced: false; clip: true; - - VerticalLayout { + // TODO: slow with border-radius + //padding only has effect on layout elements + //padding: 8px; + // height: parent.height - infobar.height - mainview.padding - self.padding * 2; + // TODO: border-radius: 8px; + VerticalLayout { padding: 10px; spacing: 10px; HorizontalLayout { @@ -105,7 +110,7 @@ export component PageAnime inherits Rectangle { if root.show_fade_cover: Rectangle { width: 100%; height: 100%; - background: Palette.background; + background: RogPalette.background; opacity: 0.8; TouchArea { height: 100%; @@ -128,9 +133,8 @@ export component PageAnime inherits Rectangle { width: 100%; height: 100%; opacity: 1; - background: Palette.background; VerticalLayout { - padding: 4px; + padding: 50px; spacing: 10px; GroupBox { height: 10px; @@ -138,8 +142,8 @@ export component PageAnime inherits Rectangle { spacing: 10px; alignment: LayoutAlignment.start; Text { - font-size: 16px; - color: Palette.control-foreground; + font-size: 18px; + color: RogPalette.text-primary; horizontal-alignment: TextHorizontalAlignment.center; text: @tr("Set which builtin animations are played"); } @@ -190,8 +194,8 @@ export component PageAnime inherits Rectangle { Button { x: root.width - self.width - 6px; y: 6px; - text: "✕"; - height: 36px; + text: "X"; + height: 40px; clicked => { root.show_builtin_advanced = false; root.show_fade_cover = false; @@ -203,9 +207,8 @@ export component PageAnime inherits Rectangle { width: 100%; height: 100%; opacity: 1; - background: Palette.background; VerticalLayout { - padding: 4px; + padding: 50px; spacing: 10px; GroupBox { height: 100px; @@ -213,8 +216,8 @@ export component PageAnime inherits Rectangle { spacing: 10px; alignment: LayoutAlignment.start; Text { - font-size: 16px; - color: Palette.control-foreground; + font-size: 18px; + color: RogPalette.text-primary; horizontal-alignment: TextHorizontalAlignment.center; text: @tr("Advanced Display Settings"); } @@ -252,8 +255,8 @@ export component PageAnime inherits Rectangle { Button { x: root.width - self.width - 6px; y: 6px; - text: "✕"; - height: 36px; + text: "X"; + height: 40px; clicked => { root.show_display_advanced = false; root.show_fade_cover = false; diff --git a/rog-control-center/ui/pages/app_settings.slint b/rog-control-center/ui/pages/app_settings.slint index 95919868..07fcd338 100644 --- a/rog-control-center/ui/pages/app_settings.slint +++ b/rog-control-center/ui/pages/app_settings.slint @@ -1,5 +1,6 @@ -import { Palette } from "std-widgets.slint"; -import { SystemToggle } from "../widgets/common.slint"; +import { VerticalBox, ScrollView, HorizontalBox, Button } from "std-widgets.slint"; +import { SystemToggle, RogItem } from "../widgets/common.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; export global AppSettingsPageData { in-out property run_in_background; @@ -8,52 +9,134 @@ export global AppSettingsPageData { callback set_startup_in_background(bool); in-out property enable_tray_icon; callback set_enable_tray_icon(bool); - in-out property enable_dgpu_notifications; - callback set_enable_dgpu_notifications(bool); + + // Master notification toggle + in-out property notifications_enabled; + callback set_notifications_enabled(bool); + + // Granular notification toggles + in-out property notify_gfx_switch; + callback set_notify_gfx_switch(bool); + in-out property notify_gfx_status; + callback set_notify_gfx_status(bool); + in-out property notify_platform_profile; + callback set_notify_platform_profile(bool); } -export component PageAppSettings inherits VerticalLayout { - Rectangle { - clip: true; +export component PageAppSettings inherits Rectangle { + background: RogPalette.background; + + ScrollView { + VerticalBox { + padding: 20px; + spacing: 20px; + alignment: start; - mainview := VerticalLayout { - padding: 10px; - spacing: 10px; - SystemToggle { - text: @tr("Run in background after closing"); - checked <=> AppSettingsPageData.run_in_background; - toggled => { - AppSettingsPageData.set_run_in_background(AppSettingsPageData.run_in_background) + // General Section + VerticalBox { + spacing: 10px; + padding: 0px; + + Rectangle { + height: 30px; + background: RogPalette.control-background; + border-radius: 4px; + border-width: 1px; + border-color: RogPalette.control-border; + + Text { + x: 10px; + vertical-alignment: center; + text: "General Settings"; + color: RogPalette.accent; + font-weight: 700; + } + } + + SystemToggle { + text: @tr("Run in background after closing"); + checked <=> AppSettingsPageData.run_in_background; + toggled => { + AppSettingsPageData.set_run_in_background(AppSettingsPageData.run_in_background) + } + } + + SystemToggle { + text: @tr("Start app in background (UI closed)"); + checked <=> AppSettingsPageData.startup_in_background; + toggled => { + AppSettingsPageData.set_startup_in_background(AppSettingsPageData.startup_in_background) + } + } + + SystemToggle { + text: @tr("Enable system tray icon"); + checked <=> AppSettingsPageData.enable_tray_icon; + toggled => { + AppSettingsPageData.set_enable_tray_icon(AppSettingsPageData.enable_tray_icon) + } } } - SystemToggle { - text: @tr("Start app in background (UI closed)"); - checked <=> AppSettingsPageData.startup_in_background; - toggled => { - AppSettingsPageData.set_startup_in_background(AppSettingsPageData.startup_in_background) - } - } + // Notifications Section + VerticalBox { + spacing: 10px; + padding: 0px; - SystemToggle { - text: @tr("Enable system tray icon"); - checked <=> AppSettingsPageData.enable_tray_icon; - toggled => { - AppSettingsPageData.set_enable_tray_icon(AppSettingsPageData.enable_tray_icon) - } - } + Rectangle { + height: 30px; + background: RogPalette.control-background; + border-radius: 4px; + border-width: 1px; + border-color: RogPalette.control-border; - SystemToggle { - text: @tr("Enable dGPU notifications"); - checked <=> AppSettingsPageData.enable_dgpu_notifications; - toggled => { - AppSettingsPageData.set_enable_dgpu_notifications(AppSettingsPageData.enable_dgpu_notifications) + Text { + x: 10px; + vertical-alignment: center; + text: "Notifications"; + color: RogPalette.accent; + font-weight: 700; + } + } + + SystemToggle { + text: @tr("Enable Notifications"); + checked <=> AppSettingsPageData.notifications_enabled; + toggled => { + AppSettingsPageData.set_notifications_enabled(AppSettingsPageData.notifications_enabled) + } + } + + // Sub-toggles container + VerticalBox { + padding-left: 30px; // Indent + spacing: 10px; + visible: AppSettingsPageData.notifications_enabled; + + SystemToggle { + text: @tr("Notify on Graphics Switch"); + checked <=> AppSettingsPageData.notify_gfx_switch; + toggled => { + AppSettingsPageData.set_notify_gfx_switch(AppSettingsPageData.notify_gfx_switch) + } + } + + SystemToggle { + text: @tr("Notify on GPU Status Change"); + checked <=> AppSettingsPageData.notify_gfx_status; + toggled => { + AppSettingsPageData.set_notify_gfx_status(AppSettingsPageData.notify_gfx_status) + } + } + + SystemToggle { + text: @tr("Notify on Power Profile Change"); + checked <=> AppSettingsPageData.notify_platform_profile; + toggled => { + AppSettingsPageData.set_notify_platform_profile(AppSettingsPageData.notify_platform_profile) + } + } } - } - - Text { - color: Palette.accent-background; - text: " WIP: some features like notifications are not complete"; } } } diff --git a/rog-control-center/ui/pages/aura.slint b/rog-control-center/ui/pages/aura.slint index 43d803ae..a6882888 100644 --- a/rog-control-center/ui/pages/aura.slint +++ b/rog-control-center/ui/pages/aura.slint @@ -1,8 +1,28 @@ -import { SystemDropdown, RogItem, SystemToggle, SystemToggleVert } from "../widgets/common.slint"; -import { Palette, Button, ComboBox, VerticalBox, GroupBox } from "std-widgets.slint"; -import { StyleMetrics, Slider, HorizontalBox, TextEdit, SpinBox, LineEdit, ScrollView } from "std-widgets.slint"; +import { + SystemDropdown, + RogItem, + SystemToggle, + SystemToggleVert, +} from "../widgets/common.slint"; +import { Button, ComboBox, VerticalBox, GroupBox } from "std-widgets.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; +import { + StyleMetrics, + Slider, + HorizontalBox, + TextEdit, + SpinBox, + LineEdit, + ScrollView, +} from "std-widgets.slint"; import { ColourSlider } from "../widgets/colour_picker.slint"; -import { AuraPageData, AuraDevType, PowerZones, LaptopAuraPower, AuraEffect } from "../types/aura_types.slint"; +import { + AuraPageData, + AuraDevType, + PowerZones, + LaptopAuraPower, + AuraEffect, +} from "../types/aura_types.slint"; import { AuraPowerGroup, AuraPowerGroupOld } from "../widgets/aura_power.slint"; export component PageAura inherits Rectangle { @@ -180,6 +200,40 @@ export component PageAura inherits Rectangle { } } + // Software Animation Controls (for Static-only keyboards) + if AuraPageData.soft_animation_available: RogItem { + min-height: 100px; + VerticalLayout { + padding: 10px; + spacing: 8px; + Text { + text: @tr("Software Animation (Static-only keyboards)"); + font-size: 14px; + font-weight: 600; + color: RogPalette.accent; + } + + HorizontalLayout { + spacing: 20px; + VerticalLayout { + Text { + text: @tr("Animation Mode"); + color: RogPalette.text-secondary; + } + + ComboBox { + current_index <=> AuraPageData.soft_animation_mode; + current_value: AuraPageData.soft_animation_modes[self.current-index]; + model <=> AuraPageData.soft_animation_modes; + selected => { + AuraPageData.cb_soft_animation_mode(AuraPageData.soft_animation_mode); + } + } + } + } + } + } + HorizontalLayout { Button { text: @tr("Power Settings"); @@ -192,11 +246,15 @@ export component PageAura inherits Rectangle { } if root.show_fade_cover: Rectangle { - background: Palette.background; + background: RogPalette.background; opacity: 0.8; TouchArea { height: 100%; width: 100%; + clicked => { + root.show_fade_cover = false; + root.show_aura_power = false; + } } } } @@ -265,7 +323,10 @@ export component PageAura inherits Rectangle { alignment: LayoutAlignment.start; Text { - text: "TODO: In progress"; + text: "LED Power Zones (Legacy)"; + font-size: 16px; + font-weight: 600; + color: #ff0033; } for state[idx] in AuraPageData.led_power.states: old_zone := AuraPowerGroupOld { diff --git a/rog-control-center/ui/pages/fans.slint b/rog-control-center/ui/pages/fans.slint index db1d7e3a..340edd6c 100644 --- a/rog-control-center/ui/pages/fans.slint +++ b/rog-control-center/ui/pages/fans.slint @@ -1,7 +1,10 @@ -import { Palette, TabWidget, Button, CheckBox } from "std-widgets.slint"; +import { Palette, TabWidget, Button, CheckBox, Slider } from "std-widgets.slint"; import { Graph, Node } from "../widgets/graph.slint"; import { SystemToggle } from "../widgets/common.slint"; import { Profile, FanType, FanPageData } from "../types/fan_types.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; + + component FanTab inherits Rectangle { in-out property enabled: false; @@ -16,40 +19,104 @@ component FanTab inherits Rectangle { in-out property <[Node]> nodes; VerticalLayout { - padding: 5px; + private property local_busy: + (root.fan_type == FanType.CPU && FanPageData.is_busy_cpu) || + (root.fan_type == FanType.GPU && FanPageData.is_busy_gpu) || + (root.fan_type == FanType.Middle && FanPageData.is_busy_mid); + + if FanPageData.show_custom_warning: Rectangle { + background: RogPalette.control-background; + border-radius: 4px; + height: 48px; + HorizontalLayout { + padding: 10px; + Text { + color: #ffd700; // Gold/Yellow + text: @tr("Zero RPM Mode Enabled: Fans will take ~25s to spin down entirely."); + vertical-alignment: TextVerticalAlignment.center; + horizontal-alignment: TextHorizontalAlignment.center; + wrap: word-wrap; + } + } + } + HorizontalLayout { + spacing: 10px; if root.tab_enabled: Graph { nodes <=> root.nodes; } + if root.tab_enabled: VerticalLayout { + width: 40px; + alignment: center; + spacing: 10px; + + Button { + text: "+"; + height: 40px; + width: 40px; + clicked => { + root.nodes = [ + { x: root.nodes[0].x, y: min(255px, root.nodes[0].y + 13px) }, + { x: root.nodes[1].x, y: min(255px, root.nodes[1].y + 13px) }, + { x: root.nodes[2].x, y: min(255px, root.nodes[2].y + 13px) }, + { x: root.nodes[3].x, y: min(255px, root.nodes[3].y + 13px) }, + { x: root.nodes[4].x, y: min(255px, root.nodes[4].y + 13px) }, + { x: root.nodes[5].x, y: min(255px, root.nodes[5].y + 13px) }, + { x: root.nodes[6].x, y: min(255px, root.nodes[6].y + 13px) }, + { x: root.nodes[7].x, y: min(255px, root.nodes[7].y + 13px) } + ]; + } + } + + Text { + text: "All"; + font-size: 10px; + horizontal-alignment: center; + color: white; + } + + Button { + text: "-"; + height: 40px; + width: 40px; + clicked => { + root.nodes = [ + { x: root.nodes[0].x, y: max(0px, root.nodes[0].y - 13px) }, + { x: root.nodes[1].x, y: max(0px, root.nodes[1].y - 13px) }, + { x: root.nodes[2].x, y: max(0px, root.nodes[2].y - 13px) }, + { x: root.nodes[3].x, y: max(0px, root.nodes[3].y - 13px) }, + { x: root.nodes[4].x, y: max(0px, root.nodes[4].y - 13px) }, + { x: root.nodes[5].x, y: max(0px, root.nodes[5].y - 13px) }, + { x: root.nodes[6].x, y: max(0px, root.nodes[6].y - 13px) }, + { x: root.nodes[7].x, y: max(0px, root.nodes[7].y - 13px) } + ]; + } + } + } + if !root.tab_enabled: Rectangle { Text { - font-size: 16px; + font-size: 24px; text: @tr("This fan is not avilable on this machine"); } } } - Rectangle { - background: Palette.border; - height: 1px; - } - HorizontalLayout { + spacing: 20px; alignment: LayoutAlignment.end; - spacing: 10px; - padding: 10px; CheckBox { - text: @tr("Enabled"); + text: @tr("Enable Manual Control"); checked <=> root.enabled; - enabled <=> root.tab_enabled; + enabled: root.tab_enabled && !local_busy; toggled => { root.toggled(); } } Button { - text: @tr("Apply"); - enabled <=> root.tab_enabled; + text: local_busy ? @tr("Applying...") : @tr("Apply Curve"); + enabled: root.tab_enabled && root.enabled && !local_busy; clicked => { root.apply(); } @@ -57,7 +124,7 @@ component FanTab inherits Rectangle { Button { text: @tr("Cancel"); - enabled <=> root.tab_enabled; + enabled: root.tab_enabled && !local_busy; clicked => { root.cancel() } @@ -65,7 +132,7 @@ component FanTab inherits Rectangle { Button { text: @tr("Factory Default (all fans)"); - enabled <=> root.tab_enabled; + enabled: root.tab_enabled && !local_busy; clicked => { root.default(); } @@ -94,6 +161,9 @@ export component PageFans inherits VerticalLayout { default => { FanPageData.set_profile_default(Profile.Balanced); } + cancel => { + FanPageData.cancel(FanType.CPU, Profile.Balanced); + } } } @@ -112,6 +182,9 @@ export component PageFans inherits VerticalLayout { default => { FanPageData.set_profile_default(Profile.Balanced); } + cancel => { + FanPageData.cancel(FanType.Middle, Profile.Balanced); + } } } @@ -130,6 +203,9 @@ export component PageFans inherits VerticalLayout { default => { FanPageData.set_profile_default(Profile.Balanced); } + cancel => { + FanPageData.cancel(FanType.GPU, Profile.Balanced); + } } } } @@ -153,6 +229,9 @@ export component PageFans inherits VerticalLayout { default => { FanPageData.set_profile_default(Profile.Performance); } + cancel => { + FanPageData.cancel(FanType.CPU, Profile.Performance); + } } } @@ -171,6 +250,9 @@ export component PageFans inherits VerticalLayout { default => { FanPageData.set_profile_default(Profile.Performance); } + cancel => { + FanPageData.cancel(FanType.Middle, Profile.Performance); + } } } @@ -189,6 +271,9 @@ export component PageFans inherits VerticalLayout { default => { FanPageData.set_profile_default(Profile.Performance); } + cancel => { + FanPageData.cancel(FanType.GPU, Profile.Performance); + } } } } @@ -212,6 +297,9 @@ export component PageFans inherits VerticalLayout { default => { FanPageData.set_profile_default(Profile.Quiet); } + cancel => { + FanPageData.cancel(FanType.CPU, Profile.Quiet); + } } } @@ -230,6 +318,9 @@ export component PageFans inherits VerticalLayout { default => { FanPageData.set_profile_default(Profile.Quiet); } + cancel => { + FanPageData.cancel(FanType.Middle, Profile.Quiet); + } } } @@ -248,6 +339,9 @@ export component PageFans inherits VerticalLayout { default => { FanPageData.set_profile_default(Profile.Quiet); } + cancel => { + FanPageData.cancel(FanType.GPU, Profile.Quiet); + } } } } diff --git a/rog-control-center/ui/pages/screenpad.slint b/rog-control-center/ui/pages/screenpad.slint new file mode 100644 index 00000000..db01dc60 --- /dev/null +++ b/rog-control-center/ui/pages/screenpad.slint @@ -0,0 +1,102 @@ +import { Button, VerticalBox, Slider, Switch } from "std-widgets.slint"; +import { ScreenpadPageData } from "../types/screenpad_types.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; +import { RogItem, SystemSlider } from "../widgets/common.slint"; + +export { ScreenpadPageData } + +export component PageScreenpad inherits Rectangle { + background: RogPalette.background; + + VerticalBox { + alignment: LayoutAlignment.start; + padding: 20px; + spacing: 20px; + + Text { + text: @tr("Screenpad Controls"); + font-size: 24px; + font-weight: 700; + color: RogPalette.accent; + } + + RogItem { + HorizontalLayout { + padding: 15px; + spacing: 20px; + alignment: LayoutAlignment.space-between; + + Text { + text: @tr("Enable Screenpad"); + font-size: 16px; + vertical-alignment: TextVerticalAlignment.center; + color: RogPalette.text-primary; + } + + Switch { + checked <=> ScreenpadPageData.power; + toggled => { + ScreenpadPageData.cb_power(self.checked); + } + } + } + } + + VerticalLayout { + spacing: 15px; + + // Brightness Slider + SystemSlider { + enabled: ScreenpadPageData.power; + text: @tr("Brightness"); + minimum: 0; + maximum: 255; + value: ScreenpadPageData.brightness; + help_text: ScreenpadPageData.brightness == -1 ? @tr("Not available") : ""; + released => { + ScreenpadPageData.cb_brightness(Math.round(self.value)); + } + } + + // Gamma Slider (New) + SystemSlider { + enabled: ScreenpadPageData.power; + text: @tr("Gamma"); + minimum: 0.1; + maximum: 2.5; + value: ScreenpadPageData.gamma; + help_text: @tr("Adjust color intensity"); + released => { + ScreenpadPageData.cb_gamma(self.value); + } + } + + RogItem { + enabled: ScreenpadPageData.power; + HorizontalLayout { + padding: 15px; + spacing: 20px; + alignment: LayoutAlignment.space-between; + + Text { + text: @tr("Sync with Primary Display"); + font-size: 16px; + vertical-alignment: TextVerticalAlignment.center; + color: RogPalette.text-primary; + } + + Switch { + enabled: ScreenpadPageData.power; + checked <=> ScreenpadPageData.sync_with_primary; + toggled => { + ScreenpadPageData.cb_sync_with_primary(self.checked); + } + } + } + } + } + + // Spacer + Rectangle {} + } +} diff --git a/rog-control-center/ui/pages/slash.slint b/rog-control-center/ui/pages/slash.slint new file mode 100644 index 00000000..fc44d933 --- /dev/null +++ b/rog-control-center/ui/pages/slash.slint @@ -0,0 +1,114 @@ +import { SystemToggle, SystemSlider, SystemDropdown, RogItem } from "../widgets/common.slint"; +import { VerticalBox, ScrollView, GroupBox } from "std-widgets.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; +import { SlashPageData } from "../types/slash_types.slint"; + +export { SlashPageData } + +export component PageSlash inherits Rectangle { + background: RogPalette.background; + + ScrollView { + VerticalBox { + padding: 20px; + spacing: 20px; + alignment: start; + + // Header + Rectangle { + height: 40px; + background: RogPalette.control-background; + border-radius: RogPalette.border-radius; + border-width: 1px; + border-color: RogPalette.control-border; + + Text { + text: @tr("Slash Lighting Control"); + color: RogPalette.accent; + font-size: 18px; + font-weight: 700; + horizontal-alignment: center; + vertical-alignment: center; + } + } + + // Main Control + RogItem { + VerticalBox { + SystemToggle { + text: @tr("Enable Slash Lighting"); + checked <=> SlashPageData.enabled; + toggled => { SlashPageData.cb_enabled(self.checked); } + } + + SystemDropdown { + text: @tr("Lighting Mode"); + model <=> SlashPageData.modes; + current_index <=> SlashPageData.mode_index; + current_value: SlashPageData.modes[SlashPageData.mode_index]; + selected => { + SlashPageData.cb_mode_index(self.current_index); + } + } + + SystemSlider { + title: @tr("Brightness"); + text: @tr("Brightness"); + value <=> SlashPageData.brightness; + minimum: 0; + maximum: 255; + help_text: ""; + released(val) => { SlashPageData.cb_brightness(val); } + } + + SystemSlider { + title: @tr("Interval / Speed"); + text: @tr("Interval / Speed"); + value <=> SlashPageData.interval; + minimum: 0; + maximum: 255; + help_text: ""; + released(val) => { SlashPageData.cb_interval(val); } + } + } + } + + // Behaviors + GroupBox { + title: @tr("Behavior Settings"); + VerticalBox { + SystemToggle { + text: @tr("Show Battery Warning"); + checked <=> SlashPageData.show_battery_warning; + toggled => { SlashPageData.cb_show_battery_warning(self.checked); } + } + SystemToggle { + text: @tr("Active on Battery"); + checked <=> SlashPageData.show_on_battery; + toggled => { SlashPageData.cb_show_on_battery(self.checked); } + } + SystemToggle { + text: @tr("Active on Boot"); + checked <=> SlashPageData.show_on_boot; + toggled => { SlashPageData.cb_show_on_boot(self.checked); } + } + SystemToggle { + text: @tr("Active on Shutdown"); + checked <=> SlashPageData.show_on_shutdown; + toggled => { SlashPageData.cb_show_on_shutdown(self.checked); } + } + SystemToggle { + text: @tr("Active on Sleep"); + checked <=> SlashPageData.show_on_sleep; + toggled => { SlashPageData.cb_show_on_sleep(self.checked); } + } + SystemToggle { + text: @tr("Active when Lid Closed"); + checked <=> SlashPageData.show_on_lid_closed; + toggled => { SlashPageData.cb_show_on_lid_closed(self.checked); } + } + } + } + } + } +} diff --git a/rog-control-center/ui/pages/supergfx.slint b/rog-control-center/ui/pages/supergfx.slint new file mode 100644 index 00000000..1cf84b0d --- /dev/null +++ b/rog-control-center/ui/pages/supergfx.slint @@ -0,0 +1,73 @@ +import { SystemDropdown, RogItem } from "../widgets/common.slint"; +import { VerticalBox, ScrollView, HorizontalBox } from "std-widgets.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; +import { SupergfxPageData } from "../types/supergfx_types.slint"; + +export { SupergfxPageData } + +export component PageSupergfx inherits Rectangle { + background: RogPalette.background; + + ScrollView { + VerticalBox { + padding: 20px; + spacing: 20px; + alignment: start; + + // Header + Rectangle { + height: 40px; + background: RogPalette.control-background; + border-radius: RogPalette.border-radius; + border-width: 1px; + border-color: RogPalette.control-border; + + Text { + text: @tr("Graphics Control (supergfx)"); + color: RogPalette.accent; + font-size: 18px; + font-weight: 700; + horizontal-alignment: center; + vertical-alignment: center; + } + } + + RogItem { + HorizontalBox { + Text { + text: @tr("Vendor: ") + SupergfxPageData.vendor; + color: RogPalette.text-secondary; + vertical-alignment: center; + } + } + } + + // Main Control + RogItem { + VerticalBox { + Text { + text: @tr("Current Mode: ") + SupergfxPageData.current_mode; + color: RogPalette.text-primary; + } + + SystemDropdown { + text: @tr("Graphics Mode"); + model <=> SupergfxPageData.supported_modes; + current_index <=> SupergfxPageData.selected_index; + current_value: SupergfxPageData.supported_modes[SupergfxPageData.selected_index]; + selected => { + SupergfxPageData.set_mode(self.current_value); + } + } + + Text { + text: @tr("Note: Changing modes requires a logout."); + color: RogPalette.text-secondary; + font-size: 12px; + wrap: word-wrap; + } + } + } + } + } +} diff --git a/rog-control-center/ui/pages/system.slint b/rog-control-center/ui/pages/system.slint index 180105c3..2588fa4d 100644 --- a/rog-control-center/ui/pages/system.slint +++ b/rog-control-center/ui/pages/system.slint @@ -1,5 +1,6 @@ import { SystemSlider, SystemDropdown, SystemToggle, SystemToggleInt, RogItem } from "../widgets/common.slint"; import { Palette, HorizontalBox , VerticalBox, ScrollView, Slider, Button, Switch, ComboBox, GroupBox, StandardButton} from "std-widgets.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; export struct AttrMinMax { min: int, @@ -66,13 +67,6 @@ export global SystemPageData { in-out property mini_led_mode; callback cb_mini_led_mode(int); - in-out property screenpad_gamma; - callback cb_screenpad_gamma(float); - // percentage - in-out property screenpad_brightness: 50; - callback cb_screenpad_brightness(int); - in-out property screenpad_sync_with_primary: false; - callback cb_screenpad_sync_with_primary(bool); in-out property asus_armoury_loaded: false; @@ -152,22 +146,27 @@ export component PageSystem inherits Rectangle { property show_fade_cover: false; property show_throttle_advanced: false; clip: true; - + //padding only has effect on layout elements + //padding: 8px; ScrollView { VerticalLayout { - padding: 12px; - spacing: 8px; + padding: 10px; + padding-top: 40px; + padding-bottom: 40px; + spacing: 10px; alignment: LayoutAlignment.start; Rectangle { - background: Palette.alternate-background; - border-color: Palette.border; + background: RogPalette.control-background; + border-color: RogPalette.control-border; border-width: 1px; - border-radius: 2px; - height: 36px; + border-radius: 8px; + height: 46px; Text { - font-size: 16px; - color: Palette.control-foreground; + font-size: 18px; + color: RogPalette.accent; horizontal-alignment: TextHorizontalAlignment.center; + vertical-alignment: TextVerticalAlignment.center; + font-weight: 700; text: @tr("Power settings"); } } @@ -206,147 +205,79 @@ export component PageSystem inherits Rectangle { } } - if SystemPageData.screenpad_brightness != -1: RogItem { - HorizontalLayout { - padding-left: 10px; - padding-right: 20px; - HorizontalLayout { - width: 40%; - alignment: LayoutAlignment.space-between; - padding-right: 15px; - Text { - font-size: 14px; - vertical-alignment: TextVerticalAlignment.center; - color: Palette.control-foreground; - text: @tr("Screenpad brightness"); - } - } - - HorizontalLayout { - width: 38%; - alignment: LayoutAlignment.stretch; - screen_bright := Slider { - enabled: true; - minimum: 0; - maximum: 100; - value: SystemPageData.screenpad_brightness; - released(value) => { - // SystemPageData.screenpad_brightness = self.value; - SystemPageData.cb_screenpad_brightness(Math.floor(self.value)); - } - } - } - - HorizontalLayout { - width: 20%; - padding-left: 14px; - alignment: LayoutAlignment.stretch; - Switch { - text: @tr("Sync with primary"); - checked <=> SystemPageData.screenpad_sync_with_primary; - toggled => { - SystemPageData.cb_screenpad_sync_with_primary(self.checked); - } - } - } - } - } - - if SystemPageData.kbd_leds_awake != -1 || - SystemPageData.kbd_leds_sleep != -1 || - SystemPageData.kbd_leds_boot != -1 || - SystemPageData.kbd_leds_shutdown != -1: VerticalLayout { - padding: 0px; - spacing: 0px; - alignment: LayoutAlignment.start; - Rectangle { - background: Palette.alternate-background; - border-color: Palette.border; - border-width: 1px; - border-radius: 2px; - height: 40px; - Text { - font-size: 16px; - color: Palette.control-foreground; - horizontal-alignment: TextHorizontalAlignment.center; - text: @tr("Keyboard Power Management"); - } - } - - GroupBox { - - HorizontalLayout { - spacing: 10px; - if SystemPageData.kbd_leds_awake != -1: SystemToggleInt { - text: @tr("Keyboard Awake Effect"); - checked_int <=> SystemPageData.kbd_leds_awake; - toggled => { - SystemPageData.cb_kbd_leds_awake(SystemPageData.kbd_leds_awake) - } - } - - if SystemPageData.kbd_leds_sleep != -1: SystemToggleInt { - text: @tr("Keyboard Sleep Effect"); - checked_int <=> SystemPageData.kbd_leds_sleep; - toggled => { - SystemPageData.cb_kbd_leds_sleep(SystemPageData.kbd_leds_sleep) - } - } - - if SystemPageData.kbd_leds_boot != -1: SystemToggleInt { - text: @tr("Keyboard Boot Effect"); - checked_int <=> SystemPageData.kbd_leds_boot; - toggled => { - SystemPageData.cb_kbd_leds_boot(SystemPageData.kbd_leds_boot) - } - } - - if SystemPageData.kbd_leds_shutdown != -1: SystemToggleInt { - text: @tr("Keyboard Shutdown Effect"); - checked_int <=> SystemPageData.kbd_leds_shutdown; - toggled => { - SystemPageData.cb_kbd_leds_shutdown(SystemPageData.kbd_leds_shutdown) - } - } - } - } - } - Rectangle { - background: Palette.alternate-background; - border-color: Palette.border; + background: RogPalette.control-background; + border-color: RogPalette.control-border; border-width: 1px; - border-radius: 2px; - height: 36px; + border-radius: 8px; + height: 46px; Text { - font-size: 16px; - color: Palette.control-foreground; + font-size: 18px; + color: RogPalette.accent; horizontal-alignment: TextHorizontalAlignment.center; + vertical-alignment: TextVerticalAlignment.center; + font-weight: 700; text: @tr("Armoury settings"); } } if !SystemPageData.asus_armoury_loaded: Rectangle { - background: maroon; - // background: darkred; + border-width: 3px; + border-color: red; max-height: 30px; VerticalBox { Text { text: @tr("no_asus_armoury_driver_1" => "The asus-armoury driver is not loaded"); font-size: 16px; - color: white; horizontal-alignment: TextHorizontalAlignment.center; } Text { text: @tr("no_asus_armoury_driver_2" => "For advanced features you will require a kernel with this driver added."); font-size: 16px; - color: white; horizontal-alignment: TextHorizontalAlignment.center; } } } + GroupBox { + title: @tr("Keyboard Power Management"); + HorizontalLayout { + spacing: 10px; + if SystemPageData.kbd_leds_awake != -1: SystemToggleInt { + text: @tr("Keyboard Awake Effect"); + checked_int <=> SystemPageData.kbd_leds_awake; + toggled => { + SystemPageData.cb_kbd_leds_awake(SystemPageData.kbd_leds_awake) + } + } + + if SystemPageData.kbd_leds_sleep != -1: SystemToggleInt { + text: @tr("Keyboard Sleep Effect"); + checked_int <=> SystemPageData.kbd_leds_sleep; + toggled => { + SystemPageData.cb_kbd_leds_sleep(SystemPageData.kbd_leds_sleep) + } + } + + if SystemPageData.kbd_leds_boot != -1: SystemToggleInt { + text: @tr("Keyboard Boot Effect"); + checked_int <=> SystemPageData.kbd_leds_boot; + toggled => { + SystemPageData.cb_kbd_leds_boot(SystemPageData.kbd_leds_boot) + } + } + + if SystemPageData.kbd_leds_shutdown != -1: SystemToggleInt { + text: @tr("Keyboard Shutdown Effect"); + checked_int <=> SystemPageData.kbd_leds_shutdown; + toggled => { + SystemPageData.cb_kbd_leds_shutdown(SystemPageData.kbd_leds_shutdown) + } + } + } + } + HorizontalBox { padding: 0px; spacing: 10px; @@ -400,6 +331,7 @@ export component PageSystem inherits Rectangle { Text { font-size: 16px; text: @tr("ppt_warning" => "The following settings are not applied until the toggle is enabled."); + color: RogPalette.text-primary; } } @@ -568,7 +500,7 @@ export component PageSystem inherits Rectangle { if root.show_fade_cover: Rectangle { width: 100%; height: 100%; - background: Palette.background; + background: RogPalette.background; opacity: 0.9; TouchArea { height: 100%; @@ -584,25 +516,24 @@ export component PageSystem inherits Rectangle { } if root.show_throttle_advanced: Rectangle { - background: Palette.background; width: 100%; height: 100%; opacity: 1; ScrollView { VerticalLayout { - alignment: start; - padding: 5px; - padding-top: 15px; + padding: 50px; + padding-top: 5px; + padding-bottom: 100px; spacing: 10px; GroupBox { VerticalBox { - alignment: start; spacing: 10px; Text { - font-size: 16px; + font-size: 18px; horizontal-alignment: TextHorizontalAlignment.center; vertical-alignment: TextVerticalAlignment.center; text: @tr("Energy Performance Preference linked to Throttle Policy"); + color: RogPalette.text-primary; } SystemToggle { @@ -647,13 +578,13 @@ export component PageSystem inherits Rectangle { GroupBox { VerticalBox { - alignment: start; spacing: 10px; Text { - font-size: 16px; + font-size: 18px; horizontal-alignment: TextHorizontalAlignment.center; vertical-alignment: TextVerticalAlignment.center; text: @tr("Throttle Policy for power state"); + color: RogPalette.text-primary; } HorizontalLayout { @@ -705,8 +636,8 @@ export component PageSystem inherits Rectangle { Button { x: root.width - self.width - 6px; y: 6px; - text: "✕"; - height: 34px; + text: "X"; + height: 40px; clicked => { root.show_throttle_advanced = false; root.show_fade_cover = false; diff --git a/rog-control-center/ui/themes/rog_theme.slint b/rog-control-center/ui/themes/rog_theme.slint new file mode 100644 index 00000000..692e0674 --- /dev/null +++ b/rog-control-center/ui/themes/rog_theme.slint @@ -0,0 +1,13 @@ +export global RogPalette { + out property background: #0a0a0a; + out property alternate-background: #111111; + out property control-background: #1e1e1e; + out property control-border: #333333; + out property control-border-hover: #555555; + out property control-border-checked: #ff0033; // ROG Red + out property text-primary: #ffffff; + out property text-secondary: #aaaaaa; + out property accent: #ff0033; + out property accent-hover: #d60000; + out property border-radius: 4px; +} diff --git a/rog-control-center/ui/types/aura_types.slint b/rog-control-center/ui/types/aura_types.slint index e6d4795f..52f1041a 100644 --- a/rog-control-center/ui/types/aura_types.slint +++ b/rog-control-center/ui/types/aura_types.slint @@ -8,6 +8,13 @@ export enum AuraDevType { AnimeOrSlash, } +// Software animation modes for keyboards that only support Static +export enum SoftAnimationMode { + None, + Rainbow, + ColorCycle, +} + export struct AuraEffect { /// The effect type mode: int, @@ -168,4 +175,18 @@ export global AuraPageData { }] }; callback cb_led_power(LaptopAuraPower); + + // Software animation properties (for Static-only keyboards) + in-out property <[string]> soft_animation_modes: [ + @tr("Animation mode" => "None"), + @tr("Animation mode" => "Rainbow"), + @tr("Animation mode" => "Color Cycle"), + @tr("Animation mode" => "Breathe"), + @tr("Animation mode" => "Pulse"), + ]; + in-out property soft_animation_mode: 0; + in-out property soft_animation_speed: 200; // ms between updates + in-out property soft_animation_available: false; // Set true when only Static mode is supported + callback cb_soft_animation_mode(int); + callback cb_soft_animation_speed(int); } diff --git a/rog-control-center/ui/types/fan_types.slint b/rog-control-center/ui/types/fan_types.slint index 5577f3b6..2bd8e365 100644 --- a/rog-control-center/ui/types/fan_types.slint +++ b/rog-control-center/ui/types/fan_types.slint @@ -35,314 +35,64 @@ export global FanPageData { in-out property quiet_gpu_enabled: true; in-out property quiet_mid_enabled: false; + in-out property is_busy_cpu: false; + in-out property is_busy_gpu: false; + in-out property is_busy_mid: false; + in-out property show_custom_warning: false; + callback set_fan_data(FanType, Profile, bool, [Node]); callback set_profile_default(Profile); + callback set_is_busy(FanType, bool); + // Last applied cache for Cancel button + in-out property <[Node]> last_applied_cpu_balanced: []; + in-out property <[Node]> last_applied_gpu_balanced: []; + in-out property <[Node]> last_applied_mid_balanced: []; + in-out property <[Node]> last_applied_cpu_performance: []; + in-out property <[Node]> last_applied_gpu_performance: []; + in-out property <[Node]> last_applied_mid_performance: []; + in-out property <[Node]> last_applied_cpu_quiet: []; + in-out property <[Node]> last_applied_gpu_quiet: []; + in-out property <[Node]> last_applied_mid_quiet: []; + + callback cancel(FanType, Profile); in-out property <[Node]> balanced_cpu: [ - { - x: 10px, - y: 10px, - }, - { - x: 40px, - y: 30px, - }, - { - x: 50px, - y: 50px, - }, - { - x: 55px, - y: 50px, - }, - { - x: 60px, - y: 60px, - }, - { - x: 65px, - y: 70px, - }, - { - x: 70px, - y: 80px, - }, - { - x: 90px, - y: 100px, - }, + { x: 30px, y: 0px }, { x: 40px, y: 0px }, { x: 50px, y: 0px }, { x: 60px, y: 0px }, + { x: 70px, y: 25px }, { x: 80px, y: 55px }, { x: 90px, y: 85px }, { x: 98px, y: 100px }, ]; in-out property <[Node]> balanced_mid: [ - { - x: 10px, - y: 10px, - }, - { - x: 40px, - y: 30px, - }, - { - x: 50px, - y: 50px, - }, - { - x: 55px, - y: 50px, - }, - { - x: 60px, - y: 60px, - }, - { - x: 65px, - y: 70px, - }, - { - x: 70px, - y: 80px, - }, - { - x: 90px, - y: 100px, - }, + { x: 30px, y: 0px }, { x: 40px, y: 0px }, { x: 50px, y: 0px }, { x: 60px, y: 0px }, + { x: 70px, y: 25px }, { x: 80px, y: 55px }, { x: 90px, y: 85px }, { x: 98px, y: 100px }, ]; in-out property <[Node]> balanced_gpu: [ - { - x: 10px, - y: 10px, - }, - { - x: 40px, - y: 30px, - }, - { - x: 50px, - y: 50px, - }, - { - x: 55px, - y: 50px, - }, - { - x: 60px, - y: 60px, - }, - { - x: 65px, - y: 70px, - }, - { - x: 70px, - y: 80px, - }, - { - x: 90px, - y: 100px, - }, + { x: 30px, y: 0px }, { x: 40px, y: 0px }, { x: 50px, y: 0px }, { x: 60px, y: 0px }, + { x: 70px, y: 25px }, { x: 80px, y: 55px }, { x: 90px, y: 85px }, { x: 98px, y: 100px }, ]; + in-out property <[Node]> performance_cpu: [ - { - x: 10px, - y: 10px, - }, - { - x: 40px, - y: 30px, - }, - { - x: 50px, - y: 50px, - }, - { - x: 55px, - y: 50px, - }, - { - x: 60px, - y: 60px, - }, - { - x: 65px, - y: 70px, - }, - { - x: 70px, - y: 80px, - }, - { - x: 90px, - y: 100px, - }, + { x: 30px, y: 0px }, { x: 40px, y: 10px }, { x: 50px, y: 30px }, { x: 60px, y: 50px }, + { x: 70px, y: 70px }, { x: 80px, y: 85px }, { x: 90px, y: 95px }, { x: 98px, y: 100px }, ]; in-out property <[Node]> performance_mid: [ - { - x: 10px, - y: 10px, - }, - { - x: 40px, - y: 30px, - }, - { - x: 50px, - y: 50px, - }, - { - x: 55px, - y: 50px, - }, - { - x: 60px, - y: 60px, - }, - { - x: 65px, - y: 70px, - }, - { - x: 70px, - y: 80px, - }, - { - x: 90px, - y: 100px, - }, + { x: 30px, y: 0px }, { x: 40px, y: 10px }, { x: 50px, y: 30px }, { x: 60px, y: 50px }, + { x: 70px, y: 70px }, { x: 80px, y: 85px }, { x: 90px, y: 95px }, { x: 98px, y: 100px }, ]; in-out property <[Node]> performance_gpu: [ - { - x: 10px, - y: 10px, - }, - { - x: 40px, - y: 30px, - }, - { - x: 50px, - y: 50px, - }, - { - x: 55px, - y: 50px, - }, - { - x: 60px, - y: 60px, - }, - { - x: 65px, - y: 70px, - }, - { - x: 70px, - y: 80px, - }, - { - x: 90px, - y: 100px, - }, + { x: 30px, y: 0px }, { x: 40px, y: 10px }, { x: 50px, y: 30px }, { x: 60px, y: 50px }, + { x: 70px, y: 70px }, { x: 80px, y: 85px }, { x: 90px, y: 95px }, { x: 98px, y: 100px }, ]; + in-out property <[Node]> quiet_cpu: [ - { - x: 10px, - y: 10px, - }, - { - x: 40px, - y: 30px, - }, - { - x: 50px, - y: 50px, - }, - { - x: 55px, - y: 50px, - }, - { - x: 60px, - y: 60px, - }, - { - x: 65px, - y: 70px, - }, - { - x: 70px, - y: 80px, - }, - { - x: 90px, - y: 100px, - }, + { x: 30px, y: 0px }, { x: 40px, y: 0px }, { x: 50px, y: 0px }, { x: 60px, y: 0px }, + { x: 70px, y: 20px }, { x: 80px, y: 40px }, { x: 90px, y: 70px }, { x: 98px, y: 90px }, ]; in-out property <[Node]> quiet_mid: [ - { - x: 10px, - y: 10px, - }, - { - x: 40px, - y: 30px, - }, - { - x: 50px, - y: 50px, - }, - { - x: 55px, - y: 50px, - }, - { - x: 60px, - y: 60px, - }, - { - x: 65px, - y: 70px, - }, - { - x: 70px, - y: 80px, - }, - { - x: 90px, - y: 100px, - }, + { x: 30px, y: 0px }, { x: 40px, y: 0px }, { x: 50px, y: 0px }, { x: 60px, y: 0px }, + { x: 70px, y: 20px }, { x: 80px, y: 40px }, { x: 90px, y: 70px }, { x: 98px, y: 90px }, ]; in-out property <[Node]> quiet_gpu: [ - { - x: 10px, - y: 10px, - }, - { - x: 40px, - y: 30px, - }, - { - x: 50px, - y: 50px, - }, - { - x: 55px, - y: 50px, - }, - { - x: 60px, - y: 60px, - }, - { - x: 65px, - y: 70px, - }, - { - x: 70px, - y: 80px, - }, - { - x: 90px, - y: 100px, - }, + { x: 30px, y: 0px }, { x: 40px, y: 0px }, { x: 50px, y: 0px }, { x: 60px, y: 0px }, + { x: 70px, y: 20px }, { x: 80px, y: 40px }, { x: 90px, y: 70px }, { x: 98px, y: 90px }, ]; function set_fan(profile: Profile, fan: FanType, data: [Node]) { diff --git a/rog-control-center/ui/types/screenpad_types.slint b/rog-control-center/ui/types/screenpad_types.slint new file mode 100644 index 00000000..57af665b --- /dev/null +++ b/rog-control-center/ui/types/screenpad_types.slint @@ -0,0 +1,13 @@ +import { RogPalette } from "../themes/rog_theme.slint"; + +export global ScreenpadPageData { + in-out property brightness: -1; + in-out property gamma: 1.0; + in-out property sync_with_primary: false; + in-out property power: true; + + callback cb_brightness(int); + callback cb_gamma(float); + callback cb_sync_with_primary(bool); + callback cb_power(bool); +} diff --git a/rog-control-center/ui/types/slash_types.slint b/rog-control-center/ui/types/slash_types.slint new file mode 100644 index 00000000..f7b03741 --- /dev/null +++ b/rog-control-center/ui/types/slash_types.slint @@ -0,0 +1,49 @@ +export global SlashPageData { + in-out property enabled; + callback cb_enabled(bool); + + in-out property brightness; + callback cb_brightness(float); + + in-out property interval; + callback cb_interval(float); + + in-out property <[string]> modes: [ + @tr("Static"), + @tr("Bounce"), + @tr("Slash"), + @tr("Loading"), + @tr("BitStream"), + @tr("Transmission"), + @tr("Flow"), + @tr("Flux"), + @tr("Phantom"), + @tr("Spectrum"), + @tr("Hazard"), + @tr("Interfacing"), + @tr("Ramp"), + @tr("GameOver"), + @tr("Start"), + @tr("Buzzer"), + ]; + in-out property mode_index; + callback cb_mode_index(int); + + in-out property show_battery_warning; + callback cb_show_battery_warning(bool); + + in-out property show_on_battery; + callback cb_show_on_battery(bool); + + in-out property show_on_boot; + callback cb_show_on_boot(bool); + + in-out property show_on_shutdown; + callback cb_show_on_shutdown(bool); + + in-out property show_on_sleep; + callback cb_show_on_sleep(bool); + + in-out property show_on_lid_closed; + callback cb_show_on_lid_closed(bool); +} diff --git a/rog-control-center/ui/types/supergfx_types.slint b/rog-control-center/ui/types/supergfx_types.slint new file mode 100644 index 00000000..24869db0 --- /dev/null +++ b/rog-control-center/ui/types/supergfx_types.slint @@ -0,0 +1,10 @@ +export global SupergfxPageData { + in-out property current_mode: "Hybrid"; + in-out property <[string]> supported_modes: ["Hybrid", "Integrated"]; + in-out property selected_index: 0; + + in-out property vendor: "Unknown"; + + callback set_mode(string); + callback refresh(); +} diff --git a/rog-control-center/ui/widgets/aura_power.slint b/rog-control-center/ui/widgets/aura_power.slint index 93817e17..c9c2ea51 100644 --- a/rog-control-center/ui/widgets/aura_power.slint +++ b/rog-control-center/ui/widgets/aura_power.slint @@ -1,10 +1,14 @@ -import { Palette, VerticalBox, HorizontalBox, GroupBox } from "std-widgets.slint"; +import { VerticalBox, HorizontalBox, GroupBox } from "std-widgets.slint"; import { SystemToggleVert, SystemDropdown } from "common.slint"; import { PowerZones } from "../types/aura_types.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; export component AuraPowerGroup inherits Rectangle { min-width: row.min-width; - opacity: 0.9; + border-radius: 8px; + background: RogPalette.control-background; + border-width: 1px; + border-color: RogPalette.control-border; in-out property group-title; in-out property boot_checked; in-out property awake_checked; @@ -14,12 +18,11 @@ export component AuraPowerGroup inherits Rectangle { callback awake_toggled(bool); callback sleep_toggled(bool); callback shutdown_toggled(bool); - VerticalBox { spacing: 10px; Text { font-size: 18px; - color: Palette.alternate-foreground; + color: RogPalette.text-primary; horizontal-alignment: TextHorizontalAlignment.center; text <=> root.group-title; } @@ -27,7 +30,7 @@ export component AuraPowerGroup inherits Rectangle { row := HorizontalBox { alignment: LayoutAlignment.center; SystemToggleVert { - min-width: 128px; + min-width: 96px; max-height: 42px; text: @tr("Boot"); checked <=> root.boot_checked; @@ -37,7 +40,7 @@ export component AuraPowerGroup inherits Rectangle { } SystemToggleVert { - min-width: 128px; + min-width: 96px; max-height: 42px; text: @tr("Awake"); checked <=> root.awake_checked; @@ -47,7 +50,7 @@ export component AuraPowerGroup inherits Rectangle { } SystemToggleVert { - min-width: 128px; + min-width: 96px; max-height: 42px; text: @tr("Sleep"); checked <=> root.sleep_checked; @@ -57,7 +60,7 @@ export component AuraPowerGroup inherits Rectangle { } SystemToggleVert { - min-width: 128px; + min-width: 96px; max-height: 42px; text: @tr("Shutdown"); checked <=> root.shutdown_checked; @@ -71,7 +74,10 @@ export component AuraPowerGroup inherits Rectangle { export component AuraPowerGroupOld inherits Rectangle { min-width: row.min-width; - opacity: 0.9; + border-radius: 8px; + background: RogPalette.control-background; + border-width: 1px; + border-color: RogPalette.control-border; in-out property current_zone; in-out property <[int]> zones; in-out property <[string]> zone_strings; @@ -83,12 +89,11 @@ export component AuraPowerGroupOld inherits Rectangle { callback awake_toggled(bool); callback sleep_toggled(bool); callback selected_zone(int); - VerticalBox { spacing: 10px; Text { font-size: 18px; - color: Palette.alternate-foreground; + color: RogPalette.text-primary; horizontal-alignment: TextHorizontalAlignment.center; text <=> root.group-title; } @@ -107,7 +112,7 @@ export component AuraPowerGroupOld inherits Rectangle { } SystemToggleVert { - min-width: 128px; + min-width: 96px; max-height: 42px; text: @tr("Boot"); checked <=> root.boot_checked; @@ -117,7 +122,7 @@ export component AuraPowerGroupOld inherits Rectangle { } SystemToggleVert { - min-width: 128px; + min-width: 96px; max-height: 42px; text: @tr("Awake"); checked <=> root.awake_checked; @@ -127,7 +132,7 @@ export component AuraPowerGroupOld inherits Rectangle { } SystemToggleVert { - min-width: 128px; + min-width: 96px; max-height: 42px; text: @tr("Sleep"); checked <=> root.sleep_checked; diff --git a/rog-control-center/ui/widgets/common.slint b/rog-control-center/ui/widgets/common.slint index 5e2e5091..bacc90a3 100644 --- a/rog-control-center/ui/widgets/common.slint +++ b/rog-control-center/ui/widgets/common.slint @@ -1,11 +1,15 @@ -import { Palette, VerticalBox , StandardButton, Button, HorizontalBox, ComboBox, Switch, Slider} from "std-widgets.slint"; +import { VerticalBox , StandardButton, Button, HorizontalBox, ComboBox, Switch, Slider} from "std-widgets.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; export component RogItem inherits Rectangle { - border-color: Palette.border; - border-width: 1px; - border-radius: 2px; - min-height: 44px; - max-height: 44px; + in property enabled: true; + background: root.enabled ? RogPalette.control-background : RogPalette.control-background.darker(0.5); + border-color: root.enabled ? RogPalette.control-border : RogPalette.control-border.darker(0.3); + border-width: 1px; // Thinner border for modern look + border-radius: RogPalette.border-radius; + min-height: 48px; + max-height: 56px; + opacity: root.enabled ? 1.0 : 0.6; } export component SystemSlider inherits RogItem { @@ -17,7 +21,6 @@ export component SystemSlider inherits RogItem { callback released(float); in property help_text; - in property enabled: true; in property has_reset: false; callback cb_do_reset(); @@ -29,24 +32,24 @@ export component SystemSlider inherits RogItem { HorizontalLayout { spacing: 6px; Text { - font-size: 14px; + font-size: 16px; vertical-alignment: TextVerticalAlignment.center; - color: Palette.control-foreground; + color: RogPalette.text-primary; text: root.text; } Text { - font-size: 14px; + font-size: 16px; horizontal-alignment: TextHorizontalAlignment.right; vertical-alignment: TextVerticalAlignment.center; - color: Palette.control-foreground; + color: RogPalette.accent; text: "\{Math.round(root.value)}"; } } } HorizontalBox { - padding-right: 10px; + padding-right: 20px; slider := Slider { enabled: root.enabled; maximum: root.maximum; @@ -63,10 +66,11 @@ export component SystemSlider inherits RogItem { y: help.y - self.height + help.height - 10px; Rectangle { drop-shadow-blur: 10px; - drop-shadow-color: black; - border-radius: 10px; - border-color: Palette.accent-background; - background: Palette.background; + drop-shadow-color: Colors.black; + border-radius: RogPalette.border-radius; + border-width: 1px; + border-color: RogPalette.accent; + background: RogPalette.control-background; Dialog { title: root.title; VerticalBox { @@ -76,12 +80,12 @@ export component SystemSlider inherits RogItem { wrap: TextWrap.word-wrap; horizontal-alignment: TextHorizontalAlignment.center; text: root.title; + color: RogPalette.text-primary; } Rectangle { height: 1px; - border-color: black; - border-width: 1px; + background: RogPalette.control-border; } Text { @@ -89,6 +93,7 @@ export component SystemSlider inherits RogItem { font-size: 16px; wrap: TextWrap.word-wrap; text: root.help_text; + color: RogPalette.text-secondary; } } @@ -113,16 +118,18 @@ export component SystemSlider inherits RogItem { y: reset.y - self.height + reset.height; Rectangle { drop-shadow-blur: 10px; - drop-shadow-color: black; - border-radius: 10px; - border-color: Palette.accent-background; - background: Palette.background; + drop-shadow-color: Colors.black; + border-radius: RogPalette.border-radius; + border-width: 1px; + border-color: RogPalette.accent; + background: RogPalette.control-background; Dialog { Text { max-width: 420px; font-size: 16px; wrap: TextWrap.word-wrap; text: @tr("confirm_reset" => "Are you sure you want to reset this?"); + color: RogPalette.text-primary; } StandardButton { @@ -161,9 +168,9 @@ export component SystemToggle inherits RogItem { alignment: LayoutAlignment.start; padding-left: 10px; Text { - font-size: 14px; + font-size: 16px; vertical-alignment: TextVerticalAlignment.center; - color: Palette.control-foreground; + color: RogPalette.text-primary; text: root.text; } } @@ -192,9 +199,9 @@ export component SystemToggleInt inherits RogItem { alignment: LayoutAlignment.start; padding-left: 10px; Text { - font-size: 14px; + font-size: 16px; vertical-alignment: TextVerticalAlignment.center; - color: Palette.control-foreground; + color: RogPalette.text-primary; text: root.text; } } @@ -222,10 +229,10 @@ export component SystemToggleVert inherits RogItem { alignment: LayoutAlignment.space-around; padding-top: 8px; Text { - font-size: 14px; + font-size: 16px; vertical-alignment: TextVerticalAlignment.bottom; horizontal-alignment: TextHorizontalAlignment.center; - color: Palette.control-foreground; + color: RogPalette.text-primary; text: root.text; } @@ -253,9 +260,9 @@ export component SystemDropdown inherits RogItem { alignment: LayoutAlignment.start; padding-left: 10px; Text { - font-size: 14px; + font-size: 16px; vertical-alignment: TextVerticalAlignment.center; - color: Palette.control-foreground; + color: RogPalette.text-primary; text: root.text; } } @@ -287,24 +294,28 @@ export component PopupNotification { height: root.height; // TODO: add properties to display Rectangle { - border-width: 2px; - border-color: Palette.accent-background; - background: Palette.background; - + border-width: 1px; + border-color: RogPalette.accent; + background: RogPalette.background; + // TODO: drop shadows slow + // drop-shadow-offset-x: 7px; + // drop-shadow-offset-y: 7px; + // drop-shadow-color: black; + // drop-shadow-blur: 30px; VerticalLayout { Dialog { VerticalLayout { alignment: start; Text { text: heading; - color: Palette.control-foreground; + color: RogPalette.text-primary; font-size: 32px; font-weight: 900; } Text { text: content; - color: Palette.control-foreground; + color: RogPalette.text-secondary; font-size: 18px; } } diff --git a/rog-control-center/ui/widgets/graph.slint b/rog-control-center/ui/widgets/graph.slint index 509ba894..208bf7b7 100644 --- a/rog-control-center/ui/widgets/graph.slint +++ b/rog-control-center/ui/widgets/graph.slint @@ -1,4 +1,5 @@ import { Palette } from "std-widgets.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; export struct Node { x: length, y: length} @@ -44,7 +45,7 @@ export component Graph inherits Rectangle { for n in 11: Path { viewbox-width: self.width / 1px; viewbox-height: self.height / 1px; - stroke: Palette.alternate-foreground.darker(200%); + stroke: RogPalette.control-border; stroke-width: 1px; MoveTo { x: scale_x_to_graph(n * 10px) / 1px; @@ -60,7 +61,7 @@ export component Graph inherits Rectangle { } for n in 11: Text { - color: Palette.accent-background; + color: RogPalette.text-secondary; font-size <=> root.axis_font_size; text: "\{n * 10}c"; x: scale_x_to_graph(n * 10px) - self.width / 3; @@ -70,7 +71,7 @@ export component Graph inherits Rectangle { for n in 11: Path { viewbox-width: self.width / 1px; viewbox-height: self.height / 1px; - stroke: Palette.alternate-foreground.darker(200%); + stroke: RogPalette.control-border; stroke-width: 1px; MoveTo { x: 0; @@ -86,7 +87,7 @@ export component Graph inherits Rectangle { } for n in 11: Text { - color: Palette.accent-background; + color: RogPalette.text-secondary; font-size <=> root.axis_font_size; text: "\{n * 10}%"; x: - self.width; @@ -97,7 +98,7 @@ export component Graph inherits Rectangle { if idx + 1 != nodes.length: Path { viewbox-width: self.width / 1px; viewbox-height: self.height / 1px; - stroke: Palette.control-foreground; + stroke: RogPalette.accent; stroke-width: 2px; MoveTo { x: scale_x_to_graph(nodes[idx].x) / 1px; @@ -114,19 +115,19 @@ export component Graph inherits Rectangle { for n[idx] in nodes: Rectangle { states [ pressed when touch.pressed: { - point.background: Palette.selection-background; - tip.background: Palette.selection-background; + point.background: RogPalette.accent; + tip.background: RogPalette.accent; tip.opacity: 1.0; } hover when touch.has-hover: { - point.background: Palette.accent-background; - tip.background: Palette.accent-background; + point.background: RogPalette.accent; + tip.background: RogPalette.accent; tip.opacity: 1.0; } ] // point := Rectangle { - background: Palette.control-foreground; + background: RogPalette.text-primary; x: scale_x_to_graph(n.x) - self.width / 2; y: graph.height - scale_y_to_graph(n.y) - self.height / 2; width: 18px; @@ -142,10 +143,14 @@ export component Graph inherits Rectangle { } else if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) < nodes[idx - 1].x { n.x = nodes[idx - 1].x + pad; } + + // Y-Axis: Monotonic Non-Decreasing if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) > nodes[idx + 1].y { - n.y = nodes[idx + 1].y - pad; + n.y = nodes[idx + 1].y; // Allow equality } else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < nodes[idx - 1].y { - n.y = nodes[idx - 1].y + pad; + n.y = nodes[idx - 1].y; // Allow equality + } else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < 0.0 { + n.y = 0px; } } else if idx == 0 { if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) < 0.0 { @@ -153,10 +158,12 @@ export component Graph inherits Rectangle { } else if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) > nodes[idx + 1].x { n.x = nodes[idx + 1].x - pad; } + + // Y-Axis: <= Next Point if n.y - scale_y_to_node(self.mouse-y - self.pressed-y) < 0.0 { - n.y = 1px; + n.y = 0px; // Allow 0 RPM } else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) > nodes[idx + 1].y { - n.y = nodes[idx + 1].y - pad; + n.y = nodes[idx + 1].y; // Allow equality } } else if idx == nodes.length - 1 { if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) > scale_x_to_node(graph.width) { @@ -164,10 +171,14 @@ export component Graph inherits Rectangle { } else if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) < nodes[idx - 1].x { n.x = nodes[idx - 1].x + pad; } + + // Y-Axis: >= Previous Point if n.y - scale_y_to_node(self.mouse-y - self.pressed-y) > scale_y_to_node(graph.height) { - n.y = scale_y_to_node(graph.height - 1px); + n.y = scale_y_to_node(graph.height); } else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < nodes[idx - 1].y { - n.y = nodes[idx - 1].y + pad; + n.y = nodes[idx - 1].y; // Allow equality + } else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < 0.0 { + n.y = 0px; } } } @@ -189,13 +200,12 @@ export component Graph inherits Rectangle { } tip := Rectangle { - background: Palette.control-foreground; + background: RogPalette.control-background; opacity: 0.3; - border-radius: 12px; x: final_x_pos(); y: final_y_pos(); - width: label.preferred-width + 14px; - height: label.preferred-height + 4px; + width: label.preferred-width; + height: label.preferred-height; function x_pos() -> length { scale_x_to_graph(n.x) - label.preferred-width - 8px } @@ -225,8 +235,8 @@ export component Graph inherits Rectangle { } // label := Text { - color: Palette.accent-foreground; - font-size: 14px; + color: RogPalette.text-primary; + font-size: 16px; text: "\{Math.floor(n.x / 1px)}c, \{fan_pct()}%"; } } diff --git a/rog-control-center/ui/widgets/sidebar.slint b/rog-control-center/ui/widgets/sidebar.slint index f29254e5..1784ea77 100644 --- a/rog-control-center/ui/widgets/sidebar.slint +++ b/rog-control-center/ui/widgets/sidebar.slint @@ -1,9 +1,12 @@ // Copyright © SixtyFPS GmbH // SPDX-License-Identifier: MIT -import { Palette, HorizontalBox, VerticalBox } from "std-widgets.slint"; +import { HorizontalBox, VerticalBox } from "std-widgets.slint"; +import { RogPalette } from "../themes/rog_theme.slint"; component SideBarItem inherits Rectangle { + // padding only has effect on layout elements + // padding: 10px; in property selected; in property has-focus; in-out property text <=> label.text; @@ -24,22 +27,34 @@ component SideBarItem inherits Rectangle { state.opacity: 0.8; } ] - state := Rectangle { opacity: 0; - background: Palette.selection-background; + border-width: 0px; // Modern look: no full border, maybe just a left bar? + // Or keep the ROG style border + border-color: RogPalette.accent; + background: root.selected ? RogPalette.control-background : RogPalette.alternate-background; + + // Add a red indicator line on the left for selected items + Rectangle { + x: 0; + width: 4px; + height: 100%; + background: root.selected ? RogPalette.accent : Colors.transparent; + } + animate opacity { duration: 150ms; } + // animate border-width { duration: 150ms; } height: l.preferred-height; } l := HorizontalBox { - x: 4px; y: (parent.height - self.height) / 2; spacing: 0px; label := Text { - color: Palette.foreground; + color: root.selected ? RogPalette.accent : RogPalette.text-primary; vertical-alignment: center; font-size: 14px; + font-weight: root.selected ? 700 : 400; } } @@ -52,16 +67,20 @@ component SideBarItem inherits Rectangle { export component SideBar inherits Rectangle { in property <[string]> model: []; in property <[bool]> available: []; + in property title <=> label.text; out property current-item: 0; out property current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab - width: 180px; + width: 160px; forward-focus: fs; accessible-role: tab; accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-item; Rectangle { - background: Palette.alternate-background; + border-width: 0px; + // border-color: RogPalette.accent; + border-radius: 0px; + background: RogPalette.alternate-background; // Darker sidebar fs := FocusScope { key-pressed(event) => { if (event.text == "\n") { @@ -94,23 +113,21 @@ export component SideBar inherits Rectangle { VerticalBox { spacing: 4px; - padding: 0px; alignment: start; - - Image { - height: 100px; - source: @image-url("../../data/rog-control-center.png"); + label := Text { + font-size: 24px; // Larger brand text + font-weight: 800; horizontal-alignment: center; - image-fit: contain; + color: RogPalette.accent; // ROG Red brand text } + // Spacer after brand text Rectangle { - height: 1px; - background: Palette.border; + height: 20px; } navigation := VerticalLayout { - spacing: -6px; + spacing: 4px; // Spacing between items alignment: start; vertical-stretch: 0; for item[index] in root.model: SideBarItem { diff --git a/rog-control-center/ui/widgets/status_bar.slint b/rog-control-center/ui/widgets/status_bar.slint new file mode 100644 index 00000000..76874de4 --- /dev/null +++ b/rog-control-center/ui/widgets/status_bar.slint @@ -0,0 +1,58 @@ +import { RogPalette } from "../themes/rog_theme.slint"; + +export global SystemStatus { + in property cpu_temp: 0; + in property gpu_temp: 0; + in property cpu_fan: 0; + in property gpu_fan: 0; + in property power_w: "--"; + in property power_avg_w: "--"; +} + +component StatusItem inherits Rectangle { + in property label; + in property value; + in property unit; + + HorizontalLayout { + spacing: 5px; + Text { text: label; color: RogPalette.text-secondary; font-weight: 700; vertical-alignment: center; } + Text { text: value; color: RogPalette.text-primary; vertical-alignment: center; } + Text { text: unit; color: RogPalette.text-secondary; font-size: 12px; vertical-alignment: center; } + } +} + +export component StatusBar inherits Rectangle { + background: RogPalette.control-background; + height: 30px; + + // Simulated top border + Rectangle { + y: 0px; + x: 0px; + width: parent.width; + height: 1px; + background: RogPalette.control-border; + } + + HorizontalLayout { + padding-left: 20px; + padding-right: 20px; + spacing: 20px; + alignment: space-between; + + HorizontalLayout { + spacing: 20px; + StatusItem { label: "CPU"; value: SystemStatus.cpu_temp; unit: "°C"; } + StatusItem { label: "GPU"; value: SystemStatus.gpu_temp; unit: "°C"; } + } + + HorizontalLayout { + spacing: 20px; + StatusItem { label: "PWR"; value: SystemStatus.power_w; unit: "W"; } + StatusItem { label: "AVG"; value: SystemStatus.power_avg_w; unit: "W"; } + StatusItem { label: "CPU Fan"; value: SystemStatus.cpu_fan; unit: "RPM"; } + StatusItem { label: "GPU Fan"; value: SystemStatus.gpu_fan; unit: "RPM"; } + } + } +} diff --git a/rog-control-center/ui/windows/tray_tooltip.slint b/rog-control-center/ui/windows/tray_tooltip.slint new file mode 100644 index 00000000..73758128 --- /dev/null +++ b/rog-control-center/ui/windows/tray_tooltip.slint @@ -0,0 +1,76 @@ +import { RogPalette } from "../themes/rog_theme.slint"; +import { SystemStatus } from "../widgets/status_bar.slint"; + +component StatusItem inherits Rectangle { + in property label; + in property value; + in property unit; + + HorizontalLayout { + spacing: 8px; + Text { + text: label; + color: RogPalette.text-secondary; + font-weight: 700; + vertical-alignment: center; + font-size: 13px; + } + Text { + text: value; + color: RogPalette.text-primary; + vertical-alignment: center; + font-size: 14px; + } + Text { + text: unit; + color: RogPalette.text-secondary; + font-size: 11px; + vertical-alignment: center; + } + } +} + +export component TrayTooltip inherits Window { + always-on-top: true; + no-frame: true; + background: transparent; + width: 280px; + height: 160px; + + Rectangle { + background: RogPalette.control-background; + border-radius: 8px; + border-width: 1px; + border-color: RogPalette.control-border; + drop-shadow-blur: 10px; + drop-shadow-color: rgba(0,0,0,0.5); + + VerticalLayout { + padding: 15px; + spacing: 12px; + + Text { + text: "System Statistics"; + color: RogPalette.accent; + font-size: 16px; + font-weight: 800; + } + + GridLayout { + spacing: 15px; + Row { + StatusItem { label: "CPU"; value: SystemStatus.cpu_temp; unit: "°C"; } + StatusItem { label: "GPU"; value: SystemStatus.gpu_temp; unit: "°C"; } + } + Row { + StatusItem { label: "FAN"; value: SystemStatus.cpu_fan; unit: "RPM"; } + StatusItem { label: "GPU"; value: SystemStatus.gpu_fan; unit: "RPM"; } + } + Row { + StatusItem { label: "PWR"; value: SystemStatus.power_w; unit: "W"; } + StatusItem { label: "AVG"; value: SystemStatus.power_avg_w; unit: "W"; } + } + } + } + } +}